Authorization Policy
Cedar-based authorization policies for Spice.ai Enterprise — fine-grained access control over datasets, models, tools, and endpoints.
Spice.ai Enterprise enforces fine-grained authorization using Cedar, the open-source policy language developed by AWS. Policies decide, on every request, whether an authenticated principal may perform a given action on a Spice resource.
Cedar-based authorization policy is a Spice.ai Enterprise feature. It is layered on top of Authentication — authentication establishes who the principal is; policy decides what they can do.
Authorization Model
Policy evaluation is the standard Cedar (principal, action, resource, context) decision. Spice.ai supplies an embedded Cedar schema that defines the entity types, actions, and attributes available in policies.
Entity types
Spice::User
An authenticated principal (OIDC subject, API key identity, …). in [Role]
org_id
Spice::Role
A role the user belongs to. For OIDC principals, sourced from the configured role/group claims; for API-key principals, the key's read or read_write permission level
—
Spice::Dataset
A registered dataset (table) in the runtime
catalog, schema
Spice::Model
An LLM model available for inference
—
Spice::Tool
A tool (built-in or MCP) available for execution
—
Spice::Endpoint
An API endpoint category (e.g. chat, search, sql)
—
Actions
Spice::Action::"query"
Spice::Dataset
SELECT / scan of a dataset.
Spice::Action::"read"
Spice::Dataset
Reading a dataset's contents. Carries the fine-grained row filter and column mask annotations (see Row Filters and Column Masks). A read permit also implicitly authorizes query.
Spice::Action::"insert"
Spice::Dataset
INSERT write path.
Spice::Action::"update"
Spice::Dataset
UPDATE write path.
Spice::Action::"delete"
Spice::Dataset
DELETE write path.
Spice::Action::"ddl"
Spice::Dataset
DDL operations on a dataset.
Spice::Action::"invoke"
Spice::Model
Inference / chat completion.
Spice::Action::"execute"
Spice::Tool
Tool invocation (built-in or MCP).
Spice::Action::"access"
Spice::Endpoint
Reaching an endpoint category.
The Cedar schema is fixed by the runtime; policies reference these types and actions directly.
Configuration
Policies are configured under runtime.authorization in spicepod.yaml. Authentication must be configured separately under runtime.auth — see Authentication.
runtime.authorization fields
enabled
bool
true
Toggles policy evaluation.
default
allow | deny
allow
Decision when no policy matches. Set to deny for production deny-by-default deployments.
provider
local | operator | cloud
local
Source of policies. local reads inline / file; operator polls the Spice K8s Operator; cloud polls the Spice Cloud Management API.
operator
object
—
Operator provider config. Fields: endpoint, poll_interval (default 30s).
cloud
object
—
Cloud provider config. Fields: poll_interval (default 60s).
PolicyDefinition
name
string
Human-readable identifier used in logs and decision diagnostics.
cedar
string
Inline Cedar policy text. Mutually compatible with path; both may be used together.
path
string
Path to a .cedar file, resolved relative to spicepod.yaml. Mutually compatible with cedar.
Policy Examples
Default-deny baseline
Read-only analysts
Restrict a dataset to a single role
Block a PII schema from non-privileged roles
To mask individual columns rather than block access entirely, use column masks.
Limit model invocation to a paid tier
Endpoint-level access (e.g. lock down /v1/sql)
Policy Providers
local
Inline Cedar text and/or .cedar files in the spicepod.
Reloaded on Spicepod restart or operator-driven config rollout.
operator
Centralized policy distribution via the Spice K8s Operator.
Polled at poll_interval (default 30s); engine atomically swaps the set.
cloud
Centralized policy distribution via Spice Cloud.
Polled at poll_interval (default 60s); engine atomically swaps the set.
Policy reloads are atomic: in-flight requests complete against the previous policy set, and subsequent requests evaluate against the new set. Empty policy fetches do not silently disable enforcement — combined with default: deny, an empty set denies everything.
Row Filters and Column Masks
Beyond coarse allow/deny, policies enforce fine-grained access — row-level filtering and column-level masking — on the read action. The runtime compiles these from Cedar policy annotations into SQL that is applied to the table scan, so filtered rows and masked values are never materialized for the request: they are enforced before any downstream operator (or the client) observes them.
Annotations attach to a permit policy for Spice::Action::"read". A read permit also implicitly authorizes query, so a single read policy can grant masked, row-filtered access in one rule.
Annotations
@row_filter("<sql predicate>")
Adds a SQL boolean predicate as a row filter. May be repeated with a suffix (e.g. @row_filter_region); multiple filters are AND-combined.
@mask_<column>("<sql expr>")
Replaces <column> with the SQL scalar expression.
@column_mask_<column>("<sql expr>")
Equivalent to @mask_<column>.
@column_mask("<column>=<sql expr>")
Equivalent, with the column named in the annotation value.
@mask_tag_<tag>("<sql expr>")
Replaces every column carrying <tag> (see Tagging columns).
@column_mask_tag("<tag>=<sql expr>")
Equivalent, with the tag named in the annotation value.
@target_table("<dataset>")
Scopes the annotations to a single dataset when the policy matches more than one.
Row filters and mask expressions are evaluated with the request's identity, so they can reference the identity SQL functions (current_user_id(), current_org_id(), current_user_has_role('...')) for per-user or per-tenant access.
Example
With these policies, an analyst running SELECT * FROM patients sees only their organization's rows with ssn and any PHI-tagged column replaced, while a physician sees their organization's rows unmasked — from the same query.
Tagging columns
Tag-based masks (@mask_tag_* / @column_mask_tag) target columns by the dataset's column metadata:
Rules
Fine-grained annotations are honored only on
permitpolicies. Attaching one to aforbidis a load-time error.A row filter must evaluate to a Boolean; a column mask expression must return the column's data type. Type mismatches fail closed — the query errors rather than returning unmasked data.
If two matching policies define conflicting masks for the same column or tag, policy load fails.
To deny access outright, use a
forbidonread/queryrather than a mask.
The identity SQL functions are also available directly in dataset views and ad-hoc WHERE clauses for row-level logic outside of policy enforcement.
Distributed Cluster Behavior
In a SpicepodCluster, the scheduler is the source of truth for policy. Executors pull policy as part of the GetAppDefinition bootstrap RPC and re-evaluate when policy changes are pushed; the same Cedar decision applies regardless of which scheduler routes a request. Policy diagnostics (matched policy IDs, decision) are emitted as structured logs and surface in runtime.task_history.
Production Checklist
See also
Last updated
Was this helpful?