Restructure solution layout by module
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Docs CI / lint-and-preview (push) Has been cancelled
				
			This commit is contained in:
		| @@ -1,42 +1,42 @@ | ||||
| # Buildx SBOM Demo Workflow | ||||
|  | ||||
| This sample GitHub Actions workflow shows how to run the StellaOps BuildX generator alongside a container build. | ||||
|  | ||||
| ## What it does | ||||
|  | ||||
| 1. Publishes the `StellaOps.Scanner.Sbomer.BuildXPlugin` with the manifest copied beside the binaries. | ||||
| 2. Calls the plug-in `handshake` command to verify the local CAS directory. | ||||
| 3. Builds a tiny Alpine-based image via `docker buildx`. | ||||
| 4. Generates a CycloneDX SBOM from the built image with `docker sbom`. | ||||
| 5. Emits a descriptor + provenance placeholder referencing the freshly generated SBOM with the `descriptor` command. | ||||
| 6. Sends the placeholder to a mock Attestor endpoint and uploads the descriptor, SBOM, and captured request as artefacts. (Swap the mock step with your real Attestor URL + `STELLAOPS_ATTESTOR_TOKEN` secret when ready.) | ||||
|  | ||||
| ## Files | ||||
|  | ||||
| - `github-actions-buildx-demo.yml` – workflow definition (`workflow_dispatch` + `demo/buildx` branch trigger). | ||||
| - `Dockerfile` – minimal demo image. | ||||
| - `github-actions-buildx-demo.yml` now captures a real SBOM via `docker sbom`. | ||||
|  | ||||
| ## Running locally | ||||
|  | ||||
| ```bash | ||||
| dotnet publish src/StellaOps.Scanner.Sbomer.BuildXPlugin/StellaOps.Scanner.Sbomer.BuildXPlugin.csproj -c Release -o out/buildx | ||||
|  | ||||
| dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll handshake \ | ||||
|   --manifest out/buildx \ | ||||
|   --cas out/cas | ||||
|  | ||||
| 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}}') | ||||
|  | ||||
| docker sbom stellaops/buildx-demo:ci --format cyclonedx-json > out/buildx-sbom.cdx.json | ||||
|  | ||||
| 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 \ | ||||
|   > out/buildx-descriptor.json | ||||
| ``` | ||||
|  | ||||
| The descriptor JSON contains deterministic annotations and provenance placeholders ready for the Attestor. | ||||
| # Buildx SBOM Demo Workflow | ||||
|  | ||||
| This sample GitHub Actions workflow shows how to run the StellaOps BuildX generator alongside a container build. | ||||
|  | ||||
| ## What it does | ||||
|  | ||||
| 1. Publishes the `StellaOps.Scanner.Sbomer.BuildXPlugin` with the manifest copied beside the binaries. | ||||
| 2. Calls the plug-in `handshake` command to verify the local CAS directory. | ||||
| 3. Builds a tiny Alpine-based image via `docker buildx`. | ||||
| 4. Generates a CycloneDX SBOM from the built image with `docker sbom`. | ||||
| 5. Emits a descriptor + provenance placeholder referencing the freshly generated SBOM with the `descriptor` command. | ||||
| 6. Sends the placeholder to a mock Attestor endpoint and uploads the descriptor, SBOM, and captured request as artefacts. (Swap the mock step with your real Attestor URL + `STELLAOPS_ATTESTOR_TOKEN` secret when ready.) | ||||
|  | ||||
| ## Files | ||||
|  | ||||
| - `github-actions-buildx-demo.yml` – workflow definition (`workflow_dispatch` + `demo/buildx` branch trigger). | ||||
| - `Dockerfile` – minimal demo image. | ||||
| - `github-actions-buildx-demo.yml` now captures a real SBOM via `docker sbom`. | ||||
|  | ||||
| ## Running locally | ||||
|  | ||||
| ```bash | ||||
| dotnet publish src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/StellaOps.Scanner.Sbomer.BuildXPlugin.csproj -c Release -o out/buildx | ||||
|  | ||||
| dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll handshake \ | ||||
|   --manifest out/buildx \ | ||||
|   --cas out/cas | ||||
|  | ||||
| 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}}') | ||||
|  | ||||
| docker sbom stellaops/buildx-demo:ci --format cyclonedx-json > out/buildx-sbom.cdx.json | ||||
|  | ||||
| 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 \ | ||||
|   > out/buildx-descriptor.json | ||||
| ``` | ||||
|  | ||||
| The descriptor JSON contains deterministic annotations and provenance placeholders ready for the Attestor. | ||||
|   | ||||
| @@ -1,85 +1,85 @@ | ||||
| name: Buildx SBOM Demo | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|   push: | ||||
|     branches: [ demo/buildx ] | ||||
|  | ||||
| jobs: | ||||
|   buildx-sbom: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v3 | ||||
|  | ||||
|       - name: Set up .NET 10 preview | ||||
|         uses: actions/setup-dotnet@v4 | ||||
|         with: | ||||
|           dotnet-version: '10.0.x' | ||||
|  | ||||
|       - name: Publish StellaOps BuildX generator | ||||
|         run: | | ||||
|           dotnet publish src/StellaOps.Scanner.Sbomer.BuildXPlugin/StellaOps.Scanner.Sbomer.BuildXPlugin.csproj \ | ||||
|             -c Release \ | ||||
|             -o out/buildx | ||||
|  | ||||
|       - name: Handshake CAS | ||||
|         run: | | ||||
|           dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll handshake \ | ||||
|             --manifest out/buildx \ | ||||
|             --cas out/cas | ||||
|  | ||||
|       - name: Build demo container image | ||||
|         run: | | ||||
|           docker buildx build --load -t stellaops/buildx-demo:ci samples/ci/buildx-demo | ||||
|  | ||||
|       - name: Capture image digest | ||||
|         id: digest | ||||
|         run: | | ||||
|           DIGEST=$(docker image inspect stellaops/buildx-demo:ci --format '{{index .RepoDigests 0}}') | ||||
|           echo "digest=$DIGEST" >> "$GITHUB_OUTPUT" | ||||
|  | ||||
|       - name: Generate SBOM from built image | ||||
|         run: | | ||||
|           mkdir -p out | ||||
|           docker sbom stellaops/buildx-demo:ci --format cyclonedx-json > out/buildx-sbom.cdx.json | ||||
|  | ||||
|       - name: Start mock Attestor | ||||
|         id: attestor | ||||
|         run: | | ||||
|           mkdir -p out | ||||
|           cat <<'PY' > out/mock-attestor.py | ||||
| import json | ||||
| import os | ||||
| from http.server import BaseHTTPRequestHandler, HTTPServer | ||||
|  | ||||
| class Handler(BaseHTTPRequestHandler): | ||||
|     def do_POST(self): | ||||
|         length = int(self.headers.get('Content-Length') or 0) | ||||
|         body = self.rfile.read(length) | ||||
|         with open(os.path.join('out', 'provenance-request.json'), 'wb') as fp: | ||||
|             fp.write(body) | ||||
|         self.send_response(202) | ||||
|         self.end_headers() | ||||
|         self.wfile.write(b'accepted') | ||||
|  | ||||
|     def log_message(self, format, *args): | ||||
|         return | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     server = HTTPServer(('127.0.0.1', 8085), Handler) | ||||
|     try: | ||||
|         server.serve_forever() | ||||
|     except KeyboardInterrupt: | ||||
|         pass | ||||
|     finally: | ||||
|         server.server_close() | ||||
| PY | ||||
|           touch out/provenance-request.json | ||||
|           python3 out/mock-attestor.py & | ||||
|           echo $! > out/mock-attestor.pid | ||||
|  | ||||
| name: Buildx SBOM Demo | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|   push: | ||||
|     branches: [ demo/buildx ] | ||||
|  | ||||
| jobs: | ||||
|   buildx-sbom: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v3 | ||||
|  | ||||
|       - name: Set up .NET 10 preview | ||||
|         uses: actions/setup-dotnet@v4 | ||||
|         with: | ||||
|           dotnet-version: '10.0.x' | ||||
|  | ||||
|       - name: Publish StellaOps BuildX generator | ||||
|         run: | | ||||
|           dotnet publish src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/StellaOps.Scanner.Sbomer.BuildXPlugin.csproj \ | ||||
|             -c Release \ | ||||
|             -o out/buildx | ||||
|  | ||||
|       - name: Handshake CAS | ||||
|         run: | | ||||
|           dotnet out/buildx/StellaOps.Scanner.Sbomer.BuildXPlugin.dll handshake \ | ||||
|             --manifest out/buildx \ | ||||
|             --cas out/cas | ||||
|  | ||||
|       - name: Build demo container image | ||||
|         run: | | ||||
|           docker buildx build --load -t stellaops/buildx-demo:ci samples/ci/buildx-demo | ||||
|  | ||||
|       - name: Capture image digest | ||||
|         id: digest | ||||
|         run: | | ||||
|           DIGEST=$(docker image inspect stellaops/buildx-demo:ci --format '{{index .RepoDigests 0}}') | ||||
|           echo "digest=$DIGEST" >> "$GITHUB_OUTPUT" | ||||
|  | ||||
|       - name: Generate SBOM from built image | ||||
|         run: | | ||||
|           mkdir -p out | ||||
|           docker sbom stellaops/buildx-demo:ci --format cyclonedx-json > out/buildx-sbom.cdx.json | ||||
|  | ||||
|       - name: Start mock Attestor | ||||
|         id: attestor | ||||
|         run: | | ||||
|           mkdir -p out | ||||
|           cat <<'PY' > out/mock-attestor.py | ||||
| import json | ||||
| import os | ||||
| from http.server import BaseHTTPRequestHandler, HTTPServer | ||||
|  | ||||
| class Handler(BaseHTTPRequestHandler): | ||||
|     def do_POST(self): | ||||
|         length = int(self.headers.get('Content-Length') or 0) | ||||
|         body = self.rfile.read(length) | ||||
|         with open(os.path.join('out', 'provenance-request.json'), 'wb') as fp: | ||||
|             fp.write(body) | ||||
|         self.send_response(202) | ||||
|         self.end_headers() | ||||
|         self.wfile.write(b'accepted') | ||||
|  | ||||
|     def log_message(self, format, *args): | ||||
|         return | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     server = HTTPServer(('127.0.0.1', 8085), Handler) | ||||
|     try: | ||||
|         server.serve_forever() | ||||
|     except KeyboardInterrupt: | ||||
|         pass | ||||
|     finally: | ||||
|         server.server_close() | ||||
| PY | ||||
|           touch out/provenance-request.json | ||||
|           python3 out/mock-attestor.py & | ||||
|           echo $! > out/mock-attestor.pid | ||||
|  | ||||
|       - name: Emit descriptor with provenance placeholder | ||||
|         env: | ||||
|           IMAGE_DIGEST: ${{ steps.digest.outputs.digest }} | ||||
| @@ -135,19 +135,19 @@ PY | ||||
|         if: always() | ||||
|         run: | | ||||
|           if [ -f out/mock-attestor.pid ]; then | ||||
|             kill $(cat out/mock-attestor.pid) | ||||
|           fi | ||||
|  | ||||
|       - name: Upload artifacts | ||||
|         uses: actions/upload-artifact@v4 | ||||
|         with: | ||||
|           name: stellaops-buildx-demo | ||||
|             kill $(cat out/mock-attestor.pid) | ||||
|           fi | ||||
|  | ||||
|       - name: Upload artifacts | ||||
|         uses: actions/upload-artifact@v4 | ||||
|         with: | ||||
|           name: stellaops-buildx-demo | ||||
|           path: | | ||||
|             out/buildx-descriptor.json | ||||
|             out/buildx-sbom.cdx.json | ||||
|             out/provenance-request.json | ||||
|             out/buildx-descriptor-repeat.json | ||||
|  | ||||
|       - name: Show descriptor summary | ||||
|         run: | | ||||
|           cat out/buildx-descriptor.json | ||||
|  | ||||
|       - name: Show descriptor summary | ||||
|         run: | | ||||
|           cat out/buildx-descriptor.json | ||||
|   | ||||
		Reference in New Issue
	
	Block a user