Files
git.stella-ops.org/docs/modules/signer/guides/keyless-signing.md
StellaOps Bot c8f3120174 Add property-based tests for SBOM/VEX document ordering and Unicode normalization determinism
- Implement `SbomVexOrderingDeterminismProperties` for testing component list and vulnerability metadata hash consistency.
- Create `UnicodeNormalizationDeterminismProperties` to validate NFC normalization and Unicode string handling.
- Add project file for `StellaOps.Testing.Determinism.Properties` with necessary dependencies.
- Introduce CI/CD template validation tests including YAML syntax checks and documentation content verification.
- Create validation script for CI/CD templates ensuring all required files and structures are present.
2025-12-26 15:17:15 +02:00

231 lines
6.8 KiB
Markdown

# Keyless Signing Guide
This guide explains how to configure and use keyless signing with Sigstore Fulcio for CI/CD pipelines.
## Overview
Keyless signing eliminates the need to manage long-lived signing keys by using short-lived X.509 certificates (~10 minute TTL) issued by Fulcio based on OIDC identity tokens. This approach:
- **Zero key management**: No secrets to rotate or protect
- **Identity-bound signatures**: Signatures are cryptographically tied to the CI/CD identity
- **Non-repudiation**: Audit trail via Rekor transparency log
- **Industry standard**: Compatible with Sigstore ecosystem (cosign, gitsign, etc.)
## How It Works
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ CI Runner │────▶│ OIDC Token │────▶│ Fulcio │────▶│ Ephemeral │
│ (GitHub/GL) │ │ Provider │ │ CA │ │ Cert │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
┌─────────────┐
│ Sign DSSE │
│ Envelope │
└─────────────┘
```
1. **CI runner provides OIDC token** - GitHub Actions, GitLab CI, etc. provide ambient identity tokens
2. **Token exchanged for certificate** - Fulcio validates the OIDC token and issues a short-lived certificate
3. **Ephemeral key generation** - A new ECDSA P-256 or Ed25519 key is generated per signing operation
4. **DSSE signing** - The payload is signed using the ephemeral key
5. **Certificate attached** - The Fulcio certificate is included in the signed bundle for verification
## Configuration
### Basic Configuration
```yaml
# etc/signer.yaml
signer:
signing:
mode: "keyless"
keyless:
enabled: true
fulcio:
url: "https://fulcio.sigstore.dev"
timeout: 30s
retries: 3
oidc:
useAmbientToken: true
```
### Private Fulcio Instance
For air-gapped or private deployments:
```yaml
signer:
signing:
keyless:
fulcio:
url: "https://fulcio.internal.example.com"
certificate:
rootBundlePath: "/etc/stellaops/fulcio-roots.pem"
additionalRoots:
- |
-----BEGIN CERTIFICATE-----
MIIBjzCCATSgAwIBAgIRANZl...
-----END CERTIFICATE-----
```
### Identity Constraints
Restrict which identities are allowed to sign:
```yaml
signer:
signing:
keyless:
identity:
expectedIssuers:
- "https://token.actions.githubusercontent.com"
- "https://gitlab.com"
expectedSubjectPatterns:
- "^https://github\.com/myorg/.*$"
- "^project_path:mygroup/myproject:.*$"
```
## CI/CD Integration
### GitHub Actions
```yaml
name: Sign Artifacts
on: [push]
jobs:
sign:
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC token
contents: read
steps:
- uses: actions/checkout@v4
- name: Install StellaOps CLI
run: |
curl -sSL https://get.stella-ops.io | bash
- name: Sign with keyless mode
run: |
stella sign --mode keyless \
--image ghcr.io/${{ github.repository }}:${{ github.sha }}
```
### GitLab CI
```yaml
sign:
image: registry.stella-ops.io/cli:latest
id_tokens:
SIGSTORE_ID_TOKEN:
aud: sigstore
script:
- stella sign --mode keyless --image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
```
## Algorithm Support
| Algorithm | Status | Use Case |
|-----------|--------|----------|
| ECDSA P-256 | Preferred | Default, widest compatibility |
| Ed25519 | Supported | Better performance, growing adoption |
Configure preferred algorithm:
```yaml
signer:
signing:
keyless:
algorithms:
preferred: "ECDSA_P256"
allowed: ["ECDSA_P256", "Ed25519"]
```
## Signed Bundle Format
The keyless signing produces a DSSE envelope with embedded certificate:
```json
{
"payloadType": "application/vnd.in-toto+json",
"payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEi...",
"signatures": [
{
"keyid": "",
"sig": "MEUCIQD..."
}
],
"certificateChain": [
"-----BEGIN CERTIFICATE-----\nMIIC...",
"-----BEGIN CERTIFICATE-----\nMIIB..."
],
"signingMode": "keyless",
"signingIdentity": {
"issuer": "https://token.actions.githubusercontent.com",
"subject": "https://github.com/org/repo/.github/workflows/ci.yml@refs/heads/main"
}
}
```
## Verification
Bundles signed with keyless mode can be verified using:
```bash
# Verify a signed bundle
stella verify --bundle verdict.json \
--expected-issuer "https://token.actions.githubusercontent.com" \
--expected-subject "https://github.com/myorg/myrepo/*"
```
The verification process:
1. Validates the certificate chain to Fulcio roots
2. Verifies the signature using the certificate's public key
3. Checks identity claims match expectations
4. Optionally validates SCT (Signed Certificate Timestamp)
## Troubleshooting
### Common Issues
**OIDC token not available**
- Ensure id-token: write permission in GitHub Actions
- Ensure id_tokens is configured in GitLab CI
- Check ACTIONS_ID_TOKEN_REQUEST_URL environment variable
**Fulcio returns 401**
- OIDC token may have expired (default 5-10 min validity)
- Audience mismatch - ensure token is for sigstore
- Issuer not trusted by Fulcio instance
**Certificate chain validation failed**
- Root certificate bundle may be outdated
- Private Fulcio instance roots not configured
- Certificate expired (Fulcio certs are ~10 min TTL)
### Debug Logging
Enable verbose logging:
```bash
STELLAOPS_LOG_LEVEL=debug stella sign --mode keyless ...
```
## Security Considerations
1. **Ephemeral keys never persist** - Keys exist only in memory during signing
2. **Short-lived certificates** - ~10 minute validity limits exposure window
3. **Identity verification** - Always configure expectedIssuers and expectedSubjectPatterns in production
4. **SCT validation** - Enable requireSct: true for public Fulcio instances
## Related Documentation
- [Signer Architecture](../architecture.md)
- [DSSE Envelope Format](../dsse-format.md)
- [CI/CD Gate Integration](../../policy/guides/cicd-gates.md)
- [Sigstore Documentation](https://docs.sigstore.dev/)