- Introduced attestation inventory and subject-rekor mapping files for tracking Docker packages. - Added a comprehensive crypto registry decision document outlining defaults and required follow-ups. - Created an offline feeds manifest for bundling air-gap resources. - Implemented a script to generate and update binary manifests for curated binaries. - Added a verification script to ensure binary artefacts are located in approved directories. - Defined new schemas for AdvisoryEvidenceBundle, OrchestratorEnvelope, ScannerReportReadyPayload, and ScannerScanCompletedPayload. - Established project files for StellaOps.Orchestrator.Schemas and StellaOps.PolicyAuthoritySignals.Contracts. - Updated vendor manifest to track pinned binaries for integrity.
23 KiB
Here’s a clean, air‑gap‑ready spine for turning container images into verifiable SBOMs and provenance—built to be idempotent and easy to slot into Stella Ops or any CI/CD.
flowchart LR
A[OCI Image/Repo]-->B[Layer Extractor]
B-->C[Sbomer: CycloneDX/SPDX]
C-->D[DSSE Sign]
D-->E[in-toto Statement (SLSA Provenance)]
E-->F[Transparency Log Adapter]
C-->G[POST /sbom/ingest]
F-->H[POST /attest/verify]
What this does (in plain words)
- Pull & crack the image → extract layers, metadata (labels, env, history).
- Build an SBOM → emit CycloneDX 1.6 and SPDX 3.0.1 (pick one or both).
- Sign artifacts → wrap SBOM/provenance in DSSE envelopes.
- Provenance → generate in‑toto Statement with SLSA Provenance v1 as the predicate.
- Auditability → optionally publish attestations to a transparency log (e.g., Rekor) so they’re tamper‑evident via Merkle proofs.
- APIs are idempotent → safe to re‑ingest the same image/SBOM/attestation without version churn.
Design notes you can hand to an agent
-
Idempotency keys
contentAddress= SHA256 of OCI manifest (or full image digest)sbomHash= SHA256 of normalized SBOM JSONattHash= SHA256 of DSSE payload (base64‑stable) Store these; reject duplicates with HTTP 200 +"status":"already_present".
-
Default formats
- SBOM export: CycloneDX v1.6 (
application/vnd.cyclonedx+json), SPDX 3.0.1 (application/spdx+json) - DSSE envelope:
application/dsse+json - in‑toto Statement:
application/vnd.in-toto+jsonwithpredicateType= SLSA Provenance v1
- SBOM export: CycloneDX v1.6 (
-
Air‑gap mode
- No external calls required; Rekor publish is optional.
- Keep a local Merkle log (pluggable) and allow later “sync‑to‑Rekor” when online.
-
Transparency log adapter
- Interface:
Put(entry) -> {logIndex, logID, inclusionProof} - Backends:
rekor,local-merkle,null(no‑op)
- Interface:
Minimal API sketch
-
POST /sbom/ingest- Body:
{ imageDigest, sbom, format, dsseSignature? } - Returns:
{ sbomId, status, sbomHash }(status:stored|already_present)
- Body:
-
POST /attest/verify- Body:
{ dsseEnvelope, expectedSubjects:[{name, digest}] } - Verifies DSSE, checks in‑toto subject ↔ image digest, optionally records/logs.
- Returns:
{ verified:true, predicateType, logIndex?, inclusionProof? }
- Body:
CLI flow (pseudocode)
# 1) Extract
stella-extract --image $IMG --out /work/extract
# 2) SBOM (Cdx + SPDX)
stella-sbomer cdx --in /work/extract --out /work/sbom.cdx.json
stella-sbomer spdx --in /work/extract --out /work/sbom.spdx.json
# 3) DSSE sign (offline keyring or HSM)
stella-sign dsse --in /work/sbom.cdx.json --out /work/sbom.cdx.dsse.json --key file:k.pem
# 4) SLSA provenance (in‑toto Statement)
stella-provenance slsa-v1 --subject $IMG_DIGEST --materials /work/extract/manifest.json \
--out /work/prov.dsse.json --key file:k.pem
# 5) (optional) Publish to transparency log
stella-log publish --in /work/prov.dsse.json --backend rekor --rekor-url $REKOR
Validation rules (quick)
- Subject binding: in‑toto Statement
subject[].digest.sha256must equal the OCI image digest you scanned. - Key policy: enforce allowed issuers (Fulcio, internal CA, GOST/SM/EIDAS/FIPS as needed).
- Normalization: canonicalize JSON before hashing/signing to keep idempotency stable.
Why this matters
- Audit‑ready: You can always prove what you scanned, how it was built, and who signed it.
- Noise‑gated: With deterministic SBOMs + provenance, downstream VEX/reachability gets much cleaner.
- Drop‑in: Works in harsh environments—offline, mirrors, sovereign crypto stacks—without changing your pipeline.
If you want, I can generate:
- a ready‑to‑use OpenAPI stub for
POST /sbom/ingestandPOST /attest/verify, - C# (.NET 10) DSSE + in‑toto helpers (interfaces + test fixtures),
- or a Docker‑compose “air‑gap bundle” showing the full spine end‑to‑end. Below is a full architecture plan you can hand to an agent as the “master spec” for implementing the SBOM & provenance spine (image → SBOM → DSSE → in-toto/SLSA → transparency log → REST APIs), with idempotent APIs and air-gap readiness.
1. Scope and Objectives
Goal: Implement a deterministic, air-gap-ready “SBOM spine” that:
-
Converts OCI images into SBOMs (CycloneDX 1.6 and SPDX 3.0.1).
-
Generates SLSA v1 provenance wrapped in in-toto Statements.
-
Signs all artifacts with DSSE envelopes using pluggable crypto providers.
-
Optionally publishes attestations to transparency logs (Rekor/local-Merkle/none).
-
Exposes stable, idempotent APIs:
POST /sbom/ingestPOST /attest/verify
-
Avoids versioning by design; APIs are extended, not versioned; all mutations are idempotent keyed by content digests.
Out of scope (for this iteration):
- Full vulnerability scanning (delegated to Scanner service).
- Policy evaluation / lattice logic (delegated to Scanner/Graph engine).
- Vendor-facing proof-market ledger and trust economics (future module).
2. High-Level Architecture
2.1 Logical Components
-
StellaOps.SupplyChain.Core (Library)
-
Shared types and utilities:
- Domain models: SBOM, DSSE, in-toto Statement, SLSA predicates.
- Canonicalization & hashing utilities.
- DSSE sign/verify abstractions.
- Transparency log entry model & Merkle proof verification.
-
-
StellaOps.Sbomer.Engine (Library)
-
Image → SBOM functionality:
- Layer & manifest analysis.
- SBOM generation: CycloneDX, SPDX.
- Extraction of metadata (labels, env, history).
- Deterministic ordering & normalization.
-
-
StellaOps.Provenance.Engine (Library)
-
Build provenance & in-toto:
- In-toto Statement generator.
- SLSA v1 provenance predicate builder.
- Subject and material resolution from image metadata & SBOM.
-
-
StellaOps.Authority (Service/Library)
-
Crypto & keys:
- Key management abstraction (file, HSM, KMS, sovereign crypto).
- DSSE signing & verification with multiple key types.
- Trust roots, certificate chains, key policies.
-
-
StellaOps.LogBridge (Service/Library)
-
Transparency log adapter:
- Rekor backend.
- Local Merkle log backend (for air-gap).
- Null backend (no-op).
- Merkle proof validation.
-
-
StellaOps.SupplyChain.Api (Service)
-
The SBOM spine HTTP API:
POST /sbom/ingestPOST /attest/verify- Optionally:
GET /sbom/{id},GET /attest/{id},GET /image/{digest}/summary.
-
Performs orchestrations:
- SBOM/attestation parsing, canonicalization, hashing.
- Idempotency and persistence.
- Delegation to Authority and LogBridge.
-
-
CLI Tools (optional but recommended)
stella-extract,stella-sbomer,stella-sign,stella-provenance,stella-log.- Thin wrappers over the above libraries; usable offline and in CI pipelines.
-
Persistence Layer
- Primary DB: PostgreSQL (or other RDBMS).
- Optional object storage: S3/MinIO for large SBOM/attestation blobs.
- Tables:
images,sboms,attestations,signatures,log_entries,keys.
2.2 Deployment View (Kubernetes / Docker)
flowchart LR
subgraph Node1[Cluster Node]
A[StellaOps.SupplyChain.Api (ASP.NET Core)]
B[StellaOps.Authority Service]
C[StellaOps.LogBridge Service]
end
subgraph Node2[Worker Node]
D[Runner / CI / Air-gap host]
E[CLI Tools\nstella-extract/sbomer/sign/provenance/log]
end
F[(PostgreSQL)]
G[(Object Storage\nS3/MinIO)]
H[(Local Merkle Log\nor Rekor)]
A --> F
A --> G
A --> C
A --> B
C --> H
E --> A
-
Air-gap mode:
- Rekor backend disabled; LogBridge uses local Merkle log (
H) ornull. - All components run within the offline network.
- Rekor backend disabled; LogBridge uses local Merkle log (
-
Online mode:
- LogBridge talks to external Rekor instance using outbound HTTPS only.
3. Domain Model and Storage Design
Use EF Core 9 with PostgreSQL in .NET 10.
3.1 Core Entities
-
ImageArtifact
Id(GUID/ULID, internal).ImageDigest(string; OCI digest; UNIQUE).Registry(string).Repository(string).Tag(string, nullable, since digest is canonical).FirstSeenAt(timestamp).MetadataJson(JSONB; manifest, labels, env).
-
Sbom
Id(string, primary key =SbomHashor derived ULID).ImageArtifactId(FK).Format(enum:CycloneDX_1_6,SPDX_3_0_1).ContentHash(string; normalized JSON SHA-256; UNIQUE withTenantId).StorageLocation(inline JSONB or external object storage key).CreatedAt.Origin(enum:Generated,Uploaded,ExternalVendor).- Unique constraint:
(TenantId, ContentHash).
-
Attestation
Id(string, primary key =AttestationHashor derived ULID).ImageArtifactId(FK).Type(enum:InTotoStatement_SLSA_v1,Other).PayloadHash(hash of DSSE payload, before envelope).DsseEnvelopeHash(hash of full DSSE JSON).StorageLocation(inline JSONB or object storage).CreatedAt.Issuer(string; signer identity / certificate subject).- Unique constraint:
(TenantId, DsseEnvelopeHash).
-
SignatureInfo
Id(GUID/ULID).AttestationId(FK).KeyId(logical key identifier).Algorithm(enum; includes PQ & sovereign algs).VerifiedAt.VerificationStatus(enum:Valid,Invalid,Unknown).DetailsJson(JSONB; trust-chain, error reasons, etc.).
-
TransparencyLogEntry
Id(GUID/ULID).AttestationId(FK).Backend(enum:Rekor,LocalMerkle).LogIndex(string).LogId(string).InclusionProofJson(JSONB).RecordedAt.- Unique constraint:
(Backend, LogId, LogIndex).
-
KeyRecord (optional if not reusing Authority’s DB)
KeyId(string, PK).KeyType(enum).Usage(enum:Signing,Verification,Both).Status(enum:Active,Retired,Revoked).MetadataJson(JSONB; KMS ARN, HSM slot, etc.).
3.2 Idempotency Keys
-
SBOM:
sbomHash = SHA256(canonicalJson(sbom)).- Uniqueness enforced by
(TenantId, sbomHash)in DB.
-
Attestation:
attHash = SHA256(canonicalJson(dsse.payload))or full envelope.- Uniqueness enforced by
(TenantId, attHash)in DB.
-
Image:
imageDigestis globally unique (per OCI spec).
4. Service-Level Architecture
4.1 StellaOps.SupplyChain.Api (.NET 10, ASP.NET Core)
Responsibilities:
- Expose HTTP API for ingest / verify.
- Handle idempotency logic & persistence.
- Delegate cryptographic operations to Authority.
- Delegate transparency logging to LogBridge.
- Perform basic validation against schemas (SBOM, DSSE, in-toto, SLSA).
Key Endpoints:
-
POST /sbom/ingest-
Request:
imageDigest(string).sbom(raw JSON).format(enum/string).- Optional:
dsseSignatureordsseEnvelope.
-
Behavior:
-
Parse & validate SBOM structure.
-
Canonicalize JSON, compute
sbomHash. -
If
sbomHashexists forimageDigestand tenant:- Return
200with{ status: "already_present", sbomId, sbomHash }.
- Return
-
Else:
- Persist
Sbomentity. - Optionally verify DSSE signature via Authority.
- Return
201with{ status: "stored", sbomId, sbomHash }.
- Persist
-
-
-
POST /attest/verify-
Request:
dsseEnvelope(JSON).expectedSubjects(list of{ name, digest }).
-
Behavior:
-
Canonicalize payload, compute
attHash. -
Verify DSSE signature via Authority.
-
Parse in-toto Statement; ensure
subject[].digest.sha256matchesexpectedSubjects. -
Persist
Attestation&SignatureInfo. -
If configured, call LogBridge to publish and store
TransparencyLogEntry. -
If
attHashalready exists:- Return
200withstatus: "already_present"and existing references.
- Return
-
Else, return
201withverified:true, plus log info when available.
-
-
-
Optional read APIs:
GET /sbom/by-image/{digest}GET /attest/by-image/{digest}GET /image/{digest}/summary(SBOM + attestations + log status).
4.2 StellaOps.Sbomer.Engine
Responsibilities:
-
Given:
- OCI image manifest & layers (from local tarball or remote registry).
-
Produce:
- CycloneDX 1.6 JSON.
- SPDX 3.0.1 JSON.
Design:
-
Use layered analyzers:
-
ILayerAnalyzerfor generic filesystem traversal. -
Language-specific analyzers (optional for SBOM detail):
DotNetAnalyzer,NodeJsAnalyzer,PythonAnalyzer,JavaAnalyzer,PhpAnalyzer, etc.
-
-
Determinism:
- Sort all lists (components, dependencies) by stable keys.
- Remove unstable fields (timestamps, machine IDs, ephemeral paths).
- Provide
Normalize()method per format that returns canonical JSON.
4.3 StellaOps.Provenance.Engine
Responsibilities:
-
Build in-toto Statement with SLSA v1 predicate:
-
subjectderived from image digest(s). -
materialsfrom:- Git commit, tag, builder image, SBOM components if available.
-
-
Ensure determinism:
- Sort materials by URI + digest.
- Normalize nested maps.
Key APIs (internal library):
InTotoStatement BuildSlsaProvenance(ImageArtifact image, Sbom sbom, ProvenanceContext ctx)string ToCanonicalJson(InTotoStatement stmt)
4.4 StellaOps.Authority
Responsibilities:
- DSSE signing & verification.
- Key management abstraction.
- Policy enforcement (which keys/trust roots are allowed).
Interfaces:
-
ISigningProviderTask<DsseEnvelope> SignAsync(byte[] payload, string payloadType, string keyId)
-
IVerificationProviderTask<VerificationResult> VerifyAsync(DsseEnvelope envelope, VerificationPolicy policy)
Backends:
- File-based keys (PEM).
- HSM/KMS (AWS KMS, Azure Key Vault, on-prem HSM).
- Sovereign crypto providers (GOST, SMx, etc.).
- Optional PQ providers (Dilithium, Falcon).
4.5 StellaOps.LogBridge
Responsibilities:
- Abstract interaction with transparency logs.
Interface:
-
ILogBackendTask<LogEntryResult> PutAsync(byte[] canonicalPayloadHash, DsseEnvelope env)Task<ProofResult> VerifyInclusionAsync(LogEntryResult entry)
Backends:
-
RekorBackend:- Calls Rekor REST API with hashed payload.
-
LocalMerkleBackend:- Maintains Merkle tree in local DB.
- Returns
logIndex,logId, and inclusion proof.
-
NullBackend:- Returns empty/no-op results.
4.6 CLI Tools (Optional)
Use the same libraries as the services:
-
stella-extract:- Input: image reference.
- Output: local tarball + manifest JSON.
-
stella-sbomer:- Input: manifest & layers.
- Output: SBOM JSON.
-
stella-sign:- Input: JSON file.
- Output: DSSE envelope.
-
stella-provenance:- Input: image digest, build metadata.
- Output: signed in-toto/SLSA DSSE.
-
stella-log:- Input: DSSE envelope.
- Output: log entry details.
5. End-to-End Flows
5.1 SBOM Ingest (Upload Path)
sequenceDiagram
participant Client
participant API as SupplyChain.Api
participant Core as SupplyChain.Core
participant DB as PostgreSQL
Client->>API: POST /sbom/ingest (imageDigest, sbom, format)
API->>Core: Validate & canonicalize SBOM
Core-->>API: sbomHash
API->>DB: SELECT Sbom WHERE sbomHash & imageDigest
DB-->>API: Not found
API->>DB: INSERT Sbom (sbomHash, imageDigest, content)
DB-->>API: ok
API-->>Client: 201 { status:"stored", sbomId, sbomHash }
Re-ingest of the same SBOM repeats steps up to SELECT, then returns status:"already_present" with 200.
5.2 Attestation Verify & Record
sequenceDiagram
participant Client
participant API as SupplyChain.Api
participant Auth as Authority
participant Log as LogBridge
participant DB as PostgreSQL
Client->>API: POST /attest/verify (dsseEnvelope, expectedSubjects)
API->>Auth: Verify DSSE (keys, policy)
Auth-->>API: VerificationResult(Valid/Invalid)
API->>API: Parse in-toto, check subjects vs expected
API->>DB: SELECT Attestation WHERE attHash
DB-->>API: Not found
API->>DB: INSERT Attestation + SignatureInfo
alt Logging enabled
API->>Log: PutAsync(attHash, envelope)
Log-->>API: LogEntryResult(logIndex, logId, proof)
API->>DB: INSERT TransparencyLogEntry
end
API-->>Client: 201 { verified:true, attestationId, logIndex?, inclusionProof? }
If attestation already exists, API returns 200 with status:"already_present".
6. Idempotency and Determinism Strategy
-
Canonicalization rules:
- Remove insignificant whitespace.
- Sort all object keys lexicographically.
- Sort arrays where order is not semantically meaningful (components, materials).
- Strip non-deterministic fields (timestamps, random IDs) where allowed.
-
Hashing:
- Always hash canonical JSON as UTF-8.
- Use SHA-256 for core IDs; allow crypto provider to also compute other digests if needed.
-
Persistence:
-
Enforce uniqueness in DB via indices on:
(TenantId, ContentHash)for SBOMs.(TenantId, AttHash)for attestations.(Backend, LogId, LogIndex)for log entries.
-
API behavior:
- Existing row →
200with"already_present". - New row →
201with"stored".
- Existing row →
-
-
API design:
- No version numbers in path.
- Add fields over time; never break or repurpose existing ones.
- Use explicit capability discovery via
GET /meta/capabilitiesif needed.
7. Air-Gap Mode and Synchronization
7.1 Air-Gap Mode
-
Configuration flag
Mode = Offlineon SupplyChain.Api. -
LogBridge backend:
- Default to
LocalMerkleorNull.
- Default to
-
Rekor-specific configuration disabled or absent.
-
DB & Merkle log stored locally inside the secure network.
7.2 Later Synchronization to Rekor (Optional Future Step)
Not mandatory for first iteration, but prepare for:
-
Background job (Scheduler module) that:
- Enumerates local
TransparencyLogEntrynot yet exported. - Publishes hashed payloads to Rekor when network is available.
- Stores mapping between local log entries and remote Rekor entries.
- Enumerates local
8. Security, Access Control, and Observability
8.1 Security
-
mTLS between internal services (SupplyChain.Api, Authority, LogBridge).
-
Authentication:
- API keys/OIDC for clients.
- Per-tenant scoping;
TenantIdmust be present in context.
-
Authorization:
- RBAC: which tenants/users can write/verify/only read.
8.2 Crypto Policies
-
Policy object defines:
- Allowed key types and algorithms.
- Trust roots (Fulcio, internal CA, sovereign PKI).
- Revocation checking strategy (CRL/OCSP, offline lists).
-
Authority enforces policies; SupplyChain.Api only consumes
VerificationResult.
8.3 Observability
-
Logs:
- Structured logs with correlation IDs; log imageDigest, sbomHash, attHash.
-
Metrics:
- SBOM ingest count, dedup hit rate.
- Attestation verify latency.
- Transparency log publish success/failure counts.
-
Traces:
- OpenTelemetry tracing across API → Authority → LogBridge.
9. Implementation Plan (Epics & Work Packages)
You can give this section directly to agents to split.
Epic 1: Core Domain & Canonicalization
-
Define .NET 10 solution structure:
-
Projects:
StellaOps.SupplyChain.CoreStellaOps.Sbomer.EngineStellaOps.Provenance.EngineStellaOps.SupplyChain.ApiStellaOps.Authority(if not already present)StellaOps.LogBridge
-
-
Implement core domain models:
- SBOM, DSSE, in-toto, SLSA v1.
-
Implement canonicalization & hashing utilities.
-
Unit tests:
- Given semantically equivalent JSON, hashes must match.
- Negative tests where order changes but meaning does not.
Epic 2: Persistence Layer
-
Design EF Core models for:
- ImageArtifact, Sbom, Attestation, SignatureInfo, TransparencyLogEntry, KeyRecord.
-
Write migrations for PostgreSQL.
-
Implement repository interfaces for read/write.
-
Tests:
- Unique constraints and idempotency behavior.
- Query performance for common access paths (by imageDigest).
Epic 3: SBOM Engine
-
Implement minimal layer analysis:
- Accepts local tarball or path (for now).
-
Implement CycloneDX 1.6 generator.
-
Implement SPDX 3.0.1 generator.
-
Deterministic normalization across formats.
-
Tests:
- Golden files for images → SBOM output.
- Stability under repeated runs.
Epic 4: Provenance Engine
-
Implement in-toto Statement model with SLSA v1 predicate.
-
Implement builder to map:
- ImageDigest → subject.
- Build metadata → materials.
-
Deterministic canonicalization.
-
Tests:
- Golden in-toto/SLSA statements for sample inputs.
- Subject matching logic.
Epic 5: Authority Integration
-
Implement
ISigningProvider,IVerificationProvidercontracts. -
Implement file-based key backend as default.
-
Implement DSSE wrapper:
SignAsync(payload, payloadType, keyId).VerifyAsync(envelope, policy).
-
Tests:
- DSSE round-trip; invalid signature scenarios.
- Policy enforcement tests.
Epic 6: Transparency Log Bridge
-
Implement
ILogBackendinterface. -
Implement
LocalMerkleBackend:- Simple Merkle tree with DB storage.
-
Implement
NullBackend. -
Define configuration model to select backend.
-
(Optional later) Implement
RekorBackend. -
Tests:
- Stable Merkle root; inclusion proof verification.
Epic 7: SupplyChain.Api
-
Implement
POST /sbom/ingest:- Request/response DTOs.
- Integration with canonicalization, persistence, idempotency logic.
-
Implement
POST /attest/verify:- End-to-end verification and persistence.
- Integration with Authority and LogBridge.
-
Optional read APIs.
-
Add input validation (JSON schema, basic constraints).
-
Integration tests:
- Full flows for new and duplicate inputs.
- Error cases (invalid DSSE, subject mismatch).
Epic 8: CLI Tools
- Implement
stella-sbomer(wraps Sbomer.Engine). - Implement
stella-provenance(wraps Provenance.Engine + Authority). - Implement
stella-signandstella-log. - Provide clear help/usage and sample scripts.
Epic 9: Hardening, Air-Gap Profile, and Docs
-
Configuration profiles:
OfflinevsOnline.- Log backend selection.
-
Security hardening:
- mTLS, authentication, authorization.
-
Observability:
- Metrics, logs, traces wiring.
-
Documentation:
-
API reference.
-
Sequence diagrams.
-
Deployment recipes for:
- Single-node air-gap.
- Clustered online deployment.
-
If you want, next step I can:
- Turn this into an AGENTS/TASKS/PROMPT set for your codex workers, or
- Produce concrete .NET 10 project skeletons (csproj layout, folder structure, and initial interfaces) for the core libraries and API service.