Skip to content

Production route attestation

This runbook is for platform and security engineers who enable the production safe-sample runtime and its automatic beginner facade. Pipeline authors do not edit these files and the five-command beginner journey does not gain another step.

The production contract is simple: a route name is metadata, not authority. Runtime starts only after dpone verifies an externally signed authorization whose route, certification, release, deployment, environment, runtime image, signer, and validity all match the workload that is about to run.

flowchart LR
    CERT["Certified route bundle"] --> BUILD["dpone build attestation"]
    DEP["Pinned deployment-set"] --> BUILD
    BUILD --> SIGN["External CI: cosign sign-blob"]
    SIGN --> VERIFY["dpone verify exact local bytes"]
    POLICY["Pinned policy and trusted root"] --> VERIFY
    VERIFY -->|verified| RUN["Safe-sample runtime"]
    VERIFY -->|invalid or unverified| STOP["Fail closed before credentials and data I/O"]

Files and ownership

File Owner Rule
route_certification_bundle.json route certification CI Must be vendor_live, passed, and certified for production
deployment.json deployment CI Must be a runnable immutable deployment
route-attestation.json deployment CI Deterministic, create-only unsigned blob
route-attestation.sigstore.json external signer Sigstore bundle over the exact attestation bytes
route-attestation-policy.json platform/security Exact signer, trust-root digest, profiles, bounds, and revocations
trusted_root.json platform/security Local pinned Sigstore trust material
route-attestation-verification.json verifier Create-only safe receipt; never contains secrets or verifier output

Do not put private keys, OIDC tokens, Vault tokens, passwords, signed download URLs, registry bodies, or secret values in any of these files.

Prerequisites

  • Use cosign >=3.0.4,<4.0.0. Older or unknown versions fail closed.
  • Materialize all verification inputs before the workload starts.
  • Give the runtime read-only access to the exact files it needs.
  • Keep verification directories platform-owned. dpone additionally rejects parent/final symlinks, .. traversal, and parent/file inode swaps while reading or publishing trust evidence.
  • Deny verifier network egress in production. Trust-root refresh is a separate reviewed deployment action.
  • Keep the attestation lifetime bounded and synchronize runtime clocks.
  • Retain the referenced route-certification and deployment artifacts for audit.

1. Write the policy

The certificate identity and issuer are exact strings, not regular expressions. The trusted-root path may be relative to the policy file.

schema: dpone.route-attestation-policy.v1
backend: cosign_keyless_v1
certificate_identity: https://github.com/PaulKov/dpone/.github/workflows/route-attestation.yml@refs/heads/master
certificate_oidc_issuer: https://token.actions.githubusercontent.com
trusted_root:
  path: trusted_root.json
  sha256: sha256:REPLACE_WITH_EXACT_ROOT_DIGEST
cosign:
  minimum_version: 3.0.4
  maximum_version_exclusive: 4.0.0
  timeout_seconds: 30
allowed_environments: [production]
allowed_authorization_profiles: [safe_sample_production]
allowed_certification_profiles: [vendor_live]
minimum_certification_level: certified
max_validity_seconds: 86400
clock_skew_seconds: 300
revoked_attestation_ids: []
revoked_certificate_identities: []

Changing this policy changes its fingerprint. Revocation is local and fail-closed: publish a new immutable policy snapshot and restart/retry the workload so it verifies the new snapshot.

2. Build the unsigned blob

Use explicit timestamps so CI inputs are reviewable and reproducible.

dpone ops route-attestation-build \
  --route-id mssql_clickhouse_incremental_merge_airflow_kpo \
  --route-certification-bundle route_certification_bundle.json \
  --deployment-set deployment.json \
  --authorization-profile safe_sample_production \
  --issued-at 2026-07-15T10:00:00Z \
  --not-before 2026-07-15T10:00:00Z \
  --expires-at 2026-07-16T10:00:00Z \
  --output route-attestation.json \
  --format json

The command refuses to replace an existing output. The attestation_id is the canonical fingerprint of claims only; volatile build metadata is not part of identity. The external signature covers the complete emitted file bytes.

3. Sign outside dpone

Run signing in the approved identity-bearing CI workflow. dpone does not sign and does not receive private key material.

cosign sign-blob --yes \
  --bundle route-attestation.sigstore.json \
  route-attestation.json

Publish the attestation and Sigstore bundle together by digest. Never edit the attestation after signing.

4. Run credential-free preflight

dpone ops route-attestation-verify \
  --attestation route-attestation.json \
  --sigstore-bundle route-attestation.sigstore.json \
  --route-certification-bundle route_certification_bundle.json \
  --policy route-attestation-policy.json \
  --deployment-set deployment.json \
  --output-dir .dpone/route-attestation-verification \
  --format json

Exit 0 means verified. Malformed platform input uses exit 2. Cryptographically invalid, expired, revoked, mismatched, unsupported, or unavailable trust uses exit 4. No state falls back to a route ID string.

5. Materialize the beginner authorization overlay

For the five-command facade, platform cache synchronization publishes all four route inputs beneath the exact deployment and pipeline identity:

.dpone-cache/route-authorizations/
  sha256-<deployment digest>/<pipeline_id>/
    route-attestation.json
    route-attestation.sigstore.json
    route-certification-bundle.json
    route-attestation-policy.json

Build this directory in a sibling staging path, verify the exact files there, then rename the complete directory into place. Never populate the final directory one file at a time. The reader treats absence as network-free local handoff, but treats an existing incomplete directory as DPONE_SAFE_SAMPLE_LIVE_INPUTS_INCOMPLETE and performs no credential or database I/O.

The final path is derived by dpone from the verified deployment context and canonical pipeline ID. It cannot contain current, come from a manifest, or be overridden by the beginner command. Parent/final symlinks, path escape, stale deployment subjects, invalid signatures, and policy mismatch all fail closed.

The environment files remain platform-owned at their existing locations:

environments/<environment>/binding-set.yaml
environments/<environment>/credential-runtime.yaml
platform/connection-registries/<environment>.yaml

Their canonical fingerprints must match the deployment. The authorization directory contains no credentials, registry body copy, Vault token, or signed download URL. With this layout complete, the normal user command automatically selects execution_mode=live_copy; no second command is needed.

The beginner report calls this layout authorization_overlay_profile: deployment_scoped_v1. That field identifies cache discovery only. It does not replace the signed attestation's authorization_profile: safe_sample_production and grants no authority by itself.

Field Owner Meaning Grants runtime authority
authorization_overlay_profile dpone cache discovery Version of the deployment-scoped local layout No
authorization_profile signed route attestation + security policy Permitted production use of the signed subject Only after full verification

Recover an incomplete overlay

  1. Stop publishing into the final directory.
  2. Verify all four files in a sibling staging directory with dpone ops route-attestation-verify.
  3. Replace the complete deployment/pipeline directory with one atomic rename; never copy a missing file into the active directory.
  4. Confirm ownership and read-only permissions, then ask the user to rerun the same fifth beginner command.
  5. If verification still fails, retain the failed inputs for audit and follow the error-specific action below. Do not remove a policy guard to make the sample pass.

6. Pass pinned files to an explicit runtime

This section is a platform/operator escape hatch. Do not send this command to a pipeline author as a sixth beginner step. These flags belong to the platform handoff, not to pipeline authoring:

dpone ops safe-sample-runtime-run \
  --plan-json /run/dpone/safe-sample-plan.json \
  --pipeline-source /run/dpone/pipeline.yaml \
  --enable-live-copy \
  --binding-set /run/dpone/binding-set.json \
  --connection-registry /run/dpone/connection-registry.json \
  --credential-runtime /run/dpone/credential-runtime.json \
  --route-attestation /run/dpone/route-attestation.json \
  --route-attestation-bundle /run/dpone/route-attestation.sigstore.json \
  --route-certification-bundle /run/dpone/route-certification-bundle.json \
  --route-attestation-policy /run/dpone/route-attestation-policy.json \
  --cache-root /run/dpone/cache \
  --output-dir /run/dpone/evidence \
  --format json

Runtime derives the expected route from the pinned pipeline and derives the release, deployment, environment, and image from the execution plan. It never uses those values from command context or author-written proof text. Only a verified receipt is converted to the existing internal capability signal.

Failure guide

Code family Meaning Action
DPONE_SAFE_SAMPLE_LIVE_INPUTS_INCOMPLETE Deployment overlay exists but is only partially materialized Re-sync the complete directory atomically
DPONE_SAFE_SAMPLE_LIVE_INPUT_PATH_INVALID Derived/local input path is unsafe or symlinked Remove it and restore from trusted platform CI
DPONE_INTERNAL_SAFE_SAMPLE_LIVE_ASSEMBLY_FAILED Unexpected internal assembly failure; exception text is redacted Preserve run context and inspect platform logs; do not bypass trust checks
DPONE_ROUTE_ATTESTATION_INPUT_* Missing, malformed, oversized, or unsafe local input Correct materialization; do not bypass
DPONE_ROUTE_ATTESTATION_POLICY_INVALID Policy is incomplete or outside supported bounds Publish a corrected immutable policy
DPONE_ROUTE_ATTESTATION_*_DIGEST_MISMATCH Exact bytes differ from signed/pinned identity Investigate drift and rebuild/re-sign
DPONE_ROUTE_ATTESTATION_SIGNATURE_INVALID Signature or exact signer identity failed Investigate signer or tampering
DPONE_ROUTE_ATTESTATION_SUBJECT_MISMATCH Proof belongs to another release/deployment/runtime Build a new attestation for this deployment
DPONE_ROUTE_ATTESTATION_EXPIRED Authorization lifetime ended Re-certify as needed and sign a fresh bounded attestation
DPONE_ROUTE_ATTESTATION_REVOKED Attestation or signer is denied by current policy Stop and follow the security incident process
DPONE_ROUTE_ATTESTATION_VERIFIER_* cosign is missing, timed out, or unsupported Repair the runtime image; result remains unverified
DPONE_ROUTE_ATTESTATION_TRUST_ROOT_UNAVAILABLE Local root bytes do not match the policy digest Restore approved trust material

Do not fix a digest mismatch by editing an immutable artifact. Build a new artifact, sign it through the approved workflow, and retain the old evidence.

Evidence and current certification status

Successful runtime evidence adds only safe verification metadata: decision, codes, attestation/certification/policy digests, route ID, release/deployment, exact signer identity, bounded validity, verifier version, and verification time. It excludes certificates, bundles, trust-root bytes, Vault paths, credentials, subprocess output, and sampled records.

Local contract tests cover the complete decision and injection boundaries. End-to-end Sigstore + Kubernetes + Vault + MSSQL + ClickHouse execution remains UNVERIFIED until an explicitly approved live environment runs this exact commit and stores its certification receipt. A skipped or mocked run is not a production pass.