Skip to content
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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

rudsberg
Copy link

@rudsberg rudsberg commented Dec 4, 2024

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 requires contents: 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 the purl 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:

  1. run in main.ts calls setUpSBOMSupport which appends --enable-sbom=export to NATIVE_IMAGE_OPTIONS. Effectively, this instructs any subsequent invocation of native-image to generate an SBOM.
  2. run in cleanup.ts calls processSBOM 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 job sbom-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 on org.json. After the job has executed, the GitHub dashboard is populated with vulnerability alerts under Security/Dependabot and the Dependency Graph under Insights/Dependency graph. Here is how the Security/Dependabot page looks like:

dependabot_alerts

A specific vulnerability:

dependabot_vulnerability

The Insights/Dependency graph includes the org.json component which was part of the SBOM and the dependencies picked up automatically from the manifest files:

dependency_graph

@oracle-contributor-agreement oracle-contributor-agreement bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label Dec 4, 2024
@rudsberg
Copy link
Author

rudsberg commented Dec 4, 2024

There is one failing test which is not related to this PR:
build-test / GraalVM (17.0.13, graalvm, ubuntu-latest, true).

Copy link
Member

@fniephaus fniephaus left a 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.

__tests__/sbom/main-test-app/pom.xml Outdated Show resolved Hide resolved
__tests__/sbom/main-test-app/pom.xml Outdated Show resolved Hide resolved
__tests__/sbom/main-test-app/verify-sbom.sh Outdated Show resolved Hide resolved
__tests__/sbom/main-test-app/verify-sbom.sh Outdated Show resolved Hide resolved
__tests__/sbom/main-test-app/pom.xml Outdated Show resolved Hide resolved
}

async function findSBOMFilePath(): Promise<string> {
const globber = await glob.create(`**/*${SBOM_FILE_SUFFIX}`)
Copy link
Member

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.

Copy link
Author

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)
Copy link
Member

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?

Copy link
Author

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.

Comment on lines 225 to 227
name: 'setup-graalvm',
version: c.ACTION_VERSION,
url: 'https://github.com/graalvm/setup-graalvm'
Copy link
Member

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:

Suggested change
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/'

Copy link
Author

@rudsberg rudsberg Jan 6, 2025

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.

.github/workflows/test.yml Outdated Show resolved Hide resolved
.github/workflows/test.yml Outdated Show resolved Hide resolved
@rudsberg rudsberg requested a review from fniephaus January 6, 2025 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OCA Verified All contributors have signed the Oracle Contributor Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants