Yocto
SBOM Yocto i buildy w CRACI
Yocto potrafi zapisać szczegółowy SBOM w formacie SPDX dla każdego obrazu. W porównaniu buildów SBOM zarejestrowany przez CRACI zawierał każdy komponent z SBOM Yocto, 88 pominiętych przez Yocto i package URL dla każdego z 653 crate'ów Rust, które Yocto wymienia bez niego, przy czasie buildu krótszym o 43%.
Zaktualizowano
Porównanie buildów: core-image-sato
Jak wygenerować SBOM w Yocto
System buildu OpenEmbedded zapisuje SBOM-y w formacie SPDX za pomocą klasy create-spdx. To, czy jest ona włączona i którą wersję SPDX zapisuje, zależy od wydania Yocto:
- Kirkstone (4.0): domyślnie wyłączona. Należy dodać
INHERIT += "create-spdx". SPDX 2.2. - Nanbield (4.3): od tego wydania generowanie SBOM jest domyślnie włączone.
- Scarthgap (5.0): domyślnie włączona, SPDX 2.2. SPDX 3.0 jest dostępne przez klasę
create-spdx-3.0. - Styhead (5.1) i nowsze: domyślnie włączona, SPDX 3.0.
Ustawia się to w pliku konfiguracyjnym, takim jak conf/local.conf. W aktualnym wydaniu zwykle nie trzeba niczego dodawać; aby wyłączyć generowanie, należy użyć INHERIT_DISTRO:remove = "create-spdx".
# conf/local.conf
# Kirkstone (4.0): SBOM generation is off by default, so turn it on
INHERIT += "create-spdx"
# Scarthgap (5.0): switch the output from SPDX 2.2 to SPDX 3.0
INHERIT_DISTRO:remove = "create-spdx"
INHERIT_DISTRO:append = " create-spdx-3.0"
# Any release: indented JSON you can read in an editor
SPDX_PRETTY = "1" Inne zmienne SPDX_ dodają szczegóły. SPDX_INCLUDE_SOURCES opisuje pliki źródłowe każdego narzędzia hosta i pakietu docelowego, co znacznie powiększa wynik. Nowsze wydania dodają opcje dla konfiguracji jądra, funkcji PACKAGECONFIG, informacji o dostawcy oraz package URL dla źródeł Cargo, Go, PyPI, npm i CPAN.
Gdzie trafiają pliki SBOM
Po zbudowaniu obrazu główny SBOM pojawia się obok niego jako IMAGE-MACHINE.spdx.json w katalogu tmp/deploy/images/MACHINE/ wewnątrz katalogu buildu. Powiązane pliki znajdują się w tym samym katalogu oraz w tmp/deploy/spdx. W Kirkstone dokumenty dla poszczególnych receptur trafiają do archiwum IMAGE-MACHINE.spdx.tar.zst.
bitbake core-image-minimal
# The image SBOM
ls tmp/deploy/images/qemux86-64/core-image-minimal-qemux86-64.spdx.json
# Per-recipe and package documents
ls tmp/deploy/spdx/
# Current releases: an SBOM for one recipe, from its metadata only
bitbake busybox -c create_recipe_sbom CycloneDX z meta-cyclonedx
Samo Yocto zapisuje tylko SPDX. Dla CycloneDX warstwa meta-cyclonedx generuje SBOM z głównego systemu plików obrazu oraz osobny plik VEX z CVE, które system buildu zna jako załatane lub ignorowane. Należy pobrać gałąź warstwy dla swojego wydania, dodać ją do warstw i dziedziczyć jej klasę:
# In your sources directory, on the branch for your release
git clone https://github.com/iris-GmbH/meta-cyclonedx.git
cd meta-cyclonedx
git checkout scarthgap
# conf/bblayers.conf
BBLAYERS += "${BSPDIR}/sources/meta-cyclonedx"
# conf/local.conf
INHERIT += "cyclonedx-export"
# Optional: include build-time packages, not only what is in the image
CYCLONEDX_RUNTIME_PACKAGES_ONLY = "0" Pliki trafiają obok obrazu do DEPLOY_DIR_IMAGE, z przyrostkami .cyclonedx.bom.json i .cyclonedx.vex.json. Domyślnie jest to CycloneDX 1.6, ustawiane przez CYCLONEDX_SPEC_VERSION. Domyślnie uwzględniane są tylko pakiety uruchomieniowe, co utrzymuje mały rozmiar SBOM, ale może pominąć komponenty, które trafiają do obrazu bez instalacji jako pakiety.
Czego nie obejmuje SBOM z Yocto
SBOM z Yocto dokładnie opisuje to, co buduje BitBake. W SPDX 3 obejmuje obraz, każdą recepturę, łącznie z natywnymi recepturami czasu buildu, ich źródła, nałożone łatki i podatności oznaczone jako naprawione. Dla core-image-sato dało to 1,632 osobnych plików. Aby sprawdzić, czego w nim brakuje, zbudowaliśmy obraz na runnerze CRACI, natywnym ARM64 z 32 vCPU, i porównaliśmy SBOM z Yocto z tym zarejestrowanym przez CRACI, komponent po komponencie, po znormalizowaniu nazw we wszystkich tych plikach.
Spośród 953 komponentów w SBOM z CRACI 865 znalazło się także w SBOM Yocto. Żaden nie występował wyłącznie w SBOM Yocto. Różnice dotyczą tego, czego Yocto nie widzi, oraz tego, jak identyfikuje to, co wymienia.
Crate'y Rust bez package URL
Oba SBOM-y zawierają te same 653 wersje 559 crate'ów Rust, takich jak cairo-rs i zune-jpeg, które kompiluje librsvg. Yocto wymienia każdy z nich tylko jako plik .crate i adres pobierania z crates.io, wewnątrz receptury, która go używa. Żaden nie ma package URL pkg:cargo. CRACI rejestruje każdy crate z package URL.
To przesądza o tym, czy można monitorować je pod kątem podatności. Dopasowywanie podatności działa na podstawie package URL: komunikat bezpieczeństwa dla crate'a określa go jako pkg:cargo/..., a nazwa pliku na liście źródeł innej receptury nie daje narzędziom SBOM ani narzędziom do podatności niczego, do czego można by ją dopasować. Przy samym SBOM z Yocto podatny crate w Państwa obrazie pozostaje niezgłoszony.
Z SBOM z CRACI każdy crate jest dopasowywany do komunikatów bezpieczeństwa, każdy pakiet w buildzie pokazuje swój status podatności, a CRACI na bieżąco ponownie ocenia SBOM w miarę publikowania nowych komunikatów, długo po zakończeniu buildu.
Co znalazł tylko CRACI
88 komponentów, których brakowało w SBOM z Yocto, pochodziło spoza metadanych BitBake:
- 23 pakiety hosta zainstalowane na maszynie buildu, takie jak
cpio2.15 z Ubuntu,libc6,localesipython3-jinja2. BitBake z nich korzysta, a SBOM z Yocto ich nie wymienia. - 10 źródeł z GitHub, w tym
patchelf,btrfs-progsi akcja GitHubactions/upload-artifact, przypięte do commita, na którym działał workflow - Inne źródła i narzędzia pobrane w trakcie buildu, takie jak
pseudo-prebuilt,tzdatai narzędzia buildu Pythona, na przykładhatchlingisetuptools_scm
Żaden z nich nie jest zainstalowany w obrazie, ale wszystkie leżą na ścieżce krytycznej buildu: przejęte narzędzie hosta lub akcja mogą przejąć Państwa obraz, nigdy nie będąc jego częścią. CRACI je wymienia, ponieważ widzi ruch wchodzący do buildu.
Ile kosztuje wbudowany SBOM
Generowanie SBOM w Yocto nie jest darmowe. Na tym samym runnerze z 32 vCPU build z tą funkcją trwał 155 min 40 s i zapisał SBOM jako 1,632 osobnych plików SPDX. Build bez niej, z rejestrowaniem przez CRACI, trwał 88 min 48 s. Przy stawce CRACI $0.002 za vCPU-minutę to około $9.96 wobec $5.68 za build, nie licząc czasu, który Państwa zespół spędza na czekaniu.
W porównaniu z runnerami hostowanymi przez GitHub różnica jest większa. CRACI wykonuje buildy około dwa razy szybciej dzięki szybszemu sprzętowi, krótszemu czasowi oczekiwania w kolejce i cache, więc ten sam build z SBOM Yocto na runnerze hostowanym przez GitHub z 32 rdzeniami ARM64 trwałby około 5 h 11 min. Przy $0.050 za minutę to $15.60. Build w CRACI kosztuje $5.68: o 64% mniej, czyli około 2,7 raza taniej. Cennik GitHub według stanu na wrzesień 2026; minuty wliczone w plan nie obejmują większych runnerów.
Wynik SPDX z Yocto zawiera jednak informacje, których CRACI nie rejestruje, takie jak łatki nakładane przez recepturę i CVE oznaczone w niej jako naprawione. Jeśli Państwa proces od nich zależy, warto pozostawić create-spdx włączone i korzystać z SBOM z CRACI równolegle. Jeśli nie, SBOM z CRACI sam obejmuje każdy komponent z SBOM Yocto, a nawet więcej.
Dlaczego ma to znaczenie dla bezpieczeństwa łańcucha dostaw
To, co trafia do buildu, decyduje o tym, co z niego wychodzi, niezależnie od tego, czy jest zainstalowane w obrazie. Atakujący o tym wiedzą, a to właśnie przez build wchodziły ostatnie ataki na łańcuch dostaw:
- Ataki ukrywają się w buildzie. Backdoor w xz utils (CVE-2024-3094) występował w wersjach 5.6.0 i 5.6.1. Jego wyzwalacz znajdował się w archiwach tarball wydania, a nie w repozytorium Git, a złośliwy kod trafiał do biblioteki w trakcie jej budowania. Czytanie kodu źródłowego tego nie ujawniło; ujawnia to wiedza o tym, który dokładnie tarball pobrał build.
- Zależności CI też są celem. W marcu 2025 r. CISA poinformowała, że każda wersja akcji GitHub
tj-actions/changed-filesbyła przejęta przez trzy dni. Akcja działa wewnątrz zadania buildu, dlatego CRACI wymienia akcje użyte przez Państwa workflow, przypięte do commita, który został uruchomiony. - Crate'y Rust znikają w plikach binarnych. Cargo kompiluje crate'y do programów, które z nich korzystają, więc podatny crate trafia do obrazu, nigdy nie pojawiając się jako pakiet. Jeśli SBOM wymienia go tylko z nazwy pliku, narzędzia do podatności również nie mogą go dopasować. Skanowanie gotowego pliku binarnego po fakcie musi zgadywać, co do niego trafiło; rejestrowanie buildu nie musi.
- Nie można reagować na to, czego się nie widzi. Gdy pojawia się komunikat bezpieczeństwa dla crate'a lub narzędzia buildu, trzeba wiedzieć, które buildy z niego korzystały. CRACI przechowuje SBOM każdego buildu i pokazuje, które buildy zawierały podatną zależność, bezpośrednią lub przechodnią, więc wiedzą Państwo, w jakim okresie byli narażeni. Działa to tylko wtedy, gdy każdy komponent ma package URL, do którego można go dopasować.
- Build powinien sięgać tylko tam, gdzie musi. Polityka ruchu wychodzącego CRACI blokuje połączenia z hostami, których build nie potrzebuje, więc przejęta zależność, która próbuje wysłać Państwa sekrety na serwer atakującego, zostaje zatrzymana, nawet w ataku, którego nikt wcześniej nie widział.
Klienci i regulacje, takie jak Cyber Resilience Act, również wymagają od producentów urządzeń podłączonych do sieci wiedzy o tym, co trafia do ich produktów. SBOM obejmujący cały build to dowód, który się obroni, gdy o to zapytają.
Pełne porównanie
Listy komponentów stojące za tymi liczbami, oba SBOM-y oraz opis tego, jak je zbudowaliśmy i porównaliśmy.
- 88 komponentów znalezionych tylko przez CRACI i 865 wymienionych w obu SBOM-ach
- Jak każdy SBOM identyfikuje 653 wersje crate'ów Rust
- Oba pliki SBOM: CycloneDX z CRACI i SPDX z Yocto
- Konfiguracja buildu, rozmiar runnera i czasy
Dziękujemy, oto pełny raport
Dlaczego buildy Yocto trudno uruchamiać w CI
Pełny build obrazu kompiluje ze źródeł toolchain, jądro i setki pakietów. Na standardowych runnerach z 2 rdzeniami, które oferuje większość usług CI, może to trwać godzinami, dlatego wiele zespołów embedded trzyma dedykowany serwer buildów pod biurkiem lub w szafie serwerowej, a ten serwer staje się kolejną maszyną do łatania, tworzenia kopii zapasowych i tłumaczenia audytorowi.
Build Yocto pobiera też bardzo dużo: archiwa źródeł, repozytoria Git i łatki z projektów upstream i mirrorów. To właśnie te pobrania musi uwzględniać Państwa SBOM i to o nich, zgodnie z regulacjami takimi jak Cyber Resilience Act, producenci urządzeń podłączonych do sieci muszą wiedzieć i je śledzić.
Co CRACI daje buildom Yocto
Runnery dopasowane do BitBake
Runnery CRACI skalują się od 1 do 32 jednostek obliczeniowych, gdzie każda jednostka to 1 vCPU i 3 GB RAM. Build Yocto może zażądać największego rozmiaru, 32 vCPU i 96 GB RAM, bezpośrednio z workflow. Zadania działają w izolowanych maszynach wirtualnych, a uruchomienia nadal pojawiają się w GitHub jak każde inne zadanie Actions.
Minuty są naliczane co do sekundy i rozliczane za vCPU-minutę, więc duży runner kosztuje więcej za minutę i kończy szybciej. Aktualne stawki podaje cennik.
Dostęp do sieci, o którym decydują Państwo
BitBake już teraz może ograniczyć swój fetcher do listy hostów za pomocą BB_ALLOWED_NETWORKS. CRACI dodaje drugą kontrolę na runnerze: politykę ruchu wychodzącego, sprawdzaną przed startem zadania i blokującą ruch w razie awarii (fail closed), więc receptura, skrypt lub przejęte narzędzie, które omija fetcher, nadal nie dotrze do hosta, na który Państwo nie zezwolili. CRACI wysyła alerty o naruszeniach polityki.
Zapis tego, co pobrał build
CRACI obserwuje ruch, który zadanie wysyła do hostów pakietów i źródeł, i rejestruje go jako dowód z buildu. Dla buildu Yocto oznacza to niezależny zapis źródeł, które faktycznie przyszły przez sieć, obok SBOM, który Yocto zapisuje sam.
Minimalny workflow
Przykład Yocto w dokumentacji CRACI buduje core-image-sato dla qemux86-64. Z punktu widzenia CRACI liczą się rozmiar runnera i konfiguracja fetchera korzystająca z oficjalnego mirrora źródeł Yocto:
jobs:
build:
runs-on: craci
steps:
- uses: cracicorp/setup@v1
with:
size: "32"
# install the host packages from the Yocto quick start, then:
- run: |
echo 'SOURCE_MIRROR_URL = "https://downloads.yoctoproject.org/mirror/sources/"' >> conf/local.conf
echo 'BB_ALLOWED_NETWORKS = "downloads.yoctoproject.org"' >> conf/local.conf
bitbake core-image-sato Przewodnik w dokumentacji zawiera pełny workflow, łącznie z zależnościami hosta i konfiguracją ustawień regionalnych, a dokumentacja konfiguracji runnera wymienia wszystkie opcje.
Warto wiedzieć
- Buildy działają na zarządzanych runnerach CRACI na europejskiej infrastrukturze, uruchamiane z GitHub Actions. Runnery hostowane przez klienta i inne systemy CI są w planach rozwoju.
- Warto kierować BitBake do mirrorów, które CRACI widzi, takich jak oficjalny mirror źródeł Yocto, a nie do dowolnych hostów. Przewodnik w dokumentacji pokazuje działającą konfigurację.
- Zachowywanie katalogu pobrań i cache shared state między uruchomieniami sprawia, że kolejne buildy są szybkie.
- Natywne runnery ARM64 są dostępne według tej samej stawki co x86-64.
Budują Państwo urządzenia podłączone do sieci na rynek UE? Proszę przeczytać, czego wymaga CRA, i jak CRACI działa w przemysłowym IoT i elektronice użytkowej. Porównują Państwo narzędzia SBOM dla Yocto? Zob. CRACI a Timesys Vigiles.
SBOM-y Yocto i CRACI: najczęściej zadawane pytania
Czy Yocto generuje SBOM?
Tak. Od Yocto 4.3 (Nanbield) system buildu OpenEmbedded domyślnie generuje SBOM w formacie SPDX za pomocą klasy create-spdx. Dla obrazu zapisuje plik IMAGE-MACHINE.spdx.json w katalogu tmp/deploy/images/MACHINE/, obejmujący komponenty, licencje, zależności, źródła, nałożone łatki i naprawione podatności. W Kirkstone (4.0) trzeba go włączyć, dodając INHERIT += "create-spdx".
Którą wersję SPDX generuje Yocto?
Od Yocto 5.1 (Styhead) domyślnie SPDX 3.0, która zastąpiła jako domyślną wersję 2.2. Scarthgap (5.0) domyślnie generuje SPDX 2.2, a na 3.0 można przejść za pomocą klasy create-spdx-3.0.
Jak uzyskać z Yocto SBOM w formacie CycloneDX?
Należy dodać warstwę meta-cyclonedx z gałęzi odpowiadającej Państwa wydaniu i dziedziczyć cyclonedx-export w local.conf. Obok obrazu powstaje wtedy SBOM .cyclonedx.bom.json i plik .cyclonedx.vex.json, domyślnie w formacie CycloneDX 1.6.
Czego brakuje w SBOM z Yocto?
W porównaniu buildów core-image-sato zarejestrowany przez CRACI SBOM zawierał wszystkie 865 komponentów z SBOM Yocto i 88 kolejnych: pakiety hosta na maszynie buildu, takie jak cpio z Ubuntu, źródła i akcje z GitHub oraz inne źródła pobrane w trakcie buildu. Yocto wymienia też 653 wersje crate'ów Rust tylko z nazwy pliku i adresu URL pobierania, bez package URL, na którym opiera się dopasowywanie podatności.
Czy można monitorować podatności w buildzie Yocto?
Tak, z CRACI. Dopasowywanie podatności działa na podstawie package URL, a wbudowany SBOM Yocto wymienia crate'y Rust tylko z nazwy pliku i adresu URL pobierania, więc nie da się ich dopasować. CRACI rejestruje crate'y Rust i pakiety maszyny buildu z package URL, względem których publikowane są komunikaty bezpieczeństwa (pkg:cargo, pkg:deb), łącznie ze wszystkimi 653 wersjami crate'ów w core-image-sato. Pokazuje status podatności każdego pakietu i na bieżąco ponownie ocenia SBOM w miarę publikowania nowych komunikatów.
Czy CRACI może zastąpić SBOM z Yocto?
Pod względem pokrycia łańcucha dostaw tak. W tym samym porównaniu SBOM z CRACI zawierał każdy komponent z wbudowanego SBOM Yocto, 88 dodatkowych i package URL dla każdego crate'a Rust, a build bez generowania SBOM przez Yocto trwał o 43% krócej. Wynik SPDX z Yocto nadal zawiera metadane receptur, których CRACI nie rejestruje, takie jak nałożone łatki i CVE oznaczone w recepturze jako naprawione. Jeśli Państwo na nich polegają, warto pozostawić create-spdx włączone.
Czy runner CRACI poradzi sobie z pełnym buildem obrazu Yocto?
Runnery CRACI mają do 32 vCPU i 96 GB RAM, a rozmiar ustawia się w workflow. Dokumentacja CRACI zawiera przykład Yocto, który buduje core-image-sato na największym rozmiarze.
Z jakiego CI korzysta build Yocto w CRACI?
Z GitHub Actions. Państwa workflow działa na zarządzanych runnerach CRACI, a uruchomienia pojawiają się w GitHub jak każde inne zadanie Actions. Inne systemy CI i runnery hostowane przez klienta są w planach rozwoju.
Proszę przynieść build Yocto na demo
Prosimy umówić demo: uruchomimy jeden z Państwa buildów BitBake na runnerze CRACI i omówimy, co pobrał.
Umów demo