-
Notifications
You must be signed in to change notification settings - Fork 40.9k
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
Add libraries actuator endpoint #25134
Add libraries actuator endpoint #25134
Conversation
d82a414
to
88aaf52
Compare
Hi @philsttr , I like your idea. Could you give me a better understanding how your approach with Do you have any concerns regarding vulnerability/security by providing such sensitive data via actuator? |
Hi @rfelgent
I don't, since:
|
Adds a libraries actuator endpoint that displays details about the libraries used by the application. Provides out-of-the-box support for displaying details about Java libraries that are bundled within the application jar/war archive. The spring-boot-maven-plugin and spring-boot-gradle-plugin now generate a META-INF/bundled-libraries.yaml file when they package the application archive. The file is included in the packaged application archive. At runtime, libraries are contributed to the libraries endpoint via LibrariesContributor beans, similar to how InfoContributers contribute to the info endpoint. spring-boot-actuator-autoconfigure auto-configures a LibrariesContributor that adds the libraries from META-INF/bundled-libraries.yaml to the libraries endpoint. This auto-configuration can be disabled using environment properties similar to how other actuator endpoints behave. An application can provide other LibrariesContributor instances to contribute more libraries to the libraries endpoint. For example, an application might want to contribute libraries dynamically added at runtime. Or an application might want to contribute details about front-end libraries. Each Library is described as a simple set of key/value pairs. For example, Java libraries with coordinates in a Maven repository typically contain entries for `groupId`, `artifactId`, and `version`. Fixes spring-projects#22924
88aaf52
to
9426c23
Compare
My initial thoughts around this proposal is that a report of this kind is much safer to be generated at build time as an additional artifact, rather than being bundled within the application artifact and exposed over an Actuator endpoint. The area of supply chain attacks is something that's been in the focus recently, and IMO proposals such as this one should take that into account very seriously. With an endpoint like this one, it's quite likely someone will leak sensitive data at some point - either due to negligence, misconfiguration or simply a security breach. That has the potential to be quite a problem if your application artifact uses dependencies that are published privately within your organization, under a namespace that hasn't been claimed on public repositories. |
https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610 is an interesting account of how this can be exploited in other ecosystems. Maven Central provides some protection against this but that's not sufficient to make the JVM ecosystem immune to this sort of attack. |
Even with the supply chain attacks, we'd like to have this functionality in our applications. I'd like to propose some alternatives in order of my preference. A. Keep the PR mostly as-is, but add more strongly worded warnings to the documentation about the security risks of the libraries endpoint. B. Keep the libraries actuator endpoint, but don't generate the metadata at build time by default. (It's currently generated at build time by default in this PR.) Make the user explicitly configure the maven/gradle plugins to generate the metadata, and include it in the artifact. This makes a user jump through one more hoop if they actually want to expose the data, since the libraries endpoint won't show anything if the metadata doesn't exist. This will help in the case the user has already configured C. Keep the libraries actuator endpoint, and generate the metadata at build time by default, but don't include it in the artifact by default. Make the user explicitly configure the maven/gradle plugins to include the metadata in the artifact. Again, this makes a user jump through one more hoop if they actually want to expose the data, since the libraries endpoint won't show anything if the metadata doesn't exist. D. Remove the libraries actuator endpoint from spring boot, but keep the ability to generate the metadata (and being able to include it in the artifact) in the spring boot maven/gradle plugins. In which case, we would move the libraries endpoint code into a private library. Keep the metadata in the current format (yaml file), or at least in some kind of machine-readable format. This will allow the libraries endpoint from our corporate library to read and expose the metadata. |
Thanks for the pull request, @philsttr. As indicated by the |
Adds a new
libraries
actuator endpoint that displays details about the libraries used by the application.Provides out-of-the-box support for displaying details about jar libraries that are bundled within the application jar/war archive.
The
spring-boot-maven-plugin
andspring-boot-gradle-plugin
now generate aMETA-INF/bundled-libraries.yaml
file when they package the application archive. The file is included in the packaged application archive, and contains details about the libraries contained within the application archive.At runtime, libraries are contributed to the libraries endpoint via
LibrariesContributor
beans, similar to howInfoContributor
beans contribute to theinfo
endpoint.spring-boot-actuator-autoconfigure
auto-configures aLibrariesContributor
that adds the libraries fromMETA-INF/bundled-libraries.yaml
to thelibraries
endpoint. This auto-configuration can be disabled using environment properties similar to how other actuator endpoints behave.An application can provide other
LibrariesContributor
beans to contribute more libraries to thelibraries
endpoint. For example, an application might want to contribute libraries dynamically added at runtime. Or an application might want to contribute details about front-end libraries.Each Library is described as a simple set of key/value pairs. For example, Java libraries with coordinates in a Maven repository typically contain entries for
groupId
,artifactId
, andversion
. Other types of libraries contributed by an application could contain other details.Fixes #22924
Example output of
/actuator/libraries
endpointAlternatives considered, and decisions made
I originally wanted to implement the
libraries
endpoint by simply inspecting the runtime classpath, rather than relying on metadata generated at build time. I ran into some pretty big challenges with that:libraries
endpoint. Specifically, there's no guaranteed way to be able to report the maven repository coordinates of a libraryBecause of the above reasons, I decided to use metadata generated when assembling the package.
I started out by creating a separate task/goal for generating this metadata, similar to the buildInfo task/goal. I ran into another challenge... The maven and gradle plugins have some pretty complex logic to determine which libraries are included in the final assembled jar/war archive. See here, here, and here. Some of this logic is dictated by configuration options (e.g. here)
I was either going to have to duplicate this logic, or get creative about how to reuse the existing logic while maintaining compatibility.
Because of the above reasons, I decided to generate the metadata automatically as part of the packaging logic. This allowed reuse of the existing logic to determine what to include in the final archive, while maintaining full compatibility.
I also struggled a bit with naming, and I welcome feedback.
libraries
, since that seemed to indicate it's primary purpose. In the original issue I filed (Spring Boot Actuator "manifest" endpoint #22924), I suggestedmanifest
, but that seemed too generic.bundled
libraries. I also consideredpackaged
, but thoughtbundled
ultimately was more clear, sincepackaged
could be mis-interpreted since all libraries are generally packaged themselves.Current state
New functionality is working, documented, and unit/integration tested.
Please provide feedback and suggestions. I'm happy to incorporate them.