coder/coderd/rbac/object.go

189 lines
4.3 KiB
Go
Raw Permalink Normal View History

package rbac
import (
"github.com/google/uuid"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/coderd/rbac/policy"
)
// ResourceUserObject is a helper function to create a user object for authz checks.
func ResourceUserObject(userID uuid.UUID) Object {
return ResourceUser.WithID(userID).WithOwner(userID.String())
}
// Object is used to create objects for authz checks when you have none in
// hand to run the check on.
// An example is if you want to list all workspaces, you can create a Object
// that represents the set of workspaces you are trying to get access too.
// Do not export this type, as it can be created from a resource type constant.
type Object struct {
// ID is the resource's uuid
ID string `json:"id"`
Owner string `json:"owner"`
// OrgID specifies which org the object is a part of.
OrgID string `json:"org_owner"`
feat: Add workspace application support (#1773) * feat: Add app support This adds apps as a property to a workspace agent. The resource is added to the Terraform provider here: https://github.com/coder/terraform-provider-coder/pull/17 Apps will be opened in the dashboard or via the CLI with `coder open <name>`. If `command` is specified, a terminal will appear locally and in the web. If `target` is specified, the browser will open to an exposed instance of that target. * Compare fields in apps test * Update Terraform provider to use relative path * Add some basic structure for routing * chore: Remove interface from coderd and lift API surface Abstracting coderd into an interface added misdirection because the interface was never intended to be fulfilled outside of a single implementation. This lifts the abstraction, and attaches all handlers to a root struct named `*coderd.API`. * Add basic proxy logic * Add proxying based on path * Add app proxying for wildcards * Add wsconncache * fix: Race when writing to a closed pipe This is such an intermittent race it's difficult to track, but regardless this is an improvement to the code. * fix: Race when writing to a closed pipe This is such an intermittent race it's difficult to track, but regardless this is an improvement to the code. * fix: Race when writing to a closed pipe This is such an intermittent race it's difficult to track, but regardless this is an improvement to the code. * fix: Race when writing to a closed pipe This is such an intermittent race it's difficult to track, but regardless this is an improvement to the code. * Add workspace route proxying endpoint - Makes the workspace conn cache concurrency-safe - Reduces unnecessary open checks in `peer.Channel` - Fixes the use of a temporary context when dialing a workspace agent * Add embed errors * chore: Refactor site to improve testing It was difficult to develop this package due to the embed build tag being mandatory on the tests. The logic to test doesn't require any embedded files. * Add test for error handler * Remove unused access url * Add RBAC tests * Fix dial agent syntax * Fix linting errors * Fix gen * Fix icon required * Adjust migration number * Fix proxy error status code * Fix empty db lookup
2022-06-04 20:13:37 +00:00
// Type is "workspace", "project", "app", etc
Type string `json:"type"`
2022-10-10 20:37:06 +00:00
ACLUserList map[string][]policy.Action ` json:"acl_user_list"`
ACLGroupList map[string][]policy.Action ` json:"acl_group_list"`
}
// ValidAction checks if the action is valid for the given object type.
func (z Object) ValidAction(action policy.Action) error {
perms, ok := policy.RBACPermissions[z.Type]
if !ok {
return xerrors.Errorf("invalid type %q", z.Type)
}
if _, ok := perms.Actions[action]; !ok {
return xerrors.Errorf("invalid action %q for type %q", action, z.Type)
}
return nil
}
// AvailableActions returns all available actions for a given object.
// Wildcard is omitted.
func (z Object) AvailableActions() []policy.Action {
perms, ok := policy.RBACPermissions[z.Type]
if !ok {
return []policy.Action{}
}
actions := make([]policy.Action, 0, len(perms.Actions))
for action := range perms.Actions {
actions = append(actions, action)
}
return actions
}
func (z Object) Equal(b Object) bool {
if z.ID != b.ID {
return false
}
if z.Owner != b.Owner {
return false
}
if z.OrgID != b.OrgID {
return false
}
if z.Type != b.Type {
return false
}
if !equalACLLists(z.ACLUserList, b.ACLUserList) {
return false
}
if !equalACLLists(z.ACLGroupList, b.ACLGroupList) {
return false
}
return true
}
func equalACLLists(a, b map[string][]policy.Action) bool {
if len(a) != len(b) {
return false
}
for k, actions := range a {
if len(actions) != len(b[k]) {
return false
}
for i, a := range actions {
if a != b[k][i] {
return false
}
}
}
return true
}
func (z Object) RBACObject() Object {
return z
}
// All returns an object matching all resources of the same type.
func (z Object) All() Object {
return Object{
2022-10-10 20:37:06 +00:00
Owner: "",
OrgID: "",
Type: z.Type,
ACLUserList: map[string][]policy.Action{},
ACLGroupList: map[string][]policy.Action{},
}
}
func (z Object) WithIDString(id string) Object {
return Object{
ID: id,
Owner: z.Owner,
OrgID: z.OrgID,
Type: z.Type,
ACLUserList: z.ACLUserList,
ACLGroupList: z.ACLGroupList,
}
}
func (z Object) WithID(id uuid.UUID) Object {
return Object{
ID: id.String(),
Owner: z.Owner,
OrgID: z.OrgID,
Type: z.Type,
ACLUserList: z.ACLUserList,
ACLGroupList: z.ACLGroupList,
}
}
// InOrg adds an org OwnerID to the resource
func (z Object) InOrg(orgID uuid.UUID) Object {
return Object{
ID: z.ID,
2022-10-10 20:37:06 +00:00
Owner: z.Owner,
OrgID: orgID.String(),
Type: z.Type,
ACLUserList: z.ACLUserList,
ACLGroupList: z.ACLGroupList,
}
}
// WithOwner adds an OwnerID to the resource
func (z Object) WithOwner(ownerID string) Object {
return Object{
ID: z.ID,
2022-10-10 20:37:06 +00:00
Owner: ownerID,
OrgID: z.OrgID,
Type: z.Type,
ACLUserList: z.ACLUserList,
ACLGroupList: z.ACLGroupList,
}
}
// WithACLUserList adds an ACL list to a given object
func (z Object) WithACLUserList(acl map[string][]policy.Action) Object {
2022-10-10 20:37:06 +00:00
return Object{
ID: z.ID,
2022-10-10 20:37:06 +00:00
Owner: z.Owner,
OrgID: z.OrgID,
Type: z.Type,
ACLUserList: acl,
ACLGroupList: z.ACLGroupList,
}
}
func (z Object) WithGroupACL(groups map[string][]policy.Action) Object {
2022-10-10 20:37:06 +00:00
return Object{
ID: z.ID,
2022-10-10 20:37:06 +00:00
Owner: z.Owner,
OrgID: z.OrgID,
Type: z.Type,
ACLUserList: z.ACLUserList,
ACLGroupList: groups,
}
}