---
title: "Cedar policy"
url: "/reference/filters/http/cedar-policy/"
kind: "reference"
summary: "Arion HTTP filter that authorizes requests with Cedar policies over JWT claims and request context."
---

> Arion site index: [/llms.txt](/llms.txt)

# Cedar policy

Arion HTTP filter that authorizes requests with Cedar policies over JWT claims and request context.

| Attachment | Type URL (`@type`) | Per-route override | Build feature |
|---|---|---|---|
| HTTP filter chain (`http_filters`) | `type.googleapis.com/arion.extensions.filters.http.cedar.cedar_policy.v3.CedarPolicy` | `disabled` only | None |

## What it does

The Cedar filter is an Arion extension that evaluates every request against a [Cedar](https://www.cedarpolicy.com/) policy set embedded in the configuration. Each request becomes an authorization query — principal, action, resource, context — and a deny answers `403` before the router runs. It gives you expression-level authorization (claim comparisons, path conditions) where header-matching [RBAC](@/reference/filters/http/rbac.md) is not enough.

## Request mapping

- **Principal** — `<principal_entity_type>::"<sub>"` from the JWT claims that [JWT authentication](@/reference/filters/http/jwt-authn.md) attached earlier in the chain; without claims it is `<principal_entity_type>::"anonymous"`.
- **Action** — `Action::"<HTTP method>"`, for example `Action::"GET"`.
- **Resource** — `<resource_entity_type>::"<path>"`, for example `HttpPath::"/health"`.
- **Context** — a record with `http` (`method`, `path`, and `query` when present) and, when authenticated, `jwt` holding the token's claims (`sub`, `iss`, `aud`, `exp`, `iat`, `nbf`, `jti` and any extra claims).

## Minimal configuration

From `arion-runtime-cedar.yaml`; the fragment is an entry in `http_filters`, before the router:

```yaml,arion=fragment
- name: cedar
  typed_config:
    "@type": type.googleapis.com/arion.extensions.filters.http.cedar.cedar_policy.v3.CedarPolicy
    schema: |
      entity User;
      entity HttpPath;
      action "GET" appliesTo {
        principal: [User],
        resource:  [HttpPath],
        context: { http: { method: String, path: String, query?: String } }
      };
    policies: |
      permit (
        principal == User::"anonymous",
        action    == Action::"GET",
        resource  == HttpPath::"/health"
      );
```

## Fields

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `policies` | string | Yes | — | Cedar policy text. Anything not permitted is implicitly denied. |
| `schema` | string | Yes | — | Cedar schema declaring entity types, actions and the context shape. |
| `entities` | string | No | empty | Entity data as Cedar JSON, for policies over entity attributes or hierarchies. |
| `enforcement_mode` | enum | No | `ENFORCE` | `ENFORCE` denies with `403`; `LOG_ONLY` logs the denial and continues. |
| `failure_mode` | enum | No | `FAIL_CLOSED` | On an evaluation error, `FAIL_CLOSED` answers `403`; `FAIL_OPEN` continues. |
| `principal_entity_type` | string | No | `User` | Entity type used for the principal. |
| `resource_entity_type` | string | No | `HttpPath` | Entity type used for the resource. |
| `validate_schema_per_request` | bool | No | `false` | Validate the built request against the schema on every evaluation. |

## Ordering and interactions

Place Cedar after JWT authentication so the `jwt` context and the `sub`-based principal exist; before it, every caller is `anonymous`. Denials short-circuit the chain, and `enforcement_mode: LOG_ONLY` is the safe way to stage a new policy set against live traffic before enforcing it. Per route the filter supports only the generic `FilterConfig` override with `disabled: true`.
