Make a recovery requirement executable
Evaluate successful and failed rehearsals against the same signed recovery policy.
Follow along
Goal: evaluate both recovery results against a signed policy, including the failed rehearsal. The command's success condition belongs in the policy; signing a result alone does not make it acceptable.
Before you start
Complete recording recovery evidence. You need rehearsal.json, gap.json, and the same source commit. Have an authorized policy signer prepare policy/recovery.json using the policy schema. It must require the recovery-rehearsal step, the relevant attestation types, and the permitted evidence producers.
The example policy attaches a Rego rule to the command-run attestation:
package commandrun
import rego.v1
deny contains msg if {
input.exitcode != 0
msg := "the restore did not recover every row"
}
This is the rule body, not a complete policy file. Add it through the policy schema's Rego configuration. It trusts your rehearsal to detect missing data; it does not independently query the database. Review policy verification before using your own test.
1. Inspect the intended policy
With jq installed:
jq . policy/recovery.json
cilock policy draft --help
cilock verify --help
Expected: the step names match the evidence, and your installed CI/lock supports the flags below. Confirm policy expiry, producer identities, the nonzero-exit rule, and subject requirements. Do not use an empty rule list for this exercise.
2. Bind the policy to your platform's trust configuration
Set P to your trusted platform origin. This example is for a local appliance running on loopback:
P=http://localhost:8080
cilock policy draft -f policy/recovery.json \
--hydrate-local --platform-url "$P" \
-o recovery.hydrated.json
Expected: a hydrated policy file. Inspect it before signing; do not blindly accept newly discovered roots. Hosted or remote environments require the verified HTTPS origin and trust configuration supplied by your administrator.
3. Sign the reviewed policy
Run as the authorized policy signer using that principal's supported approval flow:
cilock sign -f recovery.hydrated.json \
-o recovery.signed.json \
-t https://aflock.ai/policy/v0.1 --platform-url "$P"
Expected: a signed policy envelope. This does not publish the policy or activate it at a Pushgate repository. Those are separate operations with separate authorization.
4. Prepare offline verification inputs
Obtain platform-trust.pem from your administrator through a trusted channel. Set the expected policy signer email and issuer to the exact values your team authorized. Do not derive the expected identity from the untrusted evidence you are verifying.
[email protected]
POLICY_ISSUER="$P/fulcio/oidc"
SUBJECT="sha1:$(git rev-parse HEAD)"
Replace the example email and confirm the issuer; do not assume every deployment uses this issuer path. The trust bundle must contain the required certificate and timestamp trust material for your release. Preserve the original recorded commit instead of using a later checkout's HEAD.
5. Verify the successful rehearsal
cilock verify --offline \
-p recovery.signed.json -a rehearsal.json \
--subjects "$SUBJECT" \
--policy-ca-roots platform-trust.pem \
--policy-timestamp-servers platform-trust.pem \
--policy-emails "$POLICY_SIGNER_EMAIL" \
--policy-fulcio-oidc-issuer "$POLICY_ISSUER" --format json
Expected: success for the required subject, producer, step, and rule. A missing root, issuer mismatch, or expired policy is a configuration failure, not a passing recovery check.
6. Verify the failed rehearsal
cilock verify --offline \
-p recovery.signed.json -a gap.json \
--subjects "$SUBJECT" \
--policy-ca-roots platform-trust.pem \
--policy-timestamp-servers platform-trust.pem \
--policy-emails "$POLICY_SIGNER_EMAIL" \
--policy-fulcio-oidc-issuer "$POLICY_ISSUER" --format json
Expected: a nonzero verification result identifying the recovery rule's denial. Keep stderr visible. A failure due to the wrong file or trust configuration does not demonstrate that this rule worked.
Troubleshooting and next steps
If both results pass, inspect the actual signed policy and confirm the rule is attached to the command-run attestation. If both fail, first check identity, expiry, roots, step names, and subject binding. Keep the signed policy and both evidence records for review. Offline verification of these files does not establish that every appliance feature works without network access.