8.4 KiB
Cosign Interoperability Guide
This document describes how to verify StellaOps attestations using cosign and how to import cosign-created attestations into StellaOps.
Overview
StellaOps attestations use the DSSE (Dead Simple Signing Envelope) format and OCI Distribution Spec 1.1 referrers API for attachment, which is compatible with cosign's attestation workflow.
Sprint Reference: SPRINT_20251228_002_BE_oci_attestation_attach (T6)
Verifying StellaOps Attestations with Cosign
Basic Verification
# Verify any attestation attached to an image
cosign verify-attestation \
--type custom \
--certificate-identity-regexp '.*' \
--certificate-oidc-issuer-regexp '.*' \
registry.example.com/app:v1.0.0
# Verify a specific predicate type
cosign verify-attestation \
--type stellaops.io/predicates/scan-result@v1 \
--certificate-identity-regexp '.*' \
--certificate-oidc-issuer-regexp '.*' \
registry.example.com/app:v1.0.0
Verification with Trust Roots
StellaOps supports both keyless (Sigstore Fulcio) and key-based signing:
Keyless Verification (Sigstore)
# Verify attestation signed with keyless mode
cosign verify-attestation \
--type stellaops.io/predicates/scan-result@v1 \
--certificate-identity 'scanner@stellaops.io' \
--certificate-oidc-issuer 'https://oauth2.sigstore.dev/auth' \
registry.example.com/app:v1.0.0
Key-Based Verification
# Verify attestation signed with a specific key
cosign verify-attestation \
--type stellaops.io/predicates/scan-result@v1 \
--key /path/to/public-key.pem \
registry.example.com/app:v1.0.0
Rekor Transparency Log Verification
When StellaOps attestations are recorded in Rekor, cosign automatically verifies the inclusion proof:
# Verify with Rekor inclusion proof
cosign verify-attestation \
--type stellaops.io/predicates/scan-result@v1 \
--certificate-identity-regexp '.*' \
--certificate-oidc-issuer-regexp '.*' \
--rekor-url https://rekor.sigstore.dev \
registry.example.com/app:v1.0.0
# Skip Rekor verification (offline environments)
cosign verify-attestation \
--type stellaops.io/predicates/scan-result@v1 \
--key /path/to/public-key.pem \
--insecure-ignore-tlog \
registry.example.com/app:v1.0.0
StellaOps Predicate Types
StellaOps uses the following predicate type URIs:
| Predicate Type | Description | cosign --type |
|---|---|---|
stellaops.io/predicates/scan-result@v1 |
Vulnerability scan results | stellaops.io/predicates/scan-result@v1 |
stellaops.io/predicates/sbom@v1 |
Software Bill of Materials | stellaops.io/predicates/sbom@v1 |
stellaops.io/predicates/vex@v1 |
Vulnerability Exploitability eXchange | stellaops.io/predicates/vex@v1 |
https://slsa.dev/provenance/v1 |
SLSA Provenance | slsaprovenance |
Predicate Type Aliases
For convenience, cosign supports type aliases:
# These are equivalent for SLSA provenance
cosign verify-attestation --type slsaprovenance ...
cosign verify-attestation --type https://slsa.dev/provenance/v1 ...
Importing Cosign Attestations into StellaOps
StellaOps can consume attestations created by cosign:
CLI Import
# Fetch cosign attestation and import to StellaOps
cosign download attestation registry.example.com/app:v1.0.0 > attestation.json
# Import into StellaOps
stella attest import \
--envelope attestation.json \
--image registry.example.com/app:v1.0.0
API Import
curl -X POST https://stellaops.example.com/api/v1/attestations/import \
-H "Content-Type: application/json" \
-d @attestation.json
Annotation Compatibility
StellaOps uses the following annotations on attestation manifests:
| Annotation Key | Description | Cosign Equivalent |
|---|---|---|
org.opencontainers.image.created |
Creation timestamp | Standard OCI |
dev.stellaops/predicate-type |
Predicate type URI | dev.cosignproject.cosign/predicateType |
dev.stellaops/tenant |
StellaOps tenant ID | Custom |
dev.stellaops/scan-id |
Associated scan ID | Custom |
dev.sigstore.cosign/signature |
Signature placeholder | Standard Sigstore |
Custom Annotations
You can add custom annotations when attaching attestations:
# Stella CLI with custom annotations
stella attest attach \
--image registry.example.com/app:v1.0.0 \
--attestation scan.json \
--annotation "org.example/team=security" \
--annotation "org.example/policy-version=2.0"
Media Types
StellaOps attestations use standard media types:
| Media Type | Usage |
|---|---|
application/vnd.dsse.envelope.v1+json |
DSSE envelope containing attestation |
application/vnd.in-toto+json |
In-toto attestation payload |
application/vnd.oci.image.manifest.v1+json |
OCI manifest for referrers |
Trust Root Configuration
Sigstore Trust Roots
For keyless verification, configure the Sigstore trust bundle:
# stellaops.yaml
attestation:
trustRoots:
sigstore:
enabled: true
fulcioUrl: https://fulcio.sigstore.dev
rekorUrl: https://rekor.sigstore.dev
ctlogUrl: https://ctfe.sigstore.dev
Custom Trust Roots
For enterprise deployments with private Sigstore instances:
# stellaops.yaml
attestation:
trustRoots:
sigstore:
enabled: true
fulcioUrl: https://fulcio.internal.example.com
rekorUrl: https://rekor.internal.example.com
trustedRootPem: /etc/stellaops/sigstore-root.pem
Air-Gapped Environments
For offline verification:
# stellaops.yaml
attestation:
trustRoots:
offline: true
bundlePath: /etc/stellaops/trust-bundle.json
Policy Integration
Attestation verification can be integrated into admission control policies:
Gatekeeper/OPA Policy Example
package stellaops.attestation
deny[msg] {
input.kind == "Pod"
container := input.spec.containers[_]
image := container.image
# Require scan attestation
not has_valid_attestation(image, "stellaops.io/predicates/scan-result@v1")
msg := sprintf("Image %v missing valid scan attestation", [image])
}
has_valid_attestation(image, predicate_type) {
attestation := stellaops.get_attestation(image, predicate_type)
stellaops.verify_attestation(attestation)
}
Kyverno Policy Example
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-stellaops-attestation
spec:
validationFailureAction: Enforce
rules:
- name: check-scan-attestation
match:
resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "*"
attestations:
- predicateType: stellaops.io/predicates/scan-result@v1
attestors:
- entries:
- keyless:
issuer: https://oauth2.sigstore.dev/auth
subject: scanner@stellaops.io
Troubleshooting
Common Issues
No Attestations Found
# List all attestations attached to an image
cosign tree registry.example.com/app:v1.0.0
# Or use stella CLI
stella attest oci-list --image registry.example.com/app:v1.0.0
Signature Verification Failed
Check that you're using the correct verification key or identity:
# Inspect the attestation to see signer identity
cosign verify-attestation \
--type stellaops.io/predicates/scan-result@v1 \
--certificate-identity-regexp '.*' \
--certificate-oidc-issuer-regexp '.*' \
--output text \
registry.example.com/app:v1.0.0 | jq '.optional.Issuer, .optional.Subject'
Rekor Entry Not Found
If the attestation was created without Rekor submission:
cosign verify-attestation \
--insecure-ignore-tlog \
--key /path/to/public-key.pem \
registry.example.com/app:v1.0.0
Debug Mode
Enable verbose output for troubleshooting:
COSIGN_EXPERIMENTAL=1 cosign verify-attestation \
--verbose \
--type stellaops.io/predicates/scan-result@v1 \
registry.example.com/app:v1.0.0