feat: Add rbac to templateversion+orgmember endpoints (#1713)

This commit is contained in:
Steven Masley
2022-05-25 11:00:59 -05:00
committed by GitHub
parent f8410dee3a
commit eea8dc6c16
17 changed files with 302 additions and 66 deletions
+1
View File
@@ -3,6 +3,7 @@ package rbac
import (
"context"
_ "embed"
"golang.org/x/xerrors"
"github.com/open-policy-agent/opa/rego"
+37
View File
@@ -135,6 +135,12 @@ var (
Action: ActionRead,
ResourceID: "*",
},
{
// Can read available roles.
ResourceType: ResourceOrgRoleAssignment.Type,
ResourceID: "*",
Action: ActionRead,
},
},
},
}
@@ -217,6 +223,37 @@ func SiteRoles() []Role {
return roles
}
// ChangeRoleSet is a helper function that finds the difference of 2 sets of
// roles. When setting a user's new roles, it is equivalent to adding and
// removing roles. This set determines the changes, so that the appropriate
// RBAC checks can be applied using "ActionCreate" and "ActionDelete" for
// "added" and "removed" roles respectively.
func ChangeRoleSet(from []string, to []string) (added []string, removed []string) {
has := make(map[string]struct{})
for _, exists := range from {
has[exists] = struct{}{}
}
for _, roleName := range to {
// If the user already has the role assigned, we don't need to check the permission
// to reassign it. Only run permission checks on the difference in the set of
// roles.
if _, ok := has[roleName]; ok {
delete(has, roleName)
continue
}
added = append(added, roleName)
}
// Remaining roles are the ones removed/deleted.
for roleName := range has {
removed = append(removed, roleName)
}
return added, removed
}
// roleName is a quick helper function to return
// role_name:scopeID
// If no scopeID is required, only 'role_name' is returned
+49
View File
@@ -93,3 +93,52 @@ func TestListRoles(t *testing.T) {
},
orgRoleNames)
}
func TestChangeSet(t *testing.T) {
t.Parallel()
testCases := []struct {
Name string
From []string
To []string
ExpAdd []string
ExpRemove []string
}{
{
Name: "Empty",
},
{
Name: "Same",
From: []string{"a", "b", "c"},
To: []string{"a", "b", "c"},
ExpAdd: []string{},
ExpRemove: []string{},
},
{
Name: "AllRemoved",
From: []string{"a", "b", "c"},
ExpRemove: []string{"a", "b", "c"},
},
{
Name: "AllAdded",
To: []string{"a", "b", "c"},
ExpAdd: []string{"a", "b", "c"},
},
{
Name: "AddAndRemove",
From: []string{"a", "b", "c"},
To: []string{"a", "b", "d", "e"},
ExpAdd: []string{"d", "e"},
ExpRemove: []string{"c"},
},
}
for _, c := range testCases {
c := c
t.Run(c.Name, func(t *testing.T) {
t.Parallel()
add, remove := rbac.ChangeRoleSet(c.From, c.To)
require.ElementsMatch(t, c.ExpAdd, add, "expect added")
require.ElementsMatch(t, c.ExpRemove, remove, "expect removed")
})
}
}
+10
View File
@@ -22,6 +22,10 @@ var (
Type: "workspace",
}
// ResourceTemplate CRUD. Org owner only.
// create/delete = Make or delete a new template
// update = Update the template, make new template versions
// read = read the template and all versions associated
ResourceTemplate = Object{
Type: "template",
}
@@ -41,6 +45,7 @@ var (
// ResourceRoleAssignment might be expanded later to allow more granular permissions
// to modifying roles. For now, this covers all possible roles, so having this permission
// allows granting/deleting **ALL** roles.
// Never has an owner or org.
// create = Assign roles
// update = ??
// read = View available roles to assign
@@ -49,6 +54,11 @@ var (
Type: "assign_role",
}
// ResourceOrgRoleAssignment is just like ResourceRoleAssignment but for organization roles.
ResourceOrgRoleAssignment = Object{
Type: "assign_org_role",
}
// ResourceAPIKey is owned by a user.
// create = Create a new api key for user
// update = ??