> ## Documentation Index
> Fetch the complete documentation index at: https://certplane.kippel.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Policy overview

> The single YAML file that controls which hosts can request which certificates.

The broker enforces a single declarative policy file (`policy.path` in `broker.yml`). It defines named **profiles** (the shape of a certificate request) and **hosts** (which identities may request which profiles).

The authoritative schema is [`schemas/policy.schema.json`](https://github.com/TaconeoMental/Certplane/blob/main/schemas/policy.schema.json).

## Minimum policy

```yaml theme={null}
version: 1

profiles:
  public_edge_main:
    type: wildcard
    dns_names:
      - "*.example.com"
    acme:
      challenge: dns-01
      credentials: cloudflare/example-com
    renew_before: 720h

hosts:
  edge01:
    identity: edge01.h.int.example.com
    profiles:
      - public_edge_main
```

## Top-level keys

| Key        | Required | Notes                                                                |
| ---------- | -------- | -------------------------------------------------------------------- |
| `version`  | no       | Must equal `1` if set. Reserved for future migrations. Default: `1`. |
| `profiles` | yes      | Map of profile name → profile definition. At least one profile.      |
| `hosts`    | yes      | Map of host label → host definition. At least one host.              |

The broker rejects unknown top-level keys (`additionalProperties: false`).

## How a request is authorized

When an agent calls `POST /v1/certificates`:

1. The broker reads the **CN** of the client certificate (the agent's identity).
2. It looks up that identity in `hosts.<label>.identity`. If no host entry has a matching identity, the request is denied.
3. The requested `profile` (from the JSON body) must appear in that host's `profiles` list.
4. The CSR's DNS names must satisfy the profile's `dns_names` rules — wildcard profiles require the SANs to fall under the configured wildcard label; `multi_san` profiles require the SANs to be exactly drawn from the allowed list.
5. If all checks pass, the broker serves a cached bundle or issues via ACME.

Every decision — allow or deny, with reason code — is recorded in the audit log.

## Hot reload

Set `policy.watch: true` in `broker.yml` to reload the policy when the file changes on disk. The broker logs the new policy hash so you can correlate reloads with the audit stream.

## Validate before deploying

```bash theme={null}
certplane-broker -c /etc/certplane/broker.yml policy validate --policy /etc/certplane/policy.yml
```

This compiles the policy in the same code path the server uses. On success it prints:

```
policy ok: hash=abc123… profiles=N identities=M
```

The same hash appears in the broker's startup log and audit events, which makes it easy to confirm which policy is live.

## Continue

* [Profiles](/policy/profiles)
* [Hosts](/policy/hosts)
