Skip to content

Commit 47cb0ee

Browse files
committed
📝 Add SBOM
1 parent 9cbfa08 commit 47cb0ee

8 files changed

Lines changed: 316 additions & 16 deletions

File tree

docs/intro.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Ab Kapitel 2 folgt das Tutorial dem Prototyp eines Forschungsprojekts:
5151
verschiedenen Möglichkeiten verschoben.
5252
#. :doc:`performance/index` stellt Möglichkeiten vor, wie ihr euren Code
5353
schneller laufen lassen könnt.
54-
#. :doc:`productive/index` product zeigt, was notwendig ist, um reproduzierbare
54+
#. :doc:`productive/index` zeigt, was notwendig ist, um reproduzierbare
5555
Ergebnisse zu erzielen: Es werden nicht nur :doc:`reproducible environments
5656
<productive/envs/index>` benötigt, sondern auch die Versionierung des
5757
:doc:`Quellcodes <productive/git/index>` und der :doc:`Daten
@@ -61,7 +61,7 @@ Ab Kapitel 2 folgt das Tutorial dem Prototyp eines Forschungsprojekts:
6161
:doc:`Rests <productive/testing>` und :doc:`python-basics:logging/index`.
6262
Schließlich enthält das Kapitel Ratschläge zur :doc:`Verbesserung der
6363
Codequalität <productive/qa/index>` und des :doc:`sicheren Betriebs
64-
<productive/security>`.
64+
<productive/security/index>`.
6565
#. :doc:`web/index` kann entweder Dashboards aus Jupyter-Notebooks generieren
6666
oder eine umfassendere Anwendungslogik erfordern, wie in
6767
:doc:`pyviz:bokeh/embedding-export/flask`, demonstriert, oder Daten über

docs/productive/git/advanced/gitlab/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ externe Integrationen erforderlich wären, :abbr:`z.B. (zum Beispiel)` das
2222
Wenn bereits eine PaaS-Lösung wie `Kubernetes
2323
<https://de.wikipedia.org/wiki/Kubernetes>`_ verwendet wird, können mit
2424
GitLab-CI/CD Apps automatisch bereitgestellt, getestet und skaliert werden.
25-
Zudem kann automatisch die :doc:`/productive/security` eures Projekts
25+
Zudem kann automatisch die :doc:`/productive/security/index` eures Projekts
2626
überprüft werden.
2727

2828
GitLab ist eine komplett paketierte Plattform, während GitHub mit Apps aus dem

docs/productive/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,4 @@ andererseits für das :doc:`testing`, :doc:`python-basics:logging/index`,
7474
testing
7575
logging
7676
qa/index
77-
security
77+
security/index

docs/productive/licensing.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,8 +648,9 @@ Alternativen
648648

649649
* generiert `OWASP CycloneDX <https://cyclonedx.org>`_, `SPDX Software Bill
650650
of Materials (SBOM)
651-
<https://github.com/opensbom-generator/spdx-sbom-generator>`_ oder
652-
benutzerdefinierte FOSS-Attributionsdokumentation für euer Softwareprojekt
651+
<https://spdx.github.io/spdx-spec/v3.0.1/model/Software/Classes/Sbom/>`_
652+
oder benutzerdefinierte FOSS-Attributionsdokumentation für euer
653+
Softwareprojekt
653654
* automatisiert eure FOSS-Policy, um euer Softwareprojekt und seine
654655
Abhängigkeiten auf Lizenzierung, Sicherheitslücken, Quellcode und
655656
technische Standards zu prüfen
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
stages:
2+
- build
3+
- sbom
4+
5+
build:
6+
stage: build
7+
script:
8+
- uv build
9+
artifacts:
10+
paths:
11+
- dist/
12+
13+
include:
14+
- template: Security/Dependency-Scanning.gitlab-ci.yml
15+
16+
generate-sbom:
17+
stage: test
18+
image: ghcr.io/sbomify/sbomify-action
19+
variables:
20+
LOCK_FILE: uv.lock
21+
OUTPUT_FILE: gl-sbom-report.cdx.json
22+
UPLOAD: "false"
23+
ENRICH: "true"
24+
script:
25+
- /sbomify.sh
26+
artifacts:
27+
paths:
28+
- gl-sbom-report.cdx.json
29+
reports:
30+
cyclonedx: gl-sbom-report.cdx.json
31+
32+
generate-sbom:
33+
stage: sbom
34+
image: ghcr.io/sbomify/sbomify-action
35+
variables:
36+
LOCK_FILE: uv.lock
37+
OUTPUT_FILE: sbom.cdx.json
38+
COMPONENT_NAME: myapp
39+
COMPONENT_VERSION: $CI_COMMIT_TAG
40+
UPLOAD: "false"
41+
ENRICH: "true"
42+
script:
43+
- /sbomify.sh
44+
artifacts:
45+
paths:
46+
- sbom.cdx.json
47+
reports:
48+
cyclonedx: sbom.cdx.json
Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ oder besser:
9191
<https://docs.astral.sh/uv/reference/settings/#audit_ignore-until-fixed>`_
9292

9393
Ihr könnt die Schwachstellenanalyse mit ``uv-audit`` auch in eure :doc:`prek
94-
<git/advanced/hooks/prek>`-Checks übernehmen:
94+
<../git/advanced/hooks/prek>`-Checks übernehmen:
9595

9696
.. code-block:: yaml
9797
@@ -246,7 +246,7 @@ in die Codebasis eingeführt werden.
246246

247247
.. _bandit:
248248

249-
Mit `Bandit <https://github.com/PyCQA/bandit>`__, das ihr mit :doc:`qa/ruff`
249+
Mit `Bandit <https://github.com/PyCQA/bandit>`__, das ihr mit :doc:`../qa/ruff`
250250
verwenden könnt lassen sich :abbr:`u. a. (unter anderem)` folgende
251251
Schwachstellen überprüfen:
252252

@@ -271,9 +271,9 @@ Schwachstellen überprüfen:
271271
`flake8-bandit <https://docs.astral.sh/ruff/rules/#flake8-bandit-s>`_
272272
273273
Bandit könnt ihr auch in Jupyter Notebooks, IDEs und
274-
:doc:`git/advanced/hooks/prek` integrieren.
274+
:doc:`../git/advanced/hooks/prek` integrieren.
275275

276-
Zudem könnt ihr :doc:`qa/pysa` für `Taint
276+
Zudem könnt ihr :doc:`../qa/pysa` für `Taint
277277
<https://en.wikipedia.org/wiki/Taint_checking>`_-Analysen verwenden.
278278

279279
Für GitHub-Repositories könnt ihr alternativ auch `CodeQL
@@ -311,9 +311,10 @@ Risiko: Hoch
311311
Mit :ref:`geschützten Git-Zweigen <protected_branches>` können Regeln für die
312312
Übernahme von Änderungen in Standard- und Veröffentlichungszweige definiert
313313
werden, :abbr:`z.B. (zum Beispiel)` automatisierte `statische Code-Analysen
314-
<https://de.wikipedia.org/wiki/Statische_Code-Analyse>`_ mit :doc:`qa/flake8`,
315-
:doc:`qa/pysa`, :doc:`qa/wily` und :ref:`Code-Reviews <code_reviews>` über
316-
:abbr:`sog. (sogenannte)` :doc:`git/advanced/gitlab/merge-requests`.
314+
<https://de.wikipedia.org/wiki/Statische_Code-Analyse>`_ mit
315+
:doc:`../qa/flake8`, :doc:`../qa/pysa`, :doc:`../qa/wily` und :ref:`Code-Reviews
316+
<code_reviews>` über
317+
:abbr:`sog. (sogenannte)` :doc:`../git/advanced/gitlab/merge-requests`.
317318

318319
.. _code_reviews:
319320

@@ -353,12 +354,12 @@ Release-Prozesses verwendet werden, festgeschrieben werden. Dabei sollte eine
353354
*gepinnte Abhängigkeit* explizit auf einen bestimmten Hash gesetzt sein und
354355
nicht nur auf eine veränderbare Version oder einen Versionsbereich.
355356

356-
:doc:`envs/spack/index` schreibt für die jeweilige Umgebung diese Hashes in
357-
:ref:`spack_lock`, :doc:`envs/uv/index` in :ref:`uv_lock` fest.
357+
:doc:`../envs/spack/index` schreibt für die jeweilige Umgebung diese Hashes in
358+
:ref:`spack_lock`, :doc:`../envs/uv/index` in :ref:`uv_lock` fest.
358359

359360
.. tip::
360361
Üblicherweise verwalte ich diese Dateien jedoch nur bei
361-
:doc:`python-basics:packs/apps` in :doc:`Git <git/index>`. Bei
362+
:doc:`python-basics:packs/apps` in :doc:`Git <../git/index>`. Bei
362363
:doc:`python-basics:libs/index` schränke ich üblicherweise lediglich den
363364
Versionsbereich der Abhängigkeiten in der :file:`pyproject.toml`-Datei ein.
364365

@@ -386,3 +387,10 @@ verhindern. Ihr könnt dieses Risiko verringern durch
386387
.. _S324: https://docs.astral.sh/ruff/rules/hashlib-insecure-hash-function/
387388
.. _S608: https://docs.astral.sh/ruff/rules/hardcoded-sql-expression/
388389
.. _S608: https://docs.astral.sh/ruff/rules/hardcoded-sql-expression/
390+
391+
.. toctree::
392+
:hidden:
393+
:titlesonly:
394+
:maxdepth: 0
395+
396+
sbom

docs/productive/security/sbom.rst

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
.. SPDX-FileCopyrightText: 2026 cusy GmbH
2+
..
3+
.. SPDX-License-Identifier: BSD-3-Clause
4+
5+
Software Bill-of-Materials (SBOM)
6+
=================================
7+
8+
Eine Software Bill-of-Materials (SBOM) ist ein Dokument zum Austausch von
9+
Informationen über Software und deren Zusammensetzung. Dieses Format wird vor
10+
allem im Sicherheitsbereich verwendet, um Software und ihre Abhängigkeiten
11+
mithilfe von Schwachstellendatenbanken wie `CVE <https://www.cve.org/>`_ und
12+
`OSV <https://osv.dev/>`_ auf Schwachstellen zu überprüfen. Das vom
13+
CPython-Projekt verwendete SBOM-Format ist `SPDX
14+
<https://spdx.github.io/spdx-spec/v3.0.1/model/Software/Classes/Sbom/>`_, das
15+
bei Bedarf in andere Formate konvertiert werden kann. Die SBOM-Datei für die in
16+
CPython enthaltenen Abhängigkeiten wird unter `Misc/sbom.spdx.json
17+
<https://github.com/python/cpython/blob/main/Misc/sbom.spdx.json>`_ verwaltet.
18+
Die Datei wird erstellt mit `Tools/build/generate_sbom.py
19+
<https://github.com/python/cpython/blob/main/Tools/build/generate_sbom.py>`_.
20+
21+
SBOM-Datei erstellen
22+
--------------------
23+
24+
… mit uv
25+
~~~~~~~~
26+
27+
:term:`uv` bietet eine einfache Möglichkeit, eine SBOM-Datei im Format CycloneDX
28+
v1.5 zu erstellen mit:
29+
30+
.. code-block:: console
31+
32+
$ uv export --format='cyclonedx1.5' > sbom.cdx.json
33+
34+
Die Datei enthält jedoch nur sehr rudimentäre Angaben, :abbr:`z. B. (zum
35+
Beispiel)` für `cusy.tasks <https://github.com/cusyio/cusy.tasks>`_:
36+
37+
.. code-block:: json
38+
39+
"component": {
40+
"type": "library",
41+
"bom-ref": "cusy-tasks-1@26.2.0",
42+
"name": "cusy-tasks",
43+
"version": "26.2.0",
44+
"properties": [
45+
{
46+
"name": "uv:package:is_project_root",
47+
"value": "true"
48+
}
49+
]
50+
}
51+
52+
Mit ``uv export --all-groups --format='cyclonedx1.5' > sbom.cdx.json`` könnt
53+
ihr auch alle Dependency-Groups in die SBOM-Datei übernehmen.
54+
55+
… mit CycloneDX Python
56+
~~~~~~~~~~~~~~~~~~~~~~
57+
58+
Deutlich umfangreicher ist die Ausgabe von `CycloneDX Python
59+
<https://cyclonedx-bom-tool.readthedocs.io/en/latest/index.html>`_:
60+
61+
.. code-block:: json
62+
63+
{
64+
"bom-ref": "cusy-tasks==26.2.0",
65+
"description": "",
66+
"externalReferences": [
67+
{
68+
"comment": "PackageSource: Local",
69+
"type": "distribution",
70+
"url": "file:///Users/veit/cusy/prj/cusy.tasks"
71+
},
72+
{
73+
"comment": "from packaging metadata Project-URL: Documentation",
74+
"type": "documentation",
75+
"url": "https://tasks.cusy.io/"
76+
},
77+
{
78+
"comment": "from packaging metadata Project-URL: Mastodon",
79+
"type": "other",
80+
"url": "https://mastodon.social/@Python4DataScience"
81+
},
82+
{
83+
"comment": "from packaging metadata Project-URL: GitHub",
84+
"type": "vcs",
85+
"url": "https://github.com/cusyio/cusy.tasks"
86+
}
87+
],
88+
"licenses": [
89+
{
90+
"license": {
91+
"acknowledgement": "declared",
92+
"id": "BSD-3-Clause"
93+
}
94+
}
95+
],
96+
"name": "cusy-tasks",
97+
"type": "library",
98+
"version": "26.2.0"
99+
}
100+
101+
Der Kommandozeilenaufruf zum Erstellen der Datei ist:
102+
103+
.. code-block:: console
104+
105+
$ uvx --from cyclonedx-bom cyclonedx-py environment .venv --output-file sbom.cdx.json
106+
107+
.. warning::
108+
CycloneDX Python erstellt die SBOM-Datei aus dem aktuellen
109+
:file:`.venv`-Verzeichnis. Ruft ihr ``cyclonedx-bom`` also in eurer
110+
Entwicklungsumgebung auf, werdet ihr auch alle Entwicklungswerkzeuge in eurer
111+
SBOM-Datei wiederfinden.
112+
113+
… mit sbomify
114+
~~~~~~~~~~~~~
115+
116+
sbomify stellt eine GitHub Action zum Erstellen der SBOM-Datei bereit, die unter
117+
der Haube CycloneDX Python verwendet. Mit `actions/attest-sbom
118+
<https://github.com/actions/attest-sbom>`_ kann die Datei dann attestiert
119+
werden:
120+
121+
.. literalinclude:: sbomify.yml
122+
:caption: .github/workflows/sbomify.yml
123+
:language: yaml
124+
125+
In GitLab CI könnt ihr sbomify folgendermaßen verwenden:
126+
127+
.. literalinclude:: .gitlab-ci.yml
128+
:caption: .gitlab-ci.yml
129+
:language: yaml
130+
:lines: 1-12, 32-
131+
132+
Ihr könnt auch Dependency Scanning integrieren:
133+
134+
.. literalinclude:: .gitlab-ci.yml
135+
:caption: .gitlab-ci.yml
136+
:language: yaml
137+
:lines: 13-30
138+
139+
.. seealso::
140+
* `SBOM Generation in CI/CD Pipelines <https://sbomify.com/guides/ci-cd/>`_
141+
* `Dependency scanning by using SBOM
142+
<https://docs.gitlab.com/user/application_security/dependency_scanning/dependency_scanning_sbom/>`_
143+
144+
PEP 770 – SBOMs in Python-Paketen
145+
---------------------------------
146+
147+
:pep:`770` standardisiert die Einbindung von SBOMs in Python-Wheels über das
148+
Verzeichnis :file:`.dist-info/sboms/`. Wenn ihr Python-Pakete auf :term:`PyPI`
149+
veröffentlicht, bedeutet dies, dass eure User die SBOM-Datei automatisch
150+
erhalten, wenn sie euer Paket installieren, :abbr:`z. B. (zum Beispiel)`:
151+
152+
.. code-block:: console
153+
154+
myapp-26.2.0.dist-info
155+
├── METADATA
156+
├── RECORD
157+
└── sboms/
158+
└── myapp.cdx.json
159+
160+
Build-Backends wie Hatchling≥1.28 unterstützen dies bereits mit der
161+
``sbom-files``-Konfiguration:
162+
163+
.. code-block:: toml
164+
:caption: pyproject.toml
165+
166+
[tool.hatch.build.targets.wheel]
167+
sbom-files = ["myapp.cdx.json"]
168+
169+
Anstatt die SBOM-Datei beim Build von Grund auf neu zu generieren, kann eine
170+
minimale CycloneDX-SBOM-Datei in das Repository eingecheckt werden:
171+
172+
.. code-block:: json
173+
174+
{
175+
"bomFormat": "CycloneDX",
176+
"specVersion": "1.6",
177+
"version": 1,
178+
"metadata": {
179+
"component": {
180+
"type": "library",
181+
"name": "mylib",
182+
"version": "0.0.0-placeholder"
183+
}
184+
},
185+
"components": []
186+
}
187+
188+
Im :term:`CI`-Workflow wird die Platzhalter-SBOM-Datei dann mit dem Code
189+
ausgecheckt. sbomify reichert sie dann mit den aktuellen Informationen an.
190+
Anschließend baut hatchling das :term:`Wheel` mit der aktuellen SBOM-Datei und
191+
schließlich wird das Wheel auf :term:`PyPI` veröffentlicht.
192+
193+
Analyse
194+
-------
195+
196+
Zur Sicherheits- und Lizenzprüfung stehen zahlreiche Tools zur Verfügung, die
197+
sich auf unterschiedliche Problembereiche konzentrieren. Zwei Open-Source-Tools
198+
für die SBOM-Analyse sind `Dependency Track <https://dependencytrack.org>`_ und
199+
`GUAC <https://guac.sh>`_. Mit ``sbomify-action`` könnt ihr SBOMs aus der
200+
CI-Pipeline direkt in eure Dependency Track-Instanz hochladen mit:
201+
202+
.. code-block:: yaml
203+
204+
UPLOAD_DESTINATIONS=dependency-track

0 commit comments

Comments
 (0)