- Added MongoPackRunApprovalStore for managing approval states with MongoDB. - Introduced MongoPackRunArtifactUploader for uploading and storing artifacts. - Created MongoPackRunLogStore to handle logging of pack run events. - Developed MongoPackRunStateStore for persisting and retrieving pack run states. - Implemented unit tests for MongoDB stores to ensure correct functionality. - Added MongoTaskRunnerTestContext for setting up MongoDB test environment. - Enhanced PackRunStateFactory to correctly initialize state with gate reasons.
6.7 KiB
BuildX Generator Quickstart
This quickstart explains how to run the StellaOps BuildX SBOM generator offline, verify the CAS handshake, and emit OCI descriptors that downstream services can attest.
1. Prerequisites
- Docker 25+ with BuildKit enabled (
docker buildxavailable). - .NET 10 (preview) SDK matching the repository
global.json. - Optional: network access to a StellaOps Attestor endpoint (the quickstart uses a mock service).
2. Publish the plug-in binaries
The BuildX generator publishes as a .NET self-contained executable with its manifest under plugins/scanner/buildx/.
# From the repository root
DOTNET_CLI_HOME="${PWD}/.dotnet" \
dotnet publish src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/StellaOps.Scanner.Sbomer.BuildXPlugin.csproj \
-c Release \
-o out/buildx
out/buildx/now containsStellaOps.Scanner.Sbomer.BuildXPlugin.dlland the manifeststellaops.sbom-indexer.manifest.json.plugins/scanner/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin/receives the same artefacts for release packaging.- The CI pipeline also tars and signs (SHA-256 manifest) the OS analyzer plug-ins located under
plugins/scanner/analyzers/os/so they ship alongside the BuildX generator artefacts.
3. Verify the CAS handshake
dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll handshake \
--manifest out/buildx \
--cas out/cas
The command performs a deterministic probe write (sha256) into the provided CAS directory and prints the resolved path.
4. Emit a descriptor + provenance placeholder
-
Build or identify the image you want to describe and capture its digest:
docker buildx build --load -t stellaops/buildx-demo:ci samples/ci/buildx-demo DIGEST=$(docker image inspect stellaops/buildx-demo:ci --format '{{index .RepoDigests 0}}') -
Generate a CycloneDX SBOM for the built image (any tool works; here we use
docker sbom):docker sbom stellaops/buildx-demo:ci --format cyclonedx-json > out/buildx-sbom.cdx.json -
Invoke the
descriptorcommand, pointing at the SBOM file and optional metadata:dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll descriptor \ --manifest out/buildx \ --image "$DIGEST" \ --sbom out/buildx-sbom.cdx.json \ --sbom-name buildx-sbom.cdx.json \ --artifact-type application/vnd.stellaops.sbom.layer+json \ --sbom-format cyclonedx-json \ --sbom-kind inventory \ --repository git.stella-ops.org/stellaops/buildx-demo \ --build-ref $(git rev-parse HEAD) \ > out/buildx-descriptor.json
The output JSON captures:
- OCI artifact descriptor including size, digest, and annotations (
org.stellaops.*). - Provenance placeholder (
expectedDsseSha256,nonce,attestorUriwhen provided).nonceis derived deterministically from the image + SBOM metadata so repeated runs produce identical placeholders for identical inputs. - Generator metadata and deterministic timestamps.
4.1 Persist Surface manifests & payloads (optional)
Pass the new --surface-* switches to the descriptor command whenever you have Surface artefacts (layer fragments, EntryTrace graph/NDJSON) that should be cached during build-time scans. The plug-in stores the payloads under the configured CAS root (defaults to --cas) and emits a manifest pointer that Scanner/WebService can consume later.
dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll descriptor \
--manifest out/buildx \
--image "$DIGEST" \
--sbom out/buildx-sbom.cdx.json \
--surface-layer-fragments out/layer-fragments.json \
--surface-entrytrace-graph out/entrytrace-graph.json \
--surface-entrytrace-ndjson out/entrytrace.ndjson \
--surface-cache-root out/cas \
--surface-tenant demo-tenant \
--surface-manifest-output out/surface-manifest.json \
> out/buildx-descriptor.json
Environment variables mirror the CLI flags when you need deterministic defaults:
| Variable | Purpose |
|---|---|
STELLAOPS_SURFACE_CACHE_ROOT |
CAS/cache directory used for Surface artefacts (defaults to --cas). |
STELLAOPS_SURFACE_BUCKET |
Bucket name embedded in cas:// URIs (default scanner-artifacts). |
STELLAOPS_SURFACE_TENANT |
Tenant recorded in the manifest (default if omitted). |
STELLAOPS_SURFACE_LAYER_FRAGMENTS / ...ENTRYTRACE_GRAPH / ...ENTRYTRACE_NDJSON |
File paths for the respective artefacts. |
STELLAOPS_SURFACE_MANIFEST_OUTPUT |
Optional path where the manifest JSON should be duplicated for CI artefacts. |
Manifests and payloads use the same deterministic layout as Scanner.Worker (scanner/surface/...) so WebService and Offline Kit tooling can consume them without rescanning the image.
5. (Optional) Send the placeholder to an Attestor
The plug-in can POST the descriptor metadata to an Attestor endpoint, returning once it receives an HTTP 202.
python3 - <<'PY' &
from http.server import BaseHTTPRequestHandler, HTTPServer
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
_ = self.rfile.read(int(self.headers.get('Content-Length', 0)))
self.send_response(202); self.end_headers(); self.wfile.write(b'accepted')
def log_message(self, fmt, *args):
return
server = HTTPServer(('127.0.0.1', 8085), Handler)
try:
server.serve_forever()
except KeyboardInterrupt:
pass
finally:
server.server_close()
PY
MOCK_PID=$!
dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll descriptor \
--manifest out/buildx \
--image "$DIGEST" \
--sbom out/buildx-sbom.cdx.json \
--attestor http://127.0.0.1:8085/provenance \
--attestor-token "$STELLAOPS_ATTESTOR_TOKEN" \
> out/buildx-descriptor.json
kill $MOCK_PID
Set STELLAOPS_ATTESTOR_TOKEN (or pass --attestor-token) when the Attestor requires bearer authentication. Use --attestor-insecure for lab environments with self-signed certificates.
6. CI workflow example
A reusable GitHub Actions workflow is provided under samples/ci/buildx-demo/github-actions-buildx-demo.yml. It publishes the plug-in, runs the handshake, builds the demo image, emits a descriptor, and uploads both the descriptor and the mock-Attestor request as artefacts.
Add the workflow to your repository (or call it via workflow_call) and adjust the SBOM path + Attestor URL as needed. The workflow also re-runs the descriptor command and diffs the results (ignoring the generatedAt timestamp) so you catch regressions that would break deterministic CI use.
For deeper integration guidance (custom SBOM builders, exporting DSSE bundles), track ADRs in docs/modules/scanner/architecture.md §7 and follow upcoming Attestor API releases.