Skip to content

Commit 8e2d502

Browse files
committed
Add SLSA provenance attestations
1 parent cbf9042 commit 8e2d502

2 files changed

Lines changed: 158 additions & 26 deletions

File tree

.github/workflows/build.yml

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ jobs:
141141
build/dfetch-package/*.msi
142142
predicate-type: 'https://cyclonedx.org/bom'
143143
predicate-path: ${{ steps.find-sbom.outputs.path }}
144-
- name: Verify attestation
144+
- name: Verify SBOM attestation
145145
shell: bash
146146
env:
147147
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -154,6 +154,27 @@ jobs:
154154
--cert-identity "https://github.com/${{ github.repository }}/.github/workflows/build.yml@${{ github.ref }}" \
155155
--cert-oidc-issuer https://token.actions.githubusercontent.com
156156
done
157+
- name: Attest build provenance
158+
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
159+
with:
160+
subject-path: |
161+
build/dfetch-package/*.deb
162+
build/dfetch-package/*.rpm
163+
build/dfetch-package/*.pkg
164+
build/dfetch-package/*.msi
165+
- name: Verify build provenance
166+
shell: bash
167+
env:
168+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
169+
run: |
170+
for f in build/dfetch-package/*.deb build/dfetch-package/*.rpm build/dfetch-package/*.pkg build/dfetch-package/*.msi; do
171+
[ -f "$f" ] || continue
172+
gh attestation verify "$f" \
173+
--repo "${{ github.repository }}" \
174+
--predicate-type https://slsa.dev/provenance/v1 \
175+
--cert-identity "https://github.com/${{ github.repository }}/.github/workflows/build.yml@${{ github.ref }}" \
176+
--cert-oidc-issuer https://token.actions.githubusercontent.com
177+
done
157178
- name: Store the distribution packages
158179
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
159180
with:
@@ -258,6 +279,10 @@ jobs:
258279
build-whl:
259280
name: Build wheel 📦
260281
runs-on: ubuntu-latest
282+
permissions:
283+
contents: read
284+
attestations: write
285+
id-token: write
261286

262287
steps:
263288
- name: "Harden the runner (Block egress traffic: Only allow calls to allowed endpoints)"
@@ -270,6 +295,10 @@ jobs:
270295
release-assets.githubusercontent.com:443
271296
pypi.org:443
272297
files.pythonhosted.org:443
298+
fulcio.sigstore.dev:443
299+
rekor.sigstore.dev:443
300+
tuf-repo-cdn.sigstore.dev:443
301+
*.blob.core.windows.net:443
273302
274303
275304
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -287,6 +316,52 @@ jobs:
287316
run: python3 -m build
288317
- name: Generate SBOM for Python distribution
289318
run: python script/create_sbom.py --py
319+
- name: Find Python SBOM path
320+
id: find-sbom
321+
shell: bash
322+
run: |
323+
SBOM=$(find dist -name '*.cdx.json' -maxdepth 1 | head -1)
324+
echo "path=$SBOM" >> "$GITHUB_OUTPUT"
325+
- name: Attest Python packages with SBOM
326+
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
327+
with:
328+
subject-path: |
329+
dist/*.whl
330+
dist/*.tar.gz
331+
predicate-type: 'https://cyclonedx.org/bom'
332+
predicate-path: ${{ steps.find-sbom.outputs.path }}
333+
- name: Verify Python SBOM attestation
334+
shell: bash
335+
env:
336+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
337+
run: |
338+
for f in dist/*.whl dist/*.tar.gz; do
339+
[ -f "$f" ] || continue
340+
gh attestation verify "$f" \
341+
--repo "${{ github.repository }}" \
342+
--predicate-type https://cyclonedx.org/bom \
343+
--cert-identity "https://github.com/${{ github.repository }}/.github/workflows/build.yml@${{ github.ref }}" \
344+
--cert-oidc-issuer https://token.actions.githubusercontent.com
345+
done
346+
- name: Attest Python build provenance
347+
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
348+
with:
349+
subject-path: |
350+
dist/*.whl
351+
dist/*.tar.gz
352+
- name: Verify Python build provenance
353+
shell: bash
354+
env:
355+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
356+
run: |
357+
for f in dist/*.whl dist/*.tar.gz; do
358+
[ -f "$f" ] || continue
359+
gh attestation verify "$f" \
360+
--repo "${{ github.repository }}" \
361+
--predicate-type https://slsa.dev/provenance/v1 \
362+
--cert-identity "https://github.com/${{ github.repository }}/.github/workflows/build.yml@${{ github.ref }}" \
363+
--cert-oidc-issuer https://token.actions.githubusercontent.com
364+
done
290365
- name: Store the distribution packages
291366
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
292367
with:

doc/tutorials/installation.rst

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -91,63 +91,120 @@ Run the following command to verify the installation
9191
Verifying release integrity
9292
---------------------------
9393

94-
Every dfetch release is signed with SLSA provenance attestations. To verify an installed package, use the `GitHub CLI <https://cli.github.com/>`_:
94+
Every dfetch release carries cryptographic attestations signed by GitHub Actions
95+
and anchored in `Sigstore <https://www.sigstore.dev/>`_. There are two
96+
complementary kinds:
97+
98+
- **SLSA build provenance** — answers *"where did this come from?"*: proves the
99+
artifact was produced from the official source commit by the official CI
100+
workflow, and records the exact inputs used at build time.
101+
- **SBOM attestation** (CycloneDX) — answers *"what is inside it?"*: lists every
102+
dependency bundled in the package so you can audit its composition.
103+
104+
Binary installers carry **both** kinds of attestation (signed by ``build.yml``).
105+
Python packages installed from PyPI carry an **SBOM attestation only** (signed by
106+
``python-publish.yml``).
107+
108+
To verify, use the `GitHub CLI <https://cli.github.com/>`_. Pass
109+
``--predicate-type`` to target one kind specifically; omit it to accept either.
95110

96111
.. tabs::
97112

98113
.. tab:: Linux
99114

100-
**For pip installations:**
115+
**Binary installer — verify build provenance:**
116+
117+
.. code-block:: bash
118+
119+
$ gh attestation verify dfetch-<version>-nix.deb \
120+
--repo dfetch-org/dfetch \
121+
--predicate-type https://slsa.dev/provenance/v1 \
122+
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/build.yml@refs/tags/v<version> \
123+
--cert-oidc-issuer https://token.actions.githubusercontent.com
124+
125+
**Binary installer — verify SBOM attestation:**
101126

102127
.. code-block:: bash
103128
104-
$ gh attestation verify --cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/python-publish.yml@refs/tags/v<version> \
105-
--cert-oidc-issuer https://token.actions.githubusercontent.com \
106-
~/.local/lib/python3.x/site-packages/dfetch-<version>.dist-info/
129+
$ gh attestation verify dfetch-<version>-nix.deb \
130+
--repo dfetch-org/dfetch \
131+
--predicate-type https://cyclonedx.org/bom \
132+
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/build.yml@refs/tags/v<version> \
133+
--cert-oidc-issuer https://token.actions.githubusercontent.com
107134
108-
**For binary installers:**
135+
**pip / PyPI wheel — verify SBOM attestation:**
109136

110137
.. code-block:: bash
111138
112-
$ gh attestation verify --cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/build.yml@refs/tags/v<version> \
113-
--cert-oidc-issuer https://token.actions.githubusercontent.com \
114-
dfetch-<version>-nix.deb
139+
$ gh attestation verify ~/.local/lib/python3.x/site-packages/dfetch-<version>.dist-info/ \
140+
--repo dfetch-org/dfetch \
141+
--predicate-type https://cyclonedx.org/bom \
142+
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/python-publish.yml@refs/tags/v<version> \
143+
--cert-oidc-issuer https://token.actions.githubusercontent.com
115144
116145
.. tab:: macOS
117146

118-
**For pip installations:**
147+
**Binary installer — verify build provenance:**
119148

120149
.. code-block:: bash
121150
122-
$ gh attestation verify --cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/python-publish.yml@refs/tags/v<version> \
123-
--cert-oidc-issuer https://token.actions.githubusercontent.com \
124-
/usr/local/lib/python3.x/site-packages/dfetch-<version>.dist-info/
151+
$ gh attestation verify dfetch-<version>-osx.pkg \
152+
--repo dfetch-org/dfetch \
153+
--predicate-type https://slsa.dev/provenance/v1 \
154+
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/build.yml@refs/tags/v<version> \
155+
--cert-oidc-issuer https://token.actions.githubusercontent.com
125156
126-
**For binary installers:**
157+
**Binary installer — verify SBOM attestation:**
127158

128159
.. code-block:: bash
129160
130-
$ gh attestation verify --cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/build.yml@refs/tags/v<version> \
131-
--cert-oidc-issuer https://token.actions.githubusercontent.com \
132-
dfetch-<version>-osx.pkg
161+
$ gh attestation verify dfetch-<version>-osx.pkg \
162+
--repo dfetch-org/dfetch \
163+
--predicate-type https://cyclonedx.org/bom \
164+
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/build.yml@refs/tags/v<version> \
165+
--cert-oidc-issuer https://token.actions.githubusercontent.com
166+
167+
**pip / PyPI wheel — verify SBOM attestation:**
168+
169+
.. code-block:: bash
170+
171+
$ gh attestation verify /usr/local/lib/python3.x/site-packages/dfetch-<version>.dist-info/ \
172+
--repo dfetch-org/dfetch \
173+
--predicate-type https://cyclonedx.org/bom \
174+
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/python-publish.yml@refs/tags/v<version> \
175+
--cert-oidc-issuer https://token.actions.githubusercontent.com
133176
134177
.. tab:: Windows
135178

136-
**For pip installations:**
179+
**Binary installer — verify build provenance:**
180+
181+
.. code-block:: powershell
182+
183+
> gh attestation verify dfetch-<version>-win.msi `
184+
--repo dfetch-org/dfetch `
185+
--predicate-type https://slsa.dev/provenance/v1 `
186+
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/build.yml@refs/tags/v<version> `
187+
--cert-oidc-issuer https://token.actions.githubusercontent.com
188+
189+
**Binary installer — verify SBOM attestation:**
137190

138191
.. code-block:: powershell
139192
140-
> gh attestation verify --cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/python-publish.yml@refs/tags/v<version> `
141-
--cert-oidc-issuer https://token.actions.githubusercontent.com `
142-
$env:APPDATA\Python\Python3x\site-packages\dfetch-<version>.dist-info\
193+
> gh attestation verify dfetch-<version>-win.msi `
194+
--repo dfetch-org/dfetch `
195+
--predicate-type https://cyclonedx.org/bom `
196+
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/build.yml@refs/tags/v<version> `
197+
--cert-oidc-issuer https://token.actions.githubusercontent.com
143198
144-
**For binary installers:**
199+
**pip / PyPI wheel — verify SBOM attestation:**
145200

146201
.. code-block:: powershell
147202
148-
> gh attestation verify --cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/build.yml@refs/tags/v<version> `
149-
--cert-oidc-issuer https://token.actions.githubusercontent.com `
150-
dfetch-<version>-win.msi
203+
> gh attestation verify $env:APPDATA\Python\Python3x\site-packages\dfetch-<version>.dist-info\ `
204+
--repo dfetch-org/dfetch `
205+
--predicate-type https://cyclonedx.org/bom `
206+
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/python-publish.yml@refs/tags/v<version> `
207+
--cert-oidc-issuer https://token.actions.githubusercontent.com
151208
152209
See `GitHub artifact attestations`_ for details.
153210

0 commit comments

Comments
 (0)