feat: Rbac more coderd endpoints, unit test to confirm (#1437)

* feat: Enforce authorize call on all endpoints
- Make 'request()' exported for running custom requests
* Rbac users endpoints
* 401 -> 403
This commit is contained in:
Steven Masley
2022-05-17 13:43:19 -05:00
committed by GitHub
parent 495c87b6c3
commit 4ad5ac2d4a
40 changed files with 631 additions and 319 deletions

View File

@ -9,6 +9,10 @@ import (
"github.com/open-policy-agent/opa/rego"
)
type Authorizer interface {
ByRoleName(ctx context.Context, subjectID string, roleNames []string, action Action, object Object) error
}
// RegoAuthorizer will use a prepared rego query for performing authorize()
type RegoAuthorizer struct {
query rego.PreparedEvalQuery
@ -38,10 +42,10 @@ type authSubject struct {
Roles []Role `json:"roles"`
}
// AuthorizeByRoleName will expand all roleNames into roles before calling Authorize().
// ByRoleName will expand all roleNames into roles before calling Authorize().
// This is the function intended to be used outside this package.
// The role is fetched from the builtin map located in memory.
func (a RegoAuthorizer) AuthorizeByRoleName(ctx context.Context, subjectID string, roleNames []string, action Action, object Object) error {
func (a RegoAuthorizer) ByRoleName(ctx context.Context, subjectID string, roleNames []string, action Action, object Object) error {
roles := make([]Role, 0, len(roleNames))
for _, n := range roleNames {
r, err := RoleByName(n)

View File

@ -64,6 +64,10 @@ var (
return Role{
Name: member,
DisplayName: "Member",
Site: permissions(map[Object][]Action{
// All users can read all other users and know they exist.
ResourceUser: {ActionRead},
}),
User: permissions(map[Object][]Action{
ResourceWildcard: {WildcardSymbol},
}),
@ -111,7 +115,20 @@ var (
Name: roleName(orgMember, organizationID),
DisplayName: "Organization Member",
Org: map[string][]Permission{
organizationID: {},
organizationID: {
{
// All org members can read the other members in their org.
ResourceType: ResourceOrganizationMember.Type,
Action: ActionRead,
ResourceID: "*",
},
{
// All org members can read the organization
ResourceType: ResourceOrganization.Type,
Action: ActionRead,
ResourceID: "*",
},
},
},
}
},

View File

@ -6,7 +6,7 @@ const (
// errUnauthorized is the error message that should be returned to
// clients when an action is forbidden. It is intentionally vague to prevent
// disclosing information that a client should not have access to.
errUnauthorized = "unauthorized"
errUnauthorized = "forbidden"
)
// UnauthorizedError is the error type for authorization errors

View File

@ -9,6 +9,10 @@ const WildcardSymbol = "*"
// Resources are just typed objects. Making resources this way allows directly
// passing them into an Authorize function and use the chaining api.
var (
// ResourceWorkspace CRUD. Org + User owner
// create/delete = make or delete workspaces
// read = access workspace
// update = edit workspace variables
ResourceWorkspace = Object{
Type: "workspace",
}
@ -17,19 +21,60 @@ var (
Type: "template",
}
ResourceFile = Object{
Type: "file",
}
// ResourceOrganization CRUD. Has an org owner on all but 'create'.
// create/delete = make or delete organizations
// read = view org information (Can add user owner for read)
// update = ??
ResourceOrganization = Object{
Type: "organization",
}
// 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.
// create = Assign roles
// update = ??
// read = View available roles to assign
// delete = Remove role
ResourceRoleAssignment = Object{
Type: "assign_role",
}
// ResourceAPIKey is owned by a user.
// create = Create a new api key for user
// update = ??
// read = View api key
// delete = Delete api key
ResourceAPIKey = Object{
Type: "api_key",
}
// ResourceUser is the user in the 'users' table.
// ResourceUser never has any owners or in an org, as it's site wide.
// create/delete = make or delete a new user.
// read = view all 'user' table data
// update = update all 'user' table data
ResourceUser = Object{
Type: "user",
}
// ResourceUserRole 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.
ResourceUserRole = Object{
Type: "user_role",
// ResourceUserData is any data associated with a user. A user has control
// over their data (profile, password, etc). So this resource has an owner.
ResourceUserData = Object{
Type: "user_data",
}
ResourceUserPasswordRole = Object{
Type: "user_password",
// ResourceOrganizationMember is a user's membership in an organization.
// Has ONLY an organization owner. The resource ID is the user's ID
// create/delete = Create/delete member from org.
// update = Update organization member
// read = View member
ResourceOrganizationMember = Object{
Type: "organization_member",
}
// ResourceWildcard represents all resource types