# Cosign Integration Guide > **Status:** Ready for Production > **Last Updated:** 2025-12-23 > **Prerequisites:** Cosign v2.x, StellaOps CLI v1.5+ --- ## Overview This guide explains how to integrate StellaOps with [Cosign](https://docs.sigstore.dev/cosign/overview/), the signing tool from the Sigstore project. StellaOps can verify and ingest SBOM attestations signed with Cosign, enabling seamless interoperability with the broader supply chain security ecosystem. **Key Capabilities:** - ✅ Verify Cosign-signed attestations (SPDX + CycloneDX) - ✅ Extract SBOMs from Cosign DSSE envelopes - ✅ Upload attested SBOMs to StellaOps for scanning - ✅ Offline verification with bundled trust roots - ✅ Custom trust root configuration for air-gapped environments --- ## Quick Start ### 1. Verify a Cosign-Signed Attestation ```bash # Verify attestation and extract SBOM stella attest verify \ --envelope attestation.dsse.json \ --root /path/to/fulcio-root.pem \ --extract-sbom sbom.json # Upload extracted SBOM for scanning stella sbom upload \ --file sbom.json \ --artifact myapp:v1.2.3 ``` ### 2. End-to-End: Cosign → StellaOps ```bash # Step 1: Sign SBOM with Cosign cosign attest --predicate sbom.spdx.json \ --type spdx \ --key cosign.key \ myregistry/myapp:v1.2.3 # Step 2: Fetch attestation cosign verify-attestation myregistry/myapp:v1.2.3 \ --key cosign.pub \ --type spdx \ --output-file attestation.dsse.json # Step 3: Verify with StellaOps stella attest verify \ --envelope attestation.dsse.json \ --extract-sbom sbom.spdx.json # Step 4: Scan with StellaOps stella scan sbom sbom.spdx.json \ --output results.json ``` --- ## Supported Predicate Types StellaOps supports standard SBOM predicate types used by Cosign: | Predicate Type | Format | Cosign Flag | StellaOps Support | |----------------|--------|-------------|-------------------| | `https://spdx.dev/Document` | SPDX 3.0.1 | `--type spdx` | ✅ Full support | | `https://spdx.org/spdxdocs/spdx-v2.3-*` | SPDX 2.3 | `--type spdx` | ✅ Full support | | `https://cyclonedx.org/bom` | CycloneDX 1.4-1.7 | `--type cyclonedx` | ✅ Full support | | `https://slsa.dev/provenance/v1` | SLSA v1.0 | `--type slsaprovenance` | ✅ Metadata only | --- ## Common Workflows ### Workflow 1: Keyless Signing (Fulcio) **Use Case:** Sign attestations using ephemeral keys from Fulcio (requires OIDC). ```bash # Step 1: Generate SBOM (using Syft as example) syft myregistry/myapp:v1.2.3 -o spdx-json=sbom.spdx.json # Step 2: Sign with Cosign (keyless) cosign attest --predicate sbom.spdx.json \ --type spdx \ myregistry/myapp:v1.2.3 # Step 3: Verify with StellaOps (uses Sigstore public instance) stella attest verify-image myregistry/myapp:v1.2.3 \ --type spdx \ --extract-sbom sbom-verified.spdx.json # Step 4: Scan stella scan sbom sbom-verified.spdx.json ``` **Trust Configuration:** StellaOps defaults to the Sigstore public instance trust roots: - Fulcio root: https://fulcio.sigstore.dev/api/v2/trustBundle - Rekor instance: https://rekor.sigstore.dev ### Workflow 2: Key-Based Signing **Use Case:** Sign attestations with your own keys (air-gapped environments). ```bash # Step 1: Generate key pair (one-time) cosign generate-key-pair # Step 2: Sign SBOM cosign attest --predicate sbom.spdx.json \ --type spdx \ --key cosign.key \ myregistry/myapp:v1.2.3 # Step 3: Export attestation cosign verify-attestation myregistry/myapp:v1.2.3 \ --key cosign.pub \ --type spdx \ --output-file attestation.dsse.json # Step 4: Verify with StellaOps (custom public key) stella attest verify \ --envelope attestation.dsse.json \ --public-key cosign.pub \ --extract-sbom sbom.spdx.json # Step 5: Upload to StellaOps stella sbom upload --file sbom.spdx.json --artifact myapp:v1.2.3 ``` ### Workflow 3: CycloneDX Attestations **Use Case:** Work with CycloneDX BOMs from Trivy. ```bash # Step 1: Generate CycloneDX SBOM with Trivy trivy image myregistry/myapp:v1.2.3 \ --format cyclonedx \ --output sbom.cdx.json # Step 2: Sign with Cosign cosign attest --predicate sbom.cdx.json \ --type cyclonedx \ --key cosign.key \ myregistry/myapp:v1.2.3 # Step 3: Fetch and verify cosign verify-attestation myregistry/myapp:v1.2.3 \ --key cosign.pub \ --type cyclonedx \ --output-file attestation.dsse.json stella attest verify \ --envelope attestation.dsse.json \ --public-key cosign.pub \ --extract-sbom sbom.cdx.json # Step 4: Scan stella scan sbom sbom.cdx.json ``` --- ## CLI Reference ### `stella attest verify` Verify a Cosign-signed attestation and optionally extract the SBOM. ```bash stella attest verify [OPTIONS] Options: --envelope FILE DSSE envelope file (required) --root FILE Fulcio root certificate (for keyless) --public-key FILE Public key file (for key-based) --extract-sbom FILE Extract SBOM to file --offline Offline verification mode --checkpoint FILE Rekor checkpoint for offline verification --trust-root DIR Directory with trust roots --output FILE Verification report output (JSON) Examples: # Keyless verification (Sigstore public instance) stella attest verify --envelope attestation.dsse.json # Key-based verification stella attest verify \ --envelope attestation.dsse.json \ --public-key cosign.pub # Extract SBOM during verification stella attest verify \ --envelope attestation.dsse.json \ --extract-sbom sbom.json # Offline verification stella attest verify \ --envelope attestation.dsse.json \ --offline \ --trust-root /opt/stellaops/trust-roots \ --checkpoint rekor-checkpoint.json ``` ### `stella attest extract-sbom` Extract SBOM from a DSSE envelope without verification. ```bash stella attest extract-sbom [OPTIONS] Options: --envelope FILE DSSE envelope file (required) --output FILE Output SBOM file (required) --format FORMAT Force format (spdx|cyclonedx) Example: stella attest extract-sbom \ --envelope attestation.dsse.json \ --output sbom.spdx.json ``` ### `stella attest verify-image` Verify attestations attached to an OCI image. ```bash stella attest verify-image IMAGE [OPTIONS] Options: --type TYPE Predicate type (spdx|cyclonedx|slsaprovenance) --extract-sbom FILE Extract SBOM to file --public-key FILE Public key (for key-based signing) --offline Offline mode Example: stella attest verify-image myregistry/myapp:v1.2.3 \ --type spdx \ --extract-sbom sbom.spdx.json ``` --- ## Trust Configuration ### Default Trust Roots (Public Sigstore) StellaOps defaults to the Sigstore public instance: ```yaml # Default configuration (built-in) attestor: trustRoots: sigstore: enabled: true fulcioRootUrl: https://fulcio.sigstore.dev/api/v2/trustBundle rekorInstanceUrl: https://rekor.sigstore.dev cacheTTL: 24h ``` ### Custom Trust Roots (Air-Gapped) For air-gapped environments, provide trust roots offline: ```yaml # /etc/stellaops/attestor.yaml attestor: trustRoots: custom: enabled: true fulcioRoots: - /opt/stellaops/trust-roots/fulcio-root.pem - /opt/stellaops/trust-roots/fulcio-intermediate.pem rekorPublicKeys: - /opt/stellaops/trust-roots/rekor.pub ctfePublicKeys: - /opt/stellaops/trust-roots/ctfe.pub ``` **Trust Root Bundle Structure:** ``` /opt/stellaops/trust-roots/ ├── fulcio-root.pem # Fulcio root CA ├── fulcio-intermediate.pem # Fulcio intermediate CA (optional) ├── rekor.pub # Rekor public key ├── ctfe.pub # Certificate Transparency log public key └── checkpoints/ # Cached Rekor checkpoints └── rekor-checkpoint.json ``` ### Downloading Trust Roots ```bash # Download Sigstore public trust bundle curl -o trust-bundle.json \ https://tuf.sigstore.dev/targets/trusted_root.json # Extract Fulcio roots stella trust extract-fulcio-roots \ --bundle trust-bundle.json \ --output /opt/stellaops/trust-roots/ # Extract Rekor public keys stella trust extract-rekor-keys \ --bundle trust-bundle.json \ --output /opt/stellaops/trust-roots/ ``` --- ## Offline Verification ### Prerequisites 1. Trust roots downloaded and extracted 2. Rekor checkpoint bundle downloaded 3. Attestation DSSE envelope available locally ### Workflow ```bash # Step 1: Download trust bundle (online, one-time) stella trust download --output /opt/stellaops/trust-roots/ # Step 2: Download Rekor checkpoint (online, periodic) stella trust checkpoint download \ --output /opt/stellaops/trust-roots/checkpoints/rekor-checkpoint.json # Step 3: Verify offline (air-gapped environment) stella attest verify \ --envelope attestation.dsse.json \ --offline \ --trust-root /opt/stellaops/trust-roots \ --checkpoint /opt/stellaops/trust-roots/checkpoints/rekor-checkpoint.json \ --extract-sbom sbom.json # Step 4: Scan offline stella scan sbom sbom.json --offline ``` ### Checkpoint Freshness Rekor checkpoints should be refreshed periodically: - **High Security:** Daily updates - **Standard:** Weekly updates - **Low Risk:** Monthly updates Set a reminder to refresh checkpoints: ```bash # Cron job (daily at 2 AM) 0 2 * * * /usr/local/bin/stella trust checkpoint download --output /opt/stellaops/trust-roots/checkpoints/ ``` --- ## Troubleshooting ### Error: "Unsupported predicate type" **Cause:** The DSSE envelope contains a predicate type not supported by StellaOps. **Solution:** Check the predicate type: ```bash stella attest inspect --envelope attestation.dsse.json # Output will show: # Predicate Type: https://example.com/custom-type # Supported: false ``` If the predicate is SPDX or CycloneDX, ensure you're using StellaOps CLI v1.5+. ### Error: "Signature verification failed" **Cause:** The signature cannot be verified against the provided trust roots. **Troubleshooting Steps:** 1. Check trust root configuration: ```bash stella attest verify --envelope attestation.dsse.json --debug ``` 2. Verify the public key matches: ```bash # Extract public key from certificate in DSSE envelope stella attest inspect --envelope attestation.dsse.json --show-cert # Compare with your public key cat cosign.pub ``` 3. For keyless signing, ensure Fulcio root is correct: ```bash # Test Fulcio connectivity curl -v https://fulcio.sigstore.dev/api/v2/trustBundle ``` ### Error: "Failed to extract SBOM" **Cause:** The predicate payload is not a valid SBOM. **Solution:** Inspect the predicate: ```bash stella attest inspect --envelope attestation.dsse.json --show-predicate ``` Check if the predicate type matches the actual content: - `https://spdx.dev/Document` should contain SPDX JSON - `https://cyclonedx.org/bom` should contain CycloneDX JSON ### Warning: "Checkpoint is stale" **Cause:** The Rekor checkpoint is older than the freshness threshold (default: 7 days). **Solution:** Download a fresh checkpoint: ```bash stella trust checkpoint download \ --output /opt/stellaops/trust-roots/checkpoints/rekor-checkpoint.json ``` --- ## Best Practices ### 1. Verify Before Extraction Always verify the attestation signature before extracting the SBOM: ```bash # ✅ GOOD: Verify then extract stella attest verify \ --envelope attestation.dsse.json \ --extract-sbom sbom.json # ❌ BAD: Extract without verification stella attest extract-sbom \ --envelope attestation.dsse.json \ --output sbom.json ``` ### 2. Use Keyless Signing for Public Images For public container images, use keyless signing (Fulcio): - No key management overhead - Identity verified via OIDC - Transparent via Rekor ```bash # Keyless signing (recommended for public images) cosign attest --predicate sbom.spdx.json \ --type spdx \ myregistry/publicapp:v1.0.0 ``` ### 3. Use Key-Based Signing for Private/Air-Gapped For private registries or air-gapped environments, use key-based signing: - Full control over keys - No external dependencies - Works offline ```bash # Key-based signing (recommended for private/air-gapped) cosign attest --predicate sbom.spdx.json \ --type spdx \ --key cosign.key \ myregistry/privateapp:v1.0.0 ``` ### 4. Automate Trust Root Updates Set up automated trust root updates: ```bash #!/bin/bash # /usr/local/bin/update-trust-roots.sh set -e TRUST_DIR=/opt/stellaops/trust-roots # Download latest trust bundle stella trust download --output $TRUST_DIR --force # Download fresh checkpoint stella trust checkpoint download --output $TRUST_DIR/checkpoints/ # Verify trust roots stella trust verify --trust-root $TRUST_DIR echo "Trust roots updated successfully" ``` ### 5. Include Attestation in CI/CD Integrate attestation verification into your CI/CD pipeline: **GitHub Actions Example:** ```yaml name: Verify SBOM Attestation on: push: branches: [main] jobs: verify: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install StellaOps CLI run: | curl -sSfL https://cli.stellaops.io/install.sh | sh sudo mv stella /usr/local/bin/ - name: Verify attestation run: | stella attest verify-image \ ${{ env.IMAGE_REF }} \ --type spdx \ --extract-sbom sbom.spdx.json - name: Scan SBOM run: | stella scan sbom sbom.spdx.json \ --policy production \ --fail-on blocked - name: Upload results uses: actions/upload-artifact@v4 with: name: scan-results path: sbom.spdx.json ``` --- ## Advanced Topics ### Multi-Signature Verification Cosign supports multiple signatures on a single attestation. StellaOps verifies all signatures: ```bash # Attestation with multiple signatures cosign verify-attestation myregistry/myapp:v1.2.3 \ --key cosign-key1.pub \ --key cosign-key2.pub \ --type spdx \ --output-file attestation.dsse.json # StellaOps verifies all signatures stella attest verify \ --envelope attestation.dsse.json \ --public-key cosign-key1.pub \ --public-key cosign-key2.pub \ --require-all-signatures ``` ### Custom Predicate Types If you have custom predicate types, register them with StellaOps: ```yaml # /etc/stellaops/attestor.yaml attestor: predicates: custom: - type: https://example.com/custom-sbom@v1 parser: custom-sbom-parser schema: /opt/stellaops/schemas/custom-sbom.schema.json ``` ### Batch Verification Verify multiple attestations in batch: ```bash # Create batch file cat > batch.txt <