CPEX Tutorial#
A self-paced tutorial. You build a policy enforcement point in front of an agent’s tools, one capability at a time, and watch policy decide every outcome. Every module is a runnable program you can edit, break, and re-run.
By the end you can put CPEX in front of your own tools, write APL for them, extend it with a custom plugin, and test your policy.
What you’ll build#
The running example is the scenario from the Overview: one agent, three backends (HR records, source repos, outbound email), and three callers whose requests get different treatment. The docs describe that scenario. Here you build it, finishing with a capstone that reconstructs it end to end.
One idea repeats in every module: the application never changes. Only the policy changes.
Before you start#
- Rust 1.96 or newer, and Cargo.
- A container runtime with compose (Rancher Desktop, Podman, or Docker Desktop). You need it from module 2 on, where a real Keycloak resolves tokens. Modules 0 and 1 need only Rust, and module 16 additionally needs the SPIRE overlay it describes.
- The code lives in
examples/tutorial. Run a module withcargo run -p cpex-tutorial --example m01_hello.
Budget 15 to 25 minutes per module: about 3 to 4 hours for modules 0 to 10 and the capstone, which are the core path. Modules 11 to 18 are deep dives on organizing policy and on identity and delegation; take them in any order, or skip to the capstone and come back.
Modules#
| # | Module | You’ll learn | IdP? |
|---|---|---|---|
| 0 | Setup & orientation | What CPEX is; verify your setup | no |
| 1 | Hello, enforcement | Stand up an enforcement point; a route with require(); allow vs. deny | no |
| 2 | Who’s calling? (Identity) | Resolve real JWTs from Keycloak into roles and permissions | yes |
| 3 | Shaping data | result: field pipelines that redact and mask per permission | yes |
| 4 | Effects & sequencing | Ordered effects, halt-on-deny, custom deny codes, auditing | yes |
| 5 | Delegating decisions (PDP) | Hand a decision to CEL or Cedar; CPEX enforces the verdict | yes |
| 6 | Scoped credentials (Delegation) | Mint a downstream-scoped token via RFC 8693 exchange | yes |
| 7 | Information flow (Tainting) | Carry session state across requests; block write-down | yes |
| 8 | Human in the loop | Suspend an operation for human approval, then resume | yes |
| 9 | Write your own plugin | Build a custom plugin with the SDK; reference it from policy | no |
| 10 | Testing your policy | Table-driven allow/deny tests that run in CI | no |
| 11 | Organizing policy (Groups) | Factor shared identity/authz into reusable bundles routes join | yes |
| 12 | Delegation subjects | Mint a downstream token as the caller (user) or as the gateway itself (this_workload) | yes |
| 13 | Delegation as a client | Scope an agent’s own client token with subject: client (cookbook Recipe 5) | yes |
| 14 | Passthrough (forward, don’t mint) | When to forward the caller’s token unchanged instead of exchanging it (cookbook Recipe 4) | yes |
| 15 | Dual-principal (subject + actor) | Mint on behalf of a user while naming the acting agent, subject: user, actor: client (cookbook Recipe 6) | yes |
| 16 | Workload identity (SVID) | An agent authenticates by SPIFFE SVID; CPEX brokers a scoped token in two legs, subject: caller_workload (cookbook Recipe 2) | yes + SPIRE |
| 17 | Multi-issuer (trust federation) | Accept callers from more than one IdP with one resolver, each validated on its own keys | yes |
| 18 | Static attributes (data.*) | Feed policy operator-maintained facts from a data file, read per request as data.* | yes |
| C | Capstone: the three-backend agent | Assemble every control into the full Overview scenario | yes |
Start at module 0.
How each module is structured#
Every module page follows the same shape. Goal states what you can do after it in one sentence. The problem shows a concrete failure. Build it shows the policy change. Run it gives the command and expected output. Try it lists guided edits, each with the outcome to expect. Checkpoint is a short self-check. Go deeper links to the reference.