Implement SBOM actuator endpoint

Closes gh-39799
This commit is contained in:
Moritz Halbritter
2024-01-15 09:56:58 +01:00
committed by Phillip Webb
parent 75012c5173
commit 4047c00aa5
30 changed files with 22016 additions and 1 deletions

View File

@@ -72,6 +72,10 @@ public abstract class Packager {
private static final String BOOT_LAYERS_INDEX_ATTRIBUTE = "Spring-Boot-Layers-Index";
private static final String SBOM_LOCATION_ATTRIBUTE = "Sbom-Location";
private static final String SBOM_FORMAT_ATTRIBUTE = "Sbom-Format";
private static final byte[] ZIP_FILE_HEADER = new byte[] { 'P', 'K', 3, 4 };
private static final long FIND_WARNING_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
@@ -299,6 +303,7 @@ public abstract class Packager {
Manifest manifest = createInitialManifest(source);
addMainAndStartAttributes(source, manifest);
addBootAttributes(manifest.getMainAttributes());
addSbomAttributes(source, manifest.getMainAttributes());
return manifest;
}
@@ -408,6 +413,21 @@ public abstract class Packager {
}
}
private void addSbomAttributes(JarFile source, Attributes attributes) {
JarEntry sbomEntry = source.stream().filter(this::isCycloneDxBom).findAny().orElse(null);
if (sbomEntry != null) {
attributes.putValue(SBOM_LOCATION_ATTRIBUTE, sbomEntry.getName());
attributes.putValue(SBOM_FORMAT_ATTRIBUTE, "CycloneDX");
}
}
private boolean isCycloneDxBom(JarEntry entry) {
if (!entry.getName().startsWith("META-INF/sbom/")) {
return false;
}
return entry.getName().endsWith(".cdx.json") || entry.getName().endsWith("/bom.json");
}
private void putIfHasLength(Attributes attributes, String name, String value) {
if (StringUtils.hasLength(value)) {
attributes.putValue(name, value);

View File

@@ -656,6 +656,17 @@ abstract class AbstractPackagerTests<P extends Packager> {
.isEqualTo(String.join("\n", expected) + "\n");
}
@Test
void sbomManifestEntriesAreWritten() throws IOException {
this.testJarFile.addClass("com/example/Application.class", ClassWithMainMethod.class);
this.testJarFile.addFile("META-INF/sbom/application.cdx.json", new ByteArrayInputStream(new byte[0]));
P packager = createPackager(this.testJarFile.getFile());
execute(packager, NO_LIBRARIES);
assertThat(getPackagedManifest().getMainAttributes().getValue("Sbom-Format")).isEqualTo("CycloneDX");
assertThat(getPackagedManifest().getMainAttributes().getValue("Sbom-Location"))
.isEqualTo("META-INF/sbom/application.cdx.json");
}
private File createLibraryJar() throws IOException {
TestJarFile library = new TestJarFile(this.tempDir);
library.addClass("com/example/library/Library.class", ClassWithoutMainMethod.class);