feat: Add user roles, but do not yet enforce them (#1200)

* chore: Rework roles to be expandable by name alone
This commit is contained in:
Steven Masley
2022-04-29 09:04:19 -05:00
committed by GitHub
parent ba4c3ce3b9
commit 35211e2190
26 changed files with 1150 additions and 232 deletions

View File

@ -1,7 +1,6 @@
package rbac
import "fmt"
// Permission is the format passed into the rego.
type Permission struct {
// Negate makes this a negative permission
Negate bool `json:"negate"`
@ -14,122 +13,15 @@ type Permission struct {
// - Site level permissions apply EVERYWHERE
// - Org level permissions apply to EVERYTHING in a given ORG
// - User level permissions are the lowest
// In most cases, you will just want to use the pre-defined roles
// below.
// This is the type passed into the rego as a json payload.
// Users of this package should instead **only** use the role names, and
// this package will expand the role names into their json payloads.
type Role struct {
Name string `json:"name"`
Site []Permission `json:"site"`
// Org is a map of orgid to permissions. We represent orgid as a string.
// We scope the organizations in the role so we can easily combine all the
// roles.
Org map[string][]Permission `json:"org"`
User []Permission `json:"user"`
}
// Roles are stored as structs, so they can be serialized and stored. Until we store them elsewhere,
// const's will do just fine.
var (
// RoleAdmin is a role that allows everything everywhere.
RoleAdmin = Role{
Name: "admin",
Site: permissions(map[Object][]Action{
ResourceWildcard: {WildcardSymbol},
}),
}
// RoleMember is a role that allows access to user-level resources.
RoleMember = Role{
Name: "member",
User: permissions(map[Object][]Action{
ResourceWildcard: {WildcardSymbol},
}),
}
// RoleAuditor is an example on how to give more precise permissions
RoleAuditor = Role{
Name: "auditor",
Site: permissions(map[Object][]Action{
//ResourceAuditLogs: {ActionRead},
// Should be able to read user details to associate with logs.
// Without this the user-id in logs is not very helpful
ResourceWorkspace: {ActionRead},
}),
}
)
func RoleOrgDenyAll(orgID string) Role {
return Role{
Name: "org-deny-" + orgID,
Org: map[string][]Permission{
orgID: {
{
Negate: true,
ResourceType: "*",
ResourceID: "*",
Action: "*",
},
},
},
}
}
// RoleOrgAdmin returns a role with all actions allows in a given
// organization scope.
func RoleOrgAdmin(orgID string) Role {
return Role{
Name: "org-admin-" + orgID,
Org: map[string][]Permission{
orgID: {
{
Negate: false,
ResourceType: "*",
ResourceID: "*",
Action: "*",
},
},
},
}
}
// RoleOrgMember returns a role with default permissions in a given
// organization scope.
func RoleOrgMember(orgID string) Role {
return Role{
Name: "org-member-" + orgID,
Org: map[string][]Permission{
orgID: {},
},
}
}
// RoleWorkspaceAgent returns a role with permission to read a given
// workspace.
func RoleWorkspaceAgent(workspaceID string) Role {
return Role{
Name: fmt.Sprintf("agent-%s", workspaceID),
// This is at the site level to prevent the token from losing access if the user
// is kicked from the org
Site: []Permission{
{
Negate: false,
ResourceType: ResourceWorkspace.Type,
ResourceID: workspaceID,
Action: ActionRead,
},
},
}
}
func permissions(perms map[Object][]Action) []Permission {
list := make([]Permission, 0, len(perms))
for k, actions := range perms {
for _, act := range actions {
act := act
list = append(list, Permission{
Negate: false,
ResourceType: k.Type,
ResourceID: WildcardSymbol,
Action: act,
})
}
}
return list
}