Documentation
¶
Overview ¶
Package cedar is the cedar-go authorization driver (ADR-0074) behind the auth.Authorizer port (ADR-0018): it answers per-object, fine-grained data-plane decisions (KV first) that the coarse RBAC driver cannot express. It is DEFAULT-DENY — with no permitting Policy a kv::read is denied; the built-in forbid(kv::write) unless principal == resource.owner makes writes single-writer. The compiled PolicySet is cached and recompiled on a Policy change; per call only the request-relevant entities (principal Function + resource KVTable + its parent KVStore) are resolved from the metastore, never a full-store rebuild. It is a leaf under internal/auth, like the rbac driver.
Index ¶
- func CompileEgressPolicy(ns v1.NamespaceName, ep *v1.EgressPolicy, funcs []v1.ObjectName) ([]v1.Policy, error)
- func CompileRolesAssignment(ctx context.Context, ra *v1.RolesAssignment, roles RoleResolver) ([]v1.Policy, error)
- func FunctionGrants(ns v1.NamespaceName, name v1.ObjectName, text string) (map[v1.ObjectName][]string, error)
- func KnownAction(action string) bool
- func KnownEntityType(entityType string) bool
- func New(d Deps) (auth.Authorizer, error)
- func ValidateCedar(text string) error
- func ValidateCedarInNamespace(ns v1.NamespaceName, text string) error
- type Capability
- type Deps
- type EntityProvider
- type MetaReader
- type PolicySource
- type PrincipalBinding
- type PrincipalObject
- type PrincipalSource
- type Registry
- type RoleResolver
- type WriterGrant
- type WriterLister
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CompileEgressPolicy ¶
func CompileEgressPolicy(ns v1.NamespaceName, ep *v1.EgressPolicy, funcs []v1.ObjectName) ([]v1.Policy, error)
CompileEgressPolicy compiles one namespace's EgressPolicy into SYNTHETIC v1.Policy objects (Spec.Cedar), listed by the policy source alongside user KindPolicy and compiled by the existing compile()/ NewPolicyListFromBytes path — NOT a pre-built PolicySet (ADR-0117, M1). ONE permit per RULE (the namespace-attribute collapse): a domain/wildcard matches via resource.domains.contains, a CIDR via resource.ip.isInRange(ip("…")), ports as a set. The principal scope is the entity's existing `namespace` attribute (`principal is Function && principal.namespace == "<ns>"`) for a whole-namespace policy, or a bounded disjunction over the explicit spec.appliesTo list (`principal == Function::"<ns>/<fn>"`) — O(rules), independent of the namespace Function count, using NO Cedar group entity and NO edit to the registry assembly. funcs is the namespace Function-set (drives the cache revision; the compiled set does not depend on it). A nil ep or no rules ⇒ no policies (default-deny holds).
Each permit is assembled as a Cedar JSON EST document and parsed with cedar.Policy.UnmarshalJSON (injection-safe: every domain/CIDR is a JSON value node, never interpolated syntax; a malformed CIDR is a compile error, never templated). MarshalCedar renders each permit back to canonical Cedar text to preserve the M1 PolicySource→compile() contract.
func CompileRolesAssignment ¶
func CompileRolesAssignment(ctx context.Context, ra *v1.RolesAssignment, roles RoleResolver) ([]v1.Policy, error)
CompileRolesAssignment compiles a RolesAssignment's READ/query/invoke grants into synthetic v1.Policy Cedar permits (ADR-0136; the injection-safe EST path, mirroring CompileEgressPolicy). WRITE grants are NOT permits (a Cedar forbid overrides a permit) — they are surfaced via WriterGrants for the resource materializer's `writers` set. A missing role / empty grant ⇒ no policy (default-deny holds).
func FunctionGrants ¶ added in v0.5.0
func FunctionGrants(ns v1.NamespaceName, name v1.ObjectName, text string) (map[v1.ObjectName][]string, error)
FunctionGrants lists, per Function of namespace ns that a statement of Policy name references anywhere (its scope or its conditions), one grant per such statement: "policy/<ns>/<name>#<j>@<sha256 of the statement>", where "<ns>/<name>#<j>" is the ID the PDP compiles that statement under. A grant names what it grants, never its principal, so Functions referenced by one statement share it.
func KnownAction ¶
KnownAction reports whether action is in the assembled schema vocabulary (ADR-0116).
func KnownEntityType ¶
KnownEntityType reports whether entityType is in the assembled schema vocabulary (ADR-0116).
func New ¶
func New(d Deps) (auth.Authorizer, error)
New builds the cedar driver behind the auth.Authorizer port (ADR-0074). Entities + Policies are required.
func ValidateCedar ¶
ValidateCedar checks that text PARSES as Cedar and that every statement references only the curated actions + entity types (ADR-0074 policy-validity). It returns fault.Invalid on a parse error or an off-schema action/entity-type — the policy-validity admission surfaces it. cedar-go's own schema validator is experimental, so this is the curated, fixed-schema check the driver owns.
func ValidateCedarInNamespace ¶ added in v0.5.0
func ValidateCedarInNamespace(ns v1.NamespaceName, text string) error
ValidateCedarInNamespace runs ValidateCedar, then refuses a statement whose principal or resource scope (`==`, `in`, `is … in`) names a namespaced entity outside ns (ADR-0177 Decision 3). Unconstrained scopes and entities inside `when`/`unless` pass: the per-namespace PolicySet contains them.
Types ¶
type Capability ¶
type Capability struct {
// Name is the capability's short id (e.g. "kv", "invoke", "s3", "egress") — for diagnostics/dedup.
// Unique across the registry.
Name string
// Actions are the Cedar actions this capability authorizes (e.g. auth.ActionKVRead, ActionKVWrite).
// Unique across the registry (no two capabilities share an action).
Actions []auth.Action
// EmitsEntityType is the primary Cedar entity type this capability materializes as a resource (e.g.
// entityTypeKVTable). Used ONLY for schema-vocabulary assembly (KnownEntityType) — NOT a dispatch key
// (an EntityRef.Type v1.Kind never equals the Cedar entity type: KindKVStore→KVTable, KindBucket→
// BlobPrefix). Resource dispatch is by the Resource func's ok, below.
EmitsEntityType cedartypes.EntityType
// SupportingEntityTypes are the additional Cedar entity types this capability contributes to the
// schema vocabulary beyond its primary EmitsEntityType — the resource's parent (KVStore for kv,
// Bucket for s3) and any alternate principal type it admits (S3Identity for s3). A Policy may scope
// on these (`resource in KVStore::"…"`, `principal == S3Identity::"…"`), so KnownEntityType must
// accept them; they are assembled from the registry exactly like EmitsEntityType (never hand-listed).
SupportingEntityTypes []cedartypes.EntityType
// Resource materializes the resource entity (UID + parents + owner attr) for a request whose resource
// this capability owns. ok==false ⇒ not ours (try the next capability) — this ok is the SOLE resource-
// dispatch mechanism. A dangling resource still returns ok==true with bare entities (evaluable,
// default-deny). nil ⇒ the capability owns no resource shape (Policy-only over an existing entity).
Resource func(ctx context.Context, r MetaReader, resource auth.EntityRef) (em cedartypes.EntityMap, ok bool, err error)
// PrincipalBinding declares this capability's binding-as-grant attribute on the principal: Attr is the
// principal attribute name (e.g. "kvBindings"); Bind materializes its members from a resolved
// principal object (see PrincipalSource). The provider sets Attr whenever Bind returns a non-nil slice
// (possibly empty), matching today's EntitiesFor (a Function always carries links/kvBindings/blobBindings;
// the built-ins also `has`-guard, so empty ≡ absent). A Bind that returns nil for a source type
// contributes nothing (attr absent) — e.g. kv/invoke for a CatalogService. Zero value ⇒ no binding.
PrincipalBinding PrincipalBinding
// Builtin is this capability's built-in permit policy text (the .cedar granting the capability when
// principal.<attr>.contains(resource)); "" ⇒ no built-in (Policy-only). Each policy carries a unique
// @id annotation, its stable name in a deny reason.
Builtin string
}
Capability declares one authorization capability (kv, invoke, s3, egress, …) so the schema vocabulary, the EntityProvider, and the built-in permits are ASSEMBLED from the registered set — registering a new capability adds no branch to shared code (ADR-0116). All funcs are typed (no any).
Two orthogonal axes are kept separate (judge B1): a Capability is an {action + resource + built-in} on a PRINCIPAL; *where a principal's binding attributes come from* is a PrincipalSource (below), so the ADR-0088 provider principal (a CatalogService, ADR-0175) is NOT a fourth capability — s3 is one capability with two principal sources.
func CatalogCapability ¶
func CatalogCapability() Capability
CatalogCapability is the catalog::query capability (ADR-0137): spec.catalogs → the `catalogBindings` Set of CatalogService entity-refs (binding-as-query-grant); the resource is the CatalogService the query targets. It is READ-SHAPED — like invoke it owns no writable resource, so there is NO WriterLister and NO write action; the built-in permit reads principal.catalogBindings, not the resource's attrs, so default-deny holds even if the target is missing. External Identities are granted via a Catalog-scoped RolesAssignment (compiled to a permit), not this built-in.
func EgressCapability ¶
func EgressCapability() Capability
EgressCapability registers egress on the ADR-0116 registry (ADR-0117, F81): Action egress::connect; resource entity NetDestination materialized from the request EntityRef's Path (no MetaReader read — the destination is ephemeral); NO PrincipalBinding (governed by EgressPolicy, not a spec.<field> grant) and NO Builtin (default-deny — grants come only from a compiled EgressPolicy). Its Resource emits the UID + attributes {ip, port, domains}; the driver's resourceUID gains a matching KindNetDestination case (entities.go).
func InvokeCapability ¶
func InvokeCapability() Capability
InvokeCapability is the link::invoke capability (ADR-0075): spec.links → the `links` Set of target Function entities (link-as-grant); the resource is the target Function (a bare entity — the built-in permit reads principal.links, not the target's attrs, so default-deny holds even if the target is missing). It owns no principal-owned resource beyond the target Function.
func KVCapability ¶
func KVCapability() Capability
KVCapability is the kv::read/kv::write capability (ADR-0074/0076): spec.kv → the `kvBindings` Set of KVTable entity-refs (read binding-as-grant); the resource is the KVTable + its parent KVStore + the table owner (a Function entity-REFERENCE, so `principal == resource.owner` compares entities). It owns both built-ins: the write single-writer rule and the read binding-grant.
func KVCapabilityWithWriters ¶
func KVCapabilityWithWriters(w WriterLister) Capability
KVCapabilityWithWriters is KVCapability with a WriterLister so a writer-role RolesAssignment (ADR-0136) contributes to a table's `writers` set. KVCapability() (nil lister) is owner-only (back-compat).
func S3Capability ¶
func S3Capability() Capability
S3Capability is the s3::read/s3::write capability (ADR-0080): spec.blob → the `blobBindings` Set of BlobPrefix entity-refs (read binding-as-grant); the resource is the BlobPrefix + its parent Bucket + the prefix owner (a Function entity-REFERENCE). Its Bind handles BOTH a *v1.Function and a *v1.CatalogService (ADR-0088 — both carry spec.blob). It admits the external S3Identity principal type.
func S3CapabilityWithWriters ¶
func S3CapabilityWithWriters(w WriterLister) Capability
S3CapabilityWithWriters is S3Capability with a WriterLister so a writer-role RolesAssignment (ADR-0136) contributes to a prefix's `writers` set (the generalized single-writer forbid). The compose root uses this; S3Capability() (nil lister) is owner-only (back-compat).
type Deps ¶
type Deps struct {
// Entities resolves the request-relevant Cedar entities per call (principal + resource + parents).
Entities EntityProvider
// Policies supplies the user Policy resources (compiled + cached with the built-ins).
Policies PolicySource
// Builtins is the always-on built-in Cedar policy text (a Registry's Builtins()) compiled into the
// PolicySet with the user Policies. Empty ⇒ the default registry's built-ins — so the compose root can
// supply a variant built-in set (e.g. funcdctl dev's relaxed S3 writes) without a package global.
Builtins string
// Logger is the driver's logger; nil ⇒ slog.Default().
Logger *slog.Logger
}
Deps configures the cedar driver (ADR-0074).
type EntityProvider ¶
type EntityProvider interface {
EntitiesFor(ctx context.Context, principal, resource auth.EntityRef) (cedartypes.EntityMap, error)
}
EntityProvider resolves ONLY the request-relevant Cedar entities (the principal + the resource + its parents) for one Authorize call (ADR-0074) — never a full-store rebuild. Entities are materialized from the metastore's existing resources (no duplicate state); the registry (ADR-0116) composes it from the registered capabilities' resource materializers + principal-binding Sets.
func NewEntityProvider ¶
func NewEntityProvider(r MetaReader) (EntityProvider, error)
NewEntityProvider builds the default metastore-backed EntityProvider (ADR-0074): the composite provider assembled from the default capability registry (kv, invoke, s3 + the Function/CatalogService sources). r is required. Consumers that register additional capabilities build their own Registry and call (*Registry).EntityProvider directly (ADR-0116).
type MetaReader ¶
type MetaReader interface {
Get(ctx context.Context, gvk v1.GroupVersionKind, ns v1.NamespaceName, name v1.ObjectName) (v1.Object, error)
}
MetaReader is the read-only metastore view the EntityProvider needs (ADR-0074): it reads the caller Function (for the principal entity) and the target resource (for the owner/parent). Declared here so the cedar package stays a near-leaf; the wiring adapts store.Store.
type PolicySource ¶
type PolicySource interface {
// Policies returns all Policy resources and an opaque revision; the driver recompiles only when
// the revision changes (cheap cache invalidation without diffing policy text).
Policies(ctx context.Context) (policies []v1.Policy, revision string, err error)
}
PolicySource supplies the user Policy resources the driver compiles (ADR-0074). The driver compiles the built-in rules + each namespace's user Policies into one cached PolicySet per namespace (ADR-0177), recompiled when the source's revision changes.
type PrincipalBinding ¶
type PrincipalBinding struct {
// Attr is the Cedar principal attribute (e.g. "kvBindings", "links", "blobBindings").
Attr string
// Bind materializes the attribute's Set members from a resolved principal object. src is whatever a
// PrincipalSource resolved (a *v1.Function or a *v1.CatalogService); a capability that doesn't apply to
// that source type returns nil (e.g. kv/invoke return nil for a CatalogService — providers have no
// links/kv). ns is the principal namespace (for building same-namespace resource UIDs).
Bind func(ns v1.NamespaceName, src PrincipalObject) []cedartypes.EntityUID
}
PrincipalBinding is one binding-as-grant attribute a capability contributes to a principal.
type PrincipalObject ¶
type PrincipalObject = v1.PrincipalObject
PrincipalObject is a resolved principal-backing object (a *v1.Function or *v1.CatalogService); a closed interface (only api/types implements it, via an unexported marker) so PrincipalBinding.Bind type-switches without any. It aliases v1.PrincipalObject: the marker method must live in the same package as the implementing types, so the sealed interface is declared in api/types/v1alpha1 and re-exported here under the cedar name.
type PrincipalSource ¶
type PrincipalSource func(ctx context.Context, r MetaReader, p auth.EntityRef) (obj PrincipalObject, ok bool, err error)
PrincipalSource resolves the principal's backing object for a principal EntityRef, in order. The default sources are Function and CatalogService (ADR-0088), each resolving only a principal of its own type (ADR-0175) — the provider case is a principal SOURCE, not a capability. A source returns ok==false to defer to the next.
func CatalogServicePrincipalSource ¶
func CatalogServicePrincipalSource() PrincipalSource
CatalogServicePrincipalSource resolves a CatalogService principal's backing *v1.CatalogService (ADR-0088, ADR-0175): an engine is its own principal, never a same-named Function. Its spec.blob are its blobBindings; it has no links/kv.
func FunctionPrincipalSource ¶
func FunctionPrincipalSource() PrincipalSource
FunctionPrincipalSource resolves a Function principal's backing *v1.Function (ADR-0074); a principal of any other type is not its own (ADR-0175).
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is a deduped set of capabilities + an ordered principal-source list. It assembles the shared cedar artifacts (the composite EntityProvider, the KnownAction/KnownEntityType vocabulary, and the built-in PolicySet) from the registered set (ADR-0116).
func NewRegistry ¶
func NewRegistry(caps []Capability, sources []PrincipalSource) (*Registry, error)
NewRegistry validates (unique Name, unique Action across capabilities; ≥1 source) and returns the registry. A duplicate Name/Action or an empty source list is a fault.Invalid wiring error.
func (*Registry) Builtins ¶
Builtins returns the concatenated built-in permit policy text (the union of the capabilities' Builtin, in registry order so the compiled PolicySet is deterministic).
func (*Registry) EntityProvider ¶
func (reg *Registry) EntityProvider(r MetaReader) (EntityProvider, error)
EntityProvider returns the composite provider over r (ADR-0116). r is required.
func (*Registry) KnownAction ¶
KnownAction reports whether a is one of the registered capabilities' actions (the assembled schema vocabulary — replaces the hand-listed curatedActions map).
func (*Registry) KnownEntityType ¶
KnownEntityType reports whether t is one of the registered capabilities' entity types (primary EmitsEntityType ∪ SupportingEntityTypes — the assembled schema vocabulary, replacing the hand-listed curatedEntityTypes map).
type RoleResolver ¶
type RoleResolver interface {
Actions(ctx context.Context, ref v1.RoleRef, ns v1.NamespaceName) ([]string, bool)
}
RoleResolver resolves a RoleRef (a built-in name or a custom Role resource) to its action set.
func NewRoleResolver ¶
func NewRoleResolver(r MetaReader) RoleResolver
NewRoleResolver builds the production role resolver over a MetaReader.
type WriterGrant ¶
type WriterGrant struct {
Principal cedartypes.EntityUID
Scope v1.ScopeRef
}
WriterGrant is one principal authorized to WRITE a scope (a s3::write / kv::write grant).
func WriterGrants ¶
func WriterGrants(ctx context.Context, ra *v1.RolesAssignment, roles RoleResolver) []WriterGrant
WriterGrants returns the write-authorizing (principal, scope) grants of a RolesAssignment — consumed by the s3/kv resource materializer to build a resource's `writers` set (the generalized single-writer forbid). Excludes the legacy owner (added separately by the materializer).
type WriterLister ¶
type WriterLister interface {
BlobWriters(ctx context.Context, ns v1.NamespaceName, bucket, prefix string) []cedartypes.EntityUID
KVWriters(ctx context.Context, ns v1.NamespaceName, store, table string) []cedartypes.EntityUID
}
WriterLister returns the writer principal UIDs (beyond the legacy owner) authorized to WRITE a blob prefix / kv table, from writer-role RolesAssignments (ADR-0136). It backs the generalized single-writer forbid's `writers` set. A nil WriterLister ⇒ owner-only writers (back-compat, no role grants).