anchore / syft

CLI tool and library for generating a Software Bill of Materials from container images and filesystems
Apache License 2.0
6.01k stars 553 forks source link

Show richer information for JVM installations #1426

Open witchcraze opened 1 year ago

witchcraze commented 1 year ago

What would you like to be added:

This it proposal to add provider information. In this time, I'll write about OpenJDKas sample. I think there will be similar situation in other product.

Why is this needed:

There are many OpenJDK distributions. Each distributions have their own lifecycle or support policy (EOL). In addition, some distribution seems to start registering their CPE in NVD DB. So, distribution (provider) information is required to match vulns and check EOL.

EOL

NVD

cpe:2.3:a:azul:zulu is registered sepalately with different version. https://nvd.nist.gov/vuln/detail/CVE-2022-21549

Additional context:

Maybe, IMPLEMENTOR in release is good to be used in this case. But path and directory is not unified...

eclipse-temurin:17

$ docker run -it --rm eclipse-temurin:17 strings /opt/java/openjdk/release
IMPLEMENTOR="Eclipse Adoptium"
IMPLEMENTOR_VERSION="Temurin-17.0.5+8"
JAVA_VERSION="17.0.5"
JAVA_VERSION_DATE="2022-10-18"
LIBC="gnu"
MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.incubator.vector jdk.internal.le jdk.internal.opt jdk.internal.vm.ci jdk.internal.vm.compiler jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.random jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Linux"
SOURCE=".:git:46f9a382b49f"
BUILD_SOURCE="git:ce8eca7591182a7d05adf1a25d7feac1059c1ef2"
BUILD_SOURCE_REPO="https://github.com/adoptium/temurin-build.git"
SOURCE_REPO="https://github.com/adoptium/jdk17u.git"
FULL_VERSION="17.0.5+8"
SEMANTIC_VERSION="17.0.5+8"
BUILD_INFO="OS: Linux Version: 5.8.0-43-generic"
JVM_VARIANT="Hotspot"
JVM_VERSION="17.0.5+8"
IMAGE_TYPE="JDK"

amazoncorretto:17

# strings /usr/lib/jvm/java-17-amazon-corretto/release
IMPLEMENTOR="Amazon.com Inc."
IMPLEMENTOR_VERSION="Corretto-17.0.5.8.1"
JAVA_VERSION="17.0.5"
JAVA_VERSION_DATE="2022-10-18"
LIBC="gnu"
MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.incubator.vector jdk.internal.le jdk.internal.opt jdk.internal.vm.ci jdk.internal.vm.compiler jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.random jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Linux"
SOURCE=".:git:ca7b4a5ebc4e+"

azul/zulu-openjdk:17

# strings /usr/lib/jvm/zulu17-ca-amd64/release
IMPLEMENTOR="Azul Systems, Inc."
IMPLEMENTOR_VERSION="Zulu17.38+21-CA"
JAVA_VERSION="17.0.5"
JAVA_VERSION_DATE="2022-10-18"
LIBC="gnu"
MODULES="java.base com.azul.tooling java.management java.logging java.security.sasl java.naming jdk.jfr com.azul.crs.client java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.incubator.vector jdk.internal.le jdk.internal.opt jdk.internal.vm.ci jdk.internal.vm.compiler jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.random jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Linux"
SOURCE=".:git:13335e8ddc18"

mcr.microsoft.com/openjdk/jdk:17-ubuntu

# strings /usr/lib/jvm/msopenjdk-17-amd64/release
IMPLEMENTOR="Microsoft"
IMPLEMENTOR_VERSION="Microsoft-6841604"
JAVA_VERSION="17.0.5"
JAVA_VERSION_DATE="2022-10-18"
LIBC="gnu"
MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.incubator.vector jdk.internal.le jdk.internal.opt jdk.internal.vm.ci jdk.internal.vm.compiler jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.random jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Linux"
SOURCE=".:git:1c12d059433f"

sapmachine:17

# strings /usr/lib/jvm/sapmachine-17/release
IMPLEMENTOR="SAP SE"
IMPLEMENTOR_VERSION="SapMachine"
JAVA_VERSION="17.0.5"
JAVA_VERSION_DATE="2022-10-18"
LIBC="gnu"
MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.incubator.vector jdk.internal.le jdk.internal.opt jdk.internal.vm.ci jdk.internal.vm.compiler jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.random jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Linux"
SOURCE=".:git:0ab78754c21d"

redhat/ubi8 + java-17-openjdk package

# strings /usr/lib/jvm/java-17-openjdk-17.0.5.0.8-2.el8_6.x86_64/release
IMPLEMENTOR="Red Hat, Inc."
IMPLEMENTOR_VERSION="(Red_Hat-17.0.5.0.8-2.el8_6)"
JAVA_VERSION="17.0.5"
JAVA_VERSION_DATE="2022-10-18"
LIBC="gnu"
MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.incubator.vector jdk.internal.le jdk.internal.opt jdk.internal.vm.ci jdk.internal.vm.compiler jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.random jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Linux"
SOURCE=".:git:0a6252780a86+"
kzantow commented 1 year ago

How do you expect to see this information in the SBOM? There aren't places in all SBOM formats (including Syft) to currently capture this information. Could you outline the most important bits? Is this something that should make Java binaries have different CPEs/PURLs?

witchcraze commented 1 year ago

Thank you for your confirmation and sorry for the confusion.

There aren't places in all SBOM formats (including Syft) to currently capture this information.

OK

Could you outline the most important bits? Is this something that should make Java binaries have different CPEs/PURLs?

Sorry, I do not have elegant good idea.

I think eclipse-temurin is good sample. Only binary is detected.

$ syft -q eclipse-temurin:17 | grep -e jdk -e temurin -e binary
java                       17.0.5+8                                 binary

Syft will use cpe:2.3:a:oracle:openjdk and cpe:2.3:a:java:java now.

To match NVD data, cpe:2.3:a:oracle:openjdk will be good, even if this is not oracle's package.

// To focus matching NVD data, using cpe:2.3:a:oracle:jdk may be better. // Sometimes, cpe:2.3:a:oracle:openjdk is registered // https://nvd.nist.gov/vuln/detail/CVE-2022-21541 https://mail.openjdk.org/pipermail/jdk-updates-dev/2022-July/016016.html // Sometimes cpe:2.3:a:oracle:openjdk is not registered // https://nvd.nist.gov/vuln/detail/CVE-2022-21449 https://mail.openjdk.org/pipermail/vuln-announce/2022-April/000015.html

To know EOL, add vendor's CPE like cpe:2.3:a:azul:zulu will be good. But most OpenJDK distributions did not register their CPE in NVD side, I think. Creating original CPE to identify prvider is permitted ? If so, how about to add cpe:2.3:a:eclipse:temurin cpe:2.3:a:microsoft:openjdk cpe:2.3:a:Amazon:corretto ?

$ syft -q eclipse-temurin:17 -o json | jq '.artifacts[] | select(.name == "java")'
{
  "id": "2b7197d1290fa5cc",
  "name": "java",
  "version": "17.0.5+8",
  "type": "binary",
  "foundBy": "binary-cataloger",
  "locations": [
    {
      "path": "/opt/java/openjdk/bin/java",
      "layerID": "sha256:cd7884686c9fc94d950cd066744c73da12badfbf6643f8cf9a95a23dd5c28194"
    }
  ],
  "licenses": [],
  "language": "binary",
  "cpes": [
    "cpe:2.3:a:oracle:openjdk:17.0.5\\+8:*:*:*:*:*:*:*",
    "cpe:2.3:a:java:java:17.0.5\\+8:*:*:*:*:*:*:*"
  ],
  "purl": "",
  "metadataType": "BinaryMetadata",
  "metadata": {
    "classifier": "java-binary-openjdk",
    "realPath": "/opt/java/openjdk/bin/java",
    "virtualPath": "/opt/java/openjdk/bin/java"
  }
}
$ syft -q eclipse-temurin:17 -o cyclonedxjson | jq '.components[] | select(.name == "java")'
{
  "bom-ref": "2b7197d1290fa5cc",
  "type": "application",
  "name": "java",
  "version": "17.0.5+8",
  "cpe": "cpe:2.3:a:oracle:openjdk:17.0.5\\+8:*:*:*:*:*:*:*",
  "properties": [
    {
      "name": "syft:package:foundBy",
      "value": "binary-cataloger"
    },
    {
      "name": "syft:package:language",
      "value": "binary"
    },
    {
      "name": "syft:package:metadataType",
      "value": "BinaryMetadata"
    },
    {
      "name": "syft:package:type",
      "value": "binary"
    },
    {
      "name": "syft:cpe23",
      "value": "cpe:2.3:a:java:java:17.0.5\\+8:*:*:*:*:*:*:*"
    },
    {
      "name": "syft:location:0:layerID",
      "value": "sha256:cd7884686c9fc94d950cd066744c73da12badfbf6643f8cf9a95a23dd5c28194"
    },
    {
      "name": "syft:location:0:path",
      "value": "/opt/java/openjdk/bin/java"
    }
  ]
}
$ syft -q eclipse-temurin:17 -o spdxjson | jq '.packages[] | select(.name == "java")'
{
  "name": "java",
  "SPDXID": "SPDXRef-Package-binary-java-2b7197d1290fa5cc",
  "versionInfo": "17.0.5+8",
  "downloadLocation": "NOASSERTION",
  "sourceInfo": "acquired package info from the following paths: /opt/java/openjdk/bin/java",
  "licenseConcluded": "NONE",
  "licenseDeclared": "NONE",
  "copyrightText": "NOASSERTION",
  "externalRefs": [
    {
      "referenceCategory": "SECURITY",
      "referenceType": "cpe23Type",
      "referenceLocator": "cpe:2.3:a:oracle:openjdk:17.0.5\\+8:*:*:*:*:*:*:*",
      "comment": ""
    },
    {
      "referenceCategory": "SECURITY",
      "referenceType": "cpe23Type",
      "referenceLocator": "cpe:2.3:a:java:java:17.0.5\\+8:*:*:*:*:*:*:*",
      "comment": ""
    }
  ]
}
wagoodman commented 1 year ago

I think this is a great idea! One question we should answer is if there is a consistent way to correlate the binary and the release file. At a first glance the answer seems to be "yes", but that would be something we should be certain on.

Another question that needs to get answered at the implementation level is where does this arbitrary information land once its extracted by the cataloger? It also needs to structured enough to be able to influence the CPE generation logic.

(side note: we've been wanting/needing to push CPE generation logic back to the cataloger packages instead of a centralized package... this would be easier for these kinds of tailorings)

witchcraze commented 1 year ago

Thank you for your confirmation.

if there is a consistent way to correlate the binary and the release file

release file seems in upper directly from java in recent versions.

$ docker run -it --rm eclipse-temurin:17 ls /opt/java/openjdk/{bin/java,release}
/opt/java/openjdk/bin/java  /opt/java/openjdk/release

$ docker run -it --rm amazoncorretto:17 ls /usr/lib/jvm/java-17-amazon-corretto/{bin/java,release}
/usr/lib/jvm/java-17-amazon-corretto/bin/java
/usr/lib/jvm/java-17-amazon-corretto/release

$ docker run -it --rm azul/zulu-openjdk:17 ls /usr/lib/jvm/zulu17-ca-amd64/{bin/java,release}
/usr/lib/jvm/zulu17-ca-amd64/bin/java  /usr/lib/jvm/zulu17-ca-amd64/release

$ docker run -it --rm mcr.microsoft.com/openjdk/jdk:17-ubuntu ls /usr/lib/jvm/msopenjdk-17-amd64/{bin/java,release}
/usr/lib/jvm/msopenjdk-17-amd64/bin/java
/usr/lib/jvm/msopenjdk-17-amd64/release

$ docker run -it --rm sapmachine:17 ls /usr/lib/jvm/sapmachine-17/{bin/java,release}
/usr/lib/jvm/sapmachine-17/bin/java  /usr/lib/jvm/sapmachine-17/release

But amazoncorretto:8 do not have release file there

$ docker run -it --rm amazoncorretto:8 ls /usr/lib/jvm/java-1.8.0-amazon-corretto/{bin/java,release}
ls: cannot access /usr/lib/jvm/java-1.8.0-amazon-corretto/release: No such file or directory
/usr/lib/jvm/java-1.8.0-amazon-corretto/bin/java

$ docker run -it --rm amazoncorretto:8-alpine ls /usr/lib/jvm/java-8-amazon-corretto/{bin/java,release}
ls: /usr/lib/jvm/java-8-amazon-corretto/release: No such file or directory
/usr/lib/jvm/java-8-amazon-corretto/bin/java

where does this arbitrary information land

I wrote creating original CPE idea above, but adding new item - {IMPLEMENTOR, PROVIDOR or MENTAINER} in metadata of BinaryMetadata may be better I think now. Other products can use that item by binary detection, and only syft user who checkes binary metadata is impacted.

Anyway, this information will not be used widely. (maybe useful for only me ...)