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

Issue #2737 - Fulfil NTIA minimum requirements #3090

Merged
merged 10 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion src/main/java/org/dependencytrack/model/Component.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import org.apache.commons.lang3.StringUtils;
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;
Expand Down Expand Up @@ -116,6 +115,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")
leec94 marked this conversation as resolved.
Show resolved Hide resolved
@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")
@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")
Expand Down Expand Up @@ -385,6 +398,22 @@ 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 OrganizationalEntity getManufacturer() { /**Issue #2373, #2737 */
return manufacture;
}

public void setManufacturer(OrganizationalEntity manufacture) {/**Issue #2373, #2737 */
this.manufacture = manufacture;
}

public String getGroup() {
return group;
}
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/org/dependencytrack/model/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -129,6 +130,18 @@ 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")
@Size(max = 255)
@Pattern(regexp = RegexSequence.Definition.PRINTABLE_CHARS, message = "The supplier may only contain printable characters")
private OrganizationalEntity supplier;

@Persistent /**Issue #2373, #2737 */
@Column(name = "MANUFACTURE")
@Size(max = 255)
@Pattern(regexp = RegexSequence.Definition.PRINTABLE_CHARS, message = "The manufacturer may only contain printable characters")
private OrganizationalEntity manufacture;

@Persistent
@Column(name = "GROUP", jdbcType = "VARCHAR")
@Index(name = "PROJECT_GROUP_IDX")
Expand Down Expand Up @@ -285,6 +298,23 @@ public void setPublisher(String publisher) {
this.publisher = publisher;
}

public OrganizationalEntity getSupplier() {
return supplier;
}

public void setSupplier(OrganizationalEntity supplier) {
this.supplier = supplier;
}

public OrganizationalEntity getManufacturer() { /**Issue #2373, #2737 */
return manufacture;
}

public void setManufacturer(OrganizationalEntity manufacture) {/**Issue #2373, #2737 */
this.manufacture = manufacture;
}


public String getGroup() {
return group;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public static List<Component> 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));
Expand All @@ -108,6 +109,32 @@ 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()));

/**Issue #2373, #2737 */
if (cycloneDxComponent.getSupplier() != null) {
OrganizationalEntity deptrackOrgEntity = new OrganizationalEntity();
deptrackOrgEntity.setName(cycloneDxComponent.getSupplier().getName());
deptrackOrgEntity.setUrls(cycloneDxComponent.getSupplier().getUrls().toArray(new String[0]));
// to do convert contacts
// deptrackOrgEntity.setContacts(cycloneDxComponent.getSupplier().getContacts());

if (cycloneDxComponent.getSupplier().getContacts() != null) {
List<OrganizationalContact> contacts = new ArrayList<>();
for (org.cyclonedx.model.OrganizationalContact organizationalContact: cycloneDxComponent.getSupplier().getContacts()) {
OrganizationalContact contact = new OrganizationalContact();
contact.setName(organizationalContact.getName());
contact.setEmail(organizationalContact.getEmail());
contact.setPhone(organizationalContact.getPhone());
contacts.add(contact);
}
deptrackOrgEntity.setContacts(contacts);
} else {
deptrackOrgEntity.setContacts(null);
}
component.setSupplier(deptrackOrgEntity);
} /**Issue #2373, #2737 */


component.setGroup(StringUtils.trimToNull(cycloneDxComponent.getGroup()));
component.setName(StringUtils.trimToNull(cycloneDxComponent.getName()));
component.setVersion(StringUtils.trimToNull(cycloneDxComponent.getVersion()));
Expand Down Expand Up @@ -242,7 +269,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();
Expand Down Expand Up @@ -395,6 +423,31 @@ public static org.cyclonedx.model.Metadata createMetadata(final Project project)
});
cycloneComponent.setExternalReferences(references);
}
/*Issue #2737: Adding Supplier contact functionality */
if (project.getSupplier() != null) {
org.cyclonedx.model.OrganizationalEntity supplier = new org.cyclonedx.model.OrganizationalEntity();
supplier.setName(project.getSupplier().getName());

if (project.getSupplier().getUrls() != null) {
supplier.setUrls(Arrays.asList(project.getSupplier().getUrls()));
} else {
supplier.setUrls(null);
}
if (project.getSupplier().getContacts() != null) {
List<org.cyclonedx.model.OrganizationalContact> contacts = new ArrayList<>();
for (OrganizationalContact organizationalContact: project.getSupplier().getContacts()) {
org.cyclonedx.model.OrganizationalContact contact = new org.cyclonedx.model.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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import org.dependencytrack.model.Classifier;
import org.dependencytrack.model.Component;
import org.dependencytrack.model.ConfigPropertyConstants;
import org.dependencytrack.model.OrganizationalEntity;
import org.dependencytrack.model.OrganizationalContact;
import org.dependencytrack.model.Project;
import org.dependencytrack.model.ServiceComponent;
import org.dependencytrack.notification.NotificationConstants;
Expand Down Expand Up @@ -120,6 +122,29 @@ public void inform(final Event e) {
serialNumnber = (cycloneDxBom.getSerialNumber() != null) ? cycloneDxBom.getSerialNumber().replaceFirst("urn:uuid:", "") : null;
components = ModelConverter.convertComponents(qm, cycloneDxBom, project);
services = ModelConverter.convertServices(qm, cycloneDxBom, project);
/**Issue #2373, #2737 */
if (cycloneDxBom.getMetadata() != null) {
if (cycloneDxBom.getMetadata().getManufacture() != null) {
OrganizationalEntity manufacturer = new OrganizationalEntity();
manufacturer.setName(cycloneDxBom.getMetadata().getManufacture().getName());
manufacturer.setUrls(cycloneDxBom.getMetadata().getManufacture().getUrls().toArray(new String[0]));
if (cycloneDxBom.getMetadata().getManufacture().getContacts() != null){
List<OrganizationalContact> contacts = new ArrayList<>();
for (org.cyclonedx.model.OrganizationalContact organizationalContact: cycloneDxBom.getMetadata().getManufacture().getContacts()) {
OrganizationalContact contact = new OrganizationalContact();
contact.setName(organizationalContact.getName());
contact.setEmail(organizationalContact.getEmail());
contact.setPhone(organizationalContact.getPhone());
contacts.add(contact);
}
manufacturer.setContacts(contacts);
} else {
manufacturer.setContacts(null);
}
project.setManufacturer(manufacturer);
}
} /**Issue #2373, #2737 */

} else {
LOGGER.warn("A CycloneDX BOM was uploaded but accepting CycloneDX BOMs is disabled. Aborting");
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,19 @@ 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()[0]).isEqualTo("https://foo.bar.com");
assertThat(component.getSupplier().getContacts().get(0).getEmail()).isEqualTo("[email protected]");
assertThat(component.getSupplier().getContacts().get(0).getPhone()).isEqualTo("123-456-7890");

assertThat(project.getManufacturer().getName()).isEqualTo("Foo Incorporated");
assertThat(project.getManufacturer().getUrls()[0]).isEqualTo("https://foo.bar.com");
assertThat(project.getManufacturer().getContacts().get(0).getName()).isEqualTo("Foo Sr.");
assertThat(project.getManufacturer().getContacts().get(0).getEmail()).isEqualTo("[email protected]");
assertThat(project.getManufacturer().getContacts().get(0).getPhone()).isEqualTo("800-123-4567");


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");
Expand Down
36 changes: 36 additions & 0 deletions src/test/resources/bom-1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" version="1">
<metadata>
<component type="application" bom-ref="acme">
<supplier>
<name>Foo Incorporated</name>
<url>https://foo.bar.com</url>
<contact>
<name>Foo Jr.</name>
<email>[email protected]</email>
<phone>123-456-7890</phone>
</contact>
</supplier>
<publisher>DependencyTrack</publisher>
<name>Acme example</name>
<externalReferences>
Expand All @@ -19,10 +28,37 @@
</reference>
</externalReferences>
</component>
<manufacture>
<name>Foo Incorporated</name>
<url>https://foo.bar.com</url>
<contact>
<name>Foo Sr.</name>
<email>[email protected]</email>
<phone>800-123-4567</phone>
</contact>
</manufacture>
<supplier>
<name>Foo Incorporated</name>
<url>https://foo.bar.com</url>
<contact>
<name>Foo Jr.</name>
<email>[email protected]</email>
<phone>123-456-7890</phone>
</contact>
</supplier>
</metadata>
<components>
<component type="application">
<author>Sometimes this field is long because it is composed of a list of authors......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................</author>
<supplier>
<name>Foo Incorporated</name>
<url>https://foo.bar.com</url>
<contact>
<name>Foo Jr.</name>
<email>[email protected]</email>
<phone>123-456-7890</phone>
</contact>
</supplier>
<publisher>Example Incorporated</publisher>
<group>com.example</group>
<name>xmlutil</name>
Expand Down