Operator procedures for first-boot auto-init, status checks, emergency seal, rotation, and root-token re-create
This runbook covers the procedures for operating a DynamoDB-backed chamber under the kms_auto-static custody model. For the state diagram, transition rules, and design model, see the Seal State Machine. For request and response schemas, see the API Reference.
The seal/unseal flow only applies when using the DynamoDB key source.
How the Chamber Unseals
Section titled “How the Chamber Unseals”There are no operator ceremony steps. The chamber is fully self-managing:
- First boot on a fresh table — if a ceremony is configured, the chamber auto-inits: generates the master key, Shamir-splits it, KMS-wraps each share, self-tests (decrypt + re-combine + commitment verify) before writing anything durable, then writes the
MASTER_KEYrow and a root token. The replica isunsealedwithout any operator action. - Every subsequent boot — the chamber reads the
MASTER_KEYrow and reconstructs the master key from its KMS-wrapped shares (KMS auto-unseal). Again, no operator action required. - Emergency stop only — the
operator sealcommand is break-glass. Use it when you need to halt signing fleet-wide immediately. Recovery requires a manual IAM step and a restart.
Prerequisites
Section titled “Prerequisites”Confirm before deploying:
containment-chamberbinary is installed.- The signer’s IAM role has
kms:Decryptandkms:GenerateDataKeyon all ceremony KMS keys. - The signer state DynamoDB table exists and the IAM role has read/write access.
- The DynamoDB key-source table exists (for the validator keys).
- On non-Nitro deployments: the
ceremony:block is present in the config file. - On Nitro: the ceremony static is compiled in and the KMS key policies admit the enclave’s PCR0 measurement.
Use env:VAR_NAME for sensitive flags so secrets do not appear in process listings:
export CC_AUTH_TOKEN="cc_token_..."
containment-chamber operator status \ --auth-token "env:CC_AUTH_TOKEN" \ --signer-url http://localhost:9000 \ --allow-plaintext-signerCeremony Configuration
Section titled “Ceremony Configuration”Non-Nitro: ceremony: Config Block
Section titled “Non-Nitro: ceremony: Config Block”Add the ceremony: block to the signer config YAML. The block is the source of truth for custody parameters on non-Nitro deployments.
ceremony: generation: 1 kms_threshold: 2 # Shamir M — minimum shares needed to reconstruct the master key kms_keys: # N logical KMS keys; master key is split M-of-N across them - arns: - "arn:aws:kms:us-east-1:123456789012:key/aaaaaaaa-0000-0000-0000-aaaaaaaaaaaa" - "arn:aws:kms:us-west-2:123456789012:key/aaaaaaaa-0000-0000-0000-aaaaaaaaaaaa-mrk" - arns: - "arn:aws:kms:us-east-1:123456789012:key/bbbbbbbb-0000-0000-0000-bbbbbbbbbbbb" - arns: - "arn:aws:kms:us-east-1:123456789012:key/cccccccc-0000-0000-0000-cccccccccccc" retired_kms_keys: [] # Old keys kept decryptable across a rotation; empty in steady state root_token_recipients: # age X25519 public keys; the root-token bootstrap is encrypted to any of these - "age1qz2…"Each entry in kms_keys is one logical (potentially multi-Region) key. List the primary-region ARN first, then any replica-region ARNs. A minimum of kms_threshold entries must be reachable for the chamber to unseal.
Nitro: Compiled-In Static
Section titled “Nitro: Compiled-In Static”On Nitro, the ceremony parameters are baked into the binary at build time and bound to the enclave’s PCR0 measurement. No config block is needed or allowed. See Nitro Enclave Deployment for how to build and configure the ceremony static.
First Boot
Section titled “First Boot”Start the signer:
containment-chamber --config /etc/containment-chamber/config.yamlOn first boot against a fresh table, the chamber:
- Finds no
MASTER_KEYrow. - Runs auto-init: generates the master key, Shamir-splits it, KMS-wraps each share.
- Self-tests: decrypts the shares via KMS and verifies the commitment before writing anything.
- Atomically writes the
MASTER_KEYrow plus a root token (age-encrypted toroot_token_recipients) stored inROOT_TOKEN_BOOTSTRAP. - Transitions to
unsealed.
The chamber is ready when status shows unsealed. No operator action is required.
Check Status
Section titled “Check Status”containment-chamber operator status \ --auth-token env:CC_AUTH_TOKEN \ --signer-url http://localhost:9000 \ --allow-plaintext-signerThe response includes the current seal state (unsealed or sealed) and the ceremony generation. A healthy signer shows unsealed.
Emergency Seal and Recovery
Section titled “Emergency Seal and Recovery”Seal (Break-Glass)
Section titled “Seal (Break-Glass)”Sealing stops all signing fleet-wide. Use only in a genuine emergency.
containment-chamber operator seal \ --auth-token env:CC_AUTH_TOKEN \ --signer-url http://localhost:9000 \ --allow-plaintext-signerThis command:
- Writes the HMAC-stamped
SEAL_OVERRIDErow to DynamoDB. - Transitions the local replica to
Sealed. - Zeroizes the master key from memory.
- Revokes all auth tokens.
Every other replica’s background watcher observes the latch on its next tick and seals the same way. The seal is cluster-wide and restart-surviving — a replica restart without removing the latch comes back Sealed.
Recovery from Sealed
Section titled “Recovery from Sealed”-
Investigate and resolve the cause of the emergency seal before proceeding.
-
Delete the
SEAL_OVERRIDErow using an IAM principal withdynamodb:DeleteItemon the state table:Terminal window aws dynamodb delete-item \--table-name <signer-state-table> \--key '{"pk": {"S": "SEAL_OVERRIDE"}}' -
Restart every replica. Each replica boots, finds no
SEAL_OVERRIDElatch, and auto-unseals from the existingMASTER_KEYrow. -
Confirm recovery:
Terminal window containment-chamber operator status \--auth-token env:CC_AUTH_TOKEN \--signer-url http://localhost:9000 \--allow-plaintext-signerExpect
unsealed.
Rotation
Section titled “Rotation”Rotation is declarative — there are no rotate CLI commands. Change the ceremony static and redeploy; the background watcher reconciles the MASTER_KEY row automatically after unseal.
Rotate KMS Keys or Threshold
Section titled “Rotate KMS Keys or Threshold”-
Edit the
ceremony:block (non-Nitro) or rebuild the binary with a newCEREMONYstatic (Nitro):- Bump
generationby 1. - Update
kms_keysand/orkms_thresholdwith the new values. - Move the old
kms_keysentries intoretired_kms_keys— they must remain decryptable by KMS until every replica has reconciled.
ceremony:generation: 2 # bumped from 1kms_threshold: 2kms_keys:- arns: ["arn:aws:kms:us-east-1:123456789012:key/new-key-1"]- arns: ["arn:aws:kms:us-east-1:123456789012:key/new-key-2"]- arns: ["arn:aws:kms:us-east-1:123456789012:key/new-key-3"]retired_kms_keys:- arns: ["arn:aws:kms:us-east-1:123456789012:key/old-key-1"]- arns: ["arn:aws:kms:us-east-1:123456789012:key/old-key-2"]- arns: ["arn:aws:kms:us-east-1:123456789012:key/old-key-3"]root_token_recipients:- "age1qz2…" - Bump
-
Redeploy replicas in a rolling fashion.
-
After each replica unseals, its watcher compares the static’s
ceremony_config_hashagainst theMASTER_KEYrow. When it detects the generation bump, it re-wraps the (unchanged) master key under the new key set in a single DynamoDB transaction — proving the new keys can decrypt before retiring the old wraps. -
Once all replicas are running the new generation, remove
retired_kms_keysfrom the config and do a final redeploy to bump to the clean state.
The signer stays unsealed and serving throughout the entire rotation. No signing downtime.
Rotate Root-Token Recipients
Section titled “Rotate Root-Token Recipients”To change who can decrypt the root-token bootstrap:
- Update
root_token_recipientsin the ceremony static and bumpgeneration. - Redeploy. The watcher reconcile pass detects the changed recipient set and re-creates the root token (age-encrypting the new ciphertext to the updated recipient list) inside the same DynamoDB transact that re-wraps the KMS shares.
The old root token is revoked atomically as part of the reconcile commit.
Root Token Re-Create
Section titled “Root Token Re-Create”The root token is created once at auto-init and stored as an age-encrypted ciphertext in the ROOT_TOKEN_BOOTSTRAP DynamoDB row. To decrypt it, use the age private key matching one of the root_token_recipients public keys:
# Download the ciphertext and decrypt with ageaws dynamodb get-item \ --table-name <signer-state-table> \ --key '{"pk": {"S": "ROOT_TOKEN_BOOTSTRAP"}}' \ --query 'Item.ciphertext.B' \ --output text | base64 -d | age --decrypt -i ~/.age/identity.txtIf the root token is lost or the ROOT_TOKEN_BOOTSTRAP row is absent, re-create by:
- Deleting the
ROOT_TOKEN_BOOTSTRAProw:Terminal window aws dynamodb delete-item \--table-name <signer-state-table> \--key '{"pk": {"S": "ROOT_TOKEN_BOOTSTRAP"}}' - Restarting the replicas. On the next unseal, the watcher reconcile pass detects the missing bootstrap row and re-creates the root token, age-encrypting it to the current
root_token_recipients.
Attestation (Nitro)
Section titled “Attestation (Nitro)”On Nitro deployments, retrieve the NSM attestation document to verify enclave measurements:
containment-chamber operator attestation \ --auth-token env:CC_AUTH_TOKEN \ --signer-url https://enclave.example.internal:9000The attestation document includes PCR0 (the enclave image measurement that custody parameters are bound to). See Nitro Enclave Operations for PCR verification and measurement-pinning procedures.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Action |
|---|---|
| Signing returns 503 | Check operator status; the signer may be sealed or auto-init has not completed. |
| Signer process fails to start (boot error) | A stateful deployment requires a ceremony and a reachable state table. Verify the ceremony: block is present and well-formed (non-Nitro) or compiled in (Nitro); confirm the IAM role has KMS and DynamoDB access; check boot logs for the specific error. |
Status shows sealed |
A SEAL_OVERRIDE latch is present. Follow the Recovery from Sealed procedure. |
| KMS decrypt denied | Check IAM role policy and KMS key policy; on Nitro, verify the enclave’s PCR0 is admitted in the KMS condition. |
requires a custody ceremony, but none resolved |
A stateful chamber needs a ceremony. Add a ceremony: block (non-Nitro) or compile it into the EIF via CHAMBER_CEREMONY_FILE (Nitro). Auto-init does not require a DynamoDB key store. |
| Watcher reconcile fails repeatedly | Check signer logs for reconcile failed; usually a transient KMS or DynamoDB error — will retry on the next watcher tick (H5). Ensure retired_kms_keys still includes all old key ARNs until reconcile completes. |
For broader diagnostics, see Troubleshooting.
Disaster Recovery
Section titled “Disaster Recovery”If all KMS keys are lost and the MASTER_KEY row cannot be decrypted, the master key is unrecoverable through the normal path. The recovery path is the age-encrypted mnemonic backup created during key generation, if backup recipients are configured. See DynamoDB Key Source.
Next Steps
Section titled “Next Steps”- Auth Policies & Tokens — create management tokens scoped to your operations after the chamber is unsealed
- Production Hardening — restrict the seal endpoint and set up audit logging
- Upgrading — safe version bumps that preserve the existing
MASTER_KEYrow

