- 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.
231 lines
6.8 KiB
Markdown
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/)
|