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.
This commit is contained in:
273
docs/modules/signer/guides/keyless-signing.md
Normal file
273
docs/modules/signer/guides/keyless-signing.md
Normal file
@@ -0,0 +1,273 @@
|
||||
# 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/)
|
||||
Reference in New Issue
Block a user