Files
git.stella-ops.org/docs/modules/signer/guides/keyless-signing.md
StellaOps Bot 7792749bb4 feat: Add archived advisories and implement smart-diff as a core evidence primitive
- Introduced new advisory documents for archived superseded advisories, including detailed descriptions of features already implemented or covered by existing sprints.
- Added "Smart-Diff as a Core Evidence Primitive" advisory outlining the treatment of SBOM diffs as first-class evidence objects, enhancing vulnerability verdicts with deterministic replayability.
- Created "Visual Diffs for Explainable Triage" advisory to improve user experience in understanding policy decisions and reachability changes through visual diffs.
- Implemented "Weighted Confidence for VEX Sources" advisory to rank conflicting vulnerability evidence based on freshness and confidence, facilitating better decision-making.
- Established a signer module charter detailing the mission, expectations, key components, and signing modes for cryptographic signing services in StellaOps.
- Consolidated overlapping concepts from triage UI, visual diffs, and risk budget visualization advisories into a unified specification for better clarity and implementation tracking.
2025-12-26 13:01:43 +02:00

274 lines
9.6 KiB
Markdown

# Keyless Signing Guide
## Overview
Keyless signing uses ephemeral X.509 certificates from Sigstore Fulcio, eliminating the need for persistent signing keys. This approach is ideal for CI/CD pipelines where key management is complex and error-prone.
### How It Works
```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ CI Pipeline │────▶│ OIDC Provider│────▶│ Fulcio │────▶│ Rekor │
│ │ │ (GitHub/GL) │ │ (Sigstore) │ │ (Sigstore) │
│ 1. Get token │ │ 2. Issue JWT │ │ 3. Issue cert│ │ 4. Log entry │
│ │ │ (5 min) │ │ (10 min) │ │ (permanent) │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
│ │
│ │
└───────────── Attestation with cert + Rekor proof ───────────┘
```
1. **OIDC Token**: Pipeline requests identity token from CI platform
2. **Fulcio Certificate**: Token exchanged for short-lived signing certificate (~10 min)
3. **Ephemeral Key**: Private key exists only in memory during signing
4. **Rekor Logging**: Signature logged to transparency log for verification after cert expiry
### Key Benefits
| Benefit | Description |
|---------|-------------|
| **Zero Key Management** | No secrets to rotate, store, or protect |
| **Identity Binding** | Signatures tied to OIDC identity (repo, branch, workflow) |
| **Audit Trail** | All signatures logged to Rekor transparency log |
| **Short-lived Certs** | Minimizes exposure window (~10 minutes) |
| **Industry Standard** | Adopted by Kubernetes, npm, PyPI, and major ecosystems |
## Quick Start
### Prerequisites
1. StellaOps CLI installed
2. CI platform with OIDC support (GitHub Actions, GitLab CI, Gitea)
3. Network access to Fulcio and Rekor (or private instances)
### GitHub Actions Example
```yaml
name: Sign Container Image
on:
push:
branches: [main]
jobs:
build-and-sign:
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Build and Push Image
id: build
run: |
docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} .
docker push ghcr.io/${{ github.repository }}:${{ github.sha }}
echo "digest=$(docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/${{ github.repository }}:${{ github.sha }} | cut -d@ -f2)" >> $GITHUB_OUTPUT
- name: Keyless Sign
uses: stella-ops/sign-action@v1
with:
artifact-digest: ${{ steps.build.outputs.digest }}
artifact-type: image
```
### CLI Usage
```bash
# Sign with ambient OIDC token (in CI environment)
stella attest sign --keyless --artifact sha256:abc123...
# Sign with explicit token
STELLAOPS_OIDC_TOKEN="..." stella attest sign --keyless --artifact sha256:abc123...
# Verify signature (checks Rekor proof)
stella attest verify \
--artifact sha256:abc123... \
--certificate-identity "repo:myorg/myrepo:ref:refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
```
## Configuration
### Signer Configuration
```yaml
# etc/signer.yaml
signer:
signing:
mode: "keyless"
keyless:
enabled: true
fulcio:
url: "https://fulcio.sigstore.dev"
timeout: 30s
retries: 3
oidc:
issuer: "https://authority.internal"
clientId: "signer-keyless"
useAmbientToken: true
algorithms:
preferred: "ECDSA_P256"
allowed: ["ECDSA_P256", "Ed25519"]
certificate:
rootBundlePath: "/etc/stellaops/fulcio-roots.pem"
validateChain: true
requireSCT: true
```
### Private Fulcio Instance
For air-gapped or high-security environments, deploy a private Fulcio instance:
```yaml
signer:
signing:
keyless:
fulcio:
url: "https://fulcio.internal.example.com"
oidc:
issuer: "https://keycloak.internal.example.com/realms/stellaops"
certificate:
rootBundlePath: "/etc/stellaops/private-fulcio-roots.pem"
```
## Identity Verification
### Identity Constraints
When verifying signatures, specify which identities are trusted:
```bash
stella attest verify \
--artifact sha256:abc123... \
--certificate-identity "repo:myorg/myrepo:ref:refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
```
### Platform Identity Patterns
#### GitHub Actions
| Pattern | Matches |
|---------|---------|
| `repo:org/repo:.*` | Any ref in repository |
| `repo:org/repo:ref:refs/heads/main` | Main branch only |
| `repo:org/repo:ref:refs/tags/v.*` | Version tags |
| `repo:org/repo:environment:production` | Production environment |
**Issuer:** `https://token.actions.githubusercontent.com`
#### GitLab CI
| Pattern | Matches |
|---------|---------|
| `project_path:group/project:.*` | Any ref in project |
| `project_path:group/project:ref_type:branch:ref:main` | Main branch |
| `project_path:group/project:ref_protected:true` | Protected refs only |
**Issuer:** `https://gitlab.com` (or self-hosted URL)
## Long-Term Verification
### The Problem
Fulcio certificates expire in ~10 minutes. How do you verify signatures months later?
### The Solution: Rekor Proofs
```
At signing time:
┌──────────────────────────────────────────────────────────────┐
│ Signature + Certificate + Signed-Certificate-Timestamp (SCT) │
│ ↓ │
│ Logged to Rekor │
│ ↓ │
│ Merkle Inclusion Proof returned │
└──────────────────────────────────────────────────────────────┘
At verification time (even years later):
┌──────────────────────────────────────────────────────────────┐
│ 1. Check signature is valid (using cert public key) │
│ 2. Check SCT proves cert was logged when valid │
│ 3. Check Rekor inclusion proof (entry was logged) │
│ 4. Check signing time was within cert validity window │
│ ↓ │
│ Signature is valid! ✓ │
└──────────────────────────────────────────────────────────────┘
```
### Attestation Bundles
For air-gapped verification, StellaOps bundles attestations with proofs:
```bash
# Export bundle with Rekor proofs
stella attest export-bundle \
--image sha256:abc123... \
--include-proofs \
--output attestation-bundle.json
# Verify offline
stella attest verify --offline \
--bundle attestation-bundle.json \
--artifact sha256:abc123...
```
## Troubleshooting
### Common Errors
| Error | Cause | Solution |
|-------|-------|----------|
| `OIDC token expired` | Token older than 5 minutes | Re-acquire token before signing |
| `Fulcio unavailable` | Network issues | Check connectivity, increase timeout |
| `Certificate chain invalid` | Wrong Fulcio roots | Update root bundle |
| `Identity mismatch` | Wrong verify constraints | Check issuer and identity patterns |
| `Rekor proof missing` | Logging failed | Retry signing, check Rekor status |
### Debug Mode
```bash
# Enable verbose logging
STELLAOPS_LOG_LEVEL=debug stella attest sign --keyless --artifact sha256:...
# Inspect certificate details
stella attest inspect --artifact sha256:... --show-cert
```
## Security Considerations
### Best Practices
1. **Always verify identity**: Never accept `.*` as the full identity pattern
2. **Require Rekor proofs**: Use `--require-rekor` for production verification
3. **Pin OIDC issuers**: Only trust expected issuers
4. **Use environment constraints**: More specific than branch names
5. **Monitor signing activity**: Alert on unexpected identities
### Threat Model
| Threat | Mitigation |
|--------|------------|
| Stolen OIDC token | Short lifetime (~5 min), audience binding |
| Fulcio compromise | Certificate Transparency (SCT), multiple roots |
| Rekor compromise | Multiple witnesses, checkpoints, consistency proofs |
| Private key theft | Ephemeral keys, never persisted |
## Related Documentation
- [Signer Architecture](../architecture.md)
- [Attestor Bundle Format](../../attestor/bundle-format.md)
- [Air-Gap Verification](../../../airgap/attestation-verification.md)
- [CI/CD Integration](../../../guides/cicd-signing.md)
## External Resources
- [Sigstore Documentation](https://docs.sigstore.dev/)
- [Fulcio Overview](https://docs.sigstore.dev/certificate_authority/overview/)
- [Rekor Transparency Log](https://docs.sigstore.dev/logging/overview/)
- [cosign Keyless Signing](https://docs.sigstore.dev/signing/quickstart/)