-
Notifications
You must be signed in to change notification settings - Fork 30
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
Integrate Native Image SBOM with GitHub's Dependency Submission API #119
base: main
Are you sure you want to change the base?
Conversation
There is one failing test which is not related to this PR: |
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.
Thanks for the PR, @rudsberg! Looks very good already. Left a couple of comments and suggestions.
} | ||
|
||
async function findSBOMFilePath(): Promise<string> { | ||
const globber = await glob.create(`**/*${SBOM_FILE_SUFFIX}`) |
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.
Too bad we have to do this. What if there are .sbom.json
files in the repository? Ideally, we could specify a location where the SBOM is exported to, similar to the build stats export.
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.
What if there are .sbom.json files in the repository?
Then the feature would not be able to figure out which SBOM is the correct one and therefore the SBOM would not get submitted to the Submission API.
Ideally, we could specify a location where the SBOM is exported to, similar to the build stats export.
The build report feature specifies the location by using the NI flag -H:BuildOutputJSONFile
. NI does not have a similar flag to specify the output of an SBOM. An exported SBOM is instead always created in the same directory as the image itself. The problem is that I see no straightforward way to get that directory from the context of the action.
One improved approach (that does not require changing NI) could be for the SBOM feature to ensure a build output file is created and read it to retrieve the image name via general_info/name
. Then the glob pattern can be more narrow: **/${name}${SBOM_FILE_SUFFIX}
.
Naturally, this would still not handle the edge case where there is more than one file named ${image_name}${SBOM_FILE_SUFFIX}
. If we still want to cover that case, we could throw a descriptive error saying we found more than one file and users must either ensure there is only one such file or specify the file to use with an additional option like native-image-sbom-path
or output-directory
.
const sbomContent = fs.readFileSync(sbomPath, 'utf8') | ||
const sbomData = parseSBOM(sbomContent) | ||
const components = mapToComponentsWithDependencies(sbomData) | ||
printSBOMContent(components) |
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.
Maybe this should be optional? How much can this clutter the build log?
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.
One or two lines per SBOM component gets added to the Post Run setup-graalvm action
build log. Two lines are added for components with one or more dependencies. For the main-test-app
, the entire log is:
Post job cleanup.
Found SBOM: /Users/runner/work/setup-graalvm/setup-graalvm/__tests__/sbom/main-test-app/target/main-test-app.sbom.json
=== SBOM Content ===
- cpe:2.3:a:oracle:graalvm_for_jdk:25+3-LTS:*:*:*:*:*:*:*
- pkg:maven/com.oracle/[email protected]
depends on: pkg:maven/org.json/json@20241224
- pkg:maven/org.graalvm.nativeimage/svm@25%2B3-LTS
- pkg:maven/org.graalvm.sdk/collections@25%2B3-LTS
- pkg:maven/org.graalvm.sdk/nativeimage@25%2B3-LTS
- pkg:maven/org.graalvm.sdk/word@25%2B3-LTS
- pkg:maven/org.json/json@20241224
==================
Component Oracle GraalVM does not have a valid package URL (purl). Skipping.
Dependency snapshot submitted successfully.
This should be manageable even for larger projects. But I'm open to keep build logging to a minimum, if so we could make this output optional by only showing it when ACTIONS_STEP_DEBUG
is set to true
.
src/features/sbom.ts
Outdated
name: 'setup-graalvm', | ||
version: c.ACTION_VERSION, | ||
url: 'https://github.com/graalvm/setup-graalvm' |
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.
Not quite sure whether this should read the following instead:
name: 'setup-graalvm', | |
version: c.ACTION_VERSION, | |
url: 'https://github.com/graalvm/setup-graalvm' | |
name: 'Oracle GraalVM', | |
version: <JAVA_VERSION>, | |
url: 'https://www.graalvm.org/' |
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.
That's a great observation. The detector
should be the tool or system used to detect the dependencies in the project. In our case that is Native Image, rather than the Github Action that wraps Native Image.
Overview
This PR adds support to automatically generate a highly accurate SBOM with Native Image and submit it to GitHub's dependency submission API. That enables a simple integration with all the powerful security tooling that Github provides:
The feature is activated with the option
native-image-enable-sbom
. It requirescontents: write
permission and for the Dependency Graph feature to be activated (on by default for public repositories). This feature is supported for GraalVM for JDK 24 or above. It cannot be used for earlier versions since thepurl
SBOM field, which the GitHub API requires, is only available in the upcoming JDK 24 release.Approach and Testing
The high-level approach for the implementation is the following:
run
inmain.ts
callssetUpSBOMSupport
which appends--enable-sbom=export
toNATIVE_IMAGE_OPTIONS
. Effectively, this instructs any subsequent invocation ofnative-image
to generate an SBOM.run
incleanup.ts
callsprocessSBOM
which finds the SBOM, maps the content to the format the GitHub API expects, and submits it to the API.The feature is tested with a mix of unit and integration tests:
sbom.test.ts
runs unit and integration tests. The GitHub API is mocked.test.yml
is extended with a new jobsbom-test
which builds a maven project and asserts that an SBOM is created and verifies its contents.Example
Consider the test project that the job
sbom-test
uses which defines one Java class with a dependency onorg.json
. After the job has executed, the GitHub dashboard is populated with vulnerability alerts underSecurity/Dependabot
and the Dependency Graph underInsights/Dependency graph
. Here is how theSecurity/Dependabot
page looks like:A specific vulnerability:
The
Insights/Dependency graph
includes theorg.json
component which was part of the SBOM and the dependencies picked up automatically from the manifest files: