-
Notifications
You must be signed in to change notification settings - Fork 89
feat: add make sbom target #536
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -770,3 +770,127 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/wolftpm/ | |
| install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wolftpm/ | ||
| DESTINATION include/wolftpm | ||
| FILES_MATCHING PATTERN "*.h") | ||
|
|
||
|
|
||
| #################################################### | ||
| # SBOM generation target | ||
| #################################################### | ||
| # | ||
| # Usage: | ||
| # cmake -B build -DWOLFSSL_DIR=/path/to/wolfssl/source . | ||
| # cmake --build build | ||
| # cmake --build build --target sbom | ||
| # | ||
| # WOLFSSL_DIR must point to a wolfssl source tree that contains | ||
| # scripts/gen-sbom (available on the feat/sbom-embedded branch). | ||
| # | ||
| # Outputs written to the build directory: | ||
| # wolftpm-<version>.cdx.json (CycloneDX) | ||
| # wolftpm-<version>.spdx.json (SPDX JSON) | ||
| # wolftpm-<version>.spdx (SPDX tag-value, pyspdxtools validation output) | ||
|
|
||
| if(BUILD_WOLFTPM_LIB) | ||
| set(WOLFSSL_DIR "" CACHE PATH | ||
| "Path to wolfssl source tree with scripts/gen-sbom") | ||
|
|
||
| # Derive the version from wolftpm/version.h, NOT from PROJECT_VERSION. | ||
| # autotools `make sbom` uses PACKAGE_VERSION, which is sourced from | ||
| # version.h. Reading the same header here keeps the cmake and autotools | ||
| # SBOMs bit-identical in the version field even if the project() call in | ||
| # this file drifts out of sync with the header. | ||
| file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/wolftpm/version.h" | ||
| _sbom_version_line | ||
| REGEX "^#define[ \t]+LIBWOLFTPM_VERSION_STRING[ \t]+\"") | ||
| string(REGEX REPLACE | ||
| "^#define[ \t]+LIBWOLFTPM_VERSION_STRING[ \t]+\"([^\"]+)\".*" "\\1" | ||
| SBOM_VERSION "${_sbom_version_line}") | ||
| if(NOT SBOM_VERSION) | ||
| message(FATAL_ERROR | ||
| "sbom: could not parse LIBWOLFTPM_VERSION_STRING from " | ||
| "wolftpm/version.h") | ||
| endif() | ||
|
|
||
| # Validate the SBOM prerequisites at configure time so the user learns | ||
| # what is missing immediately, instead of after a full library build. | ||
| # | ||
| # These checks must NOT abort configuration of a normal build: someone who | ||
| # just wants `cmake -B build && cmake --build build` should never be forced | ||
| # to set WOLFSSL_DIR. So when a prerequisite is missing we still define a | ||
| # `sbom` target, but one that prints the reason and fails at build time. | ||
| # Only when the user explicitly opts in via -DWOLFSSL_DIR=... and that path | ||
| # turns out to be wrong do we hard-error at configure time, because at that | ||
| # point the user clearly intends to build SBOMs and a typo'd path is a | ||
| # mistake worth surfacing right away. | ||
| find_program(PYTHON3_CMD python3) | ||
| find_program(PYSPDXTOOLS_CMD pyspdxtools) | ||
|
|
||
| set(_sbom_error "") | ||
| if(WOLFSSL_DIR STREQUAL "") | ||
| set(_sbom_error | ||
| "WOLFSSL_DIR is not set. Re-run cmake with -DWOLFSSL_DIR=/path/to/wolfssl") | ||
| elseif(NOT EXISTS "${WOLFSSL_DIR}/scripts/gen-sbom") | ||
| # User opted in with a bad path -> fail configure now, not at build. | ||
| message(FATAL_ERROR | ||
| "sbom: ${WOLFSSL_DIR}/scripts/gen-sbom not found.\n" | ||
| " Check that WOLFSSL_DIR points to a wolfSSL tree with " | ||
| "SBOM support.") | ||
| elseif(NOT PYTHON3_CMD) | ||
| set(_sbom_error "'python3' not found in PATH. Cannot generate SBOM.") | ||
| elseif(NOT PYSPDXTOOLS_CMD) | ||
| set(_sbom_error | ||
| "'pyspdxtools' not found in PATH (install: pip install spdx-tools)") | ||
| endif() | ||
|
|
||
| if(NOT _sbom_error STREQUAL "") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [Low] CMake return() used at directory scope to skip the SBOM block; fragile if code is appended · Logic When an SBOM prerequisite (python3/pyspdxtools/WOLFSSL_DIR) is missing, the code defines a failing fallback Fix: Avoid |
||
| # Prerequisite missing: keep configuration working, but make the sbom | ||
| # target fail loudly if someone actually invokes it. | ||
| add_custom_target(sbom | ||
| VERBATIM | ||
| COMMAND ${CMAKE_COMMAND} -E echo "sbom: ${_sbom_error}" | ||
| COMMAND ${CMAKE_COMMAND} -E false | ||
| COMMENT "SBOM prerequisites missing") | ||
| return() | ||
| endif() | ||
|
|
||
| set(SBOM_CDX "${CMAKE_BINARY_DIR}/wolftpm-${SBOM_VERSION}.cdx.json") | ||
| set(SBOM_SPDX "${CMAKE_BINARY_DIR}/wolftpm-${SBOM_VERSION}.spdx.json") | ||
| set(SBOM_SPDX_TV "${CMAKE_BINARY_DIR}/wolftpm-${SBOM_VERSION}.spdx") | ||
| set(SBOM_STAGING "${CMAKE_BINARY_DIR}/_sbom_staging") | ||
|
|
||
| # Staged install path. install(TARGETS wolftpm) above hardcodes | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 [High] CMake sbom target hard-codes Unix shared-library layout; fails on Windows, static, and multi-config builds · Logic The CMake Fix: Derive the artifact from CMake target metadata via generator expressions ( |
||
| # `LIBRARY DESTINATION lib`, so the .so always lands in lib/, never lib64/. | ||
| # ${CMAKE_SHARED_LIBRARY_SUFFIX} resolves to .so on Linux / .dylib on mac. | ||
| set(SBOM_LIB | ||
| "${SBOM_STAGING}/lib/libwolftpm${CMAKE_SHARED_LIBRARY_SUFFIX}") | ||
|
|
||
| # ${OPTION_FILE} is the generated wolftpm/options.h, the same compile-time | ||
| # option fingerprint autotools `make sbom` feeds to gen-sbom via | ||
| # --options-h. Using it (rather than a raw `cc -dM` dump, which would only | ||
| # capture compiler builtins) keeps the cmake SBOM consistent with autotools. | ||
| add_custom_target(sbom | ||
| VERBATIM | ||
| # Stage a clean install so gen-sbom inspects the same artifact layout | ||
| # the user would actually ship. | ||
| COMMAND ${CMAKE_COMMAND} -E rm -rf ${SBOM_STAGING} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 [Medium] CMake sbom target uses cmake -E rm, unavailable on the declared minimum CMake 3.16 · API Contract Violations The Fix: Use the 3.16-compatible |
||
| COMMAND ${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR} | ||
| --prefix ${SBOM_STAGING} | ||
| COMMAND ${PYTHON3_CMD} ${WOLFSSL_DIR}/scripts/gen-sbom | ||
| --name wolftpm | ||
| --version ${SBOM_VERSION} | ||
| --supplier "wolfSSL Inc." | ||
| --license-file ${CMAKE_SOURCE_DIR}/LICENSE | ||
| --options-h ${OPTION_FILE} | ||
| --lib ${SBOM_LIB} | ||
| --cdx-out ${SBOM_CDX} | ||
| --spdx-out ${SBOM_SPDX} | ||
| # Validate the SPDX JSON and emit the tag-value rendering as a side | ||
| # effect; a malformed SBOM makes pyspdxtools exit non-zero and fails | ||
| # the target. | ||
| COMMAND ${PYSPDXTOOLS_CMD} --infile ${SBOM_SPDX} | ||
| --outfile ${SBOM_SPDX_TV} | ||
| COMMAND ${CMAKE_COMMAND} -E rm -rf ${SBOM_STAGING} | ||
| COMMENT "Generating SBOM for wolfTPM ${SBOM_VERSION}") | ||
|
|
||
| # gen-sbom reads the staged library, so the library must build first. | ||
| add_dependencies(sbom wolftpm) | ||
| endif() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -132,3 +132,70 @@ cppcheck: | |
| --suppress=invalidPrintfArgType_sint \ | ||
| --error-exitcode=89 --std=c89 \ | ||
| -I wolftpm src/ hal/ examples | ||
|
|
||
| # SBOM generation (CRA compliance) | ||
| SBOM_CDX = wolftpm-$(PACKAGE_VERSION).cdx.json | ||
| SBOM_SPDX = wolftpm-$(PACKAGE_VERSION).spdx.json | ||
| SBOM_SPDX_TV = wolftpm-$(PACKAGE_VERSION).spdx | ||
| sbomdir = $(datadir)/doc/$(PACKAGE) | ||
|
|
||
| .PHONY: sbom install-sbom uninstall-sbom | ||
|
|
||
| sbom: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 [Medium] New SBOM targets have no automated coverage · test The PR adds non-trivial autotools and CMake SBOM generation paths, but includes no automated smoke coverage for either target; the PR body lists only manual test steps. A lightweight test would have caught the artifact-path and platform assumptions in the new target logic (see the autotools libtool-filename and CMake shared-library-layout findings). Fix: Add CI or a build-system smoke test that provides a minimal fake |
||
| @if test -z "$(PYTHON3)"; then \ | ||
| echo ""; \ | ||
| echo "ERROR: 'python3' not found in PATH. Cannot generate SBOM."; \ | ||
| echo ""; \ | ||
| exit 1; \ | ||
| fi | ||
| @if test -z "$(PYSPDXTOOLS)"; then \ | ||
| echo ""; \ | ||
| echo "ERROR: 'pyspdxtools' not found in PATH. Cannot validate SBOM."; \ | ||
| echo " Install: pip install spdx-tools"; \ | ||
| echo ""; \ | ||
| exit 1; \ | ||
| fi | ||
| @if test -z "$(WOLFSSL_DIR)"; then \ | ||
| echo ""; \ | ||
| echo "ERROR: WOLFSSL_DIR is not set. Cannot locate gen-sbom."; \ | ||
| echo " Set WOLFSSL_DIR to your wolfSSL source tree, e.g.:"; \ | ||
| echo " make sbom WOLFSSL_DIR=/path/to/wolfssl"; \ | ||
| echo ""; \ | ||
| exit 1; \ | ||
| fi | ||
| @if test ! -f "$(WOLFSSL_DIR)/scripts/gen-sbom"; then \ | ||
| echo ""; \ | ||
| echo "ERROR: $(WOLFSSL_DIR)/scripts/gen-sbom not found."; \ | ||
| echo " Check that WOLFSSL_DIR points to a wolfSSL tree with SBOM support."; \ | ||
| echo ""; \ | ||
| exit 1; \ | ||
| fi | ||
| rm -rf $(abs_builddir)/_sbom_staging | ||
| $(MAKE) install DESTDIR=$(abs_builddir)/_sbom_staging | ||
| $(PYTHON3) $(WOLFSSL_DIR)/scripts/gen-sbom \ | ||
|
|
||
| --name wolftpm \ | ||
| --version $(PACKAGE_VERSION) \ | ||
| --supplier "wolfSSL Inc." \ | ||
| --license-file $(srcdir)/LICENSE \ | ||
| --options-h $(abs_builddir)/wolftpm/options.h \ | ||
| --lib $(abs_builddir)/_sbom_staging$(libdir)/libwolftpm.so.@WOLFTPM_LIBRARY_VERSION_FIRST@.@WOLFTPM_LIBRARY_VERSION_SECOND@.@WOLFTPM_LIBRARY_VERSION_THIRD@ \ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 [High] Autotools sbom target reconstructs the libtool library filename incorrectly; breaks on next version-info bump and on… · Logic The Fix: Do not reconstruct the versioned name from version-info components. After the staged install, discover the actual installed artifact under the staged |
||
| $(if $(SBOM_LICENSE_OVERRIDE),--license-override $(SBOM_LICENSE_OVERRIDE)) \ | ||
| $(if $(SBOM_LICENSE_TEXT),--license-text $(SBOM_LICENSE_TEXT)) \ | ||
| --cdx-out $(abs_builddir)/$(SBOM_CDX) \ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [Low] install-sbom mixes absolute and relative artifact paths; only works when run from the build dir · convention The Fix: Use |
||
| --spdx-out $(abs_builddir)/$(SBOM_SPDX) | ||
|
Comment on lines
+175
to
+185
Comment on lines
+179
to
+185
|
||
| rm -rf $(abs_builddir)/_sbom_staging | ||
| $(PYSPDXTOOLS) --infile $(abs_builddir)/$(SBOM_SPDX) \ | ||
| --outfile $(abs_builddir)/$(SBOM_SPDX_TV) | ||
|
|
||
| install-sbom: sbom | ||
| $(MKDIR_P) $(DESTDIR)$(sbomdir) | ||
| $(INSTALL_DATA) $(SBOM_CDX) $(DESTDIR)$(sbomdir)/ | ||
| $(INSTALL_DATA) $(SBOM_SPDX) $(DESTDIR)$(sbomdir)/ | ||
| $(INSTALL_DATA) $(SBOM_SPDX_TV) $(DESTDIR)$(sbomdir)/ | ||
|
|
||
| uninstall-sbom: | ||
| -rm -f $(DESTDIR)$(sbomdir)/$(SBOM_CDX) | ||
| -rm -f $(DESTDIR)$(sbomdir)/$(SBOM_SPDX) | ||
| -rm -f $(DESTDIR)$(sbomdir)/$(SBOM_SPDX_TV) | ||
|
|
||
| CLEANFILES += $(SBOM_CDX) $(SBOM_SPDX) $(SBOM_SPDX_TV) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔵 [Low] CMake version.h regex uses [ \t] which does not match a tab in CMake's regex dialect · Logic
The SBOM version is parsed with
REGEX "^#define[ \t]+LIBWOLFTPM_VERSION_STRING[ \t]+\"". CMake's regex engine does not interpret\tas a tab escape; inside the bracket expression[ \t]is the literal set {space, backslash, 't'}. It matches today only because the distributedwolftpm/version.huses space separators. If version.h were ever regenerated with tab separators,file(STRINGS ... REGEX)would return no match,_sbom_version_linewould be empty, and the target would abort via the FATAL_ERROR at 807-811. Currently benign — defense-in-depth only.Fix: Since version.h is generated with single spaces, match
[ ]+explicitly, or embed a literal tab in the character class if tab tolerance is actually desired.