acl

package
v1.20.2 Latest Latest
Warning

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

Go to latest
Published: Jun 25, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CachedScopeExpander

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

CachedScopeExpander wraps a ScopeExpander with an in-memory TTL cache. The cache is keyed by scope+subject and stores the expanded descendant list. It is safe for concurrent use.

func NewCachedScopeExpander

func NewCachedScopeExpander(backend ScopeExpander, ttl time.Duration) *CachedScopeExpander

NewCachedScopeExpander creates a cached wrapper around the given expander.

func (*CachedScopeExpander) ExpandScope

func (c *CachedScopeExpander) ExpandScope(ctx context.Context, scope aclscope.Scope, subject aclscope.Subject) ([]Ownerref, error)

ExpandScope returns cached descendants or falls through to the backend.

func (*CachedScopeExpander) ExpandScopes added in v1.20.2

func (c *CachedScopeExpander) ExpandScopes(ctx context.Context, seeds []Ownerref) (map[Ownerref][]Ownerref, error)

ExpandScopes expands several seeds, serving each from the in-memory cache when possible and resolving all cache misses through the backend in a single batched call. Results are keyed by seed ownerref.

func (*CachedScopeExpander) Invalidate

func (c *CachedScopeExpander) Invalidate(scope aclscope.Scope, subject aclscope.Subject)

Invalidate removes the cached expansion for a specific scope+subject.

func (*CachedScopeExpander) InvalidateAll

func (c *CachedScopeExpander) InvalidateAll()

InvalidateAll clears the entire cache.

type Ownerref

type Ownerref struct {
	Scope   aclscope.Scope
	Subject aclscope.Subject
}

Ownerref represents a scope+subject pair that a user has access to.

type OwnerrefFilter added in v1.20.2

type OwnerrefFilter struct {
	Scopes   []aclscope.Scope
	Subjects []aclscope.Subject
}

OwnerrefFilter narrows the ownerrefs returned by ResolveOwnerrefs. Each dimension is optional: an empty slice means "no restriction" for that dimension. When Scopes is non-empty, only ownerrefs whose scope is in the set are returned. When Subjects is non-empty, only ownerrefs whose subject is in the set are returned. Both must match when both are set.

func (OwnerrefFilter) IsEmpty added in v1.20.2

func (f OwnerrefFilter) IsEmpty() bool

IsEmpty reports whether the filter imposes no restriction.

func (OwnerrefFilter) Matches added in v1.20.2

func (f OwnerrefFilter) Matches(ref Ownerref) bool

Matches reports whether the given ownerref passes the filter.

type Resolver

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

Resolver resolves access for a set of groups using a Store. It loads all entries in one batch call, then compiles access in-memory. An optional ScopeExpander enables hierarchical scope resolution: if a user has access to a Project, the expander resolves all descendant ownerrefs (Workspaces, Clusters, etc.) so they are included in the result.

func NewResolver

func NewResolver(store Store, opts ...ResolverOption) *Resolver

NewResolver creates a new resolver with the given store backend. Use WithScopeExpander to enable hierarchical scope resolution.

func (*Resolver) HasAccess

func (r *Resolver) HasAccess(ctx context.Context, groups []string, scope aclscope.Scope, subject aclscope.Subject, requiredAccess aclmodels.AccessTypeV3) (bool, error)

HasAccess checks if the groups have a specific access type for the given scope+subject.

func (*Resolver) ResolveAccess

func (r *Resolver) ResolveAccess(ctx context.Context, groups []string, scope aclscope.Scope, subject aclscope.Subject) ([]aclmodels.AccessTypeV3, error)

ResolveAccess loads ACL entries for all given groups (single round-trip) and returns the union of access types that match the given scope and subject.

func (*Resolver) ResolveOwnerrefs

func (r *Resolver) ResolveOwnerrefs(ctx context.Context, groups []string, requiredAccess aclmodels.AccessTypeV3, filter OwnerrefFilter) ([]Ownerref, error)

ResolveOwnerrefs returns all scope+subject pairs the groups have access to for the given access type. Returns nil (meaning unrestricted) if any entry grants global/all access. When a ScopeExpander is configured, non-leaf scopes (e.g. Project, Workspace) are expanded to include all descendant ownerrefs alongside the original entry.

The optional filter narrows the result to specific scopes and/or subjects. An empty filter returns every resolved ownerref.

type ResolverOption

type ResolverOption func(*Resolver)

ResolverOption configures a Resolver.

func WithScopeExpander

func WithScopeExpander(expander ScopeExpander) ResolverOption

WithScopeExpander enables hierarchical scope resolution.

type ScopeExpander

type ScopeExpander interface {
	ExpandScope(ctx context.Context, scope aclscope.Scope, subject aclscope.Subject) ([]Ownerref, error)

	// ExpandScopes expands several seeds in a single round-trip, returning the
	// descendant ownerrefs for each seed keyed by the seed ownerref. It is
	// equivalent to calling ExpandScope for each seed but avoids per-seed
	// round-trips. Seeds with no descendants map to a nil/empty slice.
	ExpandScopes(ctx context.Context, seeds []Ownerref) (map[Ownerref][]Ownerref, error)
}

ScopeExpander resolves hierarchical scope relationships by walking the ownerref chain in resourcesv2. No business logic or hardcoded hierarchy — the tree emerges from rormeta.ownerref data on each resource.

ExpandScope recursively finds all resourcesv2 resources whose ownerref matches {scope, subject}, then their children, and so on.

Example: if Workspace "ws-dev" has ownerref {Project, proj-1} and Cluster "cluster-abc" has ownerref {Workspace, ws-dev}, then ExpandScope(ctx, "Project", "proj-1") returns:

[{Workspace, ws-dev}, {KubernetesCluster, cluster-abc}]

Returns nil if no resources have the given ownerref (leaf scope). The original scope+subject is NOT included in the result.

type Store

type Store interface {
	// GetByGroups returns all ACL entries for the given group names as V3 items.
	// V2 entries in the database are converted to V3 using aclmodels.V2ToV3.
	GetByGroups(ctx context.Context, groups []string) (map[string][]aclmodels.AclV3ListItem, error)

	// GetV2ByGroups returns all ACL entries for the given group names as V2 items.
	// V3 entries in the database are converted to V2 using aclmodels.V3ToV2.
	// V3-only capabilities (e.g. "kubernetes:admin") are dropped in the conversion.
	GetV2ByGroups(ctx context.Context, groups []string) (map[string][]aclmodels.AclV2ListItem, error)
}

Store is the interface for loading ACL entries. Implementations can use MongoDB, Redis, or any other backend. Both methods load all entries (V2 and V3) in a single round-trip and convert to the requested format. V2 entries are converted to V3 using the v3 struct tags on AclV2ListItemAccess. V3 entries are converted to V2 with capabilities that have no V2 equivalent silently dropped.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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