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

Fix #2955: Import components that are located under 'metadata.component.components' #2956

Closed
wants to merge 2 commits into from

Conversation

malice00
Copy link
Contributor

Description

Certain SBOM-generators save sub-projects or -modules as part of the component, instead of in the list of dependencies. This change makes sure to also import these as components, so a correct dependency-tree can be generated.

Addressed Issue

Fixes #2955

Checklist

  • I have read and understand the contributing guidelines
  • This PR fixes a defect, and I have provided tests to verify that the fix is effective
  • This PR implements an enhancement, and I have provided tests to verify that it works as intended
  • This PR introduces changes to the database model, and I have added corresponding update logic
  • This PR introduces new or alters existing behavior, and I have updated the documentation accordingly

Testing was done manually, since no tests for this part of the code exists and I wasn't sure on how to add them there.

…etadata.component.components'.

Signed-off-by: Roland Asmann <[email protected]>
@@ -92,6 +92,14 @@ public static List<Component> convertComponents(final QueryManager qm, final Bom
}
}
}
if (bom.getMetadata() != null && bom.getMetadata().getComponent() != null && bom.getMetadata().getComponent().getComponents() != null) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per the spec, such nesting is allowed even with component.components.

for (int i = 0; i < bom.getMetadata().getComponent().getComponents().size(); i++) {
final org.cyclonedx.model.Component cycloneDxComponent = bom.getMetadata().getComponent().getComponents().get(i);
if (cycloneDxComponent != null) {
components.add(convert(qm, cycloneDxComponent, project));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we track the bom-ref to avoid duplicate components?

@malice00
Copy link
Contributor Author

I've been checking the specs again:

  1. a bom-ref is not mandatory
  2. if used, it must be unique (although neither dependency-track nor cdxgen actually (currently) validate this)

So, yes, we could, but only if they are used and are not unique.
Maybe it's better to check the purl instead? Unfortunately, it's also not mandatory, but it also doesn't need to be unique!

@prabhu
Copy link

prabhu commented Aug 16, 2023

I've been checking the specs again:

1. a bom-ref is not mandatory

2. if used, it **must** be unique (although neither dependency-track nor cdxgen actually (currently) validate this)

So, yes, we could, but only if they are used and are not unique. Maybe it's better to check the purl instead? Unfortunately, it's also not mandatory, but it also doesn't need to be unique!

What do you think about the value returned by the convert method? Does it include a bom-ref?

@malice00
Copy link
Contributor Author

malice00 commented Aug 16, 2023

What do you think about the value returned by the convert method? Does it include a bom-ref?

From what I can tell, the convert method simply copies the bom-ref it received from the SBOM. This makes sense, because it would need this ref to resolve the dependencies later on. Also, when there are duplicate components, the refs should (imho) be the same (and not unique), otherwise the dependency-tree would not be correct!

During the conversion, DT does check if a certain component already exists (in persistent storage) for the project, however components are only persisted after the whole SBOM has been read and converted. This check is done on any of several fields (purl, swid, cpe, group/name/version-combo), which we could maybe do when converting as well?

Anyway, I just tested importing the same SBOM again and now there are no more duplicates! This is similar to something I had already discussed with the devs of cyclonedx-cocoapods. It's not 100% the same problem, but there it was decided to document this behavior, as it was not actually incorrect.

@malice00
Copy link
Contributor Author

I implemented a simple duplicate-check on purl -- if it is set.

for (org.cyclonedx.model.Component component : components) {
if (component != null) {
boolean hasPurl = component.getPurl() != null && !component.getPurl().isBlank();
if (hasPurl && purls.contains(component.getPurl())) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since purl is also optional, we might also need bom-ref and CPE-based checks. I suggest waiting for a response from DT developers before making this change.

@nscuro
Copy link
Member

nscuro commented Aug 17, 2023

@malice00 We recently re-worked the BOM ingestion area in hyades-apiserver and will backport that soon to this code base.

Components are flattened prior to de-duplication: https://github.com/DependencyTrack/hyades-apiserver/blob/23725258b8681ada8a5fc605a06dd45350fd83ef/src/main/java/org/dependencytrack/tasks/BomUploadProcessingTask.java#L213-L214 I believe this is where your change could be implemented as well.

We de-duplicate based on ComponentIdentity, which includes the coordinates (group, name, version), CPE, and PURL (and later in the process also the UUID). We also have logic in place to ensure that we do not break the dependency graph by de-duplicating: https://github.com/DependencyTrack/hyades-apiserver/blob/23725258b8681ada8a5fc605a06dd45350fd83ef/src/main/java/org/dependencytrack/tasks/BomUploadProcessingTask.java#L194-L205

There was also a relevant change to how existing components are looked up in the DB (see #2519 (comment)); We made this more strict.

It may be easier to incorporate your proposed change to that logic, rather than retrofitting it onto the existing one. If you can, maybe look at the changes we made and let us know if you think your requirement can be integrated there.

@malice00
Copy link
Contributor Author

@nscuro Might take me until the weekend to get to it, but I'll give it a look!

@malice00
Copy link
Contributor Author

malice00 commented Aug 19, 2023

@nscuro Nice clean codebase, looks like I can integrate very easily! Now for a test to make sure that integration actually worked... :-)

Edit:
Here's the PR on hyades' codebase

@nscuro
Copy link
Member

nscuro commented Jan 7, 2024

Hey @malice00, apologies for the long wait. Your contribution, along with all the other enhancements we made in Hyades, is now finally being backported to Dependency-Track via #3357. Thus, I'll close this PR. Thanks again for your work on this!

@nscuro nscuro closed this Jan 7, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Components in the SBOM under 'metadata.component.components' are not imported
3 participants