mirror of
https://github.com/anchore/syft.git
synced 2025-11-18 00:43:20 +01:00
* Adds java and npm package comparison * Adds probable matching of extra packages syft found and missing packages that syft did not find (but inline did). This way there is a section of output that fuzzy-matches the package names to get a better sense of "real" problems (actual missing packages) vs slightly mismatched metadata during troubleshooting. * Adds a set or probable missing packages to the report based on the probable matches (again, to aid in troubleshooting) * Fixes image reference clean function to support references with registries * Only shows metadata differences when the package was found by both inline and syft * Splits the inline-compare code into more manageable pieces Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
132 lines
4.4 KiB
Python
132 lines
4.4 KiB
Python
import os
|
|
import json
|
|
import collections
|
|
|
|
import utils.package
|
|
import utils.image
|
|
|
|
|
|
class InlineScan:
|
|
"""
|
|
Class for parsing inlnie-scan output files into a set of packages and package metadata.
|
|
"""
|
|
report_tmpl = "{image}-{report}.json"
|
|
|
|
def __init__(self, image, report_dir):
|
|
self.report_dir = report_dir
|
|
self.image = image
|
|
|
|
def packages(self):
|
|
python_packages, python_metadata = self._python_packages()
|
|
gem_packages, gem_metadata = self._gem_packages()
|
|
java_packages, java_metadata = self._java_packages()
|
|
npm_packages, npm_metadata = self._npm_packages()
|
|
os_packages, os_metadata = self._os_packages()
|
|
|
|
packages = (
|
|
python_packages | os_packages | gem_packages | java_packages | npm_packages
|
|
)
|
|
metadata = {
|
|
**python_metadata,
|
|
**os_metadata,
|
|
**gem_metadata,
|
|
**java_metadata,
|
|
**npm_metadata,
|
|
}
|
|
|
|
return utils.package.Info(packages=frozenset(packages), metadata=metadata)
|
|
|
|
def _report_path(self, report):
|
|
return os.path.join(
|
|
self.report_dir,
|
|
self.report_tmpl.format(image=utils.image.clean(self.image), report=report),
|
|
)
|
|
|
|
def _enumerate_section(self, report, section):
|
|
report_path = self._report_path(report=report)
|
|
os_report_path = self._report_path(report="content-os")
|
|
|
|
if os.path.exists(os_report_path) and not os.path.exists(report_path):
|
|
# if the OS report is there but the target report is not, that is engine's way of saying "no findings"
|
|
return
|
|
|
|
with open(report_path) as json_file:
|
|
data = json.load(json_file)
|
|
for entry in data[section]:
|
|
yield entry
|
|
|
|
def _java_packages(self):
|
|
packages = set()
|
|
metadata = collections.defaultdict(dict)
|
|
for entry in self._enumerate_section(report="content-java", section="content"):
|
|
# normalize to pseudo-inline
|
|
pkg_type = entry["type"].lower()
|
|
if pkg_type in ("java-jar", "java-war", "java-ear"):
|
|
pkg_type = "java-?ar"
|
|
elif pkg_type in ("java-jpi", "java-hpi"):
|
|
pkg_type = "java-?pi"
|
|
|
|
pkg = utils.package.Package(
|
|
name=entry["package"],
|
|
type=pkg_type,
|
|
)
|
|
packages.add(pkg)
|
|
metadata[pkg.type][pkg] = utils.package.Metadata(
|
|
version=entry["maven-version"]
|
|
)
|
|
|
|
return packages, metadata
|
|
|
|
def _npm_packages(self):
|
|
packages = set()
|
|
metadata = collections.defaultdict(dict)
|
|
for entry in self._enumerate_section(report="content-npm", section="content"):
|
|
pkg = utils.package.Package(
|
|
name=entry["package"],
|
|
type=entry["type"].lower(),
|
|
)
|
|
packages.add(pkg)
|
|
metadata[pkg.type][pkg] = utils.package.Metadata(version=entry["version"])
|
|
|
|
return packages, metadata
|
|
|
|
def _python_packages(self):
|
|
packages = set()
|
|
metadata = collections.defaultdict(dict)
|
|
for entry in self._enumerate_section(
|
|
report="content-python", section="content"
|
|
):
|
|
pkg = utils.package.Package(
|
|
name=entry["package"],
|
|
type=entry["type"].lower(),
|
|
)
|
|
packages.add(pkg)
|
|
metadata[pkg.type][pkg] = utils.package.Metadata(version=entry["version"])
|
|
|
|
return packages, metadata
|
|
|
|
def _gem_packages(self):
|
|
packages = set()
|
|
metadata = collections.defaultdict(dict)
|
|
for entry in self._enumerate_section(report="content-gem", section="content"):
|
|
pkg = utils.package.Package(
|
|
name=entry["package"],
|
|
type=entry["type"].lower(),
|
|
)
|
|
packages.add(pkg)
|
|
metadata[pkg.type][pkg] = utils.package.Metadata(version=entry["version"])
|
|
|
|
return packages, metadata
|
|
|
|
def _os_packages(self):
|
|
packages = set()
|
|
metadata = collections.defaultdict(dict)
|
|
for entry in self._enumerate_section(report="content-os", section="content"):
|
|
pkg = utils.package.Package(
|
|
name=entry["package"], type=entry["type"].lower()
|
|
)
|
|
packages.add(pkg)
|
|
metadata[pkg.type][pkg] = utils.package.Metadata(version=entry["version"])
|
|
|
|
return packages, metadata
|