Movatterモバイル変換


[0]ホーム

URL:


Alert GO-2024-3228: Coder vulnerable to post-auth URL redirection to untrusted site ('Open Redirect') in github.com/coder/coder
Notice  The highest tagged major version isv2.

rbac

package
v0.27.3Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2023 License:AGPL-3.0Imports:25Imported by:0

Details

Repository

github.com/coder/coder

Links

README

Authz

Packageauthz implements AuthoriZation for Coder.

Overview

Authorization defines whatpermission asubject has to performactions toobjects:

  • Permission is binary:yes (allowed) orno (denied).
  • Subject in this case is anything that implements interfaceauthz.Subject.
  • Action here is an enumerated list of actions, but we stick toCreate,Read,Update, andDelete here.
  • Object here is anything that implementsauthz.Object.

Permission Structure

Apermission is a rule that grants or denies access for asubject to perform anaction on aobject.Apermission is always applied at a givenlevel:

  • site level applies to all objects in a given Coder deployment.
  • org level applies to all objects that have an organization owner (org_owner)
  • user level applies to all objects that have an owner with the same ID as the subject.

Permissions at a higherlevel always override permissions at alower level.

The effect of apermission can be:

  • positive (allows)
  • negative (denies)
  • abstain (neither allows or denies, not applicable)

Negative permissionsalways overridepositive permissions at the same level.Bothnegative andpositive permissions overrideabstain at the same level.

This can be represented by the following truth table, where Y representspositive, N representsnegative, and _ representsabstain:

ActionPositiveNegativeResult
readY_Y
readYNN
read___
read_NY

Permission Representation

Permissions are represented in string format as<sign>?<level>.<object>.<id>.<action>, where:

  • negated can be either+ or-. If it is omitted, sign is assumed to be+.
  • level is eithersite,org, oruser.
  • object is any valid resource type.
  • id is any valid UUID v4.
  • id is included in the permission syntax, however only scopes may useid to specify a specific object.
  • action iscreate,read,modify, ordelete.

Example Permissions

  • +site.*.*.read: allowed to perform theread action against all objects of typeapp in a given Coder deployment.
  • -user.workspace.*.create: user is not allowed to create workspaces.

Roles

Arole is a set of permissions. When evaluating a role's permission to form an action, all the relevant permissions for the role are combined at each level. Permissions at a higher level override permissions at a lower level.

The following table shows the per-level role evaluation.Y indicates that the role provides positive permissions, N indicates the role provides negative permissions, and _ indicates the role does not provide positive or negative permissions. YN_ indicates that the value in the cell does not matter for the access result.

Role (example)SiteOrgUserResult
site-adminYYN_YN_Y
no-permissionNYN_YN_N
org-admin_YYN_Y
non-org-member_NYN_N
user__YY
__NN
unauthenticated___N

Scopes

Scopes can restrict a given set of permissions. The format of a scope matches a role with the addition of a list of resource ids. For a authorization call to be successful, the subject's roles and the subject's scopes must both allow the action. This means the resulting permissions is the intersection of the subject's roles and the subject's scopes.

An example to give a readonly token is to grant a readonly scope across all resources+site.*.*.read. The intersection with the user's permissions will be the readonly set of their permissions.

Resource IDs

There exists use cases that require specifying a specific resource. If resource IDs are allowed in the roles, then there isan unbounded set of resource IDs that be added to an "allow_list", as the number of roles a user can have is unbounded. This also adds a level of complexity to the role evaluation logic that has large costs at scale.

The use case for specifying this type of permission in a role is limited, and does not justify the extra cost. To solve this for the remaining cases (eg. workspace agent tokens), we can apply anallow_list on a scope. For most cases, theallow_list will just be["*"] which means the scope is allowed to be applied to any resource. This adds negligible cost to the role evaluation logic and 0 cost to partial evaluations.

Example of a scope for a workspace agent token, using anallow_list containing a single resource id.

    "scope": {      "name": "workspace_agent",      "display_name": "Workspace_Agent",      // The ID of the given workspace the agent token correlates to.      "allow_list": ["10d03e62-7703-4df5-a358-4f76577d4e2f"],      "site": [/* ... perms ... */],      "org": {/* ... perms ... */},      "user": [/* ... perms ... */]    }

Testing

You can test outside of golang by using theopa cli.

Evaluation

opa eval --format=pretty 'false' -d policy.rego -i input.json

Partial Evaluation

opa eval --partial --format=pretty 'data.authz.allow' -d policy.rego --unknowns input.object.owner --unknowns input.object.org_owner --unknowns input.object.acl_user_list --unknowns input.object.acl_group_list -i input.json

Documentation

Overview

Code generated by rbacgen/main.go. DO NOT EDIT.

Index

Constants

View Source
const WildcardSymbol = "*"

Variables

View Source
var (// ResourceWildcard represents all resource types// Try to avoid using this where possible.ResourceWildcard =Object{Type:WildcardSymbol,}// ResourceWorkspace CRUD. Org + User owner//create/delete = make or delete workspaces// read = access workspace//update = edit workspace variablesResourceWorkspace =Object{Type: "workspace",}// ResourceWorkspaceBuild refers to permissions necessary to// insert a workspace build job.// create/delete = ?// read = read workspace builds// update = insert/update workspace builds.ResourceWorkspaceBuild =Object{Type: "workspace_build",}// ResourceWorkspaceLocked is returned if a workspace is locked.// It grants restricted permissions on workspace builds.ResourceWorkspaceLocked =Object{Type: "workspace_locked",}// ResourceWorkspaceProxy CRUD. Org//create/delete = make or delete proxies// read = read proxy urls//update = edit workspace proxy fieldsResourceWorkspaceProxy =Object{Type: "workspace_proxy",}// ResourceWorkspaceExecution CRUD. Org + User owner//create = workspace remote execution// read = ?//update = ?// delete = ?ResourceWorkspaceExecution =Object{Type: "workspace_execution",}// ResourceWorkspaceApplicationConnect CRUD. Org + User owner//create = connect to an application// read = ?//update = ?// delete = ?ResourceWorkspaceApplicationConnect =Object{Type: "application_connect",}// ResourceAuditLog// read = access audit logResourceAuditLog =Object{Type: "audit_log",}// 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 associatedResourceTemplate =Object{Type: "template",}// ResourceGroup CRUD. Org admins only.//create/delete = Make or delete a new group.//update = Update the name or members of a group.//read = Read groups and their members.ResourceGroup =Object{Type: "group",}ResourceFile =Object{Type: "file",}ResourceProvisionerDaemon =Object{Type: "provisioner_daemon",}// 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.// Never has an owner or org.//create  = Assign roles//update  = ??//read= View available roles to assign//delete= Remove roleResourceRoleAssignment =Object{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  = ??//read= View api key//delete= Delete api keyResourceAPIKey =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 dataResourceUser =Object{Type: "user",}// 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",}// ResourceOrganizationMember is a user's membership in an organization.// Has ONLY an organization owner.//create/delete  = Create/delete member from org.//update  = Update organization member//read= View memberResourceOrganizationMember =Object{Type: "organization_member",}// ResourceLicense is the license in the 'licenses' table.// ResourceLicense is site wide.// create/delete = add or remove license from site.// read = view license claims// update = not applicable; licenses are immutableResourceLicense =Object{Type: "license",}// ResourceDeploymentValuesResourceDeploymentValues =Object{Type: "deployment_config",}ResourceDeploymentStats =Object{Type: "deployment_stats",}ResourceReplicas =Object{Type: "replicas",}// ResourceDebugInfo controls access to the debug routes `/api/v2/debug/*`.ResourceDebugInfo =Object{Type: "debug_info",}// ResourceSystem is a pseudo-resource only used for system-level actions.ResourceSystem =Object{Type: "system",}// ResourceTailnetCoordinator is a pseudo-resource for use by the tailnet coordinatorResourceTailnetCoordinator =Object{Type: "tailnet_coordinator",})

Resources are just typed objects. Making resources this way allows directlypassing them into an Authorize function and use the chaining api.

Functions

funcCanAssignRoleadded inv0.8.5

func CanAssignRole(expandableExpandableRoles, assignedRolestring)bool

CanAssignRole is a helper function that returns true if the user can assignthe specified role. This also can be used for removing a role.This is a simple implementation for now.

funcChangeRoleSetadded inv0.6.0

func ChangeRoleSet(from []string, to []string) (added []string, removed []string)

ChangeRoleSet is a helper function that finds the difference of 2 sets ofroles. When setting a user's new roles, it is equivalent to adding andremoving roles. This set determines the changes, so that the appropriateRBAC checks can be applied using "ActionCreate" and "ActionDelete" for"added" and "removed" roles respectively.

funcConfigWithACLadded inv0.13.0

func ConfigWithACL()regosql.ConvertConfig

ConfigWithACL is the basic configuration for converting rego to SQL whenthe object has group and user ACL fields.

funcConfigWithoutACLadded inv0.13.0

func ConfigWithoutACL()regosql.ConvertConfig

ConfigWithoutACL is the basic configuration for converting rego to SQL whenthe object has no ACL fields.

funcFilteradded inv0.6.0

func Filter[OObjecter](ctxcontext.Context, authAuthorizer, subjectSubject, actionAction, objects []O) ([]O,error)

Filter takes in a list of objects, and will filter the list removing allthe elements the subject does not have permission for. All objects must beof the same type.

Ideally the 'CompileToSQL' is used instead for large sets. This cost scaleslinearly with the number of objects passed in.

funcIsOrgRoleadded inv0.5.2

func IsOrgRole(roleNamestring) (string,bool)

funcIsUnauthorizedErroradded inv0.17.2

func IsUnauthorizedError(errerror)bool

IsUnauthorizedError is a convenience function to check if err is UnauthorizedError.It is equivalent to errors.As(err, &UnauthorizedError{}).

funcReloadBuiltinRolesadded inv0.22.1

func ReloadBuiltinRoles(opts *RoleOptions)

ReloadBuiltinRoles loads the static roles into the builtInRoles map.This can be called again with a different config to change the behavior.

TODO: @emyrk This would be great if it was instanced to a coderd ratherthan a global. But that is a much larger refactor right now.Essentially we did not foresee different deployments needing slightlydifferent role permissions.

funcRoleMember

func RoleMember()string

funcRoleOrgAdmin

func RoleOrgAdmin(organizationIDuuid.UUID)string

funcRoleOrgMember

func RoleOrgMember(organizationIDuuid.UUID)string

funcRoleOwneradded inv0.8.6

func RoleOwner()string

funcRoleTemplateAdminadded inv0.8.6

func RoleTemplateAdmin()string

funcRoleUserAdminadded inv0.8.6

func RoleUserAdmin()string

Types

typeAction

type Actionstring

Action represents the allowed actions to be done on an object.

const (ActionCreateAction = "create"ActionReadAction = "read"ActionUpdateAction = "update"ActionDeleteAction = "delete")

funcAllActionsadded inv0.17.2

func AllActions() []Action

AllActions is a helper function to return all the possible actions types.

typeAuthCalladded inv0.17.2

type AuthCall struct {ActorSubjectActionActionObjectObject}

typeAuthorizeFilteradded inv0.9.3

type AuthorizeFilter interface {SQLString()string}

AuthorizeFilter is a compiled partial query that can be converted to SQL.This allows enforcing the policy on the database side in a WHERE clause.

funcCompileadded inv0.9.3

typeAuthorizeradded inv0.5.10

type Authorizer interface {// Authorize will authorize the given subject to perform the given action// on the given object. Authorize is pure and deterministic with respect to// its arguments and the surrounding object.Authorize(ctxcontext.Context, subjectSubject, actionAction, objectObject)errorPrepare(ctxcontext.Context, subjectSubject, actionAction, objectTypestring) (PreparedAuthorized,error)}

funcCacheradded inv0.17.2

func Cacher(authzAuthorizer)Authorizer

Cacher returns an Authorizer that can use a cache stored on a contextto short circuit duplicate calls to the Authorizer. This is useful whenmultiple calls are made to the Authorizer for the same subject, action, andobject. The cache is on each `ctx` and is not shared between requests.If no cache is found on the context, the Authorizer is called as normal.

Cacher is safe for multiple actors.

funcNewCachingAuthorizeradded inv0.17.4

func NewCachingAuthorizer(registryprometheus.Registerer)Authorizer

NewCachingAuthorizer returns a new RegoAuthorizer that supports context basedcaching. To utilize the caching, the context passed to Authorize() must becreated with 'WithCacheCtx(ctx)'.

typeExpandableRolesadded inv0.15.3

type ExpandableRoles interface {Expand() ([]Role,error)// Names is for logging and tracing purposes, we want to know the human// names of the expanded roles.Names() []string}

ExpandableRoles is any type that can be expanded into a []Role. This is implementedas an interface so we can have RoleNames for user defined roles, and implementcustom ExpandableRoles for system type users (eg autostart/autostop system role).We want a clear divide between the two types of roles so users have no codepathto interact or assign system roles.

Note: We may also want to do the same thing with scopes to allow custom scopesupport unavailable to the user. Eg: Scope to a single resource.

typeExpandableScopeadded inv0.15.3

type ExpandableScope interface {Expand() (Scope,error)// Name is for logging and tracing purposes, we want to know the human// name of the scope.Name()string}

typeObject

type Object struct {// ID is the resource's uuidIDstring `json:"id"`Ownerstring `json:"owner"`// OrgID specifies which org the object is a part of.OrgIDstring `json:"org_owner"`// Type is "workspace", "project", "app", etcTypestring `json:"type"`ACLUserList  map[string][]Action ` json:"acl_user_list"`ACLGroupList map[string][]Action ` json:"acl_group_list"`}

Object is used to create objects for authz checks when you have none inhand to run the check on.An example is if you want to list all workspaces, you can create a Objectthat represents the set of workspaces you are trying to get access too.Do not export this type, as it can be created from a resource type constant.

funcAllResourcesadded inv0.22.1

func AllResources() []Object

func (Object)All

func (zObject) All()Object

All returns an object matching all resources of the same type.

func (Object)Equaladded inv0.17.0

func (zObject) Equal(bObject)bool

func (Object)InOrg

func (zObject) InOrg(orgIDuuid.UUID)Object

InOrg adds an org OwnerID to the resource

func (Object)RBACObjectadded inv0.6.0

func (zObject) RBACObject()Object

func (Object)WithACLUserListadded inv0.9.9

func (zObject) WithACLUserList(acl map[string][]Action)Object

WithACLUserList adds an ACL list to a given object

func (Object)WithGroupACLadded inv0.9.9

func (zObject) WithGroupACL(groups map[string][]Action)Object

func (Object)WithID

func (zObject) WithID(iduuid.UUID)Object

func (Object)WithIDStringadded inv0.15.1

func (zObject) WithIDString(idstring)Object

func (Object)WithOwner

func (zObject) WithOwner(ownerIDstring)Object

WithOwner adds an OwnerID to the resource

typeObjecteradded inv0.6.0

type Objecter interface {RBACObject()Object}

Objecter returns the RBAC object for itself.

typePartialAuthorizeradded inv0.8.6

type PartialAuthorizer struct {// contains filtered or unexported fields}

PartialAuthorizer is a prepared authorizer with the subject, action, andresource type fields already filled in. This speeds up authorizationwhen authorizing the same type of object numerous times.See rbac.Filter for example usage.

func (*PartialAuthorizer)Authorizeadded inv0.8.6

func (pa *PartialAuthorizer) Authorize(ctxcontext.Context, objectObject)error

func (*PartialAuthorizer)CompileToSQLadded inv0.13.0

CompileToSQL converts the remaining rego queries into SQL WHERE clauses.

typePermission

type Permission struct {// Negate makes this a negative permissionNegatebool   `json:"negate"`ResourceTypestring `json:"resource_type"`ActionAction `json:"action"`}

Permission is the format passed into the rego.

funcPermissionsadded inv0.17.4

func Permissions(perms map[string][]Action) []Permission

Permissions is just a helper function to make building roles that list out resourcesand actions a bit easier.

typePreparedAuthorizedadded inv0.8.6

type PreparedAuthorized interface {Authorize(ctxcontext.Context, objectObject)errorCompileToSQL(ctxcontext.Context, cfgregosql.ConvertConfig) (string,error)}

typeRegoAuthorizer

type RegoAuthorizer struct {// contains filtered or unexported fields}

RegoAuthorizer will use a prepared rego query for performing authorize()

funcNewAuthorizer

func NewAuthorizer(registryprometheus.Registerer) *RegoAuthorizer

func (RegoAuthorizer)Authorize

func (aRegoAuthorizer) Authorize(ctxcontext.Context, subjectSubject, actionAction, objectObject)error

Authorize is the intended function to be used outside this package.It returns `nil` if the subject is authorized to perform the action onthe object.If an error is returned, the authorization is denied.

func (RegoAuthorizer)Prepareadded inv0.8.6

func (aRegoAuthorizer) Prepare(ctxcontext.Context, subjectSubject, actionAction, objectTypestring) (PreparedAuthorized,error)

Prepare will partially execute the rego policy leaving the object fields unknown (except for the type).This will vastly speed up performance if batch authorization on the same type of objects is needed.

typeRole

type Role struct {Namestring `json:"name"`// DisplayName is used for UI purposes. If the role has no display name,// that means the UI should never display it.DisplayNamestring       `json:"display_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"`// contains filtered or unexported fields}

Role is a set of permissions at multiple levels:- Site level permissions apply EVERYWHERE- Org level permissions apply to EVERYTHING in a given ORG- User level permissions are the lowestThis is the type passed into the rego as a json payload.Users of this package should instead **only** use the role names, andthis package will expand the role names into their json payloads.

funcOrganizationRolesadded inv0.5.4

func OrganizationRoles(organizationIDuuid.UUID) []Role

OrganizationRoles lists all roles that can be applied to an organization userin the given organization. This is the list of available roles,and specific to an organization.

This should be a list in a database, but until then we buildthe list from the builtins.

funcRoleByNameadded inv0.5.2

func RoleByName(namestring) (Role,error)

RoleByName returns the permissions associated with a given role name.This allows just the role names to be stored and expanded when required.

This function is exported so that the Display name can be returned to theapi. We should maybe make an exported function that returns just thehuman-readable content of the Role struct (name + display name).

funcSiteRolesadded inv0.5.4

func SiteRoles() []Role

SiteRoles lists all roles that can be applied to a user.This is the list of available roles, and not specific to a user

This should be a list in a database, but until then we buildthe list from the builtins.

typeRoleNamesadded inv0.15.3

type RoleNames []string

RoleNames is a list of user assignable role names. The role names must bein the builtInRoles map. Any non-user assignable roles will generate anerror on Expand.

func (RoleNames)Expandadded inv0.15.3

func (namesRoleNames) Expand() ([]Role,error)

func (RoleNames)Namesadded inv0.15.3

func (namesRoleNames) Names() []string

typeRoleOptionsadded inv0.22.1

type RoleOptions struct {NoOwnerWorkspaceExecbool}

typeRolesadded inv0.15.3

type Roles []Role

func (Roles)Expandadded inv0.15.3

func (rolesRoles) Expand() ([]Role,error)

func (Roles)Namesadded inv0.15.3

func (rolesRoles) Names() []string

typeScopeadded inv0.9.0

type Scope struct {RoleAllowIDList []string `json:"allow_list"`}

Scope acts the exact same as a Role with the addition that is can alsoapply an AllowIDList. Any resource being checked against a Scope willreject any resource that is not in the AllowIDList.To not use an AllowIDList to reject authorization, use a wildcard for theAllowIDList. Eg: 'AllowIDList: []string{WildcardSymbol}'

funcExpandScopeadded inv0.15.1

func ExpandScope(scopeScopeName) (Scope,error)

funcWorkspaceAgentScopeadded inv0.17.2

func WorkspaceAgentScope(workspaceID, ownerIDuuid.UUID)Scope

WorkspaceAgentScope returns a scope that is the same as ScopeAll but can onlyaffect resources in the allow list. Only a scope is returned as the rolesshould come from the workspace owner.

func (Scope)Expandadded inv0.15.3

func (sScope) Expand() (Scope,error)

func (Scope)Nameadded inv0.15.3

func (sScope) Name()string

typeScopeNameadded inv0.15.1

type ScopeNamestring
const (ScopeAllScopeName = "all"ScopeApplicationConnectScopeName = "application_connect")

func (ScopeName)Expandadded inv0.15.3

func (nameScopeName) Expand() (Scope,error)

func (ScopeName)Nameadded inv0.15.3

func (nameScopeName) Name()string

typeSubjectadded inv0.15.3

type Subject struct {IDstringRolesExpandableRolesGroups []stringScopeExpandableScope// contains filtered or unexported fields}

Subject is a struct that contains all the elements of a subject in an rbacauthorize.

func (Subject)Equaladded inv0.17.0

func (sSubject) Equal(bSubject)bool

func (Subject)SafeRoleNamesadded inv0.15.3

func (sSubject) SafeRoleNames() []string

SafeRoleNames prevent nil pointer dereference.

func (Subject)SafeScopeNameadded inv0.15.3

func (sSubject) SafeScopeName()string

SafeScopeName prevent nil pointer dereference.

func (Subject)WithCachedASTValueadded inv0.23.2

func (sSubject) WithCachedASTValue()Subject

WithCachedASTValue can be called if the subject is static. This will computethe ast value once and cache it for future calls.

typeUnauthorizedError

type UnauthorizedError struct {// contains filtered or unexported fields}

UnauthorizedError is the error type for authorization errors

funcForbiddenWithInternal

func ForbiddenWithInternal(internalerror, subjectSubject, actionAction, objectObject, outputrego.ResultSet) *UnauthorizedError

ForbiddenWithInternal creates a new error that will return a simple"forbidden" to the client, logging internally the more detailed messageprovided.

func (*UnauthorizedError)Asadded inv0.17.2

func (*UnauthorizedError) As(target interface{})bool

As implements the errors.As interface.

func (UnauthorizedError)Error

func (eUnauthorizedError) Error()string

Error implements the error interface.

func (*UnauthorizedError)Input

func (e *UnauthorizedError) Input() map[string]interface{}

func (*UnauthorizedError)Internal

func (e *UnauthorizedError) Internal()error

Internal allows the internal error message to be logged.

func (*UnauthorizedError)Output

func (e *UnauthorizedError) Output()rego.ResultSet

Output contains the results of the Rego query for debugging.

func (*UnauthorizedError)SetInternaladded inv0.17.2

func (e *UnauthorizedError) SetInternal(errerror)

func (UnauthorizedError)Unwrapadded inv0.17.2

func (eUnauthorizedError) Unwrap()error

Source Files

View all Source files

Directories

PathSynopsis
Package regosql converts rego queries into SQL WHERE clauses.
Package regosql converts rego queries into SQL WHERE clauses.
sqltypes
Package sqltypes contains the types used to convert rego queries into SQL.
Package sqltypes contains the types used to convert rego queries into SQL.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f orF : Jump to
y orY : Canonical URL
go.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.Learn more.

[8]ページ先頭

©2009-2025 Movatter.jp