From 2b923e0dc2102f0cc4c358ffe9ad23c38e6a67e4 Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sat, 3 Sep 2022 17:31:11 -0700 Subject: [PATCH 01/13] fix: make a purl DT can recognize Signed-off-by: djcrabhat --- pom.xml | 2 +- .../sbom/generator/RedHatSBomGenerator.java | 36 ++++++++++++--- .../sbom/generator/UnixSBomGenerator.java | 2 +- .../unix/sbom/utils/OperatingSystemUtils.java | 2 +- .../generator/RedHatSBomGeneratorTest.java | 15 +++--- .../sbom/utils/OperatingSystemUtilsTest.java | 46 +++++++++++++++++-- .../sbom/utils/TestOperatingSystemUtil.java | 12 +++++ 7 files changed, 93 insertions(+), 22 deletions(-) create mode 100644 src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/TestOperatingSystemUtil.java diff --git a/pom.xml b/pom.xml index b53f7cb..68f111c 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ https://github.com/CycloneDX/cyclonedx-linux-generator - 5.0.4 + 7.2.0 2.5.3 1.3 diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index 7327de3..3848ce3 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -44,9 +44,15 @@ public class RedHatSBomGenerator extends UnixSBomGenerator private static final String PURL_CMD = "yumdownloader --urls"; private static final String SOFTWARE_DETAIL_CMD = "yum info"; private static final String SOFTWARE_LIST_CMD = "yum list installed"; + + private String purlNamespace = "rhel"; private ProcessBuilder processBuilder = new ProcessBuilder(); - + + public void setPurlNamespace(String ns){ + this.purlNamespace = ns; + } + /** * (U) This method is used to generate the Software Bill Of Materials (SBOM) for all RedHat * Linux Operating systems. @@ -78,7 +84,9 @@ public Bom generateSBom() version = detailMap.get("Version"); group = detailMap.get("Release"); license = processLicense(software, version); - purl = getPurl(software); + purl = getPurl(software,version); + // TODO: get arch and distro + //purl = getPurl(software,version, arch, distro); component = createComponents(software, detailMap, license, group, version, purl, detailMap.get("Priority")); bom.addComponent(addPackageManager(component, PACKAGE_MANAGER)); @@ -118,19 +126,33 @@ public String getLicenseFileName(String software, String version) } return null; } - + + + public String getPurl(String software, String version) { + return this.getPurl(software, version, null, null); + } + + public String getPurl(String software, String version, String arch, String distro) { + String purl_format = null; + if(arch == null){ + return String.format("pkg:rpm/%s/%s@%s", purlNamespace, software, version); + } + else{ + return String.format("pkg:rpm/%s/%s@%s?arch=%s&distro=%s", purlNamespace, software, version, arch, distro); + } + } + + /** * (U) This method is used to get the Product Uniform Resource Locator (PURL) or as we know it * the download Uniform Resource Locator (URL). - * + * * @param software String value of the software to get the PURL for. * @return String the URL that will be used to download this software product. * @throws SBomException in the event we are unable to get the PURL from the server. */ - public String getPurl(String software) - { + public String getPackageDownloadUrl(String software){ String purl = null; - String cmd = PURL_CMD + " " + software; processBuilder.command("bash", "-c", cmd); diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java index 6986c41..9cfc2aa 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java @@ -41,7 +41,7 @@ public class UnixSBomGenerator { protected enum AVAILABLE_LINUX_FLAVORS { - ALPINE, REDHAT, UBUNTU + ALPINE, REDHAT, UBUNTU, AL2 } protected static final Logger logger = Logger.getLogger(UnixSBomGenerator.class.getName()); diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtils.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtils.java index db11a16..2272c1d 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtils.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtils.java @@ -146,7 +146,7 @@ public Map getOs() * @param content String value read from the file. * @return Map containing the information about the Operating system. */ - public Map readOs(String content) + public static Map readOs(String content) { Map detailMap = new HashMap<>(); diff --git a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java index a002a53..d42e0ca 100644 --- a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java +++ b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java @@ -116,9 +116,10 @@ void getPurlTest() Date startDate = DateUtils.rightNowDate(); TestUtils.logTestStart(methodName, watcher.getLogger()); - - String expected = "https://rhui3.us-west-2.aws.ce.redhat.com/pulp/repos/content/dist/rhel/rhui/server/7/7Server/x86_64/os/Packages/z/zip-3.0-11.el7.x86_64.rpm"; - + + String expectedUrl = "https://rhui3.us-west-2.aws.ce.redhat.com/pulp/repos/content/dist/rhel/rhui/server/7/7Server/x86_64/os/Packages/z/zip-3.0-11.el7.x86_64.rpm"; + String expected = "pkg:rpm/rhel/zip@3.0-11.el7"; + AutoCloseable openMocks = null; String fileName = "/purl/redhatPurl.txt"; @@ -131,12 +132,12 @@ void getPurlTest() Mockito.when(pbMock.start()).thenReturn(process); - String version = generator.getPurl("zip"); + String purl = generator.getPurl("zip", "3.0-11.el7"); - if (expected.equalsIgnoreCase(version)) - watcher.getLogger().debug("Got expected version (" + version + ")"); + if (expected.equalsIgnoreCase(purl)) + watcher.getLogger().debug("Got expected version (" + purl + ")"); else - Assert.assertEquals(expected, version); + Assert.assertEquals(expected, purl); } catch (Exception e) { diff --git a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtilsTest.java b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtilsTest.java index a7b5fd8..acc1b5e 100644 --- a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtilsTest.java +++ b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtilsTest.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Date; +import java.util.HashMap; import java.util.Map; import org.apache.commons.io.IOUtils; @@ -589,12 +590,12 @@ void testReadOsUbuntu() { try (InputStream inputStream = OperatingSystemUtilsTest.class.getResourceAsStream(file)) { - String theString = IOUtils.toString(inputStream); - - OperatingSystemUtils osUtils = new OperatingSystemUtils(); - Map osMap = osUtils.readOs(theString); + String theString = IOUtils.toString(inputStream); + + var opts = readOs(theString); + var osUtils = new TestOperatingSystemUtil("Ubuntu", opts); - String osVendor = osMap.get("NAME"); + String osVendor = opts.get("NAME"); osVendor = CharMatcher.is('\"').trimFrom(osVendor); if (expected.equalsIgnoreCase(osVendor)) @@ -623,4 +624,39 @@ void testReadOsUbuntu() TestUtils.logTestFinish(methodName, startDate, watcher.getLogger()); } } + + private Map readOs(String content) + { + Map detailMap = new HashMap<>(); + + String[] contents = content.split("\n"); + String componentDetailName = null; + StringBuilder componentDetailValue = new StringBuilder(); + int index = 0; + + for (String line : contents) + { + if (line.startsWith(" ")) + { + componentDetailValue.append(line); + } + else + { + if (componentDetailName != null) + { + detailMap.put(componentDetailName, componentDetailValue.toString()); + componentDetailName = null; + componentDetailValue = new StringBuilder(); + } + + if (line.contains("=")) + { + index = line.indexOf('='); + componentDetailName = line.substring(0, index); + componentDetailValue.append(line.substring(index + 1).trim()); + } + } + } + return detailMap; + } } diff --git a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/TestOperatingSystemUtil.java b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/TestOperatingSystemUtil.java new file mode 100644 index 0000000..0ebfbdd --- /dev/null +++ b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/TestOperatingSystemUtil.java @@ -0,0 +1,12 @@ +package org.cyclonedx.contrib.com.lmco.efoss.unix.sbom.utils; + +import java.util.Map; + +public class TestOperatingSystemUtil { + private Map osMap = null; + + public TestOperatingSystemUtil(String name, Map testMap) + { + osMap = testMap; + } +} From 032278a32e2d8c631bb66b5257520c64437bb819 Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sat, 3 Sep 2022 17:36:59 -0700 Subject: [PATCH 02/13] add artifact to maven build Signed-off-by: djcrabhat --- .github/workflows/maven.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 745da7c..fd8db1a 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -16,3 +16,8 @@ jobs: java-version: '11' - name: Build with Maven run: mvn package --file pom.xml + - name: 'Upload Artifact' + uses: actions/upload-artifact@v3 + with: + name: JAR + path: target/linux-sbom-generator-*.jar From d5cc53a58875ce1996cdaae4f7642f82352294ff Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sat, 3 Sep 2022 17:55:48 -0700 Subject: [PATCH 03/13] use PackageUrl class Signed-off-by: djcrabhat --- .../sbom/generator/RedHatSBomGenerator.java | 160 ++++++++++-------- .../unix/sbom/generator/SBomGenerator.java | 4 + .../sbom/generator/UnixSBomGenerator.java | 3 +- .../generator/RedHatSBomGeneratorTest.java | 7 +- 4 files changed, 95 insertions(+), 79 deletions(-) diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index 3848ce3..e6895aa 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2018,2019 Lockheed Martin Corporation. * * This work is owned by Lockheed Martin Corporation. Lockheed Martin personnel are permitted to use and @@ -18,7 +18,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.TreeMap; +import com.github.packageurl.MalformedPackageURLException; +import com.github.packageurl.PackageURL; import org.cyclonedx.model.Bom; import org.cyclonedx.model.Component; import org.cyclonedx.model.LicenseChoice; @@ -28,7 +31,7 @@ /** * * (U) This class is responsible for generating the Software Bill Of Materials (SBOM) for all * Oracle Red Hat Linux Operating Systems. - * + * * @author wrgoff * @since 24 April 2020 */ @@ -37,16 +40,16 @@ public class RedHatSBomGenerator extends UnixSBomGenerator private static final List POSSIBLE_LICENSE_FILES = new ArrayList<>( List.of("LICENSE.txt", "LICENSE", "COPYING", "COPYING.LGPL", "PORTING", "Copying")); - + private static final String PACKAGE_MANAGER = "yum"; - + // Unix Commands. private static final String PURL_CMD = "yumdownloader --urls"; private static final String SOFTWARE_DETAIL_CMD = "yum info"; private static final String SOFTWARE_LIST_CMD = "yum list installed"; private String purlNamespace = "rhel"; - + private ProcessBuilder processBuilder = new ProcessBuilder(); public void setPurlNamespace(String ns){ @@ -56,47 +59,50 @@ public void setPurlNamespace(String ns){ /** * (U) This method is used to generate the Software Bill Of Materials (SBOM) for all RedHat * Linux Operating systems. - * + * * @return Bom The Software Bill Of Materials for this RedHat Linux Operating System. * @throws SBomException if we are unable to build the SBOM. */ - public Bom generateSBom() - { - List softwareList = generateListOfSoftware(SOFTWARE_LIST_CMD, ' ', - "Installed Packages"); - - Bom bom = new Bom(); - - if (logger.isDebugEnabled()) - logger.debug("Processing " + softwareList.size() + " software programs."); - - Map detailMap = null; - String version = null; - String group = null; - LicenseChoice license = null; - String purl = null; - Component component = null; - for (String software : softwareList) - { - if (logger.isDebugEnabled()) - logger.debug("Generating Component (" + software + ")"); - detailMap = produceDetailMap(software); - version = detailMap.get("Version"); - group = detailMap.get("Release"); - license = processLicense(software, version); - purl = getPurl(software,version); - // TODO: get arch and distro - //purl = getPurl(software,version, arch, distro); - component = createComponents(software, detailMap, license, group, - version, purl, detailMap.get("Priority")); - bom.addComponent(addPackageManager(component, PACKAGE_MANAGER)); - } - return bom; - } - + public Bom generateSBom() { + List softwareList = generateListOfSoftware(SOFTWARE_LIST_CMD, ' ', + "Installed Packages"); + + Bom bom = new Bom(); + + if (logger.isDebugEnabled()) + logger.debug("Processing " + softwareList.size() + " software programs."); + + Map detailMap = null; + String version = null; + String group = null; + LicenseChoice license = null; + PackageURL purl = null; + Component component = null; + for (String software : softwareList) { + if (logger.isDebugEnabled()) + logger.debug("Generating Component (" + software + ")"); + detailMap = produceDetailMap(software); + version = detailMap.get("Version"); + group = detailMap.get("Release"); + license = processLicense(software, version); + try { + purl = getPurl(software, version); + + // TODO: get arch and distro + //purl = getPurl(software,version, arch, distro); + } catch (MalformedPackageURLException e) { + logger.debug("Can't get purl", e); + } + component = createComponents(software, detailMap, license, group, + version, purl, detailMap.get("Priority")); + bom.addComponent(addPackageManager(component, PACKAGE_MANAGER)); + } + return bom; + } + /** * (U) This method is used to attempt to figure out which file is the license file. If any. - * + * * @param software String value of the software we are attempting to get the license file for. * @param version String value of the version of the software we are attempting to get the * license for. @@ -105,19 +111,19 @@ public Bom generateSBom() public String getLicenseFileName(String software, String version) { File tempFile = null; - + software = software.trim(); - + if (software.endsWith(".x86_64")) software = software.replace(".x86_64", ""); - + if (version != null) software = software + "-" + version.trim(); - + if (logger.isDebugEnabled()) logger.debug("Attempting to get license file from " + SOFTWARE_LICENSE_DIR + software + "."); - + for (String fileToTry : POSSIBLE_LICENSE_FILES) { tempFile = new File(SOFTWARE_LICENSE_DIR + software, fileToTry); @@ -128,19 +134,23 @@ public String getLicenseFileName(String software, String version) } - public String getPurl(String software, String version) { + public PackageURL getPurl(String software, String version) throws MalformedPackageURLException { return this.getPurl(software, version, null, null); } - public String getPurl(String software, String version, String arch, String distro) { - String purl_format = null; - if(arch == null){ - return String.format("pkg:rpm/%s/%s@%s", purlNamespace, software, version); - } - else{ - return String.format("pkg:rpm/%s/%s@%s?arch=%s&distro=%s", purlNamespace, software, version, arch, distro); - } - } + public PackageURL getPurl(String software, String version, String arch, String distro) throws MalformedPackageURLException { + String purl_format = null; + TreeMap qualifiers = new TreeMap<>(); + if (arch == null) { + qualifiers.put("arch", arch); + } + if (distro == null) { + qualifiers.put("distro", distro); + } + return new PackageURL( + PackageURL.StandardTypes.DOCKER, null, + purlNamespace.toLowerCase(), version, qualifiers, null); + } /** @@ -154,12 +164,12 @@ public String getPurl(String software, String version, String arch, String distr public String getPackageDownloadUrl(String software){ String purl = null; String cmd = PURL_CMD + " " + software; - + processBuilder.command("bash", "-c", cmd); - + if (logger.isDebugEnabled()) logger.debug("Attempting to get PURL for " + software + "."); - + try { Process process = processBuilder.start(); @@ -174,10 +184,10 @@ public String getPackageDownloadUrl(String software){ } return purl; } - + /** * (U) This method is used to parse the PURL from the output of the command process. - * + * * @param process Process that is running the YUM command. * @param software String value of the software, used for debugging purposes. * @return String the PURL if available. @@ -186,15 +196,15 @@ public String getPackageDownloadUrl(String software){ public String parsePurl(Process process, String software) { String purl = null; - + try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { purl = parsePurlCmdOutput(reader); - + if (purl == null) logger.warn("No PURL found for software package (" + software + ")."); - + int exitVal = process.waitFor(); if (exitVal != 0) { @@ -216,11 +226,11 @@ public String parsePurl(Process process, String software) } return purl; } - + /** * (U) This method is used to parse the Unix Command Output to get the download Uniform Resource * Locator (URL) also known as the Product Uniform Resource Locator (PURL) - * + * * @param reader BufferedReader to parse the output form. * @return String the PURL or download URL that can be used to download the software package. * @throws SBomException in the event we are unable to parse the command's output. @@ -254,11 +264,11 @@ else if (line.startsWith("No Match for argument")) // No PURL found. } return purl; } - + /** * (U) This method is responsible for getting the license (if present) and placing it in the * LicenseChoice Object passed back. - * + * * @param software String value of the software we are attempting to get the license for. * @param version String value of the version of the software we are attempting to get the * license for. @@ -268,18 +278,18 @@ private LicenseChoice processLicense(String software, String version) { if (logger.isDebugEnabled()) logger.debug("Attempting to get license file for " + software + "."); - + LicenseChoice licenseChoice = null; - + String licenseFile = getLicenseFileName(software, version); - + try { if (licenseFile != null) { if (logger.isDebugEnabled()) logger.debug("Attempting to process license (" + licenseFile + ")"); - + String licenseTxt = new String(Files.readAllBytes(Paths.get(licenseFile))); licenseChoice = parseLicenseText(licenseTxt, AVAILABLE_LINUX_FLAVORS.REDHAT); } @@ -292,11 +302,11 @@ private LicenseChoice processLicense(String software, String version) } return licenseChoice; } - + /** * (U) This method is used to produce a Detail Map of the Software in question. This will be * used to create a CycloneDx Component. - * + * * @param software String value of the component to build the detail map for. * @return Map containing the key value pairs about the software. * @throws SBomException in the event we can NOT produce the detail map of the software. @@ -304,7 +314,7 @@ private LicenseChoice processLicense(String software, String version) private Map produceDetailMap(String software) { String cmd = SOFTWARE_DETAIL_CMD + " " + software; - + return (produceDetailMap(cmd, AVAILABLE_LINUX_FLAVORS.REDHAT)); } } diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java index eb82c80..c93f5f0 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java @@ -173,6 +173,10 @@ public static Component createMasterComponent(String imageUrl, String name, logger.error(error, e); throw new SBomException(error); } + }else{ + master.setType(Component.Type.OPERATING_SYSTEM); + // TODO: should we set the CPE reported by hostnamectl here? + //master.setCpe(); } if (StringUtils.isValid(name)) master.setName(name.toLowerCase()); diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java index 9cfc2aa..396164c 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map; +import com.github.packageurl.PackageURL; import org.apache.log4j.Logger; import org.cyclonedx.model.AttachmentText; import org.cyclonedx.model.Component; @@ -125,7 +126,7 @@ else if (priority.equalsIgnoreCase("optional")) * @return Component Sbom Component created from the supplied inputs. */ public Component createComponents(String software, Map detailMap, - LicenseChoice license, String group, String version, String purl, String scope) + LicenseChoice license, String group, String version, PackageURL purl, String scope) { Component component = new Component(); component.setType(Type.OPERATING_SYSTEM); diff --git a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java index d42e0ca..1a13f50 100644 --- a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java +++ b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Map; +import com.github.packageurl.PackageURL; import org.cyclonedx.model.ExternalReference; import org.junit.Assert; import org.junit.jupiter.api.Test; @@ -132,12 +133,12 @@ void getPurlTest() Mockito.when(pbMock.start()).thenReturn(process); - String purl = generator.getPurl("zip", "3.0-11.el7"); + PackageURL purl = generator.getPurl("zip", "3.0-11.el7"); - if (expected.equalsIgnoreCase(purl)) + if (expected.equalsIgnoreCase(purl.toString())) watcher.getLogger().debug("Got expected version (" + purl + ")"); else - Assert.assertEquals(expected, purl); + Assert.assertEquals(expected, purl.toString()); } catch (Exception e) { From d9c226d7ad38777a5834e67fd62ef086b43fcc6e Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sat, 3 Sep 2022 18:08:15 -0700 Subject: [PATCH 04/13] fix tests Signed-off-by: djcrabhat --- .../sbom/generator/RedHatSBomGenerator.java | 25 +++++++++---------- .../sbom/generator/UnixSBomGenerator.java | 4 ++- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index e6895aa..720114a 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -138,19 +138,18 @@ public PackageURL getPurl(String software, String version) throws MalformedPacka return this.getPurl(software, version, null, null); } - public PackageURL getPurl(String software, String version, String arch, String distro) throws MalformedPackageURLException { - String purl_format = null; - TreeMap qualifiers = new TreeMap<>(); - if (arch == null) { - qualifiers.put("arch", arch); - } - if (distro == null) { - qualifiers.put("distro", distro); - } - return new PackageURL( - PackageURL.StandardTypes.DOCKER, null, - purlNamespace.toLowerCase(), version, qualifiers, null); - } + public PackageURL getPurl(String software, String version, String arch, String distro) throws MalformedPackageURLException { + String purl_format = null; + TreeMap qualifiers = new TreeMap<>(); + if (arch != null) { + qualifiers.put("arch", arch); + } + if (distro != null) { + qualifiers.put("distro", distro); + } + return new PackageURL( + PackageURL.StandardTypes.RPM, purlNamespace.toLowerCase(), software, version, qualifiers, null); + } /** diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java index 396164c..dbe8b62 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java @@ -137,7 +137,9 @@ public Component createComponents(String software, Map detailMap component.setGroup(group); component.setLicenseChoice(license); component.setPublisher(detailMap.get("From repo")); - component.setPurl(purl); + if(purl!=null) { + component.setPurl(purl); + } component.setScope(buildScope(scope)); component.setVersion(version); From b351028f7ed09dbc533f41d9ca8553cfcb1cf079 Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sat, 3 Sep 2022 18:55:04 -0700 Subject: [PATCH 05/13] add download_url detail Signed-off-by: djcrabhat --- .../efoss/unix/sbom/generator/RedHatSBomGenerator.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index 720114a..6f62494 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -93,6 +93,15 @@ public Bom generateSBom() { } catch (MalformedPackageURLException e) { logger.debug("Can't get purl", e); } + + try { + String downloadUrl = getPackageDownloadUrl(software); + if (downloadUrl != null) { + detailMap.put("download_url", downloadUrl); + } + } catch(SBomException e){ + logger.debug("Error getting download_url", e); + } component = createComponents(software, detailMap, license, group, version, purl, detailMap.get("Priority")); bom.addComponent(addPackageManager(component, PACKAGE_MANAGER)); @@ -139,7 +148,6 @@ public PackageURL getPurl(String software, String version) throws MalformedPacka } public PackageURL getPurl(String software, String version, String arch, String distro) throws MalformedPackageURLException { - String purl_format = null; TreeMap qualifiers = new TreeMap<>(); if (arch != null) { qualifiers.put("arch", arch); From ab5f1a89146f8844a18e1e202aaecad3a2692e46 Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sat, 3 Sep 2022 21:06:47 -0700 Subject: [PATCH 06/13] try parsing component Signed-off-by: djcrabhat --- pom.xml | 2 +- .../unix/sbom/generator/RedHatSBomGenerator.java | 12 +++++++++++- .../unix/sbom/generator/RedHatSBomGeneratorTest.java | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 68f111c..2ee808d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.cyclonedx.contrib.com.lmco.efoss.unix.sbom linux-sbom-generator - 3.1.0-SNAPSHOT + 3.2.0-SNAPSHOT linux-sbom-generator Unix SBOM Generator https://github.com/CycloneDX/cyclonedx-linux-generator diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index 6f62494..fcb29c9 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -144,10 +144,20 @@ public String getLicenseFileName(String software, String version) public PackageURL getPurl(String software, String version) throws MalformedPackageURLException { - return this.getPurl(software, version, null, null); + String[] parts = software.split("\\."); + + if (parts.length == 0) { + return this.getPurl(software, version, null, null); + } + if (parts.length == 1) { + return this.getPurl(parts[0], version, null, null); + } else { + return this.getPurl(parts[0], version, parts[1], null); + } } public PackageURL getPurl(String software, String version, String arch, String distro) throws MalformedPackageURLException { + TreeMap qualifiers = new TreeMap<>(); if (arch != null) { qualifiers.put("arch", arch); diff --git a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java index 1a13f50..fabb2d3 100644 --- a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java +++ b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java @@ -119,7 +119,7 @@ void getPurlTest() TestUtils.logTestStart(methodName, watcher.getLogger()); String expectedUrl = "https://rhui3.us-west-2.aws.ce.redhat.com/pulp/repos/content/dist/rhel/rhui/server/7/7Server/x86_64/os/Packages/z/zip-3.0-11.el7.x86_64.rpm"; - String expected = "pkg:rpm/rhel/zip@3.0-11.el7"; + String expected = "pkg:rpm/rhel/zip@3.0-11.el7?arch=x64_86"; AutoCloseable openMocks = null; @@ -133,7 +133,7 @@ void getPurlTest() Mockito.when(pbMock.start()).thenReturn(process); - PackageURL purl = generator.getPurl("zip", "3.0-11.el7"); + PackageURL purl = generator.getPurl("zip.x64_86", "3.0-11.el7"); if (expected.equalsIgnoreCase(purl.toString())) watcher.getLogger().debug("Got expected version (" + purl + ")"); From 0dd331d36a33a13e694f472927c32d1edca1f5f3 Mon Sep 17 00:00:00 2001 From: DJCrabhat Date: Sun, 4 Sep 2022 11:30:10 -0700 Subject: [PATCH 07/13] Update src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java Co-authored-by: sonatype-lift[bot] <37194012+sonatype-lift[bot]@users.noreply.github.com> Signed-off-by: djcrabhat --- .../com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index fcb29c9..6958188 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -144,7 +144,7 @@ public String getLicenseFileName(String software, String version) public PackageURL getPurl(String software, String version) throws MalformedPackageURLException { - String[] parts = software.split("\\."); +List parts = Splitter.on('.').splitToList(software); if (parts.length == 0) { return this.getPurl(software, version, null, null); From b0484da26fdc0eb456ab2fe4ececb8ff523227e0 Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sun, 4 Sep 2022 11:50:06 -0700 Subject: [PATCH 08/13] cleanup, make purl sonatype expects Signed-off-by: djcrabhat --- .../sbom/generator/RedHatSBomGenerator.java | 19 ++++++++++--------- .../sbom/generator/UnixSBomGenerator.java | 6 ++++++ .../generator/RedHatSBomGeneratorTest.java | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index 6958188..cc88292 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -22,6 +22,7 @@ import com.github.packageurl.MalformedPackageURLException; import com.github.packageurl.PackageURL; +import com.google.common.base.Splitter; import org.cyclonedx.model.Bom; import org.cyclonedx.model.Component; import org.cyclonedx.model.LicenseChoice; @@ -48,7 +49,7 @@ public class RedHatSBomGenerator extends UnixSBomGenerator private static final String SOFTWARE_DETAIL_CMD = "yum info"; private static final String SOFTWARE_LIST_CMD = "yum list installed"; - private String purlNamespace = "rhel"; + private String purlNamespace = null; private ProcessBuilder processBuilder = new ProcessBuilder(); @@ -97,10 +98,10 @@ public Bom generateSBom() { try { String downloadUrl = getPackageDownloadUrl(software); if (downloadUrl != null) { - detailMap.put("download_url", downloadUrl); + detailMap.put("Download-Url", downloadUrl); } } catch(SBomException e){ - logger.debug("Error getting download_url", e); + logger.debug("Error getting Download-Url", e); } component = createComponents(software, detailMap, license, group, version, purl, detailMap.get("Priority")); @@ -144,15 +145,15 @@ public String getLicenseFileName(String software, String version) public PackageURL getPurl(String software, String version) throws MalformedPackageURLException { -List parts = Splitter.on('.').splitToList(software); + List parts = Splitter.on('.').splitToList(software); - if (parts.length == 0) { + if (parts.size() == 0) { return this.getPurl(software, version, null, null); } - if (parts.length == 1) { - return this.getPurl(parts[0], version, null, null); + if (parts.size() == 1) { + return this.getPurl(parts.get(0), version, null, null); } else { - return this.getPurl(parts[0], version, parts[1], null); + return this.getPurl(parts.get(0), version, parts.get(1), null); } } @@ -166,7 +167,7 @@ public PackageURL getPurl(String software, String version, String arch, String d qualifiers.put("distro", distro); } return new PackageURL( - PackageURL.StandardTypes.RPM, purlNamespace.toLowerCase(), software, version, qualifiers, null); + PackageURL.StandardTypes.RPM, purlNamespace, software, version, qualifiers, null); } diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java index dbe8b62..44cb062 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java @@ -91,6 +91,12 @@ public List buildExternalReferences(Map detai bugs.setType(ExternalReference.Type.ISSUE_TRACKER); refs.add(bugs); } + if (detailMap.containsKey("Download-Url")){ + ExternalReference docs = new ExternalReference(); + docs.setUrl(detailMap.get("Download-Url")); + docs.setType(ExternalReference.Type.DISTRIBUTION); + refs.add(docs); + } return refs; } diff --git a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java index fabb2d3..2bf8c94 100644 --- a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java +++ b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGeneratorTest.java @@ -119,7 +119,7 @@ void getPurlTest() TestUtils.logTestStart(methodName, watcher.getLogger()); String expectedUrl = "https://rhui3.us-west-2.aws.ce.redhat.com/pulp/repos/content/dist/rhel/rhui/server/7/7Server/x86_64/os/Packages/z/zip-3.0-11.el7.x86_64.rpm"; - String expected = "pkg:rpm/rhel/zip@3.0-11.el7?arch=x64_86"; + String expected = "pkg:rpm/zip@3.0-11.el7?arch=x64_86"; AutoCloseable openMocks = null; From 5be1a1fef1e950cd8541a9b7a1e5345ccf708b81 Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sun, 4 Sep 2022 13:49:57 -0700 Subject: [PATCH 09/13] set CPE of master OS component Signed-off-by: djcrabhat --- .../unix/sbom/generator/SBomGenerator.java | 3 + .../unix/sbom/utils/OperatingSystemUtils.java | 27 ++++++- .../sbom/utils/OperatingSystemUtilsTest.java | 70 +++++++++++++++++++ 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java index c93f5f0..f83de19 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java @@ -296,6 +296,7 @@ private static Component createMasterComponent(CommandLine cli) throws SBomExcep String name = cli.getOptionValue("name"); String group = cli.getOptionValue("group"); String version = cli.getOptionValue("version"); + String cpe = cli.getOptionValue("cpe"); if ((!StringUtils.isValid(name)) || (!StringUtils.isValid(version))) { @@ -305,6 +306,8 @@ private static Component createMasterComponent(CommandLine cli) throws SBomExcep name = osUtils.getOsVendor(); if (!StringUtils.isValid(version)) version = osUtils.getOsVersion(); + if (!StringUtils.isValid(cpe)) + cpe = osUtils.getOsCpe(); } master = createMasterComponent(imageUrl, name, group, version); diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtils.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtils.java index 2272c1d..0fd98d0 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtils.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtils.java @@ -30,9 +30,9 @@ public class OperatingSystemUtils { private static final Logger logger = Logger.getLogger(OperatingSystemUtils.class.getName()); - + private static final String OS_RELEASE_FILE = "/etc/os-release"; - + private Map osMap = null; /** @@ -113,6 +113,25 @@ public String getOsVersion() return version; } + /** + * (U) This method is used to get the operating system's CPE, if it has one defined. + * + * @return String the operating system CPE. + */ + public String getOsCpe() + { + String cpe = null; + + if (osMap.containsKey("CPE_NAME")) + cpe = osMap.get("CPE_NAME"); + if (StringUtils.isValid(cpe)) + cpe = CharMatcher.is('\"').trimFrom(cpe); + + return cpe; + } + + + /** * (U) This method is used to get the operating system. From the /etc/os-release * file. @@ -133,12 +152,14 @@ public Map getOs() catch (IOException ioe) { String error = "Unable to read file(" + OS_RELEASE_FILE + ") to get the " + - "operating sytem!"; + "operating system!"; logger.error(error, ioe); throw new SBomException(error, ioe); } return detailMap; } + + /** * (U) This method is used to read the contents of the OS file. diff --git a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtilsTest.java b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtilsTest.java index acc1b5e..8385cc3 100644 --- a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtilsTest.java +++ b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/utils/OperatingSystemUtilsTest.java @@ -570,6 +570,49 @@ void testOsVersion(String file, String expectedOsVersion) } } + /** + * (U) Convenience method used to test the reading of the CPE from the + * "/etc/os-release" file. + * + * @param file String value of the contents of the + * "/etc/os-release" file. + * @param expectedCpe String value of the expected CPE. + */ + void testCpe(String file, String expectedCpe) + { + try (InputStream inputStream = OperatingSystemUtilsTest.class.getResourceAsStream(file)) + { + String osReleaseFileContents = IOUtils.toString(inputStream); + + OperatingSystemUtils osUtils = new OperatingSystemUtils(osReleaseFileContents); + + String actualCpe = osUtils.getOsCpe(); + + if (expectedCpe.equalsIgnoreCase(actualCpe)) + watcher.getLogger().debug("Got expected CPE (" + + expectedCpe + ")."); + else + watcher.getLogger().debug("Did NOT get expected CPE!\n" + + " Expected: " + expectedCpe + "\n" + + " Acutal: " + actualCpe); + + Assert.assertEquals(expectedCpe, actualCpe); + } + catch (IOException ioe) + { + String error = "Our test case failed to read the operating system " + + "etc/os-release file(" + file + ")."; + watcher.getLogger().error(error, ioe); + Assert.fail("Unable to read /etc/os-release File (" + file + "). "); + } + catch (Exception e) + { + String error = "Our test case failed unexpectedly."; + watcher.getLogger().error(error, e); + Assert.fail(error); + } + } + /** * (U) This method is used to test the parsing of the Ubuntu Os File. */ @@ -625,6 +668,33 @@ void testReadOsUbuntu() } } + /** + * (U) This method is used to test the getting of the OS name from the + * os-release file. For Redhat. + */ + @Test + void getOsCpeRedhat() + { + // @formatter:off + String methodName = new Object(){}.getClass().getEnclosingMethod().getName(); + // @formatter:on + + Date startDate = DateUtils.rightNowDate(); + + TestUtils.logTestStart(methodName, watcher.getLogger()); + + String file = "/osReleaseFiles/redhat-os-release.txt"; + String expectedCpe = "cpe:/o:redhat:enterprise_linux:8.1:GA"; + try + { + testCpe(file, expectedCpe); + } + finally + { + TestUtils.logTestFinish(methodName, startDate, watcher.getLogger()); + } + } + private Map readOs(String content) { Map detailMap = new HashMap<>(); From f18951a65b61ed9cfc64ba5149c60c60e55de46b Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sun, 4 Sep 2022 14:09:02 -0700 Subject: [PATCH 10/13] carve out cpe Signed-off-by: djcrabhat --- .../sbom/generator/AlpineSBomGenerator.java | 2 +- .../sbom/generator/RedHatSBomGenerator.java | 9 ++++++++- .../unix/sbom/generator/SBomGenerator.java | 18 ++++++++++++------ .../sbom/generator/UbuntuSBomGenerator.java | 2 +- .../unix/sbom/generator/UnixSBomGenerator.java | 6 +++++- .../sbom/generator/UnixSBomGeneratorTest.java | 2 +- 6 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/AlpineSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/AlpineSBomGenerator.java index ac375f8..47c1168 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/AlpineSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/AlpineSBomGenerator.java @@ -66,7 +66,7 @@ public Bom generateSBom() detailMap = produceDetailMap(software); version = getVersion(software); component = createComponents(software, detailMap, null, null, - version, null, null); + version, null, null, null); bom.addComponent(addPackageManager(component, PACKAGE_MANAGER)); } return bom; diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index cc88292..ee64346 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -79,6 +79,7 @@ public Bom generateSBom() { LicenseChoice license = null; PackageURL purl = null; Component component = null; + String cpe = null; for (String software : softwareList) { if (logger.isDebugEnabled()) logger.debug("Generating Component (" + software + ")"); @@ -94,6 +95,7 @@ public Bom generateSBom() { } catch (MalformedPackageURLException e) { logger.debug("Can't get purl", e); } + cpe = getCpe(software, version); try { String downloadUrl = getPackageDownloadUrl(software); @@ -104,12 +106,17 @@ public Bom generateSBom() { logger.debug("Error getting Download-Url", e); } component = createComponents(software, detailMap, license, group, - version, purl, detailMap.get("Priority")); + version, purl, detailMap.get("Priority"), cpe); bom.addComponent(addPackageManager(component, PACKAGE_MANAGER)); } return bom; } + private String getCpe(String software, String version) { + // TODO + return null; + } + /** * (U) This method is used to attempt to figure out which file is the license file. If any. * diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java index f83de19..ec35061 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/SBomGenerator.java @@ -145,13 +145,13 @@ public static void createBomFile(Bom bom, SBomCommons.AVAILABLE_FORMATS format) * imageUrl provided. */ public static Component createMasterComponent(String imageUrl, String name, - String group, String version) throws SBomException + String group, String version, String cpe) throws SBomException { Component master = null; if ((StringUtils.isValid(imageUrl)) || (StringUtils.isValid(name) && ((StringUtils.isValid(version))))) { - master = createMasterComponent(imageUrl); + master = createMasterComponent(imageUrl,name,group,version, imageUrl ,cpe); if (StringUtils.isValid(imageUrl)) { @@ -175,8 +175,9 @@ public static Component createMasterComponent(String imageUrl, String name, } }else{ master.setType(Component.Type.OPERATING_SYSTEM); - // TODO: should we set the CPE reported by hostnamectl here? - //master.setCpe(); + if(StringUtils.isValid(cpe)){ + master.setCpe(cpe); + } } if (StringUtils.isValid(name)) master.setName(name.toLowerCase()); @@ -310,7 +311,7 @@ private static Component createMasterComponent(CommandLine cli) throws SBomExcep cpe = osUtils.getOsCpe(); } - master = createMasterComponent(imageUrl, name, group, version); + master = createMasterComponent(imageUrl, name, group, version, cpe); return master; } @@ -319,12 +320,17 @@ private static Component createMasterComponent(CommandLine cli) throws SBomExcep * (U) This method is used to create the master component. It will then fill in * the image information (if provided). * + * + * @param url + * @param name + * @param group + * @param version * @param imageUrl String value of where to get the docker image from. * @return Component created, and filled in if the imageUrl is provided. * @throws SBomException in the event we are unable to pull the image via the * image URL provided. */ - private static Component createMasterComponent(String imageUrl) throws SBomException + private static Component createMasterComponent(String url, String name, String group, String version, String imageUrl, String cpe) throws SBomException { Component master = new Component(); master.setType(org.cyclonedx.model.Component.Type.CONTAINER); diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UbuntuSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UbuntuSBomGenerator.java index ba935ae..373db80 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UbuntuSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UbuntuSBomGenerator.java @@ -71,7 +71,7 @@ public Bom generateSBom() group = detailMap.get("Release"); license = processLicense(software); component = createComponents(software, detailMap, license, group, - version, null, detailMap.get("Priority")); + version, null, detailMap.get("Priority"), null); bom.addComponent(addPackageManager(component, PACKAGE_MANAGER)); } diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java index 44cb062..b6434ab 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGenerator.java @@ -129,10 +129,11 @@ else if (priority.equalsIgnoreCase("optional")) * @param version String value to set the version to. * @param purl String to set the URL used to pull the software from. * @param scope String value to help us set the scope of the software. + * @param cpe String value for cpe, if relevant * @return Component Sbom Component created from the supplied inputs. */ public Component createComponents(String software, Map detailMap, - LicenseChoice license, String group, String version, PackageURL purl, String scope) + LicenseChoice license, String group, String version, PackageURL purl, String scope, String cpe) { Component component = new Component(); component.setType(Type.OPERATING_SYSTEM); @@ -146,6 +147,9 @@ public Component createComponents(String software, Map detailMap if(purl!=null) { component.setPurl(purl); } + if(cpe!=null){ + component.setCpe(cpe); + } component.setScope(buildScope(scope)); component.setVersion(version); diff --git a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGeneratorTest.java b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGeneratorTest.java index 73a0914..09688d1 100644 --- a/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGeneratorTest.java +++ b/src/test/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/UnixSBomGeneratorTest.java @@ -137,7 +137,7 @@ void createComponentsTest() String version = detailMap.get("Version"); String group = detailMap.get("Release"); Component component = generator.createComponents("zip", - detailMap, null, group, version, null, detailMap.get("Priority")); + detailMap, null, group, version, null, detailMap.get("Priority"), null); String actualComponentName = component.getName(); String actualComponentVerison = component.getVersion(); From 66158ba98aaf92a6e6a025d7199c33e9535ea232 Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sun, 4 Sep 2022 14:56:53 -0700 Subject: [PATCH 11/13] add cpe for redhat packages Signed-off-by: djcrabhat --- .../efoss/unix/sbom/generator/RedHatSBomGenerator.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index ee64346..397b4d8 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -95,7 +95,7 @@ public Bom generateSBom() { } catch (MalformedPackageURLException e) { logger.debug("Can't get purl", e); } - cpe = getCpe(software, version); + cpe = getCpe(detailMap.get("Name"), version); try { String downloadUrl = getPackageDownloadUrl(software); @@ -112,9 +112,8 @@ public Bom generateSBom() { return bom; } - private String getCpe(String software, String version) { - // TODO - return null; + private String getCpe(String pack, String version) { + return String.format("cpe:2.3:a:%s:%s:%s:*:*:*:*:*:*:*", pack, pack, version); } /** From d9a651b5c337ae3f95da7768266809b08748fee3 Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sun, 4 Sep 2022 15:32:48 -0700 Subject: [PATCH 12/13] * vendor Signed-off-by: djcrabhat --- .../com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index 397b4d8..296ccb9 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -113,7 +113,7 @@ public Bom generateSBom() { } private String getCpe(String pack, String version) { - return String.format("cpe:2.3:a:%s:%s:%s:*:*:*:*:*:*:*", pack, pack, version); + return String.format("cpe:2.3:a:*:%s:%s:*:*:*:*:*:*:*", pack, version); } /** From 15970d1327a569b83ef0e424dca354b41a361956 Mon Sep 17 00:00:00 2001 From: djcrabhat Date: Sun, 4 Sep 2022 17:10:20 -0700 Subject: [PATCH 13/13] go back to repeating package name Signed-off-by: djcrabhat --- .../com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java index 296ccb9..397b4d8 100644 --- a/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java +++ b/src/main/java/org/cyclonedx/contrib/com/lmco/efoss/unix/sbom/generator/RedHatSBomGenerator.java @@ -113,7 +113,7 @@ public Bom generateSBom() { } private String getCpe(String pack, String version) { - return String.format("cpe:2.3:a:*:%s:%s:*:*:*:*:*:*:*", pack, version); + return String.format("cpe:2.3:a:%s:%s:%s:*:*:*:*:*:*:*", pack, pack, version); } /**