UNPKG

snyk-docker-plugin

Version:
206 lines 8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildResponse = void 0; const dep_graph_1 = require("@snyk/dep-graph"); // Module that provides functions to collect and build response after all // analyses' are done. const dockerfile_1 = require("./dockerfile"); async function buildResponse(depsAnalysis, dockerfileAnalysis, excludeBaseImageVulns) { var _a, _b; const deps = depsAnalysis.depTree.dependencies; const dockerfilePkgs = collectDockerfilePkgs(dockerfileAnalysis, deps); const finalDeps = excludeBaseImageDeps(deps, dockerfilePkgs, excludeBaseImageVulns); /** WARNING! Mutates the depTree.dependencies! */ annotateLayerIds(finalDeps, dockerfilePkgs); /** This must be called after all final changes to the DependencyTree. */ const depGraph = await dep_graph_1.legacy.depTreeToGraph(depsAnalysis.depTree, depsAnalysis.packageManager); const additionalFacts = []; const hashes = depsAnalysis.binaries; if (hashes && hashes.length > 0) { const keyBinariesHashesFact = { type: "keyBinariesHashes", data: hashes, }; additionalFacts.push(keyBinariesHashesFact); } if (dockerfileAnalysis !== undefined) { const dockerfileAnalysisFact = { type: "dockerfileAnalysis", data: dockerfileAnalysis, }; additionalFacts.push(dockerfileAnalysisFact); } if (depsAnalysis.imageId) { const imageIdFact = { type: "imageId", data: depsAnalysis.imageId, }; additionalFacts.push(imageIdFact); } if (depsAnalysis.imageLayers && depsAnalysis.imageLayers.length > 0) { const imageLayersFact = { type: "imageLayers", data: depsAnalysis.imageLayers, }; additionalFacts.push(imageLayersFact); } if (depsAnalysis.imageLabels) { const imageLabels = { type: "imageLabels", data: depsAnalysis.imageLabels, }; additionalFacts.push(imageLabels); } if (depsAnalysis.imageCreationTime) { const imageCreationTimeFact = { type: "imageCreationTime", data: depsAnalysis.imageCreationTime, }; additionalFacts.push(imageCreationTimeFact); } if (depsAnalysis.rootFsLayers && Array.isArray(depsAnalysis.rootFsLayers) && depsAnalysis.rootFsLayers.length > 0) { const rootFsFact = { type: "rootFs", data: depsAnalysis.rootFsLayers, }; additionalFacts.push(rootFsFact); } if (depsAnalysis.depTree.targetOS.prettyName) { const imageOsReleasePrettyNameFact = { type: "imageOsReleasePrettyName", data: depsAnalysis.depTree.targetOS.prettyName, }; additionalFacts.push(imageOsReleasePrettyNameFact); } const manifestFiles = depsAnalysis.manifestFiles.length > 0 ? depsAnalysis.manifestFiles : undefined; if (manifestFiles) { const imageManifestFilesFact = { type: "imageManifestFiles", data: manifestFiles, }; additionalFacts.push(imageManifestFilesFact); } const autoDetectedPackages = (_a = depsAnalysis.autoDetectedUserInstructions) === null || _a === void 0 ? void 0 : _a.dockerfilePackages; const autoDetectedLayers = (_b = depsAnalysis.autoDetectedUserInstructions) === null || _b === void 0 ? void 0 : _b.dockerfileLayers; if (autoDetectedPackages && Object.keys(autoDetectedPackages).length > 0 && autoDetectedLayers && Object.keys(autoDetectedLayers).length > 0) { const autoDetectedPackagesWithChildren = getUserInstructionDeps(autoDetectedPackages, deps); const autoDetectedUserInstructionsFact = { type: "autoDetectedUserInstructions", data: { dockerfileLayers: autoDetectedLayers, dockerfilePackages: autoDetectedPackagesWithChildren, }, }; additionalFacts.push(autoDetectedUserInstructionsFact); } const applicationDependenciesScanResults = (depsAnalysis.applicationDependenciesScanResults || []).map((appDepsScanResult) => { if (depsAnalysis.imageId) { const imageIdFact = { type: "imageId", data: depsAnalysis.imageId, }; appDepsScanResult.facts.push(imageIdFact); } return Object.assign(Object.assign({}, appDepsScanResult), { target: { image: depGraph.rootPkg.name, } }); }); const args = depsAnalysis.platform !== undefined ? { platform: depsAnalysis.platform } : undefined; const depGraphFact = { type: "depGraph", data: depGraph, }; const scanResults = [ { facts: [depGraphFact, ...additionalFacts], target: { image: depGraph.rootPkg.name, }, identity: { type: depGraph.pkgManager.name, args, }, }, ...applicationDependenciesScanResults, ]; return { scanResults, }; } exports.buildResponse = buildResponse; function collectDockerfilePkgs(dockerAnalysis, deps) { if (!dockerAnalysis) { return; } return getUserInstructionDeps(dockerAnalysis.dockerfilePackages, deps); } // Iterate over the dependencies list; if one is introduced by the dockerfile, // flatten its dependencies and append them to the list of dockerfile // packages. This gives us a reference of all transitive deps installed via // the dockerfile, and the instruction that installed it. function getUserInstructionDeps(dockerfilePackages, dependencies) { for (const dependencyName in dependencies) { if (dependencies.hasOwnProperty(dependencyName)) { const sourceOrName = dependencyName.split("/")[0]; const dockerfilePackage = dockerfilePackages[sourceOrName]; if (dockerfilePackage) { for (const dep of collectDeps(dependencies[dependencyName])) { dockerfilePackages[dep.split("/")[0]] = Object.assign({}, dockerfilePackage); } } } } return dockerfilePackages; } function collectDeps(pkg) { // ES5 doesn't have Object.values, so replace with Object.keys() and map() return pkg.dependencies ? Object.keys(pkg.dependencies) .map((name) => pkg.dependencies[name]) .reduce((allDeps, pkg) => { return [...allDeps, ...collectDeps(pkg)]; }, Object.keys(pkg.dependencies)) : []; } // Skip processing if option disabled or dockerfilePkgs is undefined. We // can't exclude anything in that case, because we can't tell which deps are // from dockerfile and which from base image. function excludeBaseImageDeps(deps, dockerfilePkgs, excludeBaseImageVulns) { if (!excludeBaseImageVulns || !dockerfilePkgs) { return deps; } return extractDockerfileDeps(deps, dockerfilePkgs); } function extractDockerfileDeps(allDeps, dockerfilePkgs) { return Object.keys(allDeps) .filter((depName) => dockerfilePkgs[depName]) .reduce((extractedDeps, depName) => { extractedDeps[depName] = allDeps[depName]; return extractedDeps; }, {}); } function annotateLayerIds(deps, dockerfilePkgs) { if (!dockerfilePkgs) { return; } for (const dep of Object.keys(deps)) { const pkg = deps[dep]; const dockerfilePkg = dockerfilePkgs[dep]; if (dockerfilePkg) { pkg.labels = Object.assign(Object.assign({}, (pkg.labels || {})), { dockerLayerId: (0, dockerfile_1.instructionDigest)(dockerfilePkg.instruction) }); } if (pkg.dependencies) { annotateLayerIds(pkg.dependencies, dockerfilePkgs); } } } //# sourceMappingURL=response-builder.js.map