Documentation
Atlas — Release & Customer Mirror Pipeline
Project-Agent-trust-merge / atlas/RELEASING.md
This is how an Atlas image goes from ARX engineering to live in the customer's cluster, with a verifiable signature chain at every step. The pipeline is the technical enforcement of Atlas's three trust guarantees.
For the customer-facing trust artifact, see docs/atlas/atlas-spec.md. For the chart-level install instructions, see atlas/charts/atlas/README.md.
---
Pipeline at a glance
`` ┌──────────────────────────────────────────────────────────────────────┐ │ 1. ARX engineering tags atlas/v1.0.0 │ │ 2. GitHub Actions builds the image │ │ 3. cosign keyless signs it (Sigstore + GHCR transparency log) │ │ 4. SBOM (SPDX) attached + signed │ │ 5. Image published to ghcr.io/gethammerpath/atlas │ │ │ │ ─────────── handoff: customer's ops team ─────────── │ │ │ │ 6. Customer's auditor verifies the cosign signature │ │ 7. Customer's CI mirrors the verified digest to private registry │ │ 8. Customer pins the digest in values.customer.yaml │ │ 9. Customer runs helm install — chart refuses ghcr.io repository │ │ │ │ ─────────── deployed: customer-private cluster ────── │ │ │ │ 10. NetworkPolicy enforces egress lock │ │ 11. Atlas serves the CEO. ARX has zero visibility. │ └──────────────────────────────────────────────────────────────────────┘ ``
---
ARX-side release (steps 1–5)
Cut a release
```bash
1. Bump versions in atlas/__init__.py + atlas/charts/atlas/Chart.yaml
$EDITOR atlas/__init__.py atlas/charts/atlas/Chart.yaml
2. Tag the release
git tag atlas/v1.0.0 git push origin atlas/v1.0.0 ```
The tag push triggers .github/workflows/atlas-release.yml. The workflow:
- Builds the image from
atlas/Dockerfile(multi-stage, non-root,
pinned base).
- Pushes to
ghcr.io/${owner}/atlas:1.0.0and:latest. - Signs with cosign keyless — uses the GitHub OIDC token
(id-token: write permission) to mint an ephemeral cert; the signature lands in the public Sigstore transparency log.
- Generates an SPDX SBOM with anchore/sbom-action.
- Attests the SBOM via
cosign attest --type spdxjsonso the
SBOM is tied to the same image digest.
The workflow's job summary prints:
- The image reference + digest
- The exact
cosign verifycommand for the customer - The mirror commands for the customer's CI
- The values.customer.yaml snippet
---
Customer-side mirror (steps 6–9)
Step 6: Verify the signature
The customer's auditor runs this on their infrastructure, not ARX's. The verification reaches Sigstore's public transparency log — no ARX endpoint involved.
``bash cosign verify \ ghcr.io/gethammerpath/atlas@sha256:... \ --certificate-identity-regexp 'https://github.com/gethammerpath/.*' \ --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' ``
Expected output: a JSON document with the cert chain, the SCT, and the build provenance. If verification fails, stop the pipeline. The customer's auditor logs the verification result in their own audit chain.
Verify the SBOM attestation:
``bash cosign verify-attestation \ --type spdxjson \ ghcr.io/gethammerpath/atlas@sha256:... \ --certificate-identity-regexp 'https://github.com/gethammerpath/.*' \ --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \ | jq -r '.payload' | base64 -d | jq '.predicate' > atlas-sbom.spdx.json ``
The customer's security team scans the SBOM with their own tooling (Snyk, Trivy, etc.) before approving the mirror.
Step 7: Mirror to private registry
```bash DIGEST="sha256:..." SRC="ghcr.io/gethammerpath/atlas@${DIGEST}" DST="registry.cisco.example/arxsec/atlas:1.0.0"
docker pull "$SRC" docker tag "$SRC" "$DST" docker push "$DST" ```
The customer's CI does this once per release. The customer's private registry is the only source the Helm chart will accept — see atlas.validateImage helper in atlas/charts/atlas/templates/_helpers.tpl.
Step 8: Pin the digest
In values.customer.yaml:
``yaml image: repository: registry.cisco.example/arxsec/atlas tag: "1.0.0" digest: "sha256:..." # the same digest verified in step 6 ``
Pinning the digest means the customer's deploy is byte-for-byte identical to what ARX engineering signed. Tag drift can't change the artifact.
Step 9: Helm install
``bash helm upgrade --install atlas ./atlas/charts/atlas \ -n arx-atlas --create-namespace \ -f values.customer.yaml ``
The chart's atlas.validateImage helper rejects any image.repository containing arxsec.io, arx.sec, or ghcr.io/arxsec — the customer can't accidentally point at the public registry.
---
Customer-side runtime (steps 10–11)
Step 10: NetworkPolicy enforces egress lock
The chart installs a NetworkPolicy that:
- Default-denies egress
- Allows DNS to cluster CoreDNS
- Allows egress only to customer-declared
allowedEndpoints
The customer's auditor verifies live:
``bash kubectl -n arx-atlas get networkpolicy atlas-atlas-egress-lock -o yaml ``
ARX endpoints don't appear. Phase 6 / Workstream E will add the witness-signed audit chain — egress-capture log entries get hashed and chained, so post-hoc tampering is detectable.
Step 11: Atlas serves the CEO
Atlas runs entirely in the customer's cluster. Customer's SRE team owns the lifecycle. ARX has no read access to anything Atlas touches.
---
Rollback
The customer rolls back to a prior signed image with:
``bash helm rollback atlas <revision> -n arx-atlas ``
Helm preserves the prior values.customer.yaml at the revision, so the prior image.digest is restored. The customer's auditor re-verifies the prior digest's signature against the same Sigstore chain.
---
Threat model — what this pipeline protects against
| Threat | Mitigation | |---|---| | ARX engineer pushes a malicious image | Sigstore transparency log makes the push public; auditor sees the unexpected entry. | | Attacker MITM the customer's pull from ghcr.io | Cosign signature verification catches the tampering. | | Attacker tags an old vulnerable image as latest | Digest pinning in values.customer.yaml ignores tags. | | Insider replaces the image in the customer's private registry | Customer's own image-scan + admission controller catches drift; the deploy still pins the digest the auditor verified. | | ARX adds a "phone home" feature in a new version | Customer must explicitly verify each new release's SBOM; the new outbound endpoint would need the customer to add it to allowedEndpoints for the NetworkPolicy to permit it. |
---
What this pipeline does NOT cover
- The build environment itself —
ubuntu-latestGitHub-hosted
runner. Customers wanting full reproducibility set up their own builder (rebuild from source, verify the digest matches).
- ARX engineering's source code review — the pipeline only
signs what the build produces. Source review happens via PR + CODEOWNERS upstream.
- Customer's runtime patching — once Atlas is deployed, the
customer's normal vulnerability-management cycle applies. New releases follow the same pipeline.
---
Versioning
atlas/v1.0.0— initial release (this slice).- Patch (
v1.0.x): bug fixes, no API changes. Customer can
upgrade in place.
- Minor (
v1.x.0): new capabilities, additive only. Customer
reviews the SBOM diff + new allowedEndpoints if any.
- Major (
v2.0.0): breaking schema/API change. Customer reviews
the migration guide before pulling.