Policy Bundle Signing
For: Platform engineers and security teams operating Axemere Gateway.
Security Overview | mTLS | Bundle Signing | Credential Encryption
The Axemere Control Plane signs every policy bundle before serving it to gateways. Gateways verify the signature before activating the bundle. This prevents a compromised database, an intercepted gRPC connection, or a misconfigured overlay from causing gateways to execute unauthorized policy.
Table of Contents
How It Works
All bundles are signed using Ed25519 over the JCS-canonical (RFC 8785) serialization of the bundle body. The signature is embedded in the bundle's signature field. Every gateway verifies the signature before activating any bundle; there is no mode in which an unsigned or tampered bundle is accepted.
If verification fails for any reason (tampered bundle, unknown signing key, missing signature), the gateway keeps the last known-good bundle active and emits a security alert metric. No policy gap occurs.
Security Properties
| Property | Guarantee |
|---|---|
| Bundle authenticity | Only the CP with the active signing key can produce a valid bundle |
| Tamper detection | Any modification to the bundle body invalidates the signature |
| Replay prevention | Monotonic version enforcement: a database trigger rejects any content change unless version strictly increases, and the integrity check covers version together with the content, so an old, validly-signed bundle can't be reintroduced under a bumped version number |
| Key separation | Policy signing key is separate from the execution record signing key |
| No policy gap on failure | Rejected bundles leave the previous bundle active, no uncovered window |
Scope: bundle signing protects a bundle from the moment it's signed through delivery to the gateway. It does not, on its own, protect the policy source data in Postgres before signing: a direct database tamper of a base bundle or an overlay would get faithfully signed and served. A separate, complementary keyed HMAC-SHA256 over the underlying policy tables closes that gap, and now also binds each row's version into the same check, so a database write can't roll a bundle's content back to an earlier, still-validly-authenticated state either. See Security Overview — Layer 2 for how the two mechanisms compose.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
bundle signature verification failed in gateway logs | Bundle modified in transit, or gateway keyring has a stale key | Force a bundle refresh: DELETE /v1/admin/policy/cache; check CP health |
| Bundles rejected after a key rotation | Gateway keyring not yet refreshed with new key | Keyring refreshes automatically after each bundle fetch; wait for the next check-in cycle or force a bundle refresh |