Skip to main content
RunBook Academy

Git, CI/CD & GitOpsFinal · Final AssessmentFinal Review

Auditability and compliance — recap

Advanced⏱ ~28 mingit

What you'll learn

  • Trace the audit chain from a commit hash through a pipeline run, an artifact, and a deployment to a running workload
  • Identify the deployment receipt fields and explain why each one is needed to reconstruct an incident six months later
  • Apply segregation of duties in the pipeline: the engineer who writes the change is not the engineer who approves it, and the system that approves it is not the system that executes it
  • Run the reconstructability test on your own system and identify which links in the chain are currently broken

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

An auditor’s question is “what is running in production, why is it running, who approved it, and which build produced it?” A defensible answer is a chain of attestations that connects a running workload back to a signed commit, a pull request, a reviewer, a CI run, a signed artifact, and a deploy identity. A non-defensible answer is one where any link is broken or unrecoverable. The cost of the chain is small when it is built into the pipeline; the cost of reconstructing the chain after the fact is the entire incident.

The audit chain

flowchart LR
    A["Commit\n(signed)"] --> B["Pull request\n(reviewer, rationale)"]
    B --> C["CI run\n(workflow, logs, status)"]
    C --> D["Signed artifact\n(SBOM, provenance)"]
    D --> E["Deploy identity\n(OIDC token, target)"]
    E --> F["Running workload\n(cluster, namespace, replicas)"]
    F -->|"reverse lookup"| E
    E -->|"reverse lookup"| D
    D -->|"reverse lookup"| C
    C -->|"reverse lookup"| B
    B -->|"reverse lookup"| A

Each link is a query the auditor should be able to run independently:

  • Commit. “Which commit introduced the change?” The answer is the SHA, the author, the timestamp, and the parent chain. Recoverable from git log for as long as the repository exists.
  • Pull request. “Which PR delivered the commit, and who reviewed it?” The answer is the PR number, the review comments, the approval record, and the merge commit. Recoverable from the forge API for as long as the forge retains it (or for as long as the audit log is streamed off-platform).
  • CI run. “Which CI run built the artifact?” The answer is the workflow file, the workflow run ID, the runner identity, the job logs, and the test results. Recoverable from the CI provider for the retention period.
  • Signed artifact. “Which bytes did the CI run produce, and what is in them?” The answer is the artifact digest, the cosign signature, the SBOM, and the provenance attestation. Recoverable from the registry for as long as the registry retains the artifact.
  • Deploy identity. “Which identity deployed the artifact to which target?” The answer is the OIDC token claim, the trust policy, the AWS role (or equivalent), and the target account/cluster. Recoverable from the cloud audit log for the retention period.
  • Running workload. “Where is the artifact running right now?” The answer is the cluster, the namespace, the replicas, and the digest pinned in the Deployment. Recoverable from the Kubernetes API for as long as the cluster exists.

The deployment receipt

The deployment receipt is the minimal set of fields that together answer the auditor’s question:

commit:        8a3f9d2c1b...
pull_request:  #4527
reviewers:     alice, bob
ci_run:        github.com/org/repo/actions/runs/12345678
artifact:      myorg/api@sha256:abc...
sbom:          myorg/api@sha256:abc....sbom
provenance:    myorg/api@sha256:abc....att
deploy_id:     arn:aws:iam::role/prod-deploy@prod.us-east-1
deployer:      github-actions-oidc@org/repo/.github/workflows/deploy.yml@refs/tags/v3.4.7
target:        arn:aws:eks:us-east-1:111111111111:cluster/prod
namespace:     api-prod
replicas:      6
timestamp:     2026-08-22T14:23:17Z

Every field is a query the auditor can re-run six months later. Missing fields are gaps in the chain: no sbom means no vulnerability answer; no reviewers means no segregation of duties; no deployer means no identity answer.

Segregation of duties in the pipeline

The compliance principle of segregation of duties maps to a CI/CD pipeline as follows:

  • The engineer who writes the change is not the engineer who approves the change. Required reviewers from CODEOWNERS, branch protection requirements, and the protected-environment approval list enforce this.
  • The system that approves the change is not the system that executes the change. Approval lives in the forge (reviewers, required status checks); execution lives in the runner (the workflow job). A single system that both approves and executes is a single system an attacker can compromise to do both.
  • The identity that executes the change is not a long-lived identity. OIDC federation produces a short-lived, job-scoped credential; the credential expires the moment the job ends.
flowchart LR
    A["Engineer\n(writes)"] -->|PR| B["Reviewer\n(approves)"]
    B -->|merge| C["Runner\n(executes)"]
    C -->|OIDC| D["Target\n(receives)"]
    style A fill:#ffd
    style B fill:#ffd
    style C fill:#ffd
    style D fill:#ffd

The four roles are independent: engineer, reviewer, runner, target. A compromise of one does not automatically compromise the others.

Production discipline

The five rules that recur across every audit and compliance review:

  1. The chain is built forward, queried backward. Every link in the chain is generated as part of the normal workflow; the auditor walks it backward from the workload to the commit.
  2. The receipt is a record, not a report. A report is generated on demand; a record is generated automatically as part of the deploy and stored alongside the audit log.
  3. Segregation of duties is structural, not procedural. A CODEOWNERS rule, a required-reviewer branch protection, and a separate runner fleet are structural controls. A team agreement to “always get a second pair of eyes” is not.
  4. OIDC first, long-lived keys last. The deploy identity is a short-lived OIDC token; the long-lived credentials are reserved for the cases where OIDC is not available.
  5. The reconstructability test is run quarterly. The test produces a list of broken links, which is a list of remediation work for the next quarter. The test is not optional and the result is not allowed to be “we’ll get to it”.

Cross-course references

  • Terraform for Production Sysadmins — Terraform state and the change record together form the audit trail for infrastructure changes; the same shape applies to a Kubernetes manifest change.
  • Linux for Production Sysadminsauditd and the system journal are the operating-system-level analogues of the CI/CD audit log; the retention discipline is the same.

Quiz

Knowledge check · 4 questions

  1. Q1. Six months after a production incident, an auditor asks: 'Which CI run produced the artifact currently running in production pod X?' Which chain of reverse lookups answers the question?

  2. Q2. The reconstructability test should be run quarterly, and any field in the deployment receipt that cannot be produced within an hour is a broken link in the audit chain.

  3. Q3. Name the four roles in a CI/CD pipeline that segregation of duties requires to be independent, and the one structural control that enforces each role separation.

  4. Q4. An auditor asks the team to produce the deployment receipt for every production deploy in the last six months. The team has Git history, CI logs, and a registry, but no automated receipt. Walk through the work required to produce the receipts and the changes needed so the next audit is not a project.

    Production has 6 deploys per week on average for the last six months: roughly 150 deploys. The team has Git history (signed commits, merged PRs), GitHub Actions logs (workflow run IDs), and a GHCR registry with image tags and digests. There is no deployment-receipt database; there is no link between a `Deployment` in the cluster and a specific workflow run; cosign signing is enabled but the signatures are not stored alongside any external record.

Passing score: 75%. Answers are checked in this browser.