SOLR-17328: Add CycloneDX SBOMs to Solr binary distributions - #4690
SOLR-17328: Add CycloneDX SBOMs to Solr binary distributions#4690ppkarwasz wants to merge 1 commit into
Conversation
Each binary distribution (full and slim) now ships a CycloneDX 1.6 bom.json describing its actual contents. Two resolvable configurations in :solr:packaging (bomFull, bomSlim) mirror the distribution assembly and are rendered by the CycloneDX Gradle plugin, then a post-processing step adjusts the result: * The metadata declares the "build" lifecycle phase (a CISA Build SBOM) and lists the post-processing and cyclonedx-npm next to the plugin in the tools. * The main component identifies the binary release with a draft "sid" purl (purl-spec issue apache#516, pkg:sid/apache.org/solr/solr@<version> with an edition qualifier) and the Solr CPE used by the NVD. * Maven BOM/platform dependencies and the internal :platform project, which are not part of the distribution, are stripped. * Solr project components get valid Maven purls (artifactId instead of the Gradle project name, with the ASF snapshots repository for snapshot builds), a description and the Apache-2.0 license. * The UI artifacts inside the webapp are covered: the npm packages bundled by browserify into the OpenAPI JS client and the Maven artifacts compiled into the wasmJs UI are nested as subassemblies of first-party solr-js-client and solr-ui components, from child SBOMs generated in :solr:webapp:js-client (official cyclonedx-npm tool, runtime dependencies only) and :solr:ui (plugin task over wasmJsRuntimeClasspath). The vendored JavaScript libraries of the AngularJS admin UI are listed from a curated list. * The location of every JAR and JavaScript file in the distribution is recorded as evidence.occurrences by matching SHA-256 hashes against the assembled directories, which also proves the vendored libraries ship unmodified. * Only the SHA-256 hash of each component is kept; the plugin emits eight algorithms per artifact, which only adds bulk. The BOM configurations resolve strictly with the JVM runtime attributes (the packaging project applies jvm-ecosystem for the attribute schema), so BOM-managed and variant-aware dependencies resolve like a runtime classpath instead of silently disappearing. bomFull resolves consistently with bomSlim, matching the distribution layout where server libraries win over module-pulled versions. The child SBOMs degrade gracefully when the UI projects are disabled with -PdisableJsClient / -PdisableUiModule. Assisted-By: Claude Fable 5 <noreply@anthropic.com>
epugh
left a comment
There was a problem hiding this comment.
It feels like there is a lot of boilerplate-ish comments. Do we need all of them? Maybe the more verbose pattern is something we want to adopt?
| cuvs-java = "26.06.0" | ||
| cuvs-lucene = "25.12.0" | ||
| cyclonedx = "3.0.2" | ||
| # @keep npm tool generating the SBOM of the OpenAPI JS client, installed by :solr:webapp:js-client |
There was a problem hiding this comment.
what does @keep mean? Do we need this comment? the -npm suffix seems clear.
| id 'jvm-ecosystem' | ||
| } | ||
|
|
||
| final APACHE_SNAPSHOTS_QUALIFIER = '&repository_url=https:%2F%2Frepository.apache.org%2Fcontent%2Fgroups%2Fsnapshots%2F' |
There was a problem hiding this comment.
this block of code seems like a lot, should it go in it's own .gradle file? There is a lot of docs about how this works in here, and I guess I don't totally know if it's needed. It would seem like a sbom.gradle might be a better home?
| // 5. Vendored JavaScript libraries | ||
| // Entries without a version marker in the file get no version and no purl | ||
| def vendoredJsLibs = [ | ||
| [file: 'angular.min.js', name: 'angular', version: '1.8.0', license: 'MIT'], |
There was a problem hiding this comment.
i don't love the hard coding here... CAn we consult other files like the licenses etc? Yes, most of these won't ever be updated at this point.. but what happens if they are bumped?
https://issues.apache.org/jira/browse/SOLR-17328
Generates precise SBOM for the Solr binary distributions (
solr-<version>.tgzandsolr-<version>-slim.tgz) that include all the informationavailable today to the build tool:
:solr:packaging,solr/webapp/web/libs,:solr:webapp:js-client, inserted as nested assemblies ofsolr-js-client.:solr:ui, inserted as nested assemblies ofsolr-ui.The components for 1 and 4 are generated by the CycloneDX Gradle Plugin, while components from 3 are generated by
@cyclonedx/cyclonedx-npm.Vendored libraries, of course, are handled as a static list that maintainers need to keep up to date.
This is the second attempt after #3929.
Known unknowns
This PR does not attempt to manually detect the components embedded in JARs through shading or binary library inclusion.
An incomplete list of artifacts with such hidden dependencies is:
(The Hadoop artifacts and
org.tallison.xmp:xmpcore-shadedfrom earlier iterations of this list no longer ship in the distribution.)SBOM location
Each archive contains its SBOM as
bom.jsonin the root of the distribution, next toLICENSE.txtandNOTICE.txt(see this comment on the previous PR for the full discussion):bom.jsonis one of the recognized CycloneDX filename patterns, so tools can discover it without configuration.syftorcdxgenremains a useful, complementary verification step.There are other publication models: a
solr-<version>.tgz.cdx.jsonsidecar next to the.ascand.sha512files ondownloads.apache.org, or embedding the SBOM in an in-toto attestation bundle together with SLSA provenance.SBOM postprocessing
The raw output of the CycloneDX Gradle Plugin and
@cyclonedx/cyclonedx-npmis postprocessed this way:buildlifecycle phase is recorded, and the post-processing and cyclonedx-npm are listed in the tools next to the plugin.sidpurl (purl-spec issue #516),pkg:sid/apache.org/solr/solr@<version>?edition=full|slim, and by the Solr CPE used by the NVD.:platformproject are stripped, they are not part of the distribution.Apache-2.0license.solr/webapp/web/libsare added.server/solr-webapp/webapp/libs/solr/index.jsare nested as subassemblies of a first-partysolr-js-clientcomponent.server/solr-webapp/webapp/uiare nested as subassemblies of a first-partysolr-uicomponent, from a child SBOM generated in:solr:uioverwasmJsRuntimeClasspath, together with the@js-joda/corenpm package bundled by the Kotlin toolchain.evidence.occurrences. This also proves that each vendored JavaScript library ships unmodified.externalReferences(SHA-512 of the registry tarballs) are preserved.This change was developed with significant use of an AI coding assistant (Claude), with human review of every step; commits carry an
Assisted-Bytrailer.Checklist
Please review the following and check all that apply:
mainbranch../gradlew precommit; the full./gradlew checktest suite was not run for this build-only change.bom.jsoncould be documented in a follow-up)