SBOMs mit Client-Tools erzeugen
Praktische CycloneDX-Workflows für Maven, Gradle, Poetry, npm und OCI-Clients, inklusive der Fälle, in denen Craftifact die SBOM automatisch binden kann.
Kurzpfad
- Erzeuge SBOMs als CycloneDX-JSON.
- Nutze bevorzugt das Sidecar-Muster, wenn das jeweilige Ökosystem es sauber unterstützt.
- Sonst publiziere zuerst Paket oder Image und lade die SBOM danach über die SBOM-Upload-API hoch.
- Nutze
artifact_idfür Paketartefakte undoci_digestzusammen mitrepositoryfür OCI-Inhalte. - Eine
201-Antwort bedeutet, dass die SBOM angenommen und zur Verarbeitung eingeplant wurde.
Welches Muster zu welchem Client passt
- Maven: aktuell der beste Fit. Lade ein
-cyclonedx.json-Sidecar im selben GAV-Pfad wie das Primärartefakt hoch. - Gradle mit Publishing in Maven-Repositorys: dasselbe Muster wie bei Maven. Hänge das CycloneDX-JSON als klassifiziertes Sidecar an.
- Poetry, Twine und npm: erzeuge das CycloneDX-JSON lokal, publiziere normal und lade die SBOM danach direkt zu Craftifact hoch.
- Docker und OCI: pushe zuerst das Image, erzeuge das CycloneDX-JSON aus dem gepushten Image und lade es dann über den OCI-Digest hoch.
- pip und Go sind hier bewusst nicht enthalten. Die aktuelle Dokumentation zeigt dort Installations- oder Proxy-Flows, aber keinen normalen Hosted-Publish-Workflow.
Gemeinsamer Upload-Endpunkt
Craftifact akzeptiert CycloneDX-JSON in der Referenz zur SBOM-Upload-API:
https://packages.example.com/api/sbom/upload/
Verwende genau eine Zielreferenz:
-
artifact_idfür Paketartefakte oci_digestzusammen mitrepositoryfür OCI-Inhalte
Bei Paket-Ökosystemen wie Python und npm ist es am einfachsten, die Artifact-ID aus deiner Automation zu übergeben. Wenn du manuell im UI arbeitest, kannst du sie auch aus der URL der Artefakt-Detailansicht übernehmen.
Den exakten Request-Vertrag, die Response-Formate und copy-fertige Upload-Beispiele hält die SBOM-Upload-API-Referenz zentral. Die Workflow-Abschnitte unten ergänzen nur die Ökosystem-spezifischen Schritte rund um diesen gemeinsamen Endpunkt.
Maven
Für Maven ist der glatteste Weg aktuell, das CycloneDX-JSON während des Builds zu erzeugen und als klassifiziertes Sidecar im selben Repository-Vorgang mit auszuliefern.
<build>
<plugins>
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>PLUGIN_VERSION</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>makeBom</goal>
</goals>
<configuration>
<outputFormat>json</outputFormat>
<schemaVersion>1.6</schemaVersion>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Die erzeugte Datei wird als artifact-version-cyclonedx.json angehängt. Genau dieses Muster erlaubt Craftifact, das SBOM-Sidecar im selben GAV-Pfad dem passenden Primärartefakt zuzuordnen.
mvn deploy \
-s settings.xml \
-DaltDeploymentRepository=craftifact::https://packages.example.com/repository/maven/libs-release/
Gradle
Wenn Gradle in ein Maven-Hosted-Repository publiziert, nutze dieselbe Sidecar-Idee: führe eine CycloneDX-Task aus und hänge das resultierende JSON mit dem Classifier cyclonedx an.
plugins {
id("maven-publish")
id("org.cyclonedx.bom") version "PLUGIN_VERSION"
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
artifact(layout.buildDirectory.file("reports/cyclonedx/bom.json")) {
builtBy(tasks.named("cyclonedxBom"))
classifier = "cyclonedx"
extension = "json"
}
}
}
}
Der genaue Output-Pfad hängt von deiner Plugin-Konfiguration ab. Für Craftifact ist entscheidend, dass am Ende eine -cyclonedx.json-Datei neben dem eigentlichen Maven-Artefakt publiziert wird.
Poetry und Twine
Für Python-Publishing ist das übliche Muster zweiteilig:
- Paket wie gewohnt bauen und publizieren
- CycloneDX-JSON separat erzeugen und danach zu Craftifact für das publizierte Artefakt hochladen
poetry build
poetry publish --repository craftifact
Ein praktikabler Generator ist cyclonedx-py:
cyclonedx-py poetry \
--output-format json \
--output-file dist/example-cyclonedx.json
Wenn du statt poetry publish mit Twine publizierst, bleibt der SBOM-Teil gleich:
twine upload \
--repository-url https://packages.example.com/repository/python/libs-release/ \
dist/*
Sobald das Paketartefakt in Craftifact vorhanden ist, kopierst du seine Artifact ID aus dem Detailbereich oder löst sie über die Artefakt-Suche API auf. Danach lädst du die SBOM mit dieser
artifact_id
hoch:
curl \
-X POST \
-H "Authorization: Bearer $CRAFTIFACT_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @dist/example-cyclonedx.json \
"https://packages.example.com/api/sbom/upload/?artifact_id=ARTIFACT_ID"
npm
Bei npm publizierst du zuerst und erzeugst die SBOM danach direkt mit dem npm-Client, wenn deine npm-Version npm sbom unterstützt.
npm publish --registry https://packages.example.com/repository/npm/libs-release/
npm sbom --sbom-format cyclonedx > package-cyclonedx.json
Danach lädst du das erzeugte CycloneDX-JSON zum publizierten Artefakt hoch:
curl \
-X POST \
-H "Authorization: Bearer $CRAFTIFACT_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @package-cyclonedx.json \
"https://packages.example.com/api/sbom/upload/?artifact_id=ARTIFACT_ID"
Wenn dein npm-Setup npm sbom noch nicht anbietet, nutze stattdessen einen anderen CycloneDX-fähigen Generator in CI und lasse den Upload zu Craftifact unverändert.
Docker und OCI
Docker bleibt der normale Client für Build und Push, aber das praktikable SBOM-Muster ist heute getrennt:
- Image pushen
- CycloneDX-JSON aus dem gepushten Image erzeugen
- Dokument über den OCI-Digest zu Craftifact hochladen
docker push packages.example.com/libs-release/demo/app:1.0.0
Ein einfacher Generator ist syft:
syft registry:packages.example.com/libs-release/demo/app:1.0.0 \
-o cyclonedx-json=image-cyclonedx.json
Nutze den Manifest-Digest aus der Push-Ausgabe oder aus einem nachgelagerten Inspect-Schritt und lade die SBOM dann hoch:
curl \
-X POST \
-H "Authorization: Bearer $CRAFTIFACT_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @image-cyclonedx.json \
"https://packages.example.com/api/sbom/upload/?oci_digest=sha256:DIGEST&repository=libs-release"
So bleibt der Docker-Workflow vertraut, während Craftifact die SBOM trotzdem für den gepushten OCI-Inhalt speichern und verarbeiten kann.
Hochgeladene und generierte SBOMs
Craftifact kann mit SBOMs aus zwei Quellen arbeiten:
- von dir bereitgestelltes CycloneDX-JSON, das du hochlädst oder als Sidecar publizierst,
- von Craftifact generierte SBOMs für unterstützte Hosted-Inhalte.
Generierte SBOMs decken aktuell Hosted-Maven-Artefakte mit .jar, .war und .ear sowie Hosted-OCI-Manifeste oder -Indexes ab.
Proxy-Repositorys werden übersprungen, und von dir bereitgestellte SBOMs haben Vorrang, wenn für dasselbe Subject bereits eine SBOM gebunden ist.
Generierte SBOMs können mit der Zeit Freshness-Status anzeigen. Wenn Generator-Version oder Schwachstellendatenbank veralten, behandle das Ergebnis als Triage-Kontext und aktualisiere es, bevor du es als abschließende Antwort nutzt.
Verwandte Seiten
- Um indexierte Komponenten im Explorer zu prüfen, siehe Abhängigkeiten erkunden.
- Um Schwachstellen-Findings für ein Subject zu prüfen, siehe Schwachstellen-Findings prüfen.
- Für den genauen Vertrag von Request und Response siehe SBOM-Upload-API.
- Für Repository-URLs und Auth-Setup siehe Client-Tools für Paketformate konfigurieren.
- Für allgemeines Verhalten der Paketfamilien siehe Hinweise zu Paketformaten.
- Für Token-Erzeugung siehe Robot-Account anlegen und Token nutzen.