From 237d839c38c10f70321591f6765a5ae06230c972 Mon Sep 17 00:00:00 2001 From: Melba <101211710+melba-lopez@users.noreply.github.com> Date: Sun, 24 Sep 2023 15:57:12 -0500 Subject: [PATCH] Mel issue 2737 (#38) * Initial commit for addressing Issue #2737 Signed-off-by: Melba Lopez * Adding supplier support with fix for organizational entity; addressing Issue #2737 Signed-off-by: Melba Lopez * Added a persistent column for supplier, bom upload processing for supplier, still tweaking how to add supplier contact info; addressing Issue #2737 Signed-off-by: Melba Lopez * Updates per nscuro comments. Co-authored by: Melba Lopez Co-authored by: nscuro Signed-off-by: Melba Lopez * Update Component.java - missing ; Signed-off-by: Melba Lopez * Update ModelConverter.java Putting back code (mouse is acting up on me and accidentally deleted code) Signed-off-by: Melba Lopez --------- Signed-off-by: Melba Lopez --- .../org/dependencytrack/model/Component.java | 23 +++++++++- .../org/dependencytrack/model/Project.java | 15 +++++++ .../parser/cyclonedx/util/ModelConverter.java | 32 +++++++++++++- .../tasks/BomUploadProcessingTaskTest.java | 7 +++ src/test/resources/bom-1.xml | 44 +++++++++++++++++++ 5 files changed, 118 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/dependencytrack/model/Component.java b/src/main/java/org/dependencytrack/model/Component.java index 2c3495ac67..6948a198fc 100644 --- a/src/main/java/org/dependencytrack/model/Component.java +++ b/src/main/java/org/dependencytrack/model/Component.java @@ -28,9 +28,9 @@ import com.github.packageurl.MalformedPackageURLException; import com.github.packageurl.PackageURL; import org.apache.commons.lang3.StringUtils; +import org.cyclonedx.model.OrganizationalEntity; import org.dependencytrack.model.validation.ValidSpdxExpression; import org.dependencytrack.resources.v1.serializers.CustomPackageURLSerializer; - import javax.jdo.annotations.Column; import javax.jdo.annotations.Element; import javax.jdo.annotations.Extension; @@ -116,6 +116,20 @@ public enum FetchGroup { @Pattern(regexp = RegexSequence.Definition.PRINTABLE_CHARS, message = "The publisher may only contain printable characters") private String publisher; + @Persistent /**Issue #2373, #2737 */ + @Column(name = "MANUFACTURE", jdbcType = "VARCHAR") + @Serialized + @Size(max = 255) + @Pattern(regexp = RegexSequence.Definition.PRINTABLE_CHARS, message = "The manufacture may only contain printable characters") + private OrganizationalEntity manufacture; + + @Persistent /**Issue #2373, #2737 */ + @Column(name = "SUPPLIER", jdbcType = "VARCHAR") + @Serialized + @Size(max = 255) + @Pattern(regexp = RegexSequence.Definition.PRINTABLE_CHARS, message = "The supplier may only contain printable characters") + private OrganizationalEntity supplier; + @Persistent @Column(name = "GROUP", jdbcType = "VARCHAR") @Index(name = "COMPONENT_GROUP_IDX") @@ -385,6 +399,13 @@ public void setPublisher(String publisher) { this.publisher = publisher; } + public OrganizationalEntity getSupplier() { /**Issue #2373, #2737 */ + return supplier; + } + + public void setSupplier(OrganizationalEntity supplier) {/**Issue #2373, #2737 */ + this.supplier = supplier; + } public String getGroup() { return group; } diff --git a/src/main/java/org/dependencytrack/model/Project.java b/src/main/java/org/dependencytrack/model/Project.java index f52eb7301a..e0a5b2c0bf 100644 --- a/src/main/java/org/dependencytrack/model/Project.java +++ b/src/main/java/org/dependencytrack/model/Project.java @@ -72,6 +72,7 @@ @Persistent(name = "name"), @Persistent(name = "author"), @Persistent(name = "publisher"), + @Persistent(name = "supplier"), @Persistent(name = "group"), @Persistent(name = "name"), @Persistent(name = "description"), @@ -129,6 +130,12 @@ public enum FetchGroup { @Pattern(regexp = RegexSequence.Definition.PRINTABLE_CHARS, message = "The publisher may only contain printable characters") private String publisher; + @Persistent /**Issue #2373, #2737 */ + @Column(name = "SUPPLIER", jdbcType = "VARCHAR") + @Size(max = 255) + @Pattern(regexp = RegexSequence.Definition.PRINTABLE_CHARS, message = "The supplier may only contain printable characters") + private OrganizationalEntity supplier; + @Persistent @Column(name = "GROUP", jdbcType = "VARCHAR") @Index(name = "PROJECT_GROUP_IDX") @@ -285,6 +292,14 @@ public void setPublisher(String publisher) { this.publisher = publisher; } + public OrganizationalEntity getSupplier() { + return supplier; + } + + public void setSupplier(OrganizationalEntity supplier) { + this.supplier = supplier; + } + public String getGroup() { return group; } diff --git a/src/main/java/org/dependencytrack/parser/cyclonedx/util/ModelConverter.java b/src/main/java/org/dependencytrack/parser/cyclonedx/util/ModelConverter.java index 7375273718..9c39fff838 100644 --- a/src/main/java/org/dependencytrack/parser/cyclonedx/util/ModelConverter.java +++ b/src/main/java/org/dependencytrack/parser/cyclonedx/util/ModelConverter.java @@ -98,6 +98,7 @@ public static List convertComponents(final QueryManager qm, final Bom return components; } + /**Convert from CycloneDX to DT */ @SuppressWarnings("deprecation") public static Component convert(final QueryManager qm, final org.cyclonedx.model.Component cycloneDxComponent, final Project project) { Component component = qm.matchSingleIdentity(project, new ComponentIdentity(cycloneDxComponent)); @@ -108,6 +109,7 @@ public static Component convert(final QueryManager qm, final org.cyclonedx.model component.setAuthor(StringUtils.trimToNull(cycloneDxComponent.getAuthor())); component.setBomRef(StringUtils.trimToNull(cycloneDxComponent.getBomRef())); component.setPublisher(StringUtils.trimToNull(cycloneDxComponent.getPublisher())); + component.setSupplier(cycloneDxComponent.getSupplier());/**Issue #2373, #2737 */ component.setGroup(StringUtils.trimToNull(cycloneDxComponent.getGroup())); component.setName(StringUtils.trimToNull(cycloneDxComponent.getName())); component.setVersion(StringUtils.trimToNull(cycloneDxComponent.getVersion())); @@ -242,7 +244,8 @@ else if (StringUtils.isNotBlank(cycloneLicense.getName())) } return component; } - + + /**Convert from DT to CycloneDX */ @SuppressWarnings("deprecation") public static org.cyclonedx.model.Component convert(final QueryManager qm, final Component component) { final org.cyclonedx.model.Component cycloneComponent = new org.cyclonedx.model.Component(); @@ -395,6 +398,31 @@ public static org.cyclonedx.model.Metadata createMetadata(final Project project) }); cycloneComponent.setExternalReferences(references); } + /*Issue #2737: Adding Supplier contact functionality */ + if (project.getSupplier() != null) { + OrganizationalEntity supplier = new OrganizationalEntity(); + supplier.setName(project.getSupplier().getName()); + + if (project.getSupplier().getUrls() != null) { + supplier.setUrls(project.getSupplier().getUrls()); + } else { + supplier.setUrls(null); + } + if (project.getSupplier().getContacts() != null) { + List contacts = new ArrayList<>(); + for (OrganizationalContact organizationalContact: project.getSupplier().getContacts()) { + OrganizationalContact contact = new OrganizationalContact(); + contact.setName(organizationalContact.getName()); + contact.setEmail(organizationalContact.getEmail()); + contact.setPhone(organizationalContact.getPhone()); + contacts.add(contact); + } + supplier.setContacts(contacts); + } + cycloneComponent.setSupplier(supplier); + } else { + cycloneComponent.setSupplier(null); + } metadata.setComponent(cycloneComponent); } return metadata; @@ -425,7 +453,7 @@ public static ServiceComponent convert(final QueryManager qm, final org.cycloned service.setProject(project); } service.setBomRef(StringUtils.trimToNull(cycloneDxService.getBomRef())); - if (cycloneDxService.getProvider() != null) { + if (cycloneDxService.getProvider() != null) { OrganizationalEntity provider = new OrganizationalEntity();; provider.setName(cycloneDxService.getProvider().getName()); if (cycloneDxService.getProvider().getUrls() != null && cycloneDxService.getProvider().getUrls().size() > 0) { diff --git a/src/test/java/org/dependencytrack/tasks/BomUploadProcessingTaskTest.java b/src/test/java/org/dependencytrack/tasks/BomUploadProcessingTaskTest.java index 5fabfc1f46..151840c827 100644 --- a/src/test/java/org/dependencytrack/tasks/BomUploadProcessingTaskTest.java +++ b/src/test/java/org/dependencytrack/tasks/BomUploadProcessingTaskTest.java @@ -141,6 +141,13 @@ public void informTest() throws Exception { assertThat(components).hasSize(1); final Component component = components.get(0); + + assertThat(component.getSupplier().getName()).isEqualTo("Foo Incorporated"); /*Issue #2373, #2737 - Adding support for Supplier*/ + assertThat(component.getSupplier().getUrls()).isEqualTo("https://foo.bar.com"); + assertThat(component.getSupplier().getContacts().get(0).getName()).isEqualTo("Foo Jr."); + assertThat(component.getSupplier().getContacts().get(0).getEmail()).isEqualTo("foojr@bar.com"); + assertThat(component.getSupplier().getContacts().get(0).getPhone()).isEqualTo("123-456-7890"); + assertThat(component.getAuthor()).isEqualTo("Sometimes this field is long because it is composed of a list of authors......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................"); assertThat(component.getPublisher()).isEqualTo("Example Incorporated"); assertThat(component.getGroup()).isEqualTo("com.example"); diff --git a/src/test/resources/bom-1.xml b/src/test/resources/bom-1.xml index 632bb199d1..e5ddcb27d8 100644 --- a/src/test/resources/bom-1.xml +++ b/src/test/resources/bom-1.xml @@ -2,6 +2,17 @@ + + Foo Incorporated + https://foo.bar.com + + + Foo Jr. + foojr@bar.com + 123-456-7890 + + + DependencyTrack Acme example @@ -19,10 +30,43 @@ + + Foo Incorporated + https://foo.bar.com + + + Foo Sr. + foo@bar.com + 800-123-4567 + + + + + Foo Incorporated + https://foo.bar.com + + + Foo Jr. + foojr@bar.com + 123-456-7890 + + + Sometimes this field is long because it is composed of a list of authors...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... + + Foo Incorporated + https://foo.bar.com + + + Foo Jr. + foojr@bar.com + 123-456-7890 + + + Example Incorporated com.example xmlutil