Skip to content

Conversation

@leodido
Copy link
Contributor

@leodido leodido commented Sep 29, 2025

Description

Adds the leeway plumbing sign-cache command for signing cache artifacts with SLSA v0.2 attestations, completing the SLSA Level 3 implementation started in PR #242 and PR #243.

Changes

  • New sign-cache command: CLI for signing cache artifacts from manifest files
  • Sigstore keyless signing: Full integration with GitHub OIDC and Sigstore infrastructure
  • Attestation generation: Creates SLSA v0.2 attestations in DSSE format
  • Manifest processing: Reads artifact paths from CI-generated manifest files
  • Upload integration: Uploads signed artifacts and .att files to S3 cache

Builds on existing cache verification (PR #242) and in-flight checksumming (PR #243) to provide complete signing infrastructure for separated CI jobs.

Related Issue(s)

Completes SLSA Level 3 cache artifact signing implementation.

Fixes https://linear.app/ona-team/issue/CLC-1959/create-leeway-signing-command

How to test

Basic functionality:

# Test signing command
echo "/tmp/test.tar.gz" > manifest.txt && touch /tmp/test.tar.gz
go build ./cmd/sign-cache && ./sign-cache --from-manifest manifest.txt --dry-run
permissions:
  id-token: write  # Required for Sigstore
steps:
  - run: leeway plumbing sign-cache --from-manifest artifacts-to-sign.txt

leodido and others added 5 commits September 26, 2025 21:08
- Add comprehensive SLSA v0.2 provenance generation using in-toto libraries
- Implement keyless signing with Sigstore integration
- Create structured error handling for signing operations
- Add GitHub Actions context validation and extraction
- Support .att file format compatible with existing verification
- Replace parallel signing approach with single-step generation and signing

Co-authored-by: Ona <no-reply@ona.com>
- Implement leeway plumbing sign-cache command for secure artifact signing
- Add --from-manifest flag to process build manifests from previous jobs
- Support parallel artifact processing with WaitGroup coordination
- Create adapter pattern for RemoteCache interface compatibility
- Enable separation of build and signing concerns in CI workflows
- Support GitHub Actions OIDC token-based keyless signing

Co-authored-by: Ona <no-reply@ona.com>
- Add github.com/sigstore/sigstore-go v1.1.2 for keyless signing
- Update in-toto libraries for SLSA v0.2 provenance generation
- Upgrade AWS SDK and other dependencies to latest versions
- Support GitHub Actions OIDC token integration

Co-authored-by: Ona <no-reply@ona.com>
- Replace TODO placeholder with actual sigstore-go v1.1.2 API calls
- Add proper DSSE format for SLSA attestations (application/vnd.in-toto+json)
- Implement TUF-based trusted root and signing config fetching
- Add dynamic Fulcio and Rekor service selection from signing config
- Remove manual OIDC token handling, let sigstore-go handle GitHub OIDC automatically
- Add comprehensive GitHub Actions environment validation (GITHUB_ACTIONS=true)
- Replace placeholder attestation envelope with real Sigstore bundles
- Improve error messages for better debugging in CI environments

Fixes critical API usage issues identified in code review.
Enables production keyless signing with GitHub OIDC tokens.

Co-authored-by: Ona <no-reply@ona.com>
- Use getRemoteCacheFromEnv() instead of getRemoteCache(cmd) for cleaner interface
- Remove unused imports (path/filepath, time) to clean up dependencies
- Improve command interface consistency with other leeway commands

Co-authored-by: Ona <no-reply@ona.com>
@leodido leodido self-assigned this Sep 29, 2025
@leodido leodido requested review from csweichel and geropl September 29, 2025 19:49
@leodido leodido marked this pull request as ready for review September 29, 2025 19:49
Long: `Reads artifact paths from manifest file, generates SLSA attestations,
and uploads to remote cache with write-only credentials.

This command is designed for CI environments where build and signing are
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧡

leodido and others added 2 commits October 21, 2025 16:10
The tempMu mutex is not required because:
- runSignCache is only called once from a single location
- tempFiles slice is never modified after initialization
- No goroutines access the tempFiles slice
- Deferred cleanup runs after wg.Wait() ensures all goroutines complete

Co-authored-by: Ona <noreply@gitpod.io>

Co-authored-by: Ona <no-reply@ona.com>
Replace hardcoded 0.5 with a named constant to improve code readability
and maintainability. The constant is placed alongside maxConcurrency for
consistency and includes a descriptive comment explaining the threshold.

Co-authored-by: Ona <noreply@gitpod.io>

Co-authored-by: Ona <no-reply@ona.com>
@leodido leodido changed the base branch from feature/in-flight-checksumming to main October 21, 2025 17:03
@leodido leodido changed the base branch from main to feature/in-flight-checksumming October 21, 2025 17:04
leodido and others added 3 commits October 21, 2025 17:25
…path

Replace hardcoded .github/workflows/build.yml assumption with the
GITHUB_WORKFLOW_REF environment variable which contains the complete
workflow reference including repository, workflow path, and git ref.

This makes the code work with any workflow file name and location,
not just build.yml in .github/workflows/.

Co-authored-by: Ona <noreply@gitpod.io>

Co-authored-by: Ona <no-reply@ona.com>
The sign-cache command runs in a separate CI job after the build
completes, signing already-built artifacts. At signing time, we don't
have access to the actual build start/finish times.

Setting both timestamps to nil is the correct approach because:
- Using signing time would be incorrect (build happened earlier)
- Using artifact mtime would be misleading (download time, not build time)
- SLSA spec allows these optional fields to be omitted
- Better to omit data than provide incorrect data

The SLSA library uses *time.Time with omitempty, so nil values will
be properly omitted from the JSON output.

Co-authored-by: Ona <noreply@gitpod.io>

Co-authored-by: Ona <no-reply@ona.com>
Add UploadFile(ctx, filePath, key) method to RemoteCache interface to
remove the mock object workaround in upload.go.

Changes:
- Add UploadFile method to RemoteCache interface with documentation
- Implement in S3Cache with rate limiting and timeout handling
- Implement in GSUtilCache using gsutil cp command
- Implement in NoRemoteCache as no-op
- Simplify upload.go by removing 87 lines of mock object code
  (mockCachePackage, mockLocalCache, uploadFileToS3, uploadToS3Cache)
- Remove unused remote package import from upload.go

The refactoring makes the code cleaner and more maintainable while
preserving the exact same upload behavior. All tests pass.

Co-authored-by: Ona <noreply@gitpod.io>

Co-authored-by: Ona <no-reply@ona.com>
}

// Upload artifact first using the new UploadFile method
if err := u.remoteCache.UploadFile(ctx, artifactPath, artifactKey); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧡

Copy link
Member

@geropl geropl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, love the cleaner code ✔️

@leodido leodido merged commit ee5b45e into feature/in-flight-checksumming Oct 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants