Documentation
¶
Index ¶
- type CachedScopeExpander
- func (c *CachedScopeExpander) ExpandScope(ctx context.Context, scope aclscope.Scope, subject aclscope.Subject) ([]Ownerref, error)
- func (c *CachedScopeExpander) ExpandScopes(ctx context.Context, seeds []Ownerref) (map[Ownerref][]Ownerref, error)
- func (c *CachedScopeExpander) Invalidate(scope aclscope.Scope, subject aclscope.Subject)
- func (c *CachedScopeExpander) InvalidateAll()
- type Ownerref
- type OwnerrefFilter
- type Resolver
- func (r *Resolver) HasAccess(ctx context.Context, groups []string, scope aclscope.Scope, ...) (bool, error)
- func (r *Resolver) ResolveAccess(ctx context.Context, groups []string, scope aclscope.Scope, ...) ([]aclmodels.AccessTypeV3, error)
- func (r *Resolver) ResolveOwnerrefs(ctx context.Context, groups []string, requiredAccess aclmodels.AccessTypeV3, ...) ([]Ownerref, error)
- type ResolverOption
- type ScopeExpander
- type Store
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 OwnerrefFilter ¶ added in v1.20.2
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.