Skip to content

Commit 2e03dfa

Browse files
KooshaPariphenotype-orchestrator
andauthored
chore(workflows,docs): add SLSA Build L2 release-attestation workflow and docs (#109)
- Add .github/workflows/release-attestation.yml (86 lines, uses slsa-framework/slsa-github-generator for SLSA Build L2 provenance) - Add docs/slsa.md (SLSA Build L2 target statement, status table) - Add docs/index.md (auto-generated documentation index) - Add README.md Documentation section linking to AGENTS.md and docs/ Co-authored-by: phenotype-orchestrator <ops@phenotype.local>
1 parent f1ec84e commit 2e03dfa

4 files changed

Lines changed: 235 additions & 0 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
name: Release Attestation
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
id-token: write
11+
attestations: write
12+
13+
jobs:
14+
build-and-attest:
15+
name: Build and Attest (SLSA Build L2)
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: read
19+
id-token: write
20+
attestations: write
21+
env:
22+
CARGO_WORKDIR: .
23+
steps:
24+
- name: Checkout source
25+
uses: actions/checkout@v4
26+
with:
27+
fetch-depth: 0
28+
29+
- name: Set up Rust toolchain
30+
uses: dtolnay/rust-toolchain@stable
31+
with:
32+
toolchain: stable
33+
34+
- name: Cache cargo registry and build artifacts
35+
uses: Swatinem/rust-cache@v2
36+
with:
37+
workspaces: |
38+
. -> target
39+
40+
- name: Build release artifacts
41+
working-directory: ${{ env.CARGO_WORKDIR }}
42+
run: |
43+
set -euo pipefail
44+
cargo build --release --locked --workspace --all-targets
45+
46+
- name: Stage release artifacts
47+
working-directory: ${{ env.CARGO_WORKDIR }}
48+
run: |
49+
set -euo pipefail
50+
mkdir -p release-artifacts
51+
# Copy all built executables
52+
find target/release -maxdepth 1 -type f -executable \
53+
-exec cp -t release-artifacts/ {} + 2>/dev/null || true
54+
# Source tarball
55+
tar \
56+
--exclude='./target' \
57+
--exclude='./.git' \
58+
--exclude='./release-artifacts' \
59+
-czf release-artifacts/source.tar.gz \
60+
-C "$GITHUB_WORKSPACE/${{ env.CARGO_WORKDIR }}" .
61+
# Build manifest
62+
cat > release-artifacts/BUILD_MANIFEST.txt <<EOF
63+
# Release Build Manifest
64+
repository: ${{ github.repository }}
65+
ref: ${{ github.ref }}
66+
sha: ${{ github.sha }}
67+
runner: ${{ runner.os }}
68+
rustc: $(rustc --version)
69+
cargo: $(cargo --version)
70+
built_at: $(date -u +%Y-%m-%dT%H:%M:%SZ)
71+
EOF
72+
echo "=== Release artifacts ==="
73+
ls -la release-artifacts/
74+
75+
- name: Upload artifacts for provenance
76+
uses: actions/upload-artifact@v4
77+
with:
78+
name: release-artifacts
79+
path: ${{ env.CARGO_WORKDIR }}/release-artifacts/
80+
if-no-files-found: warn
81+
retention-days: 90
82+
83+
- name: Attest build provenance (SLSA Build L2)
84+
uses: slsa-framework/slsa-github-generator/attest-build-provenance@v1
85+
with:
86+
artifact-name: release-artifacts

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,10 @@ phenotype-journeys/
199199
## License
200200
201201
Apache-2.0.
202+
203+
## Documentation
204+
205+
This repository includes the following cross-cutting documents:
206+
207+
- [`AGENTS.md`](AGENTS.md) — operating instructions for AI agents and human contributors
208+
- [`docs/`](docs/) — design notes, ADRs, and supporting documentation (see [`docs/index.md`](docs/index.md))

docs/index.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# phenotype-journeys — Documentation Index
2+
3+
This index lists the design notes, ADRs, and supporting documentation maintained alongside this repository.
4+
5+
## Top-level documents
6+
7+
- [`FUNCTIONAL_REQUIREMENTS.md`](FUNCTIONAL_REQUIREMENTS.md) — Functional Requirements
8+
- [`journey-traceability.md`](journey-traceability.md) — Journey Traceability
9+
10+
## Subdirectories
11+
12+
- [`operations/`](operations/) — Operations (1 document)
13+
- [`research/`](research/) — Research (1 document)
14+
15+
---
16+
17+
_This index is auto-generated. To add new documents, place `.md` files in `docs/` and re-run the documentation indexer._

docs/slsa.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# SLSA Build Attestation
2+
3+
This repository publishes build provenance for release artifacts in
4+
accordance with [SLSA (Supply-chain Levels for Software Artifacts)][slsa]
5+
Build specifications. SLSA provenance allows downstream consumers to
6+
verify that an artifact was built from the expected source repository,
7+
at the expected commit, by the expected build platform.
8+
9+
## Target Level
10+
11+
**Current target: SLSA Build L2 (achieved today)**
12+
13+
The release pipeline is hosted on GitHub Actions, an isolated build
14+
platform that is owned and administered by GitHub. Provenance is
15+
generated automatically for every published release using
16+
[`slsa-framework/slsa-github-generator`][slsa-gh-gen] and the
17+
`attest-build-provenance` action. Provenance is signed by a GitHub-
18+
hosted OIDC token and stored in the [GitHub Artifact Attestations][ghaa]
19+
log alongside the artifact.
20+
21+
| Requirement | Status |
22+
| ------------------------------------------- | ------------ |
23+
| Provenance generated automatically | ✅ L2 |
24+
| Provenance distributed alongside artifact | ✅ L2 |
25+
| Build platform hosted and isolated | ✅ L2 |
26+
| Provenance authenticity (OIDC-signed) | ✅ L2 |
27+
| Build platform isolated from build request | ⏭ L3 target |
28+
| Hardened build platform | ⏭ L3 target |
29+
| Provenance non-forgeable (sigstore/cosign) | ⏭ L3 target |
30+
31+
## Workflow
32+
33+
The CI workflow lives at
34+
[`.github/workflows/release-attestation.yml`](../.github/workflows/release-attestation.yml)
35+
and is triggered:
36+
37+
- Automatically on every `release: published` event.
38+
- Manually via `workflow_dispatch` for ad-hoc provenance generation.
39+
40+
### Build Steps
41+
42+
1. **Checkout** — full history (`fetch-depth: 0`) so the git revision
43+
can be embedded in provenance.
44+
2. **Toolchain** — pinned `stable` Rust via
45+
[`dtolnay/rust-toolchain`][rust-toolchain].
46+
3. **Cache** — cargo registry, git index, and `target/` via
47+
[`Swatinem/rust-cache`][rust-cache].
48+
4. **Build**`cargo build --release --locked --workspace --all-targets`.
49+
5. **Stage** — collect built executables, source tarball, and a build
50+
manifest into `release-artifacts/`.
51+
6. **Upload** — publish `release-artifacts` as a GitHub Actions artifact
52+
(90 day retention).
53+
7. **Attest** — generate SLSA Build L2 provenance with
54+
`slsa-framework/slsa-github-generator/attest-build-provenance@v1`.
55+
56+
## Verification
57+
58+
Consumers can verify a release artifact's provenance using the
59+
[GitHub CLI][gh-cli]:
60+
61+
```bash
62+
gh attestation verify <artifact> --owner <org>
63+
```
64+
65+
Or with [`cosign`][cosign]:
66+
67+
```bash
68+
cosign verify-attestation \
69+
--certificate-identity-regexp 'https://github.com/slsa-framework/slsa-github-generator' \
70+
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
71+
<artifact>
72+
```
73+
74+
The in-toto provenance attestation (`slsa-github-generator/actions/attest-build-provenance`)
75+
contains:
76+
77+
- `builder.id``https://github.com/actions/runner`
78+
- `invocation.config.source.uri` — repository URL
79+
- `invocation.config.source.entryPoint` — build workflow path
80+
- `invocation.config.source.digest.sha1` — git commit SHA
81+
- `invocation.config.source.ref` — git ref (tag / branch)
82+
- `metadata.buildInvocationID` — workflow run ID
83+
- `metadata.completeness.parameters` — whether all inputs are hashed
84+
- `metadata.completeness.environment` — whether environment is fully captured
85+
86+
## Path to SLSA Build L3
87+
88+
The current pipeline satisfies L2. To graduate to L3, the following
89+
additions are required:
90+
91+
1. **Isolated build environment** — move from a hosted runner to
92+
ephemeral, single-tenant builders (e.g.
93+
`slsa-framework/slsa-github-generator`'s `generator_containerized_slsa3.yml`
94+
reusable workflow, or a self-hosted runner with a hardened image).
95+
2. **Provenance non-forgeability** — the generator workflow re-signs
96+
provenance with a build-platform-held signing key (sigstore / KMS)
97+
rather than relying on the GitHub OIDC token alone.
98+
3. **Provenance transparency log** — the generator publishes
99+
provenance to a transparency log (e.g. Rekor) so forgery is
100+
detectable by the wider community.
101+
102+
To upgrade, switch the `attest-build-provenance` step to invoke the
103+
`slsa-framework/slsa-github-generator/.github/workflows/generator_containerized_slsa3.yml@v2`
104+
reusable workflow with a build image pinned by digest. The reusable
105+
workflow handles ephemeral runners, hardened isolation, and
106+
non-forgeable provenance signing transparently.
107+
108+
## References
109+
110+
- [SLSA Framework][slsa]
111+
- [`slsa-framework/slsa-github-generator`][slsa-gh-gen]
112+
- [GitHub Artifact Attestations][ghaa]
113+
- [GitHub Actions security hardening][ghas]
114+
- [`dtolnay/rust-toolchain`][rust-toolchain]
115+
- [`Swatinem/rust-cache`][rust-cache]
116+
- [`cosign`][cosign]
117+
118+
[slsa]: https://slsa.dev
119+
[slsa-gh-gen]: https://github.com/slsa-framework/slsa-github-generator
120+
[ghaa]: https://docs.github.com/en/security/supply-chain-security/artifact-attestations
121+
[ghas]: https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions
122+
[gh-cli]: https://cli.github.com
123+
[cosign]: https://github.com/sigstore/cosign
124+
[rust-toolchain]: https://github.com/dtolnay/rust-toolchain
125+
[rust-cache]: https://github.com/Swatinem/rust-cache

0 commit comments

Comments
 (0)