Repository navigation
Commit 77d3238
committed
feat(policy): support Cedar as an alternate sandbox policy language
A sandbox policy can be written in Cedar instead of YAML. The format is
chosen once per sandbox: YAML policies keep using the Rego engine
unchanged, and a .cedar policy makes Cedar the sole authority for network
connections, per-request L7 checks, and Landlock filesystem grants.
Policy model and validation:
- New crates openshell-policy-cedar-schema (canonical Cedar schema) and
openshell-policy-cedar (CedarEngine). Policies are validated in strict
mode, and shapes that cannot be enforced exactly as written are
rejected at submission in the CLI, the gateway, and the supervisor.
- Load-time analysis derives Landlock grants, the endpoints and paths
inspected per request (@protocol rest, json-rpc, mcp, graphql,
websocket, or websocket-graphql, scoped by @path), native TCP endpoints
(@transport("tcp")), and policy DNS eligibility, including delimited
host globs.
- Delimited like gives YAML-style segment globs for hosts, paths, and
binaries. It comes from ai-openshell/cedar, pinned by commit, with a
matching deny.toml allow-git exception; its Lean specification is
ai-openshell/cedar-spec.
- The schema declares only what the supervisor populates: NetworkConnect
carries no request fields, Process has no workdir, and a has test on an
undeclared attribute is rejected. A filesystem permit must list ReadFile
with WriteFile, and resource.host_port names an endpoint for policy DNS.
- @enforcement("audit") provides audit endpoints and staged audit
policies; decisions name policies by their @id annotation.
- Request policies match query parameters through context.query tags;
repeated keys are evaluated per combination of values, as YAML matches
every value.
- context.destination_ip restricts the resolved addresses a connection
may reach, the Cedar form of allowed_ips. Permits read it only as fixed
isInRange lists; connections are evaluated before DNS and again per
resolved address, private addresses need an address-constrained permit
or an exact host, and always-blocked destinations stay blocked.
- context.binary_aliases matches symlinked binaries, resolved inside the
container as YAML does, and context.binary_globs holds the glob patterns
that match the calling binary or an ancestor, so YAML binary globs
translate exactly.
- @enforcement("staged") marks a policy that is only compared against the
enforced decision; @enforcement("audit") has YAML's audit-endpoint
semantics. An HttpRequest policy may name its host with a delimited glob,
inspecting every matching host as a YAML wildcard endpoint does. A
GraphQL path is authoritative for the requests it parses. A delimited
like whose ** touches other characters, and a GraphQL-over-WebSocket
message permit without a GraphQL condition, are rejected at load.
Integration:
- SandboxPolicy gains cedar_policy_source, the gateway-managed
provider_credential_rules, and endpoint_settings. Attached providers
supply credentials and token grants on requests Cedar allows but never
grant access; their allowed_ips only narrow addresses. Provider rules
are compiled into Cedar policies tagged with their token-grant owner,
so owner selection is decided by Cedar.
- The CLI accepts .cedar policies and a separate --middleware file that
also carries endpoint settings (TLS skip, body limits, MCP versions,
persisted queries) and the process identity; policy get renders the
Cedar text, middleware, endpoint settings, process identity, and
provider rules.
- The gateway rejects format switches, Cedar global policies, and removal
of Cedar-derived Landlock grants on live sandboxes.
- Cedar sandboxes run without an OPA engine or Rego. The supervisor
builds the Cedar engine at startup admission, which owns middleware
state and its own generation, commits Cedar, credentials, and
middleware together on reload, and applies the policy validation
failure mode to Cedar. Every network decision point, including the
Windows host proxy, routes through the PolicyEngine enum; Cedar tunnels
pin Cedar's generation. Middleware selection is shared Rust, the data
both engines hand to the proxy is typed Rust with the Rego output
converted at one boundary, and engine-neutral types move out of opa.rs.
- The supervisor maps JSON-RPC, MCP, GraphQL, and WebSocket requests into
Cedar requests the way the YAML engine sees them: uppercase methods,
calls and response frames only in a POST, and one evaluation per call,
GraphQL operation, or WebSocket message.
- Cedar decisions report the policy DNS records that cover a connection,
so transparent TCP correlation works as for YAML.
- Cedar support is the default cedar feature of openshell-policy; crates
that never handle Cedar policies disable it. The Go SDK carries the new
fields.
- The RPM vendor archive captures the git source replacement tables cargo
vendor prints, so the offline RPM build resolves the Cedar dependency.
Testing and documentation:
- Unit tests for the Cedar crates and supervisor integration, and an
e2e:cedar suite run by mise run e2e and the Docker E2E matrix.
- A parity harness runs paired YAML and Cedar policies through both
engines. It ports 258 of the 260 existing YAML decision tests; the
remaining one that is valid YAML needs a Cedar language change. On
Linux, 2,904 of 2,909 cases agree; the 5 differences are deliberate and
recorded with their reasons, an evaluation error on either side fails a
case, and load rejections are asserted. Token-grant owners match YAML for every shipped provider
profile.
- Every example and e2e directory with a YAML policy has a Cedar version
beside it, and its scripts accept POLICY_FORMAT=cedar; a parity test
runs each pair through both engines.
- User documentation for Cedar policies, and a crate README.
Signed-off-by: Vishwanath Raman <vishwanathr@nvidia.com>1 parent 6546691 commit 77d3238
161 files changed
Lines changed: 42349 additions & 2535 deletions
File tree
- .github/workflows
- crates
- openshell-cli
- src
- tests
- openshell-core/src
- openshell-driver-kubernetes
- openshell-driver-mxc
- examples/e2e-policies
- tests
- openshell-driver-vm
- openshell-gateway
- openshell-policy-cedar-schema
- schema
- src
- tests
- openshell-policy-cedar
- src
- tests
- fixtures
- openshell-policy-schema/src
- openshell-policy
- src
- openshell-prover/src
- openshell-providers
- openshell-sandbox
- openshell-server/src
- compute
- grpc
- openshell-supervisor-network
- src
- cedar_parity_tests
- l7
- relay
- opa
- policy_dns
- proxy
- tests
- openshell-supervisor/src
- openshell-tui
- deploy/rpm
- docs
- extensibility/supervisor-middleware
- how-it-works/policies
- e2e
- cedar
- mcp-conformance
- policy-advisor
- examples
- agent-driven-policy-management
- governance-interceptor
- src
- jupyter-sandbox
- local-inference
- multi-agent-notepad
- policy-advisor
- sandbox-policy-quickstart
- supervisor-middleware-content-guard
- transparent-tcp-redis
- proto
- scripts/agents/gator
- sdk/go
- openshell/v1
- internal/converter
- types
- proto
- openshellv1
- sandboxv1
- tasks
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
32 | | - | |
| 32 | + | |
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
32 | 34 | | |
33 | 35 | | |
34 | 36 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
| 35 | + | |
34 | 36 | | |
35 | 37 | | |
36 | 38 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
337 | 337 | | |
338 | 338 | | |
339 | 339 | | |
| 340 | + | |
| 341 | + | |
340 | 342 | | |
341 | 343 | | |
342 | 344 | | |
| |||
0 commit comments