Skip to content

[CHORE] Add SLSA Level 2 & 3 provenance generation for 26.1.1 #1842

@oberstet

Description

@oberstet

Summary

Add SLSA Level 3 provenance generation to the release workflow using slsa-github-generator. autobahn-python already has the most complete workflow structure — this issue adds the final L3 provenance layer.

Current State (autobahn-python is the reference implementation)

Feature Status
Trusted Publishing ✅ Configured
PEP 740 Attestations ⚠️ Verify enabled
Job naming (release-stable/nightly)
Jinja2 templates (all 5)
release-post-comment.yml
SLSA L3 provenance ❌ Missing

Scope for 26.1.1

1. Verify PEP 740 Attestations

Confirm attestations: true is set in the PyPI publish step. If not, add it:

- name: Publish to PyPI
  uses: pypa/gh-action-pypi-publish@release/v1
  with:
    packages-dir: dist/
    attestations: true

2. Add SLSA L3 Provenance Jobs

Add after release-stable:

publish-slsa3-provenance:
  name: Prepare SLSA L3 Subjects
  needs: [identifiers, release-stable]
  if: needs.identifiers.outputs.release_type == 'stable'
  runs-on: ubuntu-latest
  outputs:
    subjects-base64: ${{ steps.collect-subjects.outputs.subjects-base64 }}
  steps:
    - name: Download CHECKSUMS from release
      env:
        GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        RELEASE_TAG: ${{ needs.identifiers.outputs.release_tag }}
      run: |
        gh release download "$RELEASE_TAG" \
          --repo "$GITHUB_REPOSITORY" \
          --pattern "*CHECKSUMS.sha256" \
          --dir checksums/

    - name: Convert CHECKSUMS to SLSA subjects
      id: collect-subjects
      run: |
        SUBJECTS_FILE="subjects.txt"
        > "$SUBJECTS_FILE"

        for checksums_file in checksums/*CHECKSUMS.sha256; do
          [[ ! -f "$checksums_file" ]] && continue
          while IFS= read -r line; do
            [[ -z "$line" || "$line" == *"CHECKSUMS"* ]] && continue
            HEX_HASH=$(echo "$line" | awk -F'= ' '{print $2}')
            FILE_PATH=$(echo "$line" | sed 's/SHA2-256(\.\///' | sed 's/)=.*//')
            HASH_B64=$(echo "$HEX_HASH" | xxd -r -p | base64 -w0)
            echo "${HASH_B64}  ${FILE_PATH}" >> "$SUBJECTS_FILE"
          done < "$checksums_file"
        done

        SUBJECTS_B64=$(base64 -w0 "$SUBJECTS_FILE")
        echo "subjects-base64=${SUBJECTS_B64}" >> $GITHUB_OUTPUT

generate-provenance:
  name: Generate SLSA L3 Provenance
  needs: [identifiers, publish-slsa3-provenance]
  if: needs.identifiers.outputs.release_type == 'stable'
  permissions:
    actions: read
    id-token: write
    contents: write
  uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
  with:
    base64-subjects: ${{ needs.publish-slsa3-provenance.outputs.subjects-base64 }}
    upload-assets: true
    provenance-name: "multiple.intoto.jsonl"

3. Update Release Notes Template

Add L3 verification to release-stable.md.j2:

### SLSA Level 3 (GitHub)

**Verify with slsa-verifier:**

```bash
slsa-verifier verify-artifact \
  autobahn-{{ version }}-py3-none-any.whl \
  --provenance-path multiple.intoto.jsonl \
  --source-uri github.com/crossbario/autobahn-python \
  --source-tag v{{ version }}

### 4. Add PyPI Provenance Fetch (if not present)

Fetch `.provenance.json` from PyPI API after publish and include in GitHub Release.

## Acceptance Criteria

- [ ] PEP 740 attestations verified/enabled
- [ ] `publish-slsa3-provenance` job added
- [ ] `generate-provenance` job added with slsa-github-generator
- [ ] `multiple.intoto.jsonl` uploaded to stable releases
- [ ] Release notes template updated with L3 verification
- [ ] PyPI provenance fetch implemented (if missing)

## Related

- #1839 — Typed subset initiative
- #1840 — Add ruff annotation checks
- #1838 — Type hints (merged)

## References

- [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator)
- [SLSA Level 3 Requirements](https://slsa.dev/spec/v1.0/levels#build-l3)

## Checklist

- [x] I have searched existing issues to avoid duplicates
- [x] I have described the problem clearly
- [x] I have provided use cases
- [x] I have considered alternatives
- [x] I have assessed impact and breaking changes

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions