Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- 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.
150 lines
6.7 KiB
Markdown
150 lines
6.7 KiB
Markdown
# 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 buildx` available).
|
|
- .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/`.
|
|
|
|
```bash
|
|
# 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 contains `StellaOps.Scanner.Sbomer.BuildXPlugin.dll` and the manifest `stellaops.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
|
|
|
|
```bash
|
|
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
|
|
|
|
1. Build or identify the image you want to describe and capture its digest:
|
|
|
|
```bash
|
|
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}}')
|
|
```
|
|
|
|
2. Generate a CycloneDX SBOM for the built image (any tool works; here we use `docker sbom`):
|
|
|
|
```bash
|
|
docker sbom stellaops/buildx-demo:ci --format cyclonedx-json > out/buildx-sbom.cdx.json
|
|
```
|
|
|
|
3. Invoke the `descriptor` command, pointing at the SBOM file and optional metadata:
|
|
|
|
```bash
|
|
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`, `attestorUri` when provided). `nonce` is 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.
|
|
|
|
```bash
|
|
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.
|
|
|
|
```bash
|
|
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.
|