Skip to content

Conversation

@colek42
Copy link
Member

@colek42 colek42 commented Oct 21, 2025

Summary

Implements in-process OIDC (OpenID Connect) server to enable keyless authentication for supply chain security tools like SIGSTORE and Witness when running workflows locally with act.

Motivation

GitHub Actions provides OIDC ID tokens through environment variables (ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN) to enable keyless authentication with external services. This is critical for supply chain security tools like:

  • SIGSTORE: Keyless code signing and verification
  • Witness: In-toto attestation framework
  • HashiCorp Vault: Secret management
  • AWS: Federated authentication to AWS services

Without this feature, these tools cannot be tested locally with act.

Implementation

Architecture

The implementation integrates OIDC endpoints into act's existing artifacts server (in-process, no separate service required):

  1. Request Token Flow: When a workflow container starts, act generates an ACTIONS_ID_TOKEN_REQUEST_TOKEN (HMAC-signed JWT) containing all GitHub context
  2. ID Token Flow: Workflow steps request ID tokens by POSTing to /token with the request token
  3. Token Verification: Consumers can verify tokens using the public key from /.well-known/jwks

Key Components

pkg/common/oidc.go

  • CreateOIDCRequestToken(): Generates request tokens with GitHub context
  • ParseOIDCRequestToken(): Extracts context from request tokens
  • GenerateOIDCToken(): Creates RS256-signed ID tokens
  • GenerateJWKS(): Publishes public keys for token verification
  • GitHubOIDCClaims: Complete struct with 31 claims matching GitHub's official schema

pkg/artifacts/server.go

  • POST /token: Issues OIDC ID tokens (with optional ?audience= parameter)
  • GET /.well-known/jwks: Serves public key set

pkg/runner/run_context.go

  • Sets ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN environment variables in workflow containers

cmd/root.go

  • Initializes OIDC key manager on startup

Token Schema Compliance

The implementation generates tokens that exactly match GitHub's official OIDC schema:

  • ✅ All 31 standard claims from token.actions.githubusercontent.com/.well-known/openid-configuration
  • ✅ Correct claim formats (subject, workflow_ref, etc.)
  • ✅ RS256 signing algorithm
  • ✅ JWKS public key publishing
  • ✅ Custom audience support

Standard JWT Claims

  • iss: https://token.actions.githubusercontent.com
  • sub: repo:{owner}/{repo}:ref:{ref}
  • aud: Configurable audience
  • exp, nbf, iat, jti: Standard time/ID claims

GitHub-Specific Claims

  • Workflow: workflow, workflow_ref, workflow_sha, job_workflow_ref, job_workflow_sha
  • Repository: repository, repository_id, repository_owner, repository_owner_id, repository_visibility
  • Execution: run_id, run_number, run_attempt, event_name, ref, ref_type, ref_protected
  • Actor: actor, actor_id
  • Branches: head_ref, base_ref
  • Infrastructure: runner_environment, sha

Testing

Unit Tests

  • pkg/common/oidc_test.go: Tests for all token generation functions
  • pkg/artifacts/oidc_test.go: Integration tests for HTTP endpoints
  • All tests validate token claims, signatures, and round-trip workflows

Example Usage

name: Test OIDC
on: push
jobs:
  test:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    steps:
      - name: Get OIDC Token
        run: |
          TOKEN=$(curl -s -X POST \
            -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \
            "${ACTIONS_ID_TOKEN_REQUEST_URL}?audience=sigstore" \
            | jq -r '.value')
          echo "Got ID token: ${TOKEN:0:50}..."

Running Tests

# Run all tests
go test ./pkg/common -v -run TestOIDC
go test ./pkg/artifacts -v -run TestOIDC

# Test with a workflow
./act -W .github/workflows/your-workflow.yml

Compatibility

  • ✅ Backwards compatible (no breaking changes to existing act functionality)
  • ✅ OIDC endpoints only active when artifacts server is running
  • ✅ Environment variables only set when context is available
  • ✅ Works with all existing act command-line options

Security Considerations

  • RSA 2048-bit keys generated per-run (not persisted)
  • Request tokens use HMAC signing (internal communication only)
  • ID tokens use RS256 signing (external verification)
  • Public keys available via standard JWKS endpoint
  • Deterministic IDs generated from SHA256 hashes

Related Work

This implementation was validated against:

  • GitHub's official OIDC documentation
  • Real GitHub Actions OIDC tokens
  • SIGSTORE and Witness integration requirements

🤖 Generated with Claude Code

Implements in-process OIDC server to enable keyless authentication
for supply chain security tools like SIGSTORE and Witness.

**Changes:**
- Add OIDC token generation in pkg/common/oidc.go
  - CreateOIDCRequestToken: Generate request tokens with GitHub context
  - ParseOIDCRequestToken: Extract context from request tokens
  - GenerateOIDCToken: Create RS256-signed ID tokens
  - GenerateJWKS: Publish public keys for token verification

- Integrate OIDC endpoints into artifacts server (pkg/artifacts/server.go)
  - POST /token: Issue OIDC ID tokens
  - GET /.well-known/jwks: Serve public key set

- Set OIDC environment variables in runner (pkg/runner/run_context.go)
  - ACTIONS_ID_TOKEN_REQUEST_URL
  - ACTIONS_ID_TOKEN_REQUEST_TOKEN

- Initialize OIDC key manager in cmd/root.go

**Token Schema:**
- 31 claims matching GitHub's official OIDC schema
- Validated against token.actions.githubusercontent.com
- RS256 signing with JWKS support
- Supports custom audiences (sigstore, vault, AWS, etc.)

**Tests:**
- Comprehensive unit tests for all OIDC functions
- Integration tests for HTTP endpoints
- Round-trip token validation tests

This enables local testing of OIDC-based workflows without
requiring actual GitHub Actions infrastructure.
Prevents nil pointer dereference when RunContext.Run is not set,
which can occur in unit tests that only initialize Config.
@colek42 colek42 merged commit 53118c0 into master Oct 21, 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.

3 participants