SBOM
SBOM-generatie over engineeringteams heen: één beleid, elke pipeline
De meeste organisaties hebben geen SBOM-probleem; ze hebben zes SBOM-processen. Leg eerst de output vast: één formaat, één set velden, één moment van generatie, één opslagplek. Breng daarna de pipeline van elk team daarnaartoe, bij voorkeur met generatie in de release-build. Klanten, auditors en regelgeving zoals de CRA kijken naar de SBOM en naar het proces erachter, niet naar welke scanner u hebt gekocht.
Bijgewerkt op
Waarom scanners per team geen SBOM-programma opleveren
Zet vijf tools op hetzelfde product en u krijgt vijf SBOM's. De verschillen zijn structureel, geen bugs:
- Verschillende input, op verschillende momenten gelezen. De ene tool leest de lockfile, een andere de geïnstalleerde afhankelijkheidsboom, weer een andere de container-image, nog een andere de binary. Elk ziet een ander deel van het product.
- Verschillende namen voor hetzelfde. De ene tool identificeert componenten met een package URL, een andere met een CPE, weer een andere alleen met een bestandsnaam. Twee SBOM's die dezelfde bibliotheek beschrijven, zijn niet op een gemeenschappelijke sleutel te koppelen.
- Verschillende diepte. Sommige tonen alleen directe afhankelijkheden, sommige de volledige transitieve boom, en sommige tonen ook buildtools. Waarom generatoren het over dezelfde repository oneens zijn, ziet u in open source SBOM-generatoren.
- Sommige tools beantwoorden een andere vraag. Kwetsbaarheidsscanners voor infrastructuur rapporteren wat er op draaiende hosts is geïnstalleerd. Dat is nuttig voor operations, en het is geen beschrijving van het product dat u levert.
Het gevolg: u kunt SBOM's niet over producten heen samenvoegen, ontdubbelen of vergelijken, en u kunt een auditor niet één proces laten zien, omdat er geen is.
| Methode | Input die wordt gelezen | Wanneer | Wat wordt gemist | Typische identifier |
|---|---|---|---|---|
| Lockfile- of manifestscanner | Lockfiles en manifesten in de checkout | Voor of na de build | Alles wat in geen lockfile staat: install-hooks, downloads door buildscripts, base images | Package URL |
| Scanner voor container-images | Pakketdatabases en bestanden in de image | Na de build | Tools die alleen voor de build dienen, meegecompileerde code, alles zonder pakketrecord | Package URL voor OS- en taalpakketten |
| Binary- of firmwarescanner | Strings en signaturen in de binary | Na de build | Zekerheid: versies en componenten worden afgeleid | CPE of afgeleide naam |
| Kwetsbaarheidsscanner voor hosts | Geïnstalleerde software op draaiende servers | In productie | Het product zoals het aan klanten wordt geleverd | CPE of productnaam van de leverancier |
| Vastleggen tijdens de build | Wat de release-build heeft opgehaald | Tijdens de build | Software die u niet zelf hebt gebouwd; wat niet zichtbaar was, wordt als onvolledig gemarkeerd | Package URL |
Het SBOM-beleid: wat u standaardiseert
Standaardiseer de SBOM, niet de scanner. Het beleid legt de output en het proces vast; elke pipeline voldoet eraan met de beste generator die hij kan draaien. Elke rij hieronder is te controleren.
| Eis | De regel | Waarom | Hoe u het controleert |
|---|---|---|---|
| Reikwijdte | Elke productrelease die naar een klant gaat, inclusief firmware en container-images. Interne tools optioneel. | Klanten en toezichthouders vragen naar wat u levert. | Elke release in het releaseregister heeft een SBOM. |
| Formaat en versie | Eén primair formaat, CycloneDX of SPDX, met een minimumversie. Accepteer het andere op verzoek. | Eén formaat betekent één parser, één validator en één opslagplek. BSI TR-03183-2 vraagt om CycloneDX 1.6 of hoger of SPDX 3.0.1 of hoger, een verstandige ondergrens voor EU-klanten. | Schemavalidatie rapporteert formaat en versie. |
| Minimale velden | Een package URL bij elk component dat er een heeft, een CPE alleen waar die ontbreekt, leverancier, versie, gedeclareerde licentie, afhankelijkheidsrelaties, naam en versie van de tool, tijdstempel en generatiecontext. | Deze velden gebruiken matching, licentiebeoordeling en audits. Stem ze af op de minimale elementen op wat is een SBOM. | Een veldcontrole in de pipeline telt ontbrekende waarden. |
| Moment van generatie | In de CI-build die de release produceert, elke keer. Niet op het moment van de audit, niet op een laptop. | Een nieuwe build is niet dezelfde build; zie build-time SBOM's. | De build-ID van de SBOM komt overeen met de build-ID van de release. |
| Diepte | De volledige transitieve boom, niet alleen het hoogste niveau. | Het minimum van de CRA zijn de afhankelijkheden op het hoogste niveau; kwetsbaarheden en klanten gaan dieper. | Er bestaan afhankelijkheidsrelaties onder het eerste niveau. |
| Opslagplek | Bij het release-artefact, op te vragen per product en versie. | Een SBOM die niemand kan vinden als er een advisory binnenkomt, is geen bewijs. | Haal de SBOM van een willekeurige release op per product en versie. |
| Bewaartermijn | Minstens de supportperiode van het product plus de bewaartermijn voor documentatie die uw regelgeving vereist. | De CRA stelt een bewaartermijn voor technische documentatie vast, en de SBOM maakt daar deel van uit. | Vergelijk de termijn in het beleid met de bewaartermijn van elke tool. |
| Validatie | Elke SBOM wordt in de pipeline tegen het schema gevalideerd; een ongeldige laat de build of de release-gate falen. | Ongeldige SBOM's falen ongemerkt in de tooling van de klant. | De log van de release-gate toont een validatiestap. |
| Eigenaarschap | Het productteam is eigenaar van de generatie; product security is eigenaar van het beleid, de validatieregels en de rapportage over dekking. | Generatie vraagt om de eigenaar van de pipeline; consistentie vraagt om één eigenaar van de regels. | Elke pipeline noemt een eigenaar. |
| Uitzonderingen | Een register van benoemde uitzonderingen met een einddatum: team, reden, einddatum. | Het beleid overleeft teams die er nog niet aan kunnen voldoen. | Geen enkele uitzondering is over haar einddatum heen. |
De checklist in SBOM best practices behandelt de regels voor één SBOM; dit beleid is de laag daarboven. Elk team legt in een bestand naast de pipeline vast hoe zijn pipeline aan het beleid voldoet:
# sbom-policy.yaml, one per release pipeline
product: gateway-firmware
owner: team-gateway
format: cyclonedx
spec_version: "1.6"
generated_in: release-build
generator: build-time-recording
store: artifact-registry
validation: schema, fail-on-errors
exception: none
Genereer in de build, niet achteraf per team
Generatie tijdens de build is de standaard om naar te streven. Ze beschrijft de build die is geleverd, ze bevat verborgen afhankelijkheden die in geen lockfile staan, en één mechanisme levert voor elk team op die pipeline SBOM's van dezelfde vorm. Het verschil is het makkelijkst uit te leggen met een keuken: een scanner proeft de soep en raadt het recept; een recorder kijkt wat er de keuken in gaat.
Een scanner blijft de juiste tool voor images die u niet zelf hebt gebouwd, voor binaries van derden en voor legacy-producten zonder CI. Zeg dat in het beleid en leg de generatiecontext vast, zodat een lezer weet wat elke SBOM heeft gezien.
| Situatie | Generatiemethode | Vast te leggen generatiecontext |
|---|---|---|
| Release gebouwd in CI die u beheert | Leg de build vast, of draai een generator in de release-job | "Vastgelegd tijdens de build" of "na installatie, uit bestanden" |
| Container-image gebouwd in CI | Leg de build van de image vast; scan het resultaat op OS-pakketten als de recorder die niet dekt | Build-ID en image-digest |
| Image of appliance van derden | Image-scanner, plus de SBOM van de leverancier als die er is | "Gescande output, niet door ons gebouwd" |
| Binary van een leverancier | Vraag de build-SBOM van de leverancier op; binaire analyse als controle | Leverancier, versie, hoe hij is verkregen |
| Legacy-product zonder pipeline | Scan het geleverde artefact; plan een pipeline | "Gescande output" en een uitzondering met een einddatum |
Gemengde CI: GitHub Actions, GitLab en Jenkins in één organisatie
Het beleid is bewust CI-onafhankelijk: het definieert de output, zodat een GitLab- of Jenkins-pipeline eraan kan voldoen met een generatorstap, en een GitHub Actions-pipeline vastleggen tijdens de build kan gebruiken. Regels voor een generatorstap:
- Draai hem in de release-job, na de installatiestap, niet in een aparte job die opnieuw installeert.
- Pin de versie van de generator, en pin CI-actions op een commit, niet op een tag. Waarom dat juist bij scanners belangrijk is, leest u in open source SBOM-generatoren.
- Leg de generatiecontext vast als "na installatie, uit bestanden", zodat lezers weten wat hij heeft gezien.
- Valideer de output tegen hetzelfde schema als elke andere pipeline.
Open source generatoren zoals Syft, Trivy en cdxgen kunnen allemaal CycloneDX en SPDX schrijven, dus de formaatregel dwingt geen toolkeuze af. Voor een vergelijking, zie SBOM-tools vergeleken.
CRACI ondersteunt vandaag GitHub Actions; GitLab CI en Jenkins staan op de roadmap, zonder datum. Het gevolg voor de uitrol: begin met vastleggen tijdens de build waar GitHub Actions wordt gebruikt, houd elders generatorstappen aan, en volg beide in hetzelfde dekkingsrapport.
Als een klant een specifieke formaatversie wil
Een klant vraagt om CycloneDX 1.6, en uw tooling schrijft 1.7. Dat gebeurt omdat hun ingestietool of hun eigen beleid op een versie is vastgezet; de ondergrens van het BSI is 1.6, dus EU-klanten noemen die vaak. Uw opties:
- Vraag of de nieuwere versie wordt geaccepteerd. Vaak is dat zo.
- Converteer met de CycloneDX CLI, valideer daarna tegen de doelversie, en controleer wat verloren is gegaan: velden die alleen in de nieuwere specificatie bestaan, vallen weg.
- Bij een SPDX-verzoek converteert dezelfde CLI van en naar SPDX JSON 2.3. De documentatie waarschuwt dat conversie tussen SPDX en CycloneDX "kan leiden tot het verlies van enige informatie".
cyclonedx convert --input-file bom.cdx.json --input-format json \
--output-file bom-1.6.cdx.json --output-format json --output-version v1_6
cyclonedx validate --input-file bom-1.6.cdx.json --input-format json \
--input-version v1_6 --fail-on-errors
De validator controleert tegen CycloneDX 1.7, tenzij u --input-version meegeeft. Beleidsregel: bewaar de
oorspronkelijke SBOM als het officiële record. Een geconverteerde kopie is een afgeleide levering; sla de afleiding (tool, versie, datum) erbij
op. Meer over het beantwoorden van deze verzoeken in SBOM-verzoeken van klanten, en over de twee
formaten in CycloneDX vs SPDX.
Licentiegegevens voor juridische zaken
Dezelfde SBOM kan de juridische afdeling bedienen, als het beleid om de juiste velden vraagt. Juridische zaken heeft de licentie van elk component nodig, het verschil tussen een gedeclareerde licentie (wat het pakket zegt) en een vastgestelde (wat iemand heeft geverifieerd), copyleft-verplichtingen, en een lijst van componenten zonder licentie. CycloneDX 1.6 markeert licenties als gedeclareerd of vastgesteld, en SPDX heeft voor beide aparte velden.
- Vereis SPDX-licentie-identifiers of -expressies, zoals
MITofApache-2.0 OR MIT. -
Markeer
NOASSERTIONen ontbrekende licenties voor beoordeling. In SPDX betekentNOASSERTIONdat er geen vaststelling is gedaan of geen informatie is gegeven; het is geen licentie. - Stuur copyleft-licenties vóór de release door naar juridische zaken, niet erna.
Een SBOM bevat gedeclareerde licenties. Een beoordeling van licentiecompliance, met vastgestelde licenties, vermeldingen en verplichtingen, is juridisch werk of een taak voor een gespecialiseerde tool; zie open source licentiecompliance.
Team voor team uitrollen
| Fase | Eigenaar | Afrondingscriterium | Typisch obstakel |
|---|---|---|---|
| 1. Inventarisatie: producten, pipelines, CI-systemen en huidige generatoren, één rij per release-pipeline | Product security | Elk geleverd product heeft een rij | Niemand weet welke pipeline een release bouwt |
| 2. Publiceer het beleid met het uitzonderingsregister | Product security | Beleid goedgekeurd en gepubliceerd | Discussie over welke tool verplicht wordt (het beleid schrijft er geen voor) |
| 3. Pilot met een of twee teams die een reden hebben: een klantverzoek, een deadline, een product dat de huidige tool niet aankan | Pilotteams | Pilotreleases worden geleverd met conforme SBOM's | Teams zonder dringende reden geven het geen prioriteit |
| 4. Voeg validatie-gates toe in de pilotpipelines | Pilotteams | Een ongeldige SBOM laat de release falen | Angst om releases te blokkeren; begin met een waarschuwing |
| 5. Breid uit per CI-systeem; schaf een scanner per team pas af als de vervanger aan het beleid voldoet | Productteams | Dekkingsdoel gehaald per CI-systeem | Pipelines zonder eigenaar |
| 6. Rapporteer de dekking maandelijks | Product security | Het rapport gaat elke maand naar het management | Metrics die met de hand worden berekend |
De inventarisatiespreadsheet uit fase 1 zou de laatste moeten zijn; afstappen van spreadsheets komt aan bod in SBOM-automatisering. Een product op basis van Yocto is een veelgekozen pilot, omdat scanners voor algemeen gebruik er moeite mee hebben; zie waarom SBOM-scanners Yocto-builds missen.
Dekking meten
De cijfers waar management en auditors om vragen, elk gedefinieerd als een verhouding:
- Releasedekking: releases geleverd met een beleidsconforme SBOM ÷ geleverde releases.
- Productdekking: producten met minstens één conforme SBOM in de huidige supportperiode ÷ producten in support.
- Slagingspercentage validatie: SBOM's die de validatie doorstaan ÷ gegenereerde SBOM's.
- Identifierdekking: componenten met een package URL (of een CPE) ÷ componenten.
- Licentiedekking: componenten met een gedeclareerde licentie ÷ componenten.
- Volledigheid: SBOM's waarvan de generator aangeeft dat ze volledig zijn ÷ SBOM's. Alleen mogelijk waar de tool dit rapporteert.
- Tijd tot SBOM: tijd van release tot beschikbare SBOM.
Een voorbeeld van een maandrapport (illustratieve cijfers):
| Metric | GitHub Actions-pipelines | GitLab- en Jenkins-pipelines | Alle |
|---|---|---|---|
| Releasedekking | 46 / 48 | 19 / 27 | 65 / 75 |
| Slagingspercentage validatie | 100% | 92% | 97% |
| Identifierdekking | 99% | 88% | 95% |
| Openstaande uitzonderingen | 1 | 4 | 5 |
Als bewijs voor een toezichthouder of een auditor bestaat de set uit het beleid, het uitzonderingsregister, het dekkingsrapport en een paar voorbeeld-SBOM's. Het toont één proces, toegepast en gemeten. Voor de CRA-kant, zie de CRA-gids.
Waar CRACI past
Voor GitHub Actions-pipelines is CRACI de runner: u stelt runs-on: craci in, en elke job krijgt een vastgelegde
SBOM zonder generatorstap. Elke SBOM bevat een volledigheidsstatus, de transitieve afhankelijkheden, een package URL per
pakket en de gedeclareerde licentie van elk component, en is te exporteren als CycloneDX of SPDX. Licentiebeleidsregels kunnen een
build blokkeren, gemonitorde SBOM's worden continu opnieuw beoordeeld, en de buildgeschiedenis laat zien welke builds een kwetsbare
afhankelijkheid bevatten. Zo voldoen die teams standaard aan de rijen "gegenereerd in de release-build", "identifier" en "licentie" van het
beleid. SBOM's van derden kunnen worden toegevoegd, zodat ingekochte componenten naast uw builds worden gemonitord.
Zie SBOM-generatie met CRACI en SBOM's in GitHub Actions.
Wanneer CRACI niet het antwoord is
- Teams op GitLab CI of Jenkins: vandaag niet, het staat op de roadmap. Gebruik een generatorstap die aan het beleid voldoet.
- GitHub Enterprise Server: vandaag niet ondersteund.
- Infrastructuur- en hostscanning, dus wat er op servers is geïnstalleerd en misconfiguraties: een andere taak; houd die tools.
- Binaire of firmware-analyse van images van leveranciers die u niet zelf bouwt: CRACI legt builds vast en scant geen binaries.
- Lange bewaartermijn: CRACI bewaart builddata standaard 180 dagen, met een aangepaste bewaartermijn op Enterprise. Als uw beleid SBOM's langer nodig heeft, exporteer ze dan naar uw eigen opslag.
SBOM-generatie over teams heen: veelgestelde vragen
Hoe standaardiseren we SBOM-generatie over teams heen die verschillende tools gebruiken?
Standaardiseer de output, niet de tool. Schrijf één beleid dat het formaat en de versie vastlegt, de minimale velden, wanneer de SBOM wordt gegenereerd, waar hij wordt opgeslagen, hoe lang hij wordt bewaard en wie hem valideert. Laat elke pipeline eraan voldoen met de beste generator die hij kan draaien, en meet de dekking tegen het beleid.
Wat moet een SBOM-beleid bevatten?
Reikwijdte, formaat en minimumversie, minimale velden (package URL, leverancier, versie, gedeclareerde licentie, afhankelijkheden, tool, tijdstempel, generatiecontext), generatie in de release-build, volledige transitieve diepte, opslag bij de release, bewaartermijn, validatie in de pipeline, eigenaarschap en een register van uitzonderingen met een einddatum.
Moet elk team zijn eigen scanner draaien, of moeten SBOM's uit de build komen?
Uit de build, waar dat kan. Een build-time SBOM beschrijft de build die is geleverd en geeft elk team op die pipeline SBOM's van dezelfde vorm. Houd scanners voor wat u niet zelf hebt gebouwd: images van derden, binaries van leveranciers en legacy-producten zonder pipeline.
Een klant wil onze SBOM in een oudere CycloneDX-versie. Wat doen we?
Vraag eerst of de nieuwere versie wordt geaccepteerd. Zo niet, converteer dan een kopie met de CycloneDX CLI (cyclonedx convert met --output-version v1_6), valideer die tegen die versie, en controleer welke velden zijn weggevallen. Bewaar het origineel als het officiële record en sla op hoe de kopie is afgeleid.
Hoe krijgen we licentiegegevens uit onze SBOM's bij juridische zaken?
Vereis in het beleid SPDX-licentie-identifiers of -expressies, markeer NOASSERTION en ontbrekende licenties voor beoordeling, en stuur copyleft-licenties vóór de release door naar juridische zaken. De SBOM bevat gedeclareerde licenties; vastgestelde licenties, vermeldingen en verplichtingen vragen om een licentiebeoordeling.
Hoe meten we SBOM-dekking over producten heen?
Als verhoudingen: releases geleverd met een conforme SBOM, producten in support met een conforme SBOM, slagingspercentage van de validatie, componenten met een package URL, componenten met een gedeclareerde licentie, volledige SBOM's waar de tool dit rapporteert, en de tijd van release tot SBOM. Rapporteer ze maandelijks per CI-systeem.
Welk bewijs hebben we nodig om een auditor te laten zien dat SBOM-generatie consistent is?
Het beleid, het uitzonderingsregister, het maandelijkse dekkingsrapport en een paar voorbeeld-SBOM's met hun generatiecontext. Samen tonen ze één proces, toegepast op elke release en gemeten, en dat is wat een auditor of een klant controleert.
Test het op één GitHub Actions-pipeline
Boek een demo en draai één release-pipeline op CRACI. Krijg een SBOM die uit de build is vastgelegd en toets die aan uw beleid.
Demo boeken