rbac

package
v1.17.4 Latest Latest
Warning

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

Go to latest
Published: Jun 15, 2026 License: Apache-2.0 Imports: 18 Imported by: 13

README

pkg/rbac

This package computes effective authority inside UNI after authentication and identity propagation have already happened.

Intent

The package is the platform's effective-authority engine.

It takes authenticated actor context and delegated identity context, resolves roles and group membership from identity storage, and produces ACLs that the rest of the system can enforce.

Its main responsibilities are:

  • resolve permissions for users, service accounts, and system accounts
  • apply global, organization, and project scope
  • prevent confused-deputy behaviour when a service acts as an impersonated principal
  • constrain administrative delegation so callers cannot grant authority they do not themselves hold

This package is not just a convenience layer for handler checks. It is part of the security model.

Security Model

The package enforces several important security rules:

  • authority is derived from roles via group membership and actor type
  • permissions are additive within the allowed role set
  • protected roles are internal-only roles and are never user-facing
  • a caller may only grant a role if the caller already holds all permissions contained in that role
  • when a system service acts as an impersonated principal, the effective ACL is the intersection of the principal's ACL and the service's ACL

Those rules prevent several different forms of privilege escalation:

  • user-facing exposure of internal platform roles
  • granting permissions the caller does not personally hold
  • confused-deputy expansion through service-to-service calls

Scope Model

The package works with the same three logical scope levels defined by identity roles:

  • global
  • organization
  • project

ACL construction and handler enforcement both follow that structure. Global permissions can satisfy organization and project checks, organization permissions can satisfy some project checks, and project permissions remain the narrowest scope.

This scoped structure is used both for direct authorization decisions and for query limiting in list operations.

Actor Model

The package distinguishes three important actor classes:

  • users
  • service accounts
  • system accounts

Users derive access from organization membership, groups, and roles.

Service accounts derive access from their bound organization and group membership.

System accounts derive access from configured platform roles mapped from their authenticated service identity, typically an mTLS certificate common name.

When a system account carries an impersonated principal, RBAC does not simply switch to the principal's ACL. Instead, it intersects the principal ACL with the system account ACL so the service cannot exercise permissions that either side lacks.

Invariants

  • Effective authority is computed from stored identity state, not invented ad hoc in handlers.
  • Protected roles are not part of normal user-facing role administration.
  • Role grantability is bounded by the caller's own effective permissions.
  • ACL intersection for impersonated system-account calls is deliberate least-privilege behaviour.
  • Service accounts are organization-bound and their scoped access must remain consistent with that binding.
  • Group membership is the main route from actors to roles.
  • The ACL output is both an enforcement artifact and a visibility artifact, so incorrect ACL construction affects both authorization and UX.

Caveats

  • The package is tightly coupled to the identity storage and scoping model, including groups, projects, organization mappings, and label-based queries.
  • Some migration-era behaviour is still present, especially compatibility with the deprecated Group.UserIDs field alongside the newer Subjects model.
  • The package contains a mix of ACL construction, scope filtering, and handler-facing convenience checks, so it is broader than a pure policy-definition layer.
  • Some pragmatic compatibility behaviour exists around scoped lookups and transition paths, so security-sensitive changes here should be reviewed in terms of end-to-end actor behaviour rather than local code shape alone.

TODO

  • Re-check places where globally scoped callers are allowed to skip existence verification for user-supplied scoped resource identifiers, especially create paths that accept project IDs in the request body.

Relationship To Other Packages

  • pkg/oauth2 establishes actor identity and session/token validity
  • pkg/principal carries delegated identity and impersonation signals
  • pkg/rbac converts those inputs into effective local authority
  • middleware and handlers consume the resulting ACLs to enforce access and shape responses
  • pkg/oauth2, which establishes actor identity, session validity, and local admission before RBAC resolution
  • pkg/userdb, which shields RBAC from the raw local identity storage model when resolving users, organization memberships, and service accounts
  • pkg/principal, which carries delegated identity and impersonation signals consumed here
  • pkg/apis/unikorn/v1alpha1, which defines the stored role, group, organization, project, user, and service-account resources this package resolves

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrResourceReference      = goerrors.New("resource reference error")
	ErrNoAuthz                = goerrors.New("no authorization data in userinfo")
	ErrWrongOrganizationCount = goerrors.New("expected exactly one organization ID")
	ErrNotInOrganization      = goerrors.New("subject not a member of organization")
	ErrInvalidPrincipalType   = goerrors.New("invalid impersonated principal type")
)
View Source
var (
	ErrNoMatches = goerrors.New("selector would select nothing")
)

Functions

func AddOrganizationAndProjectIDQuery added in v1.11.0

func AddOrganizationAndProjectIDQuery(ctx context.Context, selector labels.Selector, organizationQuery []string, projectQuery []string) (labels.Selector, error)

AddOrganizationAndProjectIDQuery gets all organizationIDs the user can access (or has requested explicit and has access to).

func AddOrganizationIDQuery added in v1.11.0

func AddOrganizationIDQuery(ctx context.Context, selector labels.Selector, query []string) (labels.Selector, error)

AddOrganizationIDQuery adds an organizational query selector that limits resources to be listed to those available in the ACL and optionally constrained to those in the request query using a boolean intersection.

func AddQuery added in v1.11.0

func AddQuery(selector labels.Selector, label string, vals []string) (labels.Selector, error)

AddQuery adds a set of query values to a label selector.

func AllowGlobalScope added in v0.2.20

func AllowGlobalScope(ctx context.Context, endpoint string, operation openapi.AclOperation) error

AllowGlobalScope tries to allow the requested operation at the global scope.

func AllowOrganizationScope added in v0.2.20

func AllowOrganizationScope(ctx context.Context, endpoint string, operation openapi.AclOperation, organizationID string) error

AllowOrganizationScope tries to allow the requested operation at the global scope, then the organization scope.

func AllowProjectScope added in v0.2.20

func AllowProjectScope(ctx context.Context, endpoint string, operation openapi.AclOperation, organizationID, projectID string) error

AllowProjectScope tries to allow the requested operation at the global scope, then the organization scope, and finally at the project scope.

func AllowProjectScopeCreate added in v1.16.0

func AllowProjectScopeCreate(ctx context.Context, client openapi.ClientWithResponsesInterface, endpoint string, operation openapi.AclOperation, organizationID, projectID string) error

AllowProjectScopeCreate is like AllowProjectScope but intended for v2 create operations where the project ID is supplied in the request body rather than the URL path. When access is granted via an organization-scoped ACL the project ID is untrusted user input, so this function additionally verifies the project exists via the identity API before returning nil. Global-scope callers (platform administrators) are exempt from this check and their supplied project ID is trusted directly.

func AllowRole added in v0.2.21

func AllowRole(ctx context.Context, role *unikornv1.Role, organizationID string) error

AllowRole determines whether your ACL contains the same or higher privileges than the role, which is then used to determine role visibility and limit privilege escalation.

func FromContext added in v0.2.20

func FromContext(ctx context.Context) *openapi.Acl

func HasNoMatches added in v1.12.0

func HasNoMatches(err error) bool

HasNoMatches is a short cut when nothing would be matched e.g. the user has no matching organization ID for the provided selector, and a list handler can just return an empty array directly.

func NewContext added in v0.2.20

func NewContext(ctx context.Context, acl *openapi.Acl) context.Context

func OrganizationIDs added in v1.11.0

func OrganizationIDs(ctx context.Context) []string

OrganizationIDs returns a list of all organization IDs from the ACL for the purposes of limiting list type API operations.

Types

type Options added in v0.2.54

type Options struct {
	PlatformAdministratorRoleIDs  []string
	PlatformAdministratorSubjects []string
	SystemAccountRoleIDs          map[string]string
}

func (*Options) AddFlags added in v0.2.54

func (o *Options) AddFlags(f *pflag.FlagSet)

type RBAC

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

RBAC contains all the scoping rules for services across the platform.

func New

func New(client client.Client, namespace string, options *Options) *RBAC

New creates a new RBAC client.

func (*RBAC) GetACL added in v0.1.23

func (r *RBAC) GetACL(ctx context.Context, organizationID string) (*openapi.Acl, error)

GetACL returns a granular set of permissions for a user based on their scope. This is used for API level access control and UX.

func (*RBAC) NewSuperContext added in v0.2.59

func (r *RBAC) NewSuperContext(ctx context.Context) (context.Context, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL