Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions docs/concepts/enforcement.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,82 @@ Server-Timing: capiscio-auth;dur=0.618;desc="CapiscIO Verification"
* `dur`: Duration in milliseconds.
* `desc`: Description of the operation.

## 5. Policy Enforcement (PDP Integration)

Badge verification answers **"who is calling?"** — but not **"are they allowed to do this?"**. Policy enforcement adds authorization decisions via a Policy Decision Point (PDP).

### How It Works

The Policy Enforcement Point (PEP) sits between badge verification and your route handlers. After a badge is verified, the PEP asks an external PDP whether the request should proceed.

```
┌─────────┐ ┌─────────────┐ ┌─────┐ ┌──────────────┐
│ Request │────▶│ Badge │────▶│ PEP │────▶│ Your Handler │
│(+ badge) │ │ Verification│ │ │ │ │
└─────────┘ └─────────────┘ └──┬──┘ └──────────────┘
┌────▼────┐
│ PDP │
│(external)│
└─────────┘
```

The PEP sends a **PIP request** (Policy Information Point) containing identity, action, and resource attributes. The PDP returns ALLOW or DENY, plus optional **obligations** the PEP must enforce.

### Enforcement Modes

Four modes control how strictly the PEP enforces PDP decisions. They form a total order from most permissive to most restrictive:

| Mode | PDP Denies | PDP Unavailable | Unknown Obligation |
|------|-----------|-----------------|-------------------|
| **EM-OBSERVE** | Log only, allow through | Allow (emit `ALLOW_OBSERVE`) | Log, skip |
| **EM-GUARD** | Block request | Deny (fail-closed) | Log, skip |
| **EM-DELEGATE** | Block request | Deny (fail-closed) | Log warning, proceed |
| **EM-STRICT** | Block request | Deny (fail-closed) | Deny request |

Start with `EM-OBSERVE` to monitor decisions without affecting traffic, then tighten as your policies mature.

### Obligations

A PDP can attach obligations to an ALLOW decision — actions the PEP must perform before forwarding the request. Examples from the RFC:

| Obligation Type | Purpose | Example Params |
|----------------|---------|----------------|
| `rate_limit.apply` | Enforce per-agent rate limits | `{ "rpm": 100, "key": "agent-did" }` |
| `redact.fields` | Remove sensitive fields | `{ "fields": ["/pii/email"] }` |
| `log.enhanced` | Enhanced audit logging | `{ "level": "audit" }` |
| `require_step_up` | Require human review | `{ "mode": "human_review" }` |

How the PEP handles obligation failures depends on the enforcement mode. In EM-STRICT, failing to enforce any known obligation blocks the request. In EM-OBSERVE, failures are logged but the request proceeds.

### Decision Caching

The PEP caches ALLOW decisions to reduce PDP latency. Cache keys are derived from the agent DID, badge JTI, operation, and resource. The effective TTL is the minimum of:

- The PDP-returned `ttl`
- The badge `exp` (expiry)
- The envelope `expires_at` (if present)

DENY decisions are not cached by default.

### Break-Glass Override

For emergencies, a break-glass token bypasses the PDP entirely. The token is a signed JWS (EdDSA) with a scoped grant and an expiry (recommended: 5 minutes). It skips authorization but **not** authentication — the badge must still be valid.

The PEP emits `capiscio.policy.override = true` telemetry for audit when a break-glass token is used.

!!! warning "Break-Glass Keys"
Use a separate Ed25519 keypair for break-glass tokens. Do not reuse your CA badge-signing key.

### Badge-Only Mode

If no PDP endpoint is configured, the PEP is a no-op passthrough. Badge verification still runs, but no policy decisions are made. This is the default behavior.

!!! tip "Getting Started"
See [Policy Enforcement Setup](../how-to/security/policy-enforcement.md) for step-by-step configuration.

---

## Summary: What Guard Does and Doesn't Do

| Guard Does | Guard Doesn't |
Expand All @@ -135,3 +211,5 @@ Server-Timing: capiscio-auth;dur=0.618;desc="CapiscIO Verification"
| ✅ Enforce payload integrity (SHA-256 body hash) | ❌ Manage a central registry (coming soon) |
| ✅ Block replay attacks (timestamp validation) | ❌ Replace your IAM/SSO (human auth) |
| ✅ Work with keys you provision | ❌ Auto-discover external agent keys (coming soon) |
| ✅ Enforce PDP policy decisions (when configured) | ❌ Provide a PDP (bring your own) |
| ✅ Support break-glass emergency overrides | ❌ Bypass authentication for overrides |
181 changes: 181 additions & 0 deletions docs/how-to/security/policy-enforcement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
---
title: Policy Enforcement Setup
description: Configure PDP integration to add authorization decisions to your agent
---

# Policy Enforcement Setup

Add authorization decisions to badge-verified requests by connecting to a Policy Decision Point (PDP).

---

## Problem

You need to:

- Control which agents can access which endpoints based on policy
- Enforce rate limits, field redaction, or audit logging per-agent
- Gradually roll out policy enforcement without breaking existing traffic
- Override policy in emergencies

---

## Solution

Configure the CapiscIO server to forward policy queries to your PDP. The PEP middleware runs after badge verification and before your route handlers.

---

## Prerequisites

- A running CapiscIO server with badge verification enabled
- A PDP that accepts HTTP POST requests with PIP-format decision requests (RFC-005 §5.1)

---

## Step 1: Start in Observe Mode

Begin with `EM-OBSERVE` to monitor PDP decisions without affecting traffic:

```bash
export CAPISCIO_PDP_ENDPOINT=http://localhost:9090/v1/evaluate
export CAPISCIO_ENFORCEMENT_MODE=EM-OBSERVE
export CAPISCIO_PDP_TIMEOUT_MS=500
```

In this mode, PDP DENY decisions are logged but requests proceed. If the PDP is unreachable, requests also proceed with an `ALLOW_OBSERVE` telemetry marker.

Restart the server and monitor logs for `capiscio.policy_enforced` events.

---

## Step 2: Review Decisions

Check server logs for policy events. Each request that passes through the PEP emits:

| Field | Description |
|-------|-------------|
| `capiscio.policy.decision` | `ALLOW`, `DENY`, or `ALLOW_OBSERVE` |
| `capiscio.policy.decision_id` | Unique ID from the PDP |
| `capiscio.policy.error_code` | `PDP_UNAVAILABLE` if PDP was unreachable |

Verify that legitimate requests receive `ALLOW` and unauthorized access patterns receive `DENY` before tightening the enforcement mode.

---

## Step 3: Tighten Enforcement

Once decisions look correct, switch to `EM-GUARD`:

```bash
export CAPISCIO_ENFORCEMENT_MODE=EM-GUARD
```

Now PDP DENY decisions block requests with `403 Forbidden`. If the PDP is unavailable, requests are denied with `503 Service Unavailable` (fail-closed).

For full obligation enforcement, use `EM-STRICT`:

```bash
export CAPISCIO_ENFORCEMENT_MODE=EM-STRICT
```

In EM-STRICT, unknown obligation types cause the request to be denied.

---

## Step 4: Configure Break-Glass (Optional)

For emergency access when the PDP is down or mis-configured:

1. Generate a dedicated Ed25519 keypair for break-glass tokens:

```bash
capiscio keygen --output breakglass-key
```

2. Configure the server with the public key path:

```bash
export CAPISCIO_BREAKGLASS_PUBLIC_KEY=/etc/capiscio/breakglass-key.pub.pem
```

3. In an emergency, issue a break-glass token and include it as the `X-Capiscio-Breakglass` header. The token must contain a `reason`, scoped `methods`/`routes`, and a short expiry.

!!! warning
Break-glass bypasses authorization but **not** authentication. The request must still carry a valid badge.

---

## Configuration Reference

All PDP-related environment variables:

| Variable | Default | Description |
|----------|---------|-------------|
| `CAPISCIO_PDP_ENDPOINT` | _(empty)_ | PDP URL. Empty = badge-only mode (no policy enforcement) |
| `CAPISCIO_PDP_TIMEOUT_MS` | `500` | PDP query timeout in milliseconds |
| `CAPISCIO_ENFORCEMENT_MODE` | `EM-OBSERVE` | One of: `EM-OBSERVE`, `EM-GUARD`, `EM-DELEGATE`, `EM-STRICT` |
| `CAPISCIO_BREAKGLASS_PUBLIC_KEY` | _(empty)_ | Path to break-glass Ed25519 public key file |
| `CAPISCIO_PEP_ID` | _(empty)_ | PEP instance identifier (sent to PDP as `X-Capiscio-PEP-ID`) |
| `CAPISCIO_WORKSPACE` | _(empty)_ | Workspace/tenant identifier |

---

## PDP Request Format

The PEP sends a JSON POST to the PDP endpoint. Your PDP must accept this format:

```json
{
"pip_version": "capiscio.pip.v1",
"subject": {
"did": "did:web:agent.example.com",
"badge_jti": "badge-uuid",
"ial": "1",
"trust_level": "DV"
},
"action": {
"operation": "POST /api/v1/badges",
"capability_class": null
},
"resource": {
"identifier": "/api/v1/badges"
},
"context": {
"txn_id": "txn-uuid",
"enforcement_mode": "EM-GUARD"
},
"environment": {
"workspace": "production",
"pep_id": "server-01",
"time": "2026-03-01T12:00:00Z"
}
}
```

And return:

```json
{
"decision": "ALLOW",
"decision_id": "eval-uuid",
"obligations": [],
"reason": "Policy matched: allow-trusted-agents",
"ttl": 300
}
```

---

## Verification

Confirm policy enforcement is active:

```bash
# Send a request and check response headers
curl -v https://your-server/api/v1/badges \
-H "X-Capiscio-Badge: $BADGE_JWS"

# Look for Server-Timing header with policy timing
# Server-Timing: capiscio-auth;dur=0.6, capiscio-policy;dur=12.3
```
26 changes: 26 additions & 0 deletions docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,32 @@ config = SecurityConfig.from_env()

---

## Policy Enforcement (Server)

These environment variables configure the PDP integration on the CapiscIO server (RFC-005). They are read by the server, not the SDK.

| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `CAPISCIO_PDP_ENDPOINT` | `string` | _(empty)_ | PDP URL. Empty = badge-only mode |
| `CAPISCIO_PDP_TIMEOUT_MS` | `int` | `500` | PDP query timeout in milliseconds |
| `CAPISCIO_ENFORCEMENT_MODE` | `string` | `EM-OBSERVE` | `EM-OBSERVE`, `EM-GUARD`, `EM-DELEGATE`, or `EM-STRICT` |
| `CAPISCIO_BREAKGLASS_PUBLIC_KEY` | `string` | _(empty)_ | Path to break-glass Ed25519 public key |
| `CAPISCIO_PEP_ID` | `string` | _(empty)_ | PEP instance identifier |
| `CAPISCIO_WORKSPACE` | `string` | _(empty)_ | Workspace/tenant identifier |

### Example

```bash
# Enable policy enforcement in observe mode
export CAPISCIO_PDP_ENDPOINT=http://pdp.internal:9090/v1/evaluate
export CAPISCIO_ENFORCEMENT_MODE=EM-OBSERVE
export CAPISCIO_PDP_TIMEOUT_MS=500
```

See [Policy Enforcement Setup](../how-to/security/policy-enforcement.md) for step-by-step configuration.

---

## Complete Example

```python
Expand Down
Loading
Loading