mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
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:
@ -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)
|
||||
|
@ -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: "*",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user