From 4ff01b0fe147994ab2c4c27821dbd8876930943c Mon Sep 17 00:00:00 2001 From: Andrey Markelov Date: Sat, 4 Jul 2026 09:46:34 -0700 Subject: [PATCH] Add SBOM, Cosign signature, and SLSA provenance to releases Generate an SPDX SBOM, sign SHA256SUMS with Cosign (keyless via Sigstore), and produce SLSA Level 3 provenance using slsa-github-generator. Document verification steps in README and add --timeout guidance to automation docs. --- .github/workflows/release.yml | 43 +++++++++++++++++++++++++++++++++++ README.md | 20 ++++++++++++++++ docs/automation.md | 10 ++++++++ packaging/package-release.sh | 11 ++++++++- 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2be05709..36b33fe4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,11 +13,19 @@ jobs: runs-on: ubuntu-latest permissions: contents: write + id-token: write + outputs: + asset_version: ${{ steps.version.outputs.asset_version }} + slsa_subjects_file: ${{ steps.slsa_subjects.outputs.handle }} steps: - uses: actions/checkout@v7 - uses: actions/setup-go@v6 with: go-version: "1.25" + - name: Set release version + id: version + shell: bash + run: echo "asset_version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" - run: go install golang.org/x/vuln/cmd/govulncheck@latest - run: govulncheck ./... - run: go install honnef.co/go/tools/cmd/staticcheck@v0.7.0 @@ -25,15 +33,50 @@ jobs: - run: go vet ./... - run: go test ./... - run: go build ./... + - run: mkdir -p dist + - name: Generate SBOM + uses: anchore/sbom-action@v0 + with: + path: . + format: spdx-json + output-file: dist/dbxcli_${{ steps.version.outputs.asset_version }}_sbom.spdx.json + upload-artifact: false + upload-release-assets: false - run: ./build.sh env: VERSION: ${{ github.ref_name }} - run: ./packaging/package-release.sh env: VERSION: ${{ github.ref_name }} + - name: Generate SLSA subjects + shell: bash + run: base64 -w0 dist/SHA256SUMS > dist/SHA256SUMS.base64 + - name: Upload SLSA subjects + id: slsa_subjects + uses: slsa-framework/slsa-github-generator/actions/generator/generic/create-base64-subjects-from-file@v2.1.0 + with: + path: dist/SHA256SUMS.base64 + - name: Install Cosign + uses: sigstore/cosign-installer@v4.1.0 + - name: Sign checksums + run: cosign sign-blob --yes --bundle dist/SHA256SUMS.sigstore.json dist/SHA256SUMS - uses: softprops/action-gh-release@v3 with: files: | dist/*.tar.gz dist/*.zip dist/SHA256SUMS + dist/SHA256SUMS.sigstore.json + dist/*_sbom.spdx.json + + provenance: + needs: release + permissions: + actions: read + contents: write + id-token: write + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 + with: + base64-subjects-as-file: ${{ needs.release.outputs.slsa_subjects_file }} + upload-assets: true + provenance-name: dbxcli_${{ needs.release.outputs.asset_version }}_slsa.intoto.jsonl diff --git a/README.md b/README.md index dad68227..c4323ef4 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,23 @@ tar -xzf dbxcli_X.Y.Z_linux_amd64.tar.gz sudo mv dbxcli_X.Y.Z_linux_amd64/dbxcli /usr/local/bin/ ``` +For security-sensitive direct downloads, verify the signed checksum file and +provenance before installing: + +```sh +curl -LO https://github.com/dropbox/dbxcli/releases/download/vX.Y.Z/SHA256SUMS.sigstore.json +cosign verify-blob SHA256SUMS \ + --bundle SHA256SUMS.sigstore.json \ + --certificate-identity "https://github.com/dropbox/dbxcli/.github/workflows/release.yml@refs/tags/vX.Y.Z" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" + +curl -LO https://github.com/dropbox/dbxcli/releases/download/vX.Y.Z/dbxcli_X.Y.Z_slsa.intoto.jsonl +slsa-verifier verify-artifact dbxcli_X.Y.Z_linux_amd64.tar.gz \ + --provenance-path dbxcli_X.Y.Z_slsa.intoto.jsonl \ + --source-uri github.com/dropbox/dbxcli \ + --source-tag vX.Y.Z +``` + Release assets include: * `dbxcli_X.Y.Z_darwin_amd64.tar.gz` @@ -152,6 +169,9 @@ Release assets include: * `dbxcli_X.Y.Z_openbsd_amd64.tar.gz` * `dbxcli_X.Y.Z_windows_amd64.zip` * `SHA256SUMS` +* `SHA256SUMS.sigstore.json` +* `dbxcli_X.Y.Z_sbom.spdx.json` +* `dbxcli_X.Y.Z_slsa.intoto.jsonl` ### Build from source diff --git a/docs/automation.md b/docs/automation.md index d9e6c7d4..6888dfea 100644 --- a/docs/automation.md +++ b/docs/automation.md @@ -130,6 +130,16 @@ Use `--output=json` when the caller needs stable statuses, result kinds, warnings, or error codes. Use text output when a command is part of a human terminal workflow or when the command intentionally writes file bytes to stdout. +Set an explicit network timeout for CI jobs that should fail instead of waiting +indefinitely on Dropbox network operations: + +```sh +dbxcli --timeout 2m ls --output=json / +``` + +`--timeout` uses Go duration units such as `30s`, `2m`, or `1h`. The default +`0` disables the command deadline. + Check auth and identity before running a job: ```sh diff --git a/packaging/package-release.sh b/packaging/package-release.sh index a04df7d7..4a107dfb 100755 --- a/packaging/package-release.sh +++ b/packaging/package-release.sh @@ -86,10 +86,19 @@ else checksum_cmd=(shasum -a 256) fi -(cd "${dist_dir}" && "${checksum_cmd[@]}" "${archive_names[@]}" > SHA256SUMS) +checksum_names=("${archive_names[@]}") +sbom_name="dbxcli_${asset_version}_sbom.spdx.json" +if [[ -f "${dist_dir}/${sbom_name}" ]]; then + checksum_names+=("${sbom_name}") +fi + +(cd "${dist_dir}" && "${checksum_cmd[@]}" "${checksum_names[@]}" > SHA256SUMS) echo "Created release archives in ${dist_dir}:" for archive_name in "${archive_names[@]}"; do echo " ${archive_name}" done +for checksum_name in "${checksum_names[@]:${#archive_names[@]}}"; do + echo " ${checksum_name}" +done echo " SHA256SUMS"