Alex Goodman 1230650771
allow for java manifest data to be optional
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
2020-10-29 11:28:27 -04:00

96 lines
3.3 KiB
Python

import os
import json
import collections
import utils.package
import utils.image
from utils.traverse import dig
class Syft:
"""
Class for parsing syft output into a set of packages and package metadata.
"""
report_tmpl = "{image}.json"
def __init__(self, image, report_dir):
self.report_path = os.path.join(
report_dir, self.report_tmpl.format(image=utils.image.clean(image))
)
def _enumerate_section(self, section):
with open(self.report_path) as json_file:
data = json.load(json_file)
for entry in data[section]:
yield entry
def packages(self):
packages = set()
metadata = collections.defaultdict(dict)
for entry in self._enumerate_section(section="artifacts"):
extra = {}
# normalize to inline
pkg_type = entry["type"].lower()
if pkg_type in ("wheel", "egg", "python"):
pkg_type = "python"
elif pkg_type in ("deb",):
pkg_type = "dpkg"
elif pkg_type in ("java-archive",):
# normalize to pseudo-inline
pkg_type = "java-?ar"
elif pkg_type in ("jenkins-plugin",):
# normalize to pseudo-inline
pkg_type = "java-?pi"
elif pkg_type in ("apk",):
pkg_type = "apkg"
pkg = utils.package.Package(
name=entry["name"],
type=pkg_type,
)
packages.add(pkg)
if "java" in pkg_type:
# lets match what inline scan expects to output
path = dig(entry, "locations", 0, "path")
specVendor = dig(entry, "metadata", "manifest", "specificationVendor")
implVendor = dig(entry, "metadata", "manifest", "implementationVendor")
specVersion = dig(entry, "metadata", "manifest", "specificationVersion") or None
implVersion = dig(entry, "metadata", "manifest", "implementationVersion") or None
extra = {
"implementation-version": implVersion,
"specification-version": specVersion,
"origin": dig(entry, "metadata", "pomProperties", "groupId"),
"location": path,
"package": dig(entry, "metadata", "pomProperties", "artifactId"),
}
if dig(entry, "metadata", "parentPackage"):
extra['origin'] = dig(entry, "metadata", "pomProperties", "groupId")
else:
# this is a nested package...
if specVendor:
extra['origin'] = specVendor
elif implVendor:
extra['origin'] = implVendor
pomPath = dig(entry, "metadata", "pomProperties", "Path")
if path and pomPath:
extra["location"] = "%s:%s" % (path, pomPath),
# temp temp temp
extra.pop("location")
elif pkg_type == "apkg":
entry["version"] = entry["version"].split("-")[0]
metadata[pkg.type][pkg] = utils.package.Metadata(version=entry["version"], extra=tuple(sorted(extra.items())))
return utils.package.Info(packages=frozenset(packages), metadata=metadata)