2022-04-13 13:35:35 +00:00
|
|
|
package rbac
|
|
|
|
|
2022-04-29 14:04:19 +00:00
|
|
|
import (
|
|
|
|
"github.com/google/uuid"
|
2024-05-16 17:07:44 +00:00
|
|
|
"golang.org/x/xerrors"
|
2024-05-15 14:46:35 +00:00
|
|
|
|
|
|
|
"github.com/coder/coder/v2/coderd/rbac/policy"
|
2022-04-29 14:04:19 +00:00
|
|
|
)
|
|
|
|
|
2023-07-26 14:33:48 +00:00
|
|
|
// 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())
|
|
|
|
}
|
|
|
|
|
2022-04-13 13:35:35 +00:00
|
|
|
// 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 {
|
2023-01-19 19:41:36 +00:00
|
|
|
// ID is the resource's uuid
|
|
|
|
ID string `json:"id"`
|
2022-08-09 18:16:53 +00:00
|
|
|
Owner string `json:"owner"`
|
2022-04-13 13:35:35 +00:00
|
|
|
// OrgID specifies which org the object is a part of.
|
|
|
|
OrgID string `json:"org_owner"`
|
|
|
|
|
2022-06-04 20:13:37 +00:00
|
|
|
// Type is "workspace", "project", "app", etc
|
2022-04-13 13:35:35 +00:00
|
|
|
Type string `json:"type"`
|
2022-10-10 20:37:06 +00:00
|
|
|
|
2024-05-15 14:46:35 +00:00
|
|
|
ACLUserList map[string][]policy.Action ` json:"acl_user_list"`
|
|
|
|
ACLGroupList map[string][]policy.Action ` json:"acl_group_list"`
|
2022-04-13 13:35:35 +00:00
|
|
|
}
|
|
|
|
|
2024-05-15 16:09:42 +00:00
|
|
|
// 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 {
|
2024-05-16 17:07:44 +00:00
|
|
|
return xerrors.Errorf("invalid type %q", z.Type)
|
2024-05-15 16:09:42 +00:00
|
|
|
}
|
|
|
|
if _, ok := perms.Actions[action]; !ok {
|
2024-05-16 17:07:44 +00:00
|
|
|
return xerrors.Errorf("invalid action %q for type %q", action, z.Type)
|
2024-05-15 16:09:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-02-03 19:03:46 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-05-15 14:46:35 +00:00
|
|
|
func equalACLLists(a, b map[string][]policy.Action) bool {
|
2023-02-03 19:03:46 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-05-24 13:43:34 +00:00
|
|
|
func (z Object) RBACObject() Object {
|
|
|
|
return z
|
|
|
|
}
|
|
|
|
|
2022-04-13 13:35:35 +00:00
|
|
|
// 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,
|
2024-05-15 14:46:35 +00:00
|
|
|
ACLUserList: map[string][]policy.Action{},
|
|
|
|
ACLGroupList: map[string][]policy.Action{},
|
2022-04-13 13:35:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-19 19:41:36 +00:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-13 13:35:35 +00:00
|
|
|
// InOrg adds an org OwnerID to the resource
|
2022-04-29 14:04:19 +00:00
|
|
|
func (z Object) InOrg(orgID uuid.UUID) Object {
|
2022-04-13 13:35:35 +00:00
|
|
|
return Object{
|
2023-01-19 19:41:36 +00:00
|
|
|
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,
|
2022-04-13 13:35:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithOwner adds an OwnerID to the resource
|
|
|
|
func (z Object) WithOwner(ownerID string) Object {
|
|
|
|
return Object{
|
2023-01-19 19:41:36 +00:00
|
|
|
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
|
2024-05-15 14:46:35 +00:00
|
|
|
func (z Object) WithACLUserList(acl map[string][]policy.Action) Object {
|
2022-10-10 20:37:06 +00:00
|
|
|
return Object{
|
2023-01-19 19:41:36 +00:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-15 14:46:35 +00:00
|
|
|
func (z Object) WithGroupACL(groups map[string][]policy.Action) Object {
|
2022-10-10 20:37:06 +00:00
|
|
|
return Object{
|
2023-01-19 19:41:36 +00:00
|
|
|
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,
|
2022-04-13 13:35:35 +00:00
|
|
|
}
|
|
|
|
}
|