CycloneDX eric7

Sat, 04 Jun 2022 16:57:02 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 04 Jun 2022 16:57:02 +0200
branch
eric7
changeset 9122
ddf8ed8f7387
parent 9121
6ac528d4f318
child 9123
aefb731a4b4e

CycloneDX
- added capability to list dependencies in the SBOM file

eric7/CycloneDXInterface/CycloneDXConfigDialog.py file | annotate | diff | comparison | revisions
eric7/CycloneDXInterface/CycloneDXConfigDialog.ui file | annotate | diff | comparison | revisions
eric7/CycloneDXInterface/CycloneDXUtilities.py file | annotate | diff | comparison | revisions
--- a/eric7/CycloneDXInterface/CycloneDXConfigDialog.py	Sat Jun 04 16:56:22 2022 +0200
+++ b/eric7/CycloneDXInterface/CycloneDXConfigDialog.py	Sat Jun 04 16:57:02 2022 +0200
@@ -141,8 +141,9 @@
         
         @return tuple containing the input source, the input file name, the
             file format, the schema version, the path of the SBOM file to be
-            written and a flag indicating to include vulnerability information
-        @rtype tuple of (str, str, str, str, str, bool)
+            written, a flag indicating to include vulnerability information
+            and a flag indicating to include dependency information
+        @rtype tuple of (str, str, str, str, str, bool, bool)
         """
         if self.environmentButton.isChecked():
             inputSource = "environment"
@@ -186,4 +187,5 @@
         return (
             inputSource, inputFile, fileFormat, schemaVersion, sbomFile,
             self.vulnerabilityCheckBox.isChecked(),
+            self.dependenciesCheckBox.isChecked(),
         )
--- a/eric7/CycloneDXInterface/CycloneDXConfigDialog.ui	Sat Jun 04 16:56:22 2022 +0200
+++ b/eric7/CycloneDXInterface/CycloneDXConfigDialog.ui	Sat Jun 04 16:57:02 2022 +0200
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>650</width>
-    <height>308</height>
+    <height>338</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -99,21 +99,41 @@
       <string>SBOM Output</string>
      </property>
      <layout class="QGridLayout" name="gridLayout">
-      <item row="1" column="0">
-       <widget class="QLabel" name="label_2">
-        <property name="text">
-         <string>File Format:</string>
-        </property>
-       </widget>
-      </item>
-      <item row="2" column="0">
+      <item row="3" column="0">
        <widget class="QLabel" name="label_3">
         <property name="text">
          <string>Schema Version:</string>
         </property>
        </widget>
       </item>
-      <item row="1" column="1">
+      <item row="4" column="0">
+       <widget class="QLabel" name="label_4">
+        <property name="text">
+         <string>File Name:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <widget class="QComboBox" name="schemaVersionComboBox">
+        <property name="toolTip">
+         <string>Select the SBOM schema version of the SBOM file</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="2">
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>413</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="2" column="1">
        <widget class="QComboBox" name="fileFormatComboBox">
         <property name="toolTip">
          <string>Select the format of the SBOM file</string>
@@ -130,27 +150,14 @@
         </item>
        </widget>
       </item>
-      <item row="3" column="0">
-       <widget class="QLabel" name="label_4">
+      <item row="2" column="0">
+       <widget class="QLabel" name="label_2">
         <property name="text">
-         <string>File Name:</string>
+         <string>File Format:</string>
         </property>
        </widget>
       </item>
-      <item row="1" column="2">
-       <spacer name="horizontalSpacer">
-        <property name="orientation">
-         <enum>Qt::Horizontal</enum>
-        </property>
-        <property name="sizeHint" stdset="0">
-         <size>
-          <width>413</width>
-          <height>20</height>
-         </size>
-        </property>
-       </spacer>
-      </item>
-      <item row="3" column="1" colspan="2">
+      <item row="4" column="1" colspan="2">
        <widget class="EricPathPicker" name="filePicker" native="true">
         <property name="focusPolicy">
          <enum>Qt::StrongFocus</enum>
@@ -160,13 +167,6 @@
         </property>
        </widget>
       </item>
-      <item row="2" column="1">
-       <widget class="QComboBox" name="schemaVersionComboBox">
-        <property name="toolTip">
-         <string>Select the SBOM schema version of the SBOM file</string>
-        </property>
-       </widget>
-      </item>
       <item row="0" column="0" colspan="3">
        <widget class="QCheckBox" name="vulnerabilityCheckBox">
         <property name="toolTip">
@@ -180,6 +180,19 @@
         </property>
        </widget>
       </item>
+      <item row="1" column="0" colspan="3">
+       <widget class="QCheckBox" name="dependenciesCheckBox">
+        <property name="toolTip">
+         <string>Select to include dependency information in the generated SBOM</string>
+        </property>
+        <property name="text">
+         <string>Include Dependencies</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>
@@ -209,6 +222,7 @@
   <tabstop>poetryButton</tabstop>
   <tabstop>requirementsButton</tabstop>
   <tabstop>vulnerabilityCheckBox</tabstop>
+  <tabstop>dependenciesCheckBox</tabstop>
   <tabstop>fileFormatComboBox</tabstop>
   <tabstop>schemaVersionComboBox</tabstop>
   <tabstop>filePicker</tabstop>
--- a/eric7/CycloneDXInterface/CycloneDXUtilities.py	Sat Jun 04 16:56:22 2022 +0200
+++ b/eric7/CycloneDXInterface/CycloneDXUtilities.py	Sat Jun 04 16:57:02 2022 +0200
@@ -82,7 +82,7 @@
     dlg = CycloneDXConfigDialog(venvName)
     if dlg.exec() == QDialog.DialogCode.Accepted:
         (inputSource, inputFile, fileFormat, schemaVersion, sbomFile,
-         withVulnerabilities) = dlg.getData()
+         withVulnerabilities, withDependencies) = dlg.getData()
         
         # check error conditions first
         if inputSource not in ("environment", "pipenv", "poetry",
@@ -118,6 +118,9 @@
         if withVulnerabilities:
             addCycloneDXVulnerabilities(parser)
         
+        if withDependencies:
+            addCycloneDXDependencies(parser, venvName)
+        
         if fileFormat == "XML":
             outputFormat = OutputFormat.XML
         elif fileFormat == "JSON":
@@ -191,6 +194,46 @@
                     ))
 
 
+def addCycloneDXDependencies(parser, venvName):
+    """
+    Function to add dependency data to the list of created components.
+    
+    @param parser reference to the parser object containing the list of
+        components
+    @type BaseParser
+    @param venvName name of the virtual environment
+    @type str
+    """
+    components = parser.get_components()
+    
+    pip = ericApp().getObject("Pip")
+    dependencies = pip.getDependencyTree(venvName)
+    for dependency in dependencies:
+        _addCycloneDXDependency(dependency, components)
+
+
+def _addCycloneDXDependency(dependency, components):
+    """
+    Function to add a dependency to the given list of components.
+    
+    @param dependency dependency to be added
+    @type dict
+    @param components list of components
+    @type list of Component
+    """
+    component = findCyccloneDXComponent(components, dependency["package_name"])
+    if component is not None:
+        bomRefs = component.dependencies
+        for dep in dependency["dependencies"]:
+            depComponent = findCyccloneDXComponent(
+                components, dep["package_name"])
+            if depComponent is not None:
+                bomRefs.add(depComponent.bom_ref)
+                # recursively add sub-dependencies
+                _addCycloneDXDependency(dep, components)
+        component.dependencies = bomRefs
+
+
 def findCyccloneDXComponent(components, name):
     """
     Function to find a component in a given list of components.

eric ide

mercurial