Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 105 additions & 2 deletions coderd/rbac/authz_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,19 +312,35 @@ func TestAuthorizeDomain(t *testing.T) {

testAuthorize(t, "UserACLList", user, []authTestCase{
{
resource: ResourceWorkspace.WithOwner(unusedID.String()).InOrg(unusedID).WithACLUserList(map[string][]policy.Action{
resource: ResourceWorkspace.WithOwner(unusedID.String()).InOrg(defOrg).WithACLUserList(map[string][]policy.Action{
user.ID: ResourceWorkspace.AvailableActions(),
}),
actions: ResourceWorkspace.AvailableActions(),
allow: true,
},
{
resource: ResourceWorkspace.WithOwner(unusedID.String()).InOrg(unusedID).WithACLUserList(map[string][]policy.Action{
resource: ResourceWorkspace.WithOwner(unusedID.String()).InOrg(defOrg).WithACLUserList(map[string][]policy.Action{
user.ID: {policy.WildcardSymbol},
}),
actions: ResourceWorkspace.AvailableActions(),
allow: true,
},
{
// User ACLs only grant permissions in organizations where the
// subject is currently a member.
resource: ResourceWorkspace.WithOwner(unusedID.String()).InOrg(unusedID).WithACLUserList(map[string][]policy.Action{
user.ID: ResourceWorkspace.AvailableActions(),
}),
actions: ResourceWorkspace.AvailableActions(),
allow: false,
},
{
resource: ResourceWorkspace.WithOwner(unusedID.String()).InOrg(unusedID).WithACLUserList(map[string][]policy.Action{
user.ID: {policy.WildcardSymbol},
}),
actions: ResourceWorkspace.AvailableActions(),
allow: false,
},
{
resource: ResourceWorkspace.WithOwner(unusedID.String()).InOrg(unusedID).WithACLUserList(map[string][]policy.Action{
user.ID: {policy.ActionRead, policy.ActionUpdate},
Expand Down Expand Up @@ -714,6 +730,93 @@ func TestAuthorizeDomain(t *testing.T) {
}))
}

// TestAuthorizeUserACLOrgMembership verifies that user ACL grants require org
// membership, while site-wide roles still authorize independent of ACLs.
func TestAuthorizeUserACLOrgMembership(t *testing.T) {
t.Parallel()

orgID := uuid.New()

// Site template-admin, not a member of orgID.
siteTemplateAdmin := Subject{
ID: "site-template-admin",
Scope: must(ExpandScope(ScopeAll)),
Roles: Roles{
must(RoleByName(RoleMember())),
must(RoleByName(RoleTemplateAdmin())),
},
}
testAuthorize(t, "SiteTemplateAdminNotInOrg", siteTemplateAdmin, []authTestCase{
{
// Authorized by the site role, no ACL needed.
resource: ResourceTemplate.InOrg(orgID),
actions: []policy.Action{policy.ActionUpdate},
allow: true,
},
{
// Redundant ACL entry; still authorized by the site role.
resource: ResourceTemplate.InOrg(orgID).WithACLUserList(map[string][]policy.Action{
siteTemplateAdmin.ID: {policy.ActionUpdate},
}),
actions: []policy.Action{policy.ActionUpdate},
allow: true,
},
})

// Site user-admin (no template perms), not a member of orgID.
siteUserAdmin := Subject{
ID: "site-user-admin",
Scope: must(ExpandScope(ScopeAll)),
Roles: Roles{
must(RoleByName(RoleMember())),
must(RoleByName(RoleUserAdmin())),
},
}
testAuthorize(t, "SiteUserAdminNotInOrg", siteUserAdmin, []authTestCase{
{
// No template role and no ACL entry: denied.
resource: ResourceTemplate.InOrg(orgID),
actions: []policy.Action{policy.ActionUpdate},
allow: false,
},
{
// An ACL grant must not authorize a non-member.
resource: ResourceTemplate.InOrg(orgID).WithACLUserList(map[string][]policy.Action{
siteUserAdmin.ID: {policy.ActionUpdate},
}),
actions: []policy.Action{policy.ActionUpdate},
allow: false,
},
})

// Same site user-admin, now also a member of orgID.
siteUserAdminOrgMember := Subject{
ID: "site-user-admin-org-member",
Scope: must(ExpandScope(ScopeAll)),
Roles: Roles{
must(RoleByName(RoleMember())),
must(RoleByName(RoleUserAdmin())),
orgMemberRole(orgID),
},
}
testAuthorize(t, "SiteUserAdminOrgMember", siteUserAdminOrgMember, []authTestCase{
{
// Org membership alone does not grant template update.
resource: ResourceTemplate.InOrg(orgID),
actions: []policy.Action{policy.ActionUpdate},
allow: false,
},
{
// As an org member, the ACL grant takes effect.
resource: ResourceTemplate.InOrg(orgID).WithACLUserList(map[string][]policy.Action{
siteUserAdminOrgMember.ID: {policy.ActionUpdate},
}),
actions: []policy.Action{policy.ActionUpdate},
allow: true,
},
})
}

// TestAuthorizeLevels ensures level overrides are acting appropriately
func TestAuthorizeLevels(t *testing.T) {
t.Parallel()
Expand Down
4 changes: 3 additions & 1 deletion coderd/rbac/policy.rego
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,9 @@ object_is_included_in_scope_allow_list if {

# ACL for users
acl_allow if {
# TODO: Should you have to be a member of the org too?
# The subject must be a member of the object's organization for a
# user ACL grant to apply.
is_org_member
perms := input.object.acl_user_list[input.subject.id]

# Check if either the action or * is allowed
Expand Down
Loading