Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ permissions:

jobs:
release:
# Any repository may call a public reusable workflow, and the certificate its run gets names
# this file at the ref it called - build-release.yml@refs/heads/main from someone else's
# workflow, over what that repository checked out. So the builder runs here or nowhere, and a
# verifier pins the source repository besides the SAN (--certificate-github-workflow-repository).
if: github.repository == 'spin-stack/spin-machine'
runs-on: ubuntu-24.04
# Every artefact compiled from cold on four cores: QEMU and the kernel are each tens of minutes.
timeout-minutes: 300
Expand Down Expand Up @@ -194,10 +199,12 @@ jobs:
cosign attest-blob --yes --type slsaprovenance1 --predicate _output/provenance.json \
--bundle "${f}.provenance.sigstore.json" "${f}" > /dev/null
cosign verify-blob --bundle "${f}.sigstore.json" --certificate-identity "${IDENTITY}" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com "${f}"
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-github-workflow-repository spin-stack/spin-machine "${f}"
cosign verify-blob-attestation --type slsaprovenance1 --bundle "${f}.provenance.sigstore.json" \
--certificate-identity "${IDENTITY}" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com "${f}"
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-github-workflow-repository spin-stack/spin-machine "${f}"
done
# The tarball's SBOM (hack/release), attested over it: what it is made of, by the
# workflow that built it. The same SBOM is inside it, at usr/share/spin-stack/sbom.
Expand All @@ -206,7 +213,8 @@ jobs:
--bundle "${f}.cdx.sigstore.json" "${f}" > /dev/null
cosign verify-blob-attestation --type cyclonedx --bundle "${f}.cdx.sigstore.json" \
--certificate-identity "${IDENTITY}" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com "${f}"
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-github-workflow-repository spin-stack/spin-machine "${f}"
done
go tool attestgate files -require provenance _output/release
go tool attestgate files -require cdx -except '*.sha256,machine.env,*.cdx.json' _output/release
Expand Down
3 changes: 2 additions & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@ tasks:
gh release download "$tag" -p "$sbom" -p "$sbom.sigstore.json" -D "$dir"
cosign verify-blob --bundle "$dir/$sbom.sigstore.json" \
--certificate-identity https://github.com/spin-stack/spin-machine/.github/workflows/build-release.yml@refs/heads/main \
--certificate-oidc-issuer https://token.actions.githubusercontent.com "$dir/$sbom"
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-github-workflow-repository spin-stack/spin-machine "$dir/$sbom"
# osv-scanner exits 1 when it found something, which is the answer; above 1 it failed.
status=0
go run "github.com/google/osv-scanner/v2/cmd/osv-scanner@$(go tool versions version osv-scanner)" \
Expand Down
13 changes: 8 additions & 5 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,17 @@ and `<file>.provenance.sigstore.json`, its SLSA provenance (`go tool provenance`
dispatched workflow at its commit, and every pin in `versions.yaml`). `release.yml` publishes
nothing itself: it calls `build-release.yml`, a workflow only a call starts, which builds from cold
on GitHub's own runner, signs, attests and publishes - so the certificate names the builder, and
that is the identity whoever takes a file checks both bundles against:
that is the identity whoever takes a file checks both bundles against. With the repository it ran
in: any repository can call a public reusable workflow, and its run's certificate names this
builder too, so the SAN alone is not this repository's (the builder's job also refuses to run
anywhere else).

```sh
id=https://github.com/spin-stack/spin-machine/.github/workflows/build-release.yml@refs/heads/main
cosign verify-blob --bundle f.sigstore.json --certificate-identity "$id" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com f
cosign verify-blob-attestation --type slsaprovenance1 --bundle f.provenance.sigstore.json \
--certificate-identity "$id" --certificate-oidc-issuer https://token.actions.githubusercontent.com f
pin=(--certificate-identity "$id" --certificate-oidc-issuer https://token.actions.githubusercontent.com
--certificate-github-workflow-repository spin-stack/spin-machine)
cosign verify-blob --bundle f.sigstore.json "${pin[@]}" f
cosign verify-blob-attestation --type slsaprovenance1 --bundle f.provenance.sigstore.json "${pin[@]}" f
```

Every release ran on `refs/heads/main`, and that is the ref its certificate names; which release
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ tool (
)

require (
github.com/spin-stack/go-tools v0.0.0-20261013171334-a38a073cfc2d
github.com/spin-stack/go-tools v0.0.0-20261013172709-defd29ba99c4
golang.org/x/sys v0.48.0
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ github.com/in-toto/attestation v1.2.0 h1:aPRUZ3azbqD7yEBD5fP3TD8Dszf+YHo284SOcpa
github.com/in-toto/attestation v1.2.0/go.mod h1:r79G45gOmzPismgObLSL+rZTFxUgZLOQJI6LofTZgXk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spin-stack/go-tools v0.0.0-20261013171334-a38a073cfc2d h1:4xHpFO/xiIXTnln50gS42x3zLGYGIlXhaePU3NTIFiA=
github.com/spin-stack/go-tools v0.0.0-20261013171334-a38a073cfc2d/go.mod h1:cy1ojfIbEjrfZi0lGzE+wjueaWw1jrotHQ+vyFz9pZQ=
github.com/spin-stack/go-tools v0.0.0-20261013172709-defd29ba99c4 h1:0w4kv6lPpa80XPxqPuEYjcSSzc4pgYLtrLtcDsrPX5c=
github.com/spin-stack/go-tools v0.0.0-20261013172709-defd29ba99c4/go.mod h1:cy1ojfIbEjrfZi0lGzE+wjueaWw1jrotHQ+vyFz9pZQ=
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
github.com/terminalstatic/go-xsd-validate v0.1.8 h1:UVrTCy1j3DhwaYTTUF+QYO/Nan13S0tf+Jwi+p45Bf0=
Expand Down
2 changes: 1 addition & 1 deletion workflows/workflows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
// runs after an unconditional provenance attestation in its job; the ones that look like an upload
// and ship nothing anyone installs are named here, each with why.
func TestEveryUploadIsAttested(t *testing.T) {
g := attestgate.Gate{Root: "..", RequireSBOM: true, MainOnly: []string{"release.yml"}, Builder: "build-release.yml", NotPublished: map[string]string{
g := attestgate.Gate{Root: "..", RequireSBOM: true, MainOnly: []string{"release.yml"}, Builder: "build-release.yml", Repository: "spin-stack/spin-machine", NotPublished: map[string]string{
"ci.yml/gate/Upload Go coverage HTML": "a coverage page for a person, kept seven days",
"kernel.yml/build/Upload the kernel": "a lane's kernel for a person to fetch; a release builds its own",
"lab.yml/lab/Keep the log": "a measurement's log, for a person",
Expand Down