SBOM with Spring Boot
This article will teach you, how to leverage SBOM support in Spring Boot to implement security checks for your apps. A Software Bill of Materials (SBOM) lists all your app codebase’s open-source and third-party components. As a result, it allows us to perform vulnerability scanning, license checks, and risk analysis. Spring Boot 3.3 introduces built-in support for generating SBOMs during app build and exposing them through the actuator endpoint. In this article, we will analyze the app based on the latest version of Spring Boot and another one using the outdated version of the libraries. You will see how to use the snyk
CLI to verify the generated SBOM files.
It is the first article on my blog after a long holiday break. I hope you enjoy it. If you are interested in Spring Boot you can find several other posts about it on my blog. I can recommend my article about another fresh Spring Boot feature related to security, that describes SSL certs hot reload on Kubernetes.
Source Code
If you would like to try this exercise by yourself, you may always take a look at my source code. Today you will have to clone two sample Git repositories. The first one contains automatically updated source code of microservices based on the latest version of the Spring Boot framework. The second repository contains an archived version of microservices based on the earlier, unsupported version of Spring Boot. Once you clone both of these repositories, you just need to follow my instructions.
By the way, you can verify SBOMs generated for your Spring Boot apps in various ways. I decided to use snyk
CLI for that. Alternatively, you can use the web version of the Snyk SBOM checker available here. In order to install the snyk
CLI on your machine you need to follow its documentation. I used homebrew to install it on my macOS:
$ brew tap snyk/tap
$ brew install snyk
ShellSessionEnable SBOM Support in Spring Boot
By default, Spring Boot supports the CycloneDX format for generating SBOMs. In order to enable it, we need to include the cyclonedx-maven-plugin
Maven plugin in your project root pom.xml
.
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
XMLThere are several microservices defined in the same Git repository. They are all using the same root pom.xml
. Each of them defines its list of dependencies. For this exercise, we need to have at least the Spring Boot Web and Actuator starters. However, let’s take a look at the whole list of dependencies for the employee-service
(one of our sample microservices):
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-micrometer</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.instancio</groupId>
<artifactId>instancio-junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
XMLAfter including the cyclonedx-maven-plugin
plugin we need to execute the mvn package
command in the repository root directory:
$ mvn clean package -DskipTests
ShellSessionThe plugin will generate SBOM files for all the existing microservices and place them in the target/classes/META-INF/sbom
directory for each Maven module.
The generated SBOM file will always be placed inside the JAR file as well. Let’s take a look at the location of the SBOM file inside the employee-service
uber JAR.
In order to expose the actuator SBOM endpoint we need to include the following configuration property. Since our configuration is stored by the Spring Cloud Config server, we need to put such a property in the YAML files inside the config-service/src/main/resources/config
directory.
management:
endpoints:
web:
exposure:
include: health,sbom
ShellSessionThen, let’s start the config-service
with the following Maven command:
$ cd config-service
$ mvn clean spring-boot:run
ShellSessionAfter that, we can start our sample microservice. It loads the configuration properties from the config-service
. It listens on the dynamically generated port number. For me, it is 53498
. In order to see the contents of the generated SBOM file, we need to call the GET /actuator/sbom/application
path.
Generate and Verify SBOMs with the Snyk CLI
The exact structure of the SBOM file is not very important from our perspective. We need a tool that allows us to verify components and dependencies published inside that file. As I mentioned before, we can use the snyk
CLI for that. We will examine the file generated in the repository root directory. Here’s the snyk
command that allows us to print all the detected vulnerabilities in the SBOM file:
$ snyk sbom test \
--file=target/classes/META-INF/sbom/application.cdx.json \
--experimental
ShellSessionHere’s the report created as the output of the command executed above. As you see, there are two detected issues related to the included dependencies. Of course, I’m not including those dependencies directly in the Maven pom.xml
. They were automatically included by the Spring Boot starters used by the microservices. By the way, I was even not aware that Spring Boot includes kotlin-stdlib
even if I’m not using any Kotlin library directly in the app.
Although there are two issues detected in the report, it doesn’t look very bad. Now, let’s try to analyze something more outdated. I have already mentioned my old repository with microservices: sample-spring-microservices
. It is already in the archived status and uses Spring Boot in the 1.5
version. If we don’t want to modify anything there, we can also use snyk
CLI to generate SBOM instead of the Maven plugin. Since built-in support for SBOM comes with Spring Boot 3.3 there is no sense in including a plugin for the apps with the 1.5
version. Here’s the snyk
command that generates SBOM for all the projects inside the repository and exports it to the application.cdx.json
file:
$ snyk sbom --format=cyclonedx1.4+json --all-projects > application.cdx.json
ShellSessionThen, let’s examine the SBOM file using the same command as before:
$ snyk sbom test --file=application.cdx.json --experimental
ShellSessionNow, the results are much more pessimistic. There are 211 detected issues, including 6 critical.
Final Thoughts
SBOMs allow organizations to identify and address potential security risks more effectively. Spring Boot support for generating SBOM files simplifies the process when incorporating them into the organizational software development life cycle.
2 COMMENTS