309 lines
8.4 KiB
Markdown
309 lines
8.4 KiB
Markdown
# Cosign Interoperability Guide
|
|
|
|
This document describes how to verify StellaOps attestations using [cosign](https://github.com/sigstore/cosign) and how to import cosign-created attestations into StellaOps.
|
|
|
|
## Overview
|
|
|
|
StellaOps attestations use the [DSSE (Dead Simple Signing Envelope)](https://github.com/secure-systems-lab/dsse) 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
|
|
|
|
```bash
|
|
# 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)
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```yaml
|
|
# 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:
|
|
|
|
```yaml
|
|
# 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:
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```rego
|
|
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
|
|
|
|
```yaml
|
|
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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
COSIGN_EXPERIMENTAL=1 cosign verify-attestation \
|
|
--verbose \
|
|
--type stellaops.io/predicates/scan-result@v1 \
|
|
registry.example.com/app:v1.0.0
|
|
```
|
|
|
|
## References
|
|
|
|
- [Cosign Documentation](https://docs.sigstore.dev/cosign/overview/)
|
|
- [DSSE Specification](https://github.com/secure-systems-lab/dsse)
|
|
- [In-toto Attestation Framework](https://in-toto.io/)
|
|
- [OCI Distribution Spec 1.1 Referrers](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#referrers)
|
|
- [StellaOps Attestor Architecture](../modules/attestor/architecture.md)
|