Skip to content

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

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions