entitlements

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidBoundValue = errors.New("entitlements: bound value must not be empty, a wildcard, or contain ':'")

ErrInvalidBoundValue is returned by BindRequirements when a Binding maps a placeholder to "", "*", or a value containing ':'. "" and "*" are the wildcard spelling, not a concrete resourceName: binding one would silently widen the requirement to the whole resource class. A ':' would re-split the bound pattern into the wrong shape when re-parsed — Rust and Python rebuild the pattern as a string and are exposed to that hazard, while Go and TypeScript construct it directly and are not; rejecting the colon in all four ports is what keeps their results identical. A binder that could not resolve a value must fail like an unbound placeholder rather than widen the gate or diverge across ports.

View Source
var ErrUnboundPlaceholder = errors.New("entitlements: unbound placeholder in requirement")

ErrUnboundPlaceholder is returned by BindRequirements when a requirement declares a {placeholder} that the supplied Binding does not resolve. An unbound placeholder is an error, never a pass.

View Source
var ErrWildcardRequirement = errors.New("entitlements: wildcard resourceName is not allowed in a requirement")

ErrWildcardRequirement is returned by BindRequirements under strict mode when a requirement's resourceName is a wildcard ("*" or empty, which includes the short and medium syntaxes). Wildcards are meaningful only on the held side; as a requirement the spelling is ambiguous. Use a {placeholder} for the resource being addressed, or an opaque scope for a context-less capability.

Functions

func Compact added in v0.3.0

func Compact(entitlements []string) []string

Compact returns the subset of entitlements with every entry removed that is strictly dominated by another entry, or that is an exact / equivalent-form duplicate (e.g. "pages:read", "pages::read", "pages:*:read" collapse to the first-seen one). The result grants exactly the same authority as the input; surviving entries keep their original strings and their first-seen order.

It is defined purely in terms of Dominates, so its notion of "broader than" can never drift from attenuation. Opaque and malformed scopes collapse only by exact equality. Compaction is intended for preparing an entitlement array (e.g. before minting a narrowed token); it does not consult the checker's anonymous/base patterns or the intern cache.

func Dominates added in v0.2.1

func Dominates(held, requested string) bool

Dominates reports whether the held entitlement is equal to or BROADER than the requested one under the kdex-entitlements grammar. This is the predicate for attenuation (minting a token that carries a subset of the caller's authority). Unlike request-time matching (entitlementMatches), a wildcard resourceName is honored ONLY on the held side: a specific grant cannot dominate a wildcard request, so a mint can never broaden authority.

Opaque scopes (no ':') dominate only by exact match.

func VerifyAttenuation added in v0.2.1

func VerifyAttenuation(held, requested []string) (offender string, ok bool)

VerifyAttenuation returns ("", true) when every requested entitlement is dominated by at least one held entitlement. Otherwise it returns the first requested entitlement that no held entitlement dominates, and false.

Types

type Binding added in v0.4.0

type Binding map[string]string

Binding maps a requirement placeholder key to the concrete resourceName it stands for, e.g. {"vector_store_id": "vs_abc"}.

type Entitlements

type Entitlements map[string][]string

Entitlements is a map where keys are security schemes (e.g., "bearer", "oauth2") and values are slices of entitlement strings. Entitlement strings can be in long, medium, short, or opaque forms.

type EntitlementsChecker

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

EntitlementsChecker handles the verification of user entitlements against security requirements. It supports exact matches and wildcard patterns for resource names and verbs.

Pattern Forms:

  • Long Form: <resource>:<resourceName>:<verb>
  • Medium Form: <resource>::<verb> (means <resource>:*:<verb>)
  • Short Form: <resource>:<verb> (means <resource>:*:<verb>)
  • Opaque Form: <resource> (not a wildcard, only matches exactly)

Opaque form is intended to support JWT claims and other forms of requirements like HTTP Headers.

Encoding: resourceName must not contain colons ':' since they would be misinterpreted by the pattern splitting logic. The library does not escape resourceNames - the same string is used on both sides of every match comparison, so callers must use the same form when writing entitlements/requirements as they pass to the Verify*ResourceEntitlements / CalculateResourceRequirements helpers. If a caller's natural resourceName carries a ':', encode it consistently (e.g. url.PathEscape) at the caller's boundary on both the input side and the verification side.

Examples:

  • pages:/foo:read - read access to page "foo" (explicit resource name)
  • pages:*:read - read access to all pages (explicit wildcard)
  • pages::read - read access to all pages (implicit wildcard)
  • pages:read - read access to all pages (short form)
  • pages:/foo:all - all access to page "foo" (explicit resource name)
  • pages:*:all - all access to all pages (explicit wildcard)
  • pages::all - all access to all pages (implicit wildcard)
  • pages:all - all access to all pages (short form)
  • email - exact match only (opaque form)

func NewEntitlementsChecker

func NewEntitlementsChecker(
	anonymousEntitlements []string,
	defaultScheme string,
	grantReadyByDefault bool,
) *EntitlementsChecker

NewEntitlementsChecker creates a new entitlements checker with the specified settings. anonymousEntitlements is a list of patterns granted only to callers whose entitlements map is empty (no schemes present, or every scheme's list empty). Authenticated callers do not receive these patterns; use WithBaseEntitlements for patterns that should apply to every caller. defaultScheme is the fallback security scheme used when none is specified. grantReadyByDefault determines if the identity requirement is automatically satisfied.

func (*EntitlementsChecker) BindRequirements added in v0.4.0

func (ec *EntitlementsChecker) BindRequirements(reqs ParsedRequirements, b Binding) (ParsedRequirements, error)

BindRequirements substitutes every {placeholder} resourceName in reqs with its value from b and returns the rewritten requirements. Requirement sets containing no placeholder are returned unchanged.

Returns ErrUnboundPlaceholder if any placeholder has no entry in b — an unbound placeholder is a configuration error, never a pass. Keys in b that match no placeholder are ignored, so a caller may pass a superset (e.g. every path value it resolved) without knowing the requirement.

Returns ErrInvalidBoundValue if a placeholder is bound to "", "*", or a value containing ':'. "" and "*" are the wildcard spelling of a resourceName, not a concrete value: binding one would silently widen the requirement to the whole resource class. A ':' is rejected because this method constructs the bound pattern directly (see the comment below), but Rust and Python have no pre-parsed type and must re-emit the bound pattern as a string that verify then re-parses — there, a value containing ':' re-splits into the wrong shape and the pattern silently becomes opaque. Rejecting the colon here, in every port, is what keeps all four producing identical results instead of fixing only the two that happen to rebuild the string. A binder that could not resolve a value must fail like an unbound placeholder rather than widen the gate or diverge across ports.

Under WithStrictRequirements, also returns ErrWildcardRequirement if any requirement in reqs — placeholder or not — has a wildcard resourceName ("" or "*", including the short/medium syntaxes). This check runs before the placeholder no-op above, so a wildcard-only requirement set (no placeholder at all) is still rejected rather than passed through unchanged.

func (*EntitlementsChecker) CalculateResourceRequirements

func (ec *EntitlementsChecker) CalculateResourceRequirements(
	resource string,
	resourceName string,
	requirements Requirements,
	verbs ...string,
) (Requirements, error)

CalculateResourceRequirements calculates the requirements for a resource instance. It returns a copy of the requirements with an identity requirement added for the specific resource. The optional verbs parameter allows specifying the verb for the identity requirement (defaults to "read").

func (*EntitlementsChecker) ParseEntitlements

func (ec *EntitlementsChecker) ParseEntitlements(entitlements Entitlements) ParsedEntitlements

ParseEntitlements converts a raw Entitlements map into ParsedEntitlements for efficient reuse in multiple verification calls.

func (*EntitlementsChecker) ParseRequirements

func (ec *EntitlementsChecker) ParseRequirements(requirements Requirements) ParsedRequirements

ParseRequirements converts raw Requirements into ParsedRequirements for efficient reuse in multiple verification calls.

func (*EntitlementsChecker) VerifyEntitlements

func (ec *EntitlementsChecker) VerifyEntitlements(
	entitlements Entitlements,
	requirements Requirements,
) (result bool)

VerifyEntitlements checks if the user's entitlements satisfy the given security requirements. It returns true if any of the alternative requirement sets (OR'd) is fully satisfied.

func (*EntitlementsChecker) VerifyParsedEntitlements

func (ec *EntitlementsChecker) VerifyParsedEntitlements(
	entitlements ParsedEntitlements,
	requirements ParsedRequirements,
) (result bool)

VerifyParsedEntitlements is a high-performance check that uses pre-parsed entitlements and requirements. It is intended for scenarios where the same entitlements or requirements are checked repeatedly.

func (*EntitlementsChecker) VerifyResourceEntitlements

func (ec *EntitlementsChecker) VerifyResourceEntitlements(
	resource string,
	resourceName string,
	entitlements Entitlements,
	requirements Requirements,
	verbs ...string,
) (bool, error)

VerifyResourceEntitlements checks if the user's entitlements satisfy the security requirements for a specific resource instance. It automatically adds an identity requirement for the resource. The optional verbs parameter allows specifying the verb for the identity requirement (defaults to "read").

func (*EntitlementsChecker) VerifyResourceParsedEntitlements

func (ec *EntitlementsChecker) VerifyResourceParsedEntitlements(
	resource string,
	resourceName string,
	parsedEntitlements ParsedEntitlements,
	parsedRequirements ParsedRequirements,
	verbs ...string,
) (bool, error)

VerifyResourceParsedEntitlements is a high-performance check for a specific resource instance using pre-parsed entitlements and requirements.

Under WithStrictRequirements, a resourceName of "*" makes the identity requirement this method builds illegal by spelling, so it is denied regardless of grants — see WithStrictRequirements for the full explanation.

func (*EntitlementsChecker) WildcardRequirements added in v0.4.0

func (ec *EntitlementsChecker) WildcardRequirements(reqs Requirements) []string

WildcardRequirements returns the requirement strings whose resourceName is a wildcard ("*", empty, or the short/medium syntaxes) — the spellings strict mode rejects outright. Results are de-duplicated and in first-seen order.

It is a migration inventory, not a complete strict-mode pre-flight: strict also rejects an unbound placeholder at verification time, which this query does not report (a placeholder is the migration's destination, not a target). An empty result means no requirement still uses a wildcard spelling.

It is a pure query so a caller may log, count, or fail in its own idiom. Use it to inventory what remains to migrate before enabling WithStrictRequirements.

func (*EntitlementsChecker) WithBaseEntitlements added in v0.2.0

func (ec *EntitlementsChecker) WithBaseEntitlements(patterns []string) *EntitlementsChecker

WithBaseEntitlements sets the base entitlements: patterns that apply to every caller (authenticated or anonymous) under the default scheme. Unlike anonymousEntitlements (which apply only when the caller's entitlements map is empty), base entitlements form a floor of grants that every request receives.

Replaces any previously set base entitlements. Intended for use during checker construction; not safe for concurrent mutation with verify calls in flight.

func (*EntitlementsChecker) WithLogger

func (ec *EntitlementsChecker) WithLogger(log logr.Logger) *EntitlementsChecker

WithLogger attaches a logger to the EntitlementsChecker for debugging purposes.

func (*EntitlementsChecker) WithStrictRequirements added in v0.4.0

func (ec *EntitlementsChecker) WithStrictRequirements(strict bool) *EntitlementsChecker

WithStrictRequirements rejects wildcard resourceNames on the requirement side. It never affects entitlements, where wildcards remain meaningful.

When enabled, BindRequirements returns ErrWildcardRequirement for such a requirement (the loud path), and verification treats both a wildcard requirement and an unbound placeholder as unsatisfiable (a fail-closed backstop for callers that skip BindRequirements).

Defaults to false; a future major version will default it to true. Intended for use during checker construction; not safe for concurrent mutation with verify calls in flight.

VerifyResourceEntitlements and VerifyResourceParsedEntitlements build their identity requirement from the caller-supplied resourceName (as "<resource>:<resourceName>:<verb>"). They already reject an empty resourceName outright, but "*" passes that guard; under strict, "*" makes the identity a wildcard requirement — illegal by spelling — so the check denies unconditionally, regardless of the caller's grants, including a genuine wildcard grant like "pages::all". Callers must pass a concrete resourceName. There is deliberately no requirement spelling for "holds authority over the whole class"; use an opaque capability scope for that.

type ParsedEntitlements

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

ParsedEntitlements represents a set of user entitlements that have been pre-parsed into internal patterns for high-performance verification.

type ParsedRequirements

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

ParsedRequirements represents a set of security requirements that have been pre-parsed into internal patterns for high-performance verification.

type Requirements

type Requirements []map[string][]string

Requirements is a slice of maps representing alternative security requirement sets. Each map in the slice represents an alternative set of requirements (OR'd). Within each map, all schemes and their associated scopes must be satisfied (AND'd).

Jump to

Keyboard shortcuts

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