Skip to content

Commit

Permalink
Add manufacturer information
Browse files Browse the repository at this point in the history
  • Loading branch information
kornefalk committed Nov 20, 2024
1 parent db2a35b commit 0a491c6
Show file tree
Hide file tree
Showing 4 changed files with 394 additions and 0 deletions.
91 changes: 91 additions & 0 deletions src/main/java/org/cyclonedx/maven/BaseCycloneDxMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@
import org.cyclonedx.model.LifecycleChoice;
import org.cyclonedx.model.Lifecycles;
import org.cyclonedx.model.Metadata;
import org.cyclonedx.model.OrganizationalContact;
import org.cyclonedx.model.OrganizationalEntity;
import org.cyclonedx.model.Property;
import org.cyclonedx.model.organization.PostalAddress;
import org.cyclonedx.parsers.JsonParser;
import org.cyclonedx.parsers.Parser;
import org.cyclonedx.parsers.XmlParser;
Expand All @@ -57,6 +60,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;

Expand Down Expand Up @@ -247,6 +251,13 @@ public abstract class BaseCycloneDxMojo extends AbstractMojo {
@Parameter
private ExternalReference[] externalReferences;

/**
* Manufacturer information for automatic creator information
* @since 2.9.1
*/
@Parameter(property = "cyclonedx.manufacturer", required = false)
private OrganizationalEntity manufacturer = null;

@org.apache.maven.plugins.annotations.Component
private MavenProjectHelper mavenProjectHelper;

Expand Down Expand Up @@ -351,6 +362,10 @@ public void execute() throws MojoExecutionException {
if (detectUnusedForOptionalScope) {
metadata.addProperty(newProperty("maven.optional.unused", Boolean.toString(detectUnusedForOptionalScope)));
}

if (hasManufacturerInformation()) {
metadata.setManufacturer(manufacturer);
}
}

final Component rootComponent = metadata.getComponent();
Expand All @@ -362,6 +377,82 @@ public void execute() throws MojoExecutionException {
}
}

/**
* Check the mojo configuration for the optional manufacturer contents.
*
* @return {@code true} if there is any manufacturer information configured.
*/
boolean hasManufacturerInformation() {
if (manufacturer == null) {
return false;
}

return isNotNullOrEmpty(manufacturer.getAddress()) ||
isNotNullOrEmpty(manufacturer.getName()) ||
isNotNullOrEmptyContacts(manufacturer.getContacts()) ||
isNotNullOrEmptyString(manufacturer.getUrls());
}

/**
* @param text Some text
* @return {@code true} if there is any text
*/
boolean isNotNullOrEmpty(String text) {
return text != null && !text.trim().isEmpty();
}

/**
* @param list A list of text
* @return {@code true} if there is any element has a text value
*/
boolean isNotNullOrEmptyString(List<String> list) {
if (list != null && !list.isEmpty()) {
return list.stream().filter(Objects::nonNull).anyMatch(this::isNotNullOrEmpty);
}
return false;
}

/**
* @param list A list of contacts
* @return {@code true} if there is any contact has something configured
*/
boolean isNotNullOrEmptyContacts(List<OrganizationalContact> list) {
if (list != null && !list.isEmpty()) {
return list.stream().filter(Objects::nonNull).anyMatch(this::isNotNullOrEmpty);

}
return false;
}

/**
* @param address A postal address entry
* @return {@code true} if there is any postal address information exists
*/
boolean isNotNullOrEmpty(PostalAddress address) {
if (address == null) {
return false;
}
return isNotNullOrEmpty(address.getStreetAddress()) ||
isNotNullOrEmpty(address.getCountry()) ||
isNotNullOrEmpty(address.getPostalCode()) ||
isNotNullOrEmpty(address.getLocality()) ||
isNotNullOrEmpty(address.getPostOfficeBoxNumber()) ||
isNotNullOrEmpty(address.getRegion());
}

/**
* @param contact A contact entry
* @return {@code true} if there is any contact information exists
*/
boolean isNotNullOrEmpty(OrganizationalContact contact) {
if (null == contact) {
return false;
}
return isNotNullOrEmpty(contact.getName()) ||
isNotNullOrEmpty(contact.getEmail()) ||
isNotNullOrEmpty(contact.getPhone());
}

private Property newProperty(String name, String value) {
Property property = new Property();
property.setName(name);
Expand Down
111 changes: 111 additions & 0 deletions src/site/markdown/manufacturer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Manufacturer
Manufacturer is common in BOMs created through automated processes.

When creating a number of BOMs for several projects within one organization
or company, it is convenient to attach this information at one place.

This will also conform to upcoming EU regulation that all SBOM files shall

>At minimum, the product with digital elements shall be accompanied by:
>1. the name, registered trade name or registered trademark of the manufacturer, and the
> postal address, the email address or other digital contact as well as, where
> available, the website at which the manufacturer can be contacted;
>2. the single point of contact where information about vulnerabilities of the product
> with digital elements can be reported and received, and where the manufacturer’s
> policy on coordinated vulnerability disclosure can be found
>3. name and type and any additional information enabling the unique identification
> of the product with digital elements
>4. the intended purpose of the product with digital elements, including the security
> environment provided by the manufacturer, as well as the product’s essential
> functionalities and information about the security properties
## Configuration
The configuration is optional. If none is specified, the manufacturer information is not visible.
See https://cyclonedx.org/docs/latest/json/#metadata_manufacturer for more information.

### name
The name of the organization,

### address
The physical address (location) of the organization.
##### country
The country name or the two-letter ISO 3166-1 country code.
##### region
The region or state in the country.
##### locality
The locality or city within the country.
##### postOfficeBoxNumber
The post office box number.
##### postalCode
The postal code.
##### streetAddress
The street address.

### url
The URL of the organization. Multiple URLs are allowed.

# contact
A contact at the organization. Multiple contacts are allowed.

##### name
The name of a contact
##### email
The email address of the contact.
##### phone
The phone number of the contact.

## Example of configuration

```xml
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>${cyclonedx-maven-plugin.version}</version>
<configuration>
<manufacturer>
<name>Example Company</name>
<url>https://www.example.com/contact</url>
<contact>
<contact>
<name>Steve Springett</name>
<email>[email protected]</email>
</contact>
<contact>
<name>Another contact</name>
<phone>1-800-555-1111</phone>
</contact>
</contact>
</manufacturer>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
```

This configuration will add the following to the BOM file (JSON format):
```json
"manufacturer" : {
"name" : "Example Company",
"url" : [
"https://www.example.com/contact"
],
"contact" : [
{
"name" : "Steve Springett",
"email" : "[email protected]"
},
{
"name" : "Another contact",
"phone" : "1-800-555-1111"
}
]
}
```

## Links
- [EU regulation proposal about SBOM generation.](https://www.europarl.europa.eu/doceo/document/TA-9-2024-0130_EN.pdf)

1 change: 1 addition & 0 deletions src/site/site.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<item name="CycloneDX" href="https://www.cyclonedx.org/" />
<item name="Tool Center" href="https://cyclonedx.org/tool-center/" />
<item name="CycloneDX Maven Plugin" href="index.html" />
<item name="Manufacture References" href="manufacturer.html"/>
</breadcrumbs>
<links>
<item name="Sources" href="https://www.github.com/CycloneDX/cyclonedx-maven-plugin"/>
Expand Down
Loading

0 comments on commit 0a491c6

Please sign in to comment.