Belső eszközből TYPO3-termék: amit az extension-gyártóknak tudniuk kell az SBOM-okról
Aki egy belső eszközből kereskedelmi TYPO3-extensiont csinál, szoftvergyártóvá válik — és a Cyber Resilience Act elvárja a gyártóktól, hogy tudják, mit tartalmaz a termékük. Gyakorlati áttekintés a Software Bill of Materialsről egy TYPO3-extension PHP- és frontend-részeihez.
A Digital Zombiesnál folyamatosan dolgozunk TYPO3-frissítéseken. Az évek során saját folyamatokat, szkripteket és technikai tudást fejlesztettünk ki, hogy ezek a projektek kiszámíthatóbbak legyenek. Így természetes volt elgondolkodni azon, hogy ennek az eszköztárnak egy része lehetne-e olyan TYPO3-extension, amelyet más ügynökségek is használhatnak.
Mérnöki szempontból az első kérdések ismerősek voltak. Mit automatizáljon az extension? Mely TYPO3-verziókat támogassa? Hogyan illeszthető be meglévő projektekbe felesleges bonyolultság nélkül? Hogyan teszteljük és tartjuk karban?
Aztán felmerült egy másik kérdés:
Ha egy belső eszközből kereskedelmi TYPO3-extensiont csinálunk, akkor egyszerűen hasznos kódot adunk el — vagy egy szoftvertermék gyártójává válunk?
Ez a megkülönböztetés egyre fontosabb az európai Cyber Resilience Act (CRA) miatt. A CRA kiberbiztonsági követelményeket vezet be az EU piacán forgalmazott, digitális elemeket tartalmazó termékekre. Attól függően, hogyan fejlesztik, forgalmazzák és terjesztik, egy kereskedelmi TYPO3-extension is ilyen terméknek minősülhet. Hogy a CRA egyáltalán vonatkozik-e egy tipikus TYPO3-weboldalprojektre, az külön kérdés, amelyet a TYPO3-weboldalprojektekről és a CRA-ról szóló társcikkben vizsgálok.
Ez a cikk nem kívánja meghatározni minden egyes TYPO3-extension jogi besorolását. Egy TYPO3-mérnökcég vezérigazgatójaként közelítem meg a témát, nem jogászként. Ehelyett egyetlen gyakorlati mérnöki következményre szeretnék koncentrálni, amelyet a kereskedelmi extension-fejlesztőknek érdemes megérteniük: a Software Bill of Materialsre, amelyet általában SBOM-nak rövidítenek.
Mit tartalmaz egy SBOM? Hogyan készíthetünk ilyet egy TYPO3-extension PHP- és frontend-részeihez? És hogyan köthetjük össze ezt az információt a release-ekkel, a sérülékenységi értesítésekkel és az azokból következő mérnöki döntésekkel?
Amikor a belső kódból termék lesz
Ugyanaz a TYPO3-extension nagyon eltérő kereskedelmi helyzetekben létezhet.
Egy ügynökség fejleszthet extensiont kizárólag egy ügyfélprojekthez. Egy cég készíthet belső eszközt a saját fejlesztőinek. Egy extension-szerző szabadon közzétehet kódot anélkül, hogy pénzt keresne rajta. Vagy az extensiont szabványosított termékként licencelik, értékesítik és támogatják sok ügyfél számára.
Technikai szempontból a kód szinte azonosnak tűnhet. Kereskedelmi és esetleg jogi szempontból a helyzetek különböznek.
Amikor azt fontolgattuk, hogy belső frissítő eszköztárunk egyes részeit újrafelhasználható extensionné alakítjuk, a puszta funkcionalitáson túl kellett néznünk. Szoftvert eladni azt jelenti, hogy nemcsak azért vállalunk felelősséget, hogy a jelenlegi verzió működik-e, hanem azért is, hogyan fejlesztik, frissítik és támogatják.
Ez olyan kérdéseket vet fel, mint:
- Meddig támogatjuk az egyes release-eket?
- Hogyan értesülünk a függőségeink sérülékenységeiről?
- Milyen gyorsan tudjuk megállapítani, mely verziók érintettek?
- Hogyan terjesztjük a biztonsági frissítéseket?
- Mi történik, ha egy függőséget már nem tartanak karban?
- Hogyan dokumentáljuk a fejlesztés során hozott döntéseket?
Ezek a CRA nélkül is észszerű mérnöki kérdések. A rendelet csak megnehezíti a halogatásukat.
Az egyik első követelmény tudni, mit tartalmaz valójában a termék. Itt válik relevánssá az SBOM.
Mi az az SBOM?
A Software Bill of Materials egy termékben található szoftverkomponensek strukturált leltára. Gyakran hasonlítják összetevők listájához, bár egy szoftveralkalmazás bonyolultabb, mert a komponensei egymástól függenek.
Egy SBOM tartalmazhatja:
- a komponensek és csomagok neveit;
- a pontos verziókat;
- a csomagok szállítóit vagy szerzőit;
- a csomagazonosítókat;
- a licencinformációkat;
- az ellenőrzőösszegeket;
- a közvetlen függőségeket;
- a tranzitív függőségeket;
- a komponensek közötti kapcsolatokat.
Az eredményt általában szabványos, gépileg olvasható formátumban tárolják. Két bevett formátum a CycloneDX és az SPDX. A cikk példáihoz a CycloneDX-et használom, mert a modellje a szoftver-ellátási lánc és a sérülékenységkezelés eseteire készült.
A CycloneDX képes komponenseket, szolgáltatásokat, függőségi kapcsolatokat, sérülékenységeket és a leltár teljességére vonatkozó információt ábrázolni. Az aktuális specifikáció itt érhető el: cyclonedx.org/specification/overview.
Egy TYPO3-extension esetében ez azért számít, mert még egy viszonylag kis termék is tartalmazhat többet a saját PHP-osztályainál. Függhet TYPO3 Core csomagoktól, más extensionöktől, Symfony-komponensektől, külső PHP-könyvtáraktól és a backend-modulhoz vagy a frontend-kimenethez használt npm-csomagoktól.
Strukturált leltár nélkül egy alapvető biztonsági kérdés megválaszolása a vártnál tovább tarthat:
Tartalmazza-e az extensionünk ügyfelek által használt valamelyik verziója az érintett komponenst?
Az SBOM gépileg olvashatóvá teszi a leltárt, így tárolható, összehasonlítható és összeköthető sérülékenység-figyelő rendszerekkel.
Mit mond a CRA az SBOM-okról?
A Cyber Resilience Act az SBOM elkészítését a gyártók sérülékenységkezelési követelményei közé sorolja. Az I. melléklet II. része előírja a gyártóknak, hogy azonosítsák és dokumentálják a termékeikben lévő sérülékenységeket és komponenseket — többek között egy elterjedt, gépileg olvasható formátumú SBOM elkészítésével. Ennek legalább a termék legfelső szintű függőségeit le kell fednie.
A teljes rendelet elérhető az EUR-Lexen.
Ez nem jelenti azt, hogy minden SBOM-ot nyilvánosan elérhetővé kell tenni. Azt sem jelenti, hogy egy SBOM elkészítése elegendő a CRA-megfelelőség igazolásához. Ez egy szélesebb folyamat egyik része, amelybe beletartozik a biztonságos termékfejlesztés, a sérülékenységkezelés, a dokumentáció, a biztonsági frissítések és az incidensbejelentés.
Egy extension-fejlesztő számára tehát az érdemi mérnöki kérdés nem pusztán az, hogyan hozzunk létre egy adott fájlt. Hanem az, hogy megbízhatóan azonosítani tudjuk-e az egyes kiadott verziók komponenseit, és reagálni tudunk-e, ha valamelyikük sérülékennyé válik.
Mi az a termék, amit dokumentálunk?
Mielőtt bármit is generálnánk, meg kell határoznunk a termék határát.
Ez nyilvánvalónak hangzik, de a folyamat egyik legfontosabb döntése. Egy kereskedelmi TYPO3-extension és a teljes TYPO3-telepítés, amelyben használják, nem ugyanaz a termék.
Képzeljük el, hogy egy vendor/upgrade-assistant nevű extensiont árulunk. A composer.json fájlja a következőt tartalmazhatja:
{
"name": "vendor/upgrade-assistant",
"description": "Upgrade analysis and assistance tools for TYPO3",
"type": "typo3-cms-extension",
"require": {
"php": "^8.2 || ^8.3 || ^8.4",
"typo3/cms-core": "^13.4 || ^14.0",
"symfony/console": "^7.2"
}
}
Egy újrafelhasználható Composer-csomag általában ne tartalmazzon kézzel karbantartott "version" mezőt. A Composer a release verzióját le tudja vezetni a Git-tagből vagy a repository metaadataiból.
Az extension deklarálja, mely verziókat támogatja, de nem határozza meg, pontosan mely TYPO3- vagy Symfony-verziók települnek egy ügyfélprojektbe. A Composer ezeket a verziókat a teljes telepítés követelményeivel együtt oldja fel.
Így két különböző leltár marad nekünk.
Az extension-szintű SBOM
Az extension-szintű SBOM azt a terméket írja le, amelyet terjesztünk. Azonosítania kell:
- az extensiont és a release verzióját;
- a deklarált Composer-követelményeit;
- az extensionnel csomagolt PHP-könyvtárakat;
- a fordított assetekbe foglalt JavaScript-könyvtárakat;
- a csomagon belül terjesztett egyéb harmadik féltől származó kódot.
Ez az a termékhatár, amely fölött az extension-gyártónak van a legközvetlenebb kontrollja.
A projekt-szintű SBOM
A projekt-szintű SBOM a teljes telepített TYPO3-projektből készül. Tartalmazhatja:
- a pontos telepített TYPO3 Core verziót;
- a kereskedelmi extensiont;
- az összes többi telepített extensiont;
- a teljes feloldott Composer-függőségi fát;
- az ügyfélspecifikus csomagokat;
- a projekt-szintű frontend-függőségeket.
Egy extension-gyártó nem tud minden ügyfélhez pontos projekt-szintű SBOM-ot készíteni, mert a végleges csomagverziókat az ügyfél projektje oldja fel. Fordítva viszont a projekt-szintű SBOM nem szünteti meg az extension-gyártó felelősségét abban, hogy megértse, mit terjeszt az extension részeként.
Composer-SBOM készítése
A CycloneDX PHP Composer plugin a Composer csomaginformációiból készít SBOM-ot. A dokumentációja szerint PHP 8.1-et vagy újabbat és Composer 2.3-at vagy újabbat támogat.
Fejlesztői függőségként adható hozzá:
composer require --dev cyclonedx/cyclonedx-php-composer
mkdir -p build
composer CycloneDX:make-sbom \
--output-format=JSON \
--output-file=build/sbom-backend.cdx.json \
--omit=dev \
--spec-version=1.7 \
--validate
A fenti parancsnév és opciók megfelelnek a plugin aktuális dokumentációjának: github.com/CycloneDX/cyclonedx-php-composer.
A plugin az 1.7-ig terjedő CycloneDX-specifikációverziókat támogatja, és validálni tudja az elkészült dokumentumot. Az információt a composer.json-ből, a telepített Composer-környezetből vagy egy működő composer.lock fájlból nyeri. A dokumentáció azt ajánlja, hogy ahol elérhető, a telepített környezetet használjuk.
A --omit=dev opció azt jelenti, hogy a fejlesztői függőségek kimaradnak az elkészült leltárból. Így maga a plugin használható a build során anélkül, hogy a terjesztett extension részeként megjelenne.
Van azonban egy fontos sorrendi részlet. Ha a plugin require-dev alatt van telepítve, ez nem fog működni:
composer install --no-dev
composer CycloneDX:make-sbom
Az első parancs kihagyja a plugint, így a második parancs már nem biztos, hogy elérhető.
Egy release-pipeline-ban ehelyett az elemző jobban telepíthetjük az összes függőséget, elkészíthetjük az SBOM-ot úgy, hogy a tartalmából kizárjuk a fejlesztői függőségeket, majd egy külön lépésben létrehozhatjuk a production-artefaktumot:
composer install --no-interaction --prefer-dist
mkdir -p build
composer CycloneDX:make-sbom \
--output-format=JSON \
--output-file=build/sbom-backend.cdx.json \
--omit=dev \
--spec-version=1.7 \
--validate
Egy alternatíva, hogy a CycloneDX plugint globálisan telepítjük a CI-környezetbe. Ebben az esetben magának a projektnek nem kell requirelnie a generátort. Bármelyik módszert is választjuk, az eszköz verzióját rögzíteni vagy naplózni kell, hogy a folyamat reprodukálható maradjon.
Az extension release verziójának beállítása
Egy library-repositoryban a gyökérkomponens verzióját nem mindig ismeri fel a rendszer a várt módon, különösen ha a pipeline a Git-tag nélküli commitot csekkolja ki.
A plugin erre explicit --mc-version opciót kínál a fő komponenshez:
composer CycloneDX:make-sbom \
--output-format=JSON \
--output-file=build/sbom-backend.cdx.json \
--omit=dev \
--spec-version=1.7 \
--mc-version=1.2.0 \
--validate
Egy valódi pipeline-ban az 1.2.0 a validált release-tagből származzon, ne pedig több helyre kézzel beírva.
A Composer korlátja újrafelhasználható extensionöknél
Az elkészült Composer-SBOM pontos arra a függőséghalmazra, amely abban a környezetben van telepítve, ahol a parancs fut. Nem automatikusan pontos leírása minden ügyféltelepítésnek.
Tegyük fel, hogy az extension a következőt requireli:
{
"require": {
"symfony/console": "^7.2"
}
}
Az extension tesztkörnyezete talán Symfony Console 7.4-et old fel, míg egy ügyféltelepítés egy másik kompatibilis verziót tartalmazhat. Mindkettő kielégíti a deklarált megkötést.
Ezért az extension CI-környezetéből készült SBOM-ot pontosan kell leírni. Dokumentálhatja:
- az extension által deklarált közvetlen követelményeket;
- a csomagolt harmadik féltől származó kódot;
- a release teszteléséhez használt pontos függőséghalmazt.
Nem szabad úgy bemutatni, mint bizonyítékot arra, mely pontos verziók futnak minden ügyféltelepítésben.
Egy több TYPO3-verziót támogató kereskedelmi extensionhöz hasznos lehet minden támogatott függőségi mátrixhoz külön teszt-SBOM-ot készíteni. Ezek a dokumentumok megmutatják, mely kombinációkat teszteltük, míg a végleges ügyfélprojektnek továbbra is saját projekt-szintű leltárra van szüksége.
Egy TYPO3-specifikus lehetőség: SBOMinator
Már létezik egy kísérleti TYPO3-extension, amely közvetlenül egy TYPO3-telepítésből készít SBOM-ot: sbominator/sbom-typo3.
Az extension a CloudFest Hackathon 2025 során indult. Egy TYPO3 backend-modult biztosít, amelyből egy adminisztrátor SPDX- vagy CycloneDX-formátumban tölthet le leltárt.
A csomag és az aktuális állapota itt található: packagist.org/packages/sbominator/sbom-typo3.
A dokumentált telepítési parancs:
composer require "sbominator/sbom-typo3:@dev"
Ehhez azonban egyértelmű figyelmeztetés kell. A karbantartók kísérletinek és proof of conceptnek írják le az extensiont. Azt is közlik, hogy a generált SBOM-tartalom még validálásra és finomításra szorul. A jelenlegi függőségi deklarációi fejlesztői megkötéseket használnak, ezért inkább fejlesztői vagy tesztkörnyezetben értékelném, mintsem közvetlenül egy production-projektbe vezetném be.
Az SBOMinator ennek ellenére nagyon fontos, mert megmutatja, hogyan lehetne egy projekt-szintű leltárt elérhetővé tenni a TYPO3-on belül. Ahelyett, hogy egy adminisztrátort kérnénk meg, hogy futtasson egy parancsot a szerveren, egy backend-modult biztosít, amely megvizsgálja a weboldal által használt szoftverkomponenseket, és letöltésként kínálja fel az eredményt.
Ez más problémát old meg, mint a kereskedelmi extension példánk.
| Módszer | Elsődleges hatókör |
|---|---|
| CycloneDX Composer plugin az extension repositoryban | Az extension fejlesztési és release-függőséghalmaza |
| npm-SBOM az extension repositoryban | Az extension frontend-függőségi fája |
| SBOMinator a TYPO3-on belül | Egy teljes TYPO3-telepítésben észlelt komponensek |
| Projekt-pipeline SBOM | Egy konkrét deployolt release feloldott függőségei |
Egy extension-gyártó számára az SBOMinator nem helyettesítheti a termékszintű release-folyamatot. Az ügyfél teljes TYPO3-környezetében fut, ezért szélesebb telepítést ír le. Ugyanakkor a gyártó Composer-SBOM-ja nem tudja leírni az ügyfél teljes projektjét.
A megközelítések kiegészítik egymást. Az extension-gyártó azt dokumentálja, amit fejleszt és terjeszt. A projekt üzemeltetője azt dokumentálja, amit végül telepítenek és deployolnak.
Kerüld a láthatatlan PHP-függőségeket
A legtöbb TYPO3-extension esetében hagyni kell, hogy a Composer kezelje a PHP-függőségeket. Ha egy harmadik féltől származó könyvtárat bemásolunk az extensionbe, vagy egy belső vendor/ könyvtárat terjesztünk, az megnehezíti az azonosítást, a frissítéseket és a sérülékenység-figyelést.
Ha külső kódot ilyen helyekre másolunk, azt valószínűleg nem azonosítja automatikusan a rendszer:
Resources/Private/Lib/
Resources/Public/JavaScript/Vendor/
Classes/Utility/ThirdParty/
A Composer-bejegyzés hiánya nem teszi a harmadik féltől származó kódot saját kóddá. Csak nehezebben követhetővé teszi az eredetét és a verzióját.
Amikor később bejelentenek egy sérülékenységet, a bemásolt könyvtár még ott lehet, pedig már senki sem emlékszik, honnan került oda. Egy olyan kereskedelmi terméknél, amelynek több éven át biztonsági támogatást kell kapnia, ez felesleges kockázatot teremt.
A külső PHP-könyvtáraknak ezért ott, ahol csak lehetséges, láthatónak kell maradniuk a Composer számára. Ha a csomagolás elkerülhetetlen, a komponenst egy másik kontrollált folyamaton keresztül kell felvenni a termékleltárba.
A frontend-SBOM elkészítése
Egy Composer-SBOM nem írja le azokat az npm-csomagokat, amelyeket egy extension backend-moduljának vagy frontend-funkcióinak buildeléséhez használnak.
A jelenlegi npm-verziók natív npm sbom parancsot biztosítanak. Feltéve, hogy a package-lock.json jelen van, és a függőségeket npm ci-vel telepítettük, egy extension CycloneDX-dokumentuma így készíthető el:
mkdir -p build
npm sbom \
--sbom-format=cyclonedx \
--sbom-type=library \
> build/sbom-frontend.cdx.json
Egy újrafelhasználható TYPO3-extensionhöz a library a megfelelő típus. Egy teljes, deployolt TYPO3-projekthez általában az application lenne pontosabb.
A parancsot és a lehetséges értékeket az npm dokumentálja: docs.npmjs.com/cli/v11/commands/npm-sbom.
Ha a pipeline szándékosan a package-lock.json-ből akarja generálni a dokumentumot, a telepített node_modules fa használata nélkül, az npm ezt támogatja:
npm sbom \
--package-lock-only \
--sbom-format=cyclonedx \
--sbom-type=library \
> build/sbom-frontend.cdx.json
Ez a parancs érvényes, de az eredmény kevesebb metaadatot tartalmaz. Az npm dokumentálja, hogy a csak-lockfile mód nem olvas ki olyan információt, mint a leírások, a honlapok és az engine-követelmények a függőségi csomagokból.
Miért lehet félrevezető az --omit=dev
Az npm szintén támogatja az --omit=dev-et:
npm sbom \
--sbom-format=cyclonedx \
--sbom-type=library \
--omit=dev \
> build/sbom-frontend.cdx.json
Egy terjesztett TYPO3-extensionhöz nem használnám ezt az opciót automatikusan.
A frontend-buildfüggőségeket gyakran a devDependencies alatt deklarálják, de a kódjuk mégis belekerülhet az extensionnel szállított JavaScriptbe. A Vite, a webpack vagy az esbuild több száz npm-modult néhány fordított fájllá alakíthat. Az ügyfél nem kap node_modules-t, de az elkészült assetek mégis tartalmazhatnak ezekből a csomagokból származó kódot.
Egy kizárólag SCSS-átalakításra használt Sass-fordító a buildkörnyezet része. Egy olyan JavaScript-könyvtár, amelyet a terjesztett kimenetbe csomagolnak, a keletkező termék részévé válik. Mindkettő szerepelhet a devDependencies alatt, pedig eltérő szerepet játszanak.
A csomagkezelő szerinti besorolás önmagában tehát nem határozza meg a termékhatárt. A release-folyamatnak kell eldöntenie, mely függőségek adnak kódot a terjesztett artefaktumhoz.
{
"name": "@vendor/upgrade-assistant",
"version": "1.2.0",
"private": true,
"dependencies": {
"lodash": "4.17.21"
}
}
npm ci
mkdir -p build
npm sbom \
--sbom-format=cyclonedx \
--sbom-type=library \
> build/sbom-frontend.cdx.json
A "private": true beállítás akkor hasznos, ha a package.json csak a TYPO3-extension buildeléséhez létezik, és nem szabad véletlenül közzétenni magát az npm-registryben.
A fenti parancsot npm 11.9.0-val ellenőriztük. Érvényes CycloneDX-dokumentumot állított elő, a gyökérkomponenst librarynek minősítette, és a lezárt függőséget a pontos verziójával együtt tartalmazta.
A tervezett architektúránk: release-ek, SBOM-ok és sérülékenységek összekötése
Amikor a frissítéstámogató extensionünk architektúráján gondolkodtunk, nem akartuk, hogy az SBOM-generálás egy elszigetelt pipeline-parancs legyen, amely két olyan fájlt állít elő, amelyekre soha többé nem néz rá senki.
A hasznos rész ott kezdődik, amikor a különálló darabokat összekötjük.
Egy kereskedelmi TYPO3-extension tartalmazhat Composerrel kezelt PHP-függőségeket és npm-mel kezelt frontend-függőségeket. Ezek külön függőségi fákat, így külön SBOM-fájlokat eredményeznek. Ugyanakkor mindkét leltár ugyanannak a termék-release-nek a részeit írja le.
A tervezett architektúránk ezért egy olyan release-identitásra épült, amely összeköti:
- az extension verzióját;
- a Git-commitot;
- a terjesztett ZIP- vagy Composer-csomagot;
- a Composer-SBOM-ot;
- az npm-SBOM-ot;
- a támogatott TYPO3-verziókat;
- az ismert sérülékenységeket;
- a mérnöki értékelésünk eredményét;
- az érintett release-t leváltó biztonsági frissítéseket.
Egy egyszerűsített release-job a következőt tartalmazhatja:
composer install --no-interaction --prefer-dist
npm ci
npm run build
mkdir -p build
composer CycloneDX:make-sbom \
--output-format=JSON \
--output-file=build/sbom-backend.cdx.json \
--omit=dev \
--spec-version=1.7 \
--mc-version=1.2.0 \
--validate
npm sbom \
--sbom-format=cyclonedx \
--sbom-type=library \
> build/sbom-frontend.cdx.json
Ez a példa a következőket feltételezi:
- a CycloneDX Composer plugin fejlesztői függőségként van telepítve;
- a
composer.lockés apackage-lock.jsonelérhető; - az npm támogatja az
sbomparancsot; - az
1.2.0verziót buildeljük; - a frontend-assetek a release-artefaktum csomagolása előtt készülnek el.
Az eredmény nem egy SBOM, hanem két érvényes CycloneDX-dokumentum:
upgrade-assistant-1.2.0-backend.cdx.json
upgrade-assistant-1.2.0-frontend.cdx.json
Ezeknek a fájloknak a puszta összefűzése nem eredményezne érvényes kombinált SBOM-ot. Ehelyett mindkét dokumentumot ugyanahhoz a release-rekordhoz kell kötni.
Fogalmilag ez a rekord a következőt tartalmazhatja:
{
"product": "vendor/upgrade-assistant",
"version": "1.2.0",
"commit": "4f82c91",
"artifacts": {
"package": "upgrade-assistant-1.2.0.zip",
"backendSbom": "upgrade-assistant-1.2.0-backend.cdx.json",
"frontendSbom": "upgrade-assistant-1.2.0-frontend.cdx.json"
}
}
Ez nem SBOM-formátum, és nem is szabad annak feltüntetni. Ez egy példa arra a metaadatra, amely a termék-release és a kapcsolódó artefaktumok összekötéséhez szükséges.
A fontos architektúrabeli elv az, hogy egy sérülékenység soha ne csak egy absztrakt csomagra mutasson. El kell vezetnie minket az érintett termék-release-ekhez, onnan pedig azokhoz az ügyfelekhez vagy telepítésekhez, amelyeknek frissítésre lehet szükségük.
A fájlok elkészítése a könnyebbik rész
A Composer és az npm már most is meg tudja adni egy alapszintű függőségleltárhoz szükséges információk nagy részét. A nehezebb kérdés az, mi történik, amikor az extension kiadása után több hónappal új sérülékenységet tesznek közzé.
Az SBOM-fájlok nem értesítenek minket automatikusan. Komponensinformációt tartalmaznak, de valaminek folyamatosan össze kell vetnie ezt a leltárt az aktuális sérülékenységforrásokkal.
Egy teljes folyamathoz ezért egy további réteg kell:
- a pipeline elkészíti az SBOM-okat;
- az SBOM-okat a termék-release-szel együtt tárolják;
- a komponenseiket egy figyelőrendszerbe importálják;
- a rendszer rendszeresen ellenőrzi az aktuális sérülékenységi adatbázisokat;
- egy releváns találat értesítést hoz létre;
- egy mérnök felméri, hogy az extension valóban érintett-e;
- az értékelést és a belőle következő intézkedést dokumentálják;
- egy frissítést készítenek elő, és az érintett release-hez kötik.
Ez is az egyik legérdekesebb architektúrabeli kérdés volt számunkra. Egyszer elkészíteni egy SBOM-ot viszonylag egyszerű. Hat hónappal később megbízható értesítést kapni, amikor egy újonnan felfedezett sérülékenység egy tranzitív függőséget érint, tartós rendszert igényel.
A figyelőplatformnak többet kell tudnia, mint a jelenlegi függőségi fa. Meg kell őriznie a korábbi release-eket, mert az ügyfelek az 1.2.0 verzió közzététele után is használhatják még az 1.1.0 verziót.
Egy sérülékenység ezért eltérő értékelésekhez vezethet:
| Release | Komponens | Eredmény | Intézkedés |
|---|---|---|---|
| 1.0.0 | Érintett függőség | Érintett | Biztonsági frissítés szükséges |
| 1.1.0 | Érintett függőség | Nem kihasználható | Értékelés dokumentálva |
| 1.2.0 | Frissített függőség | Nem érintett | Nincs teendő |
Ez a történeti kapcsolat az egyik oka annak, hogy egy kereskedelmi termékhez nem elég a composer audit vagy az npm audit csak a legfrissebb main-branchen futtatni. Ezek a parancsok értékes információt adhatnak az aktuális checkoutról, de nem figyelnek automatikusan minden korábban terjesztett release-t.
A sérülékenységi találattól a mérnöki döntésig
Egy sérülékenységi adatbázis azonosítani tud egy lehetséges egyezést egy advisory és egy csomagverzió között. Nem mindig tudja megállapítani, hogy a kereskedelmi extension valóban érintett-e.
Például:
- lehet, hogy a sérülékeny függvényt nem használják;
- lehet, hogy az érintett kódútvonal nem érhető el;
- lehet, hogy a sérülékenység olyan konfigurációt igényel, amelyet az extension nem támogat;
- lehet, hogy a függőséget csak a build során használják;
- lehet, hogy a terjesztett asset nem tartalmazza az érintett részt;
- lehet, hogy az extensionben már létezik enyhítés.
Ennek az ellenkezője is igaz. Egy függőségvizsgáló nem tud sérülékenységet azonosítani a saját egyedi PHP- vagy JavaScript-kódunkban, egyszerűen azért, mert ahhoz a kódhoz nincs külső csomag-advisory.
Az értesítés tehát egy mérnöki folyamat kezdete, nem a lezárása.
Minden releváns találatnál meg kell határoznunk:
- mely release-ek tartalmazzák a komponenst;
- jelen van-e az érintett funkció;
- elérhető-e az extension rendeltetésszerű használatában;
- rendelkezésre áll-e frissítés vagy enyhítés;
- szükséges-e új extension-release;
- mely ügyfeleket vagy telepítéseket kell értesíteni.
A CycloneDX támogatja a VEX-et is, a Vulnerability Exploitability eXchange-et. A VEX-szel dokumentálható, hogy egy termék érintett-e egy ismert sérülékenységben, és megmagyarázható az értékelés eredménye: cyclonedx.org/capabilities/vex.
Ez azért fontos, mert a vizsgálati találatok ismételt, dokumentálatlan elvetése nem hoz létre megbízható biztonsági folyamatot. Ha arra jutunk, hogy egy extension nem érintett, ezt a következtetést össze kell kötni a sérülékenységgel, az érintett termék-release-ekkel és a döntés mögötti technikai indoklással.
Az értesítés kihívása
A sérülékenységi értesítési réteg különös figyelmet érdemel, mert az egész folyamat minősége rajta múlik.
Egy olyan értesítőrendszert, amely túl sok irreleváns riasztást gyárt, végül figyelmen kívül hagynak. Egy olyan rendszer, amely csak a közvetlen függőségeket ellenőrzi, elmulaszthat egy sérülékenységet a függőségi fa mélyebb szintjén. Egy olyan rendszer, amely csak a legfrissebb release-t figyeli, védtelenül hagyja a támogatott régebbi verziókat használó ügyfeleket.
Egy hasznos figyelőfolyamatnak ezért képesnek kell lennie:
- felismerni a szabványos csomagazonosítókat, például a Package URL-eket;
- feldolgozni mind a Composer-, mind az npm-komponenseket;
- megőrizni a korábbi termék-release-eket;
- megkülönböztetni a közvetlen és a tranzitív függőségeket;
- elkerülni az ugyanahhoz a sérülékenységhez tartozó duplikált riasztásokat;
- tükrözni a frissített vagy visszavont advisorykat;
- az érintett termékeket a felelős mérnökcsapathoz rendelni;
- tárolni az értékelés és a javítás státuszát;
- újra értesíteni, amikor a rendelkezésre álló információ megváltozik.
Itt nyer működési értéket az SBOM. Szabványosított leltárt ad a figyelőrendszernek, de a rendszernek még mindig cselekvésre alkalmas mérnöki feladattá kell alakítania az új sérülékenységi információt.
Egy több terméket karbantartó cég számára ebből központi szolgáltatás válhat, nem pedig minden repositoryban külön folyamat. Minden release-pipeline elküldi az SBOM-jait a platformnak, míg a platform végzi a folyamatos figyelést, az értesítéseket és a dokumentált értékeléseket.
Hol illeszkedik az SBOMinator ebbe az architektúrába
A kísérleti sbominator/sbom-typo3 extension ugyanahhoz a témához a telepített weboldal nézőpontjából közelít. CycloneDX- vagy SPDX-leltárakat tud készíteni egy TYPO3-telepítésen belülről.
Ez egy további hasznos bemenetet ad az architektúrához.
Az extension-gyártó pipeline-ja azokat a függőségeket írja le, amelyek egy adott termék-release-hez kapcsolódnak. Az SBOMinator azokat a komponenseket próbálja leírni, amelyek az ügyfél teljes TYPO3-telepítésében jelen vannak.
Ezek a nézőpontok összeköthetők:
- a gyártó tudja, mely függőségek tartoznak a kereskedelmi extensionhöz;
- a projekt üzemeltetője tudja, mely pontos csomagverziók oldódtak fel a telepítésben;
- a figyelőplatform tudja, mely release-ek és telepítések lehetnek érintettek;
- a mérnöki értékelés meghatározza, szükséges-e intézkedés.
Az SBOMinatort jelenleg kísérleti proof of conceptként írják le, ezért a kimenetét még validálni kell, mielőtt egy production-megfelelőségi folyamat részévé válna. Ennek ellenére megmutatja, hogyan vehet részt maga a TYPO3 egy nagyobb szoftverleltár-architektúrában.
Az érdekes hosszú távú lehetőség nem csupán egy SBOM kézi letöltése a TYPO3-backendből. Hanem a leltár biztonságos továbbítása egy központi platformra, amely a telepítés teljes élettartama alatt figyelni tudja azt.
Ma többet várnak el a szoftvergyártóktól
A Cyber Resilience Act előtt egy kereskedelmi extension-fejlesztő főként a funkció fejlesztésére, új verziók közzétételére és arra összpontosíthatott, hogy reagáljon, amikor az ügyfelek problémát jeleztek.
Egy professzionálisan karbantartott szoftvertermékhez ez már nem elég.
Egy gyártónak egyre inkább strukturált folyamatra van szüksége a következőkhöz:
- a termékben lévő összes komponens azonosítása;
- a sérülékenységek figyelése egy release után;
- annak felmérése, hogy a termék érintett-e;
- biztonsági frissítések biztosítása;
- a technikai döntések dokumentálása;
- egy támogatási időszak meghatározása és kommunikálása;
- szükség esetén az illetékes felek értesítése.
Ez több munkát jelent, mint amennyit a CRA előtt általában elvártak egy TYPO3-extension-fejlesztőtől. Azt is jelenti, hogy a karbantartási és biztonsági felelősséget figyelembe kell venni egy kereskedelmi extension ár- és támogatási modelljének meghatározásakor.
A mögöttes célt azonban nem tartom észszerűtlennek. Egy szoftverterméket vásárló ügyfél joggal várhatja el, hogy a gyártó tudja, mely komponenseket tartalmaz, követi az újonnan közzétett biztonsági információt, és frissítést tud adni, ha releváns sérülékenységet fedeznek fel.
A CRA olyan felelősségeket formalizál, amelyeket az érett szoftvergyártóknak amúgy is komolyan kellene venniük. A megvalósítása technikai és szervezeti kihívásokat fog teremteni, különösen a kisebb extension-szállítóknak, de a követelmények mögötti szándék érthető.
Összegzés
Egy kereskedelmi TYPO3-extension elkészítése ma többet jelent, mint egy hasznos funkció fejlesztése és egy csomag közzététele.
A backend- és frontend-függőségeket azonosítani kell. Az elkészült SBOM-okat egy konkrét release-hez kell kötni. A korábbi release-eknek láthatónak kell maradniuk. A sérülékenységi információt folyamatosan figyelni kell, és egy riasztásnak dokumentált mérnöki értékeléshez, szükség esetén biztonsági frissítéshez kell vezetnie.
Ez volt az az architekturális irány, amelyet a saját extensionünkhöz fontolgattunk:
Kösd össze minden termék-release-t a backend- és frontend-SBOM-jaival, figyeld folyamatosan ezeket a leltárakat, és alakítsd a releváns sérülékenységi információt cselekvésre alkalmas mérnöki folyamattá.
A Cyber Resilience Act többet vár el a szoftvergyártóktól, mint amennyit sok extension-fejlesztő 2024 előtt tett. Ez többletmunkát jelent, de értékes célja is van: a termékek ne váljanak láthatatlanná a gyártóik számára azután, hogy eladták őket. Ezzel az elvvel egyetértünk.
Egy SBOM önmagában nem teszi biztonságossá a szoftvert, de ha összekötjük release-ekkel, sérülékenység-figyeléssel, értesítésekkel és mérnöki döntésekkel, egy felelősségteljesebb termék-életciklus alapjává válik.