snyk-docker-plugin
Version:
Snyk CLI docker plugin
131 lines (118 loc) • 2.92 kB
text/typescript
import {
AnalysisType,
AnalyzedPackage,
IAptFiles,
ImageAnalysis,
} from "../types";
export function analyze(
targetImage: string,
aptFiles: IAptFiles,
): Promise<ImageAnalysis> {
const pkgs = parseDpkgFile(aptFiles.dpkgFile);
if (aptFiles.extFile) {
setAutoInstalledPackages(aptFiles.extFile, pkgs);
}
return Promise.resolve({
Image: targetImage,
AnalyzeType: AnalysisType.Apt,
Analysis: pkgs,
});
}
export function analyzeDistroless(
targetImage: string,
aptFiles: string[],
): Promise<ImageAnalysis> {
const analyzedPackages: AnalyzedPackage[] = [];
for (const fileContent of aptFiles) {
const currentPackages = parseDpkgFile(fileContent);
analyzedPackages.push(...currentPackages);
}
return Promise.resolve({
Image: targetImage,
AnalyzeType: AnalysisType.Apt,
Analysis: analyzedPackages,
});
}
function parseDpkgFile(text: string): AnalyzedPackage[] {
const pkgs: AnalyzedPackage[] = [];
let curPkg: any = null;
for (const line of text.split("\n")) {
curPkg = parseDpkgLine(line, curPkg, pkgs);
}
return pkgs;
}
function parseDpkgLine(
text: string,
curPkg: AnalyzedPackage,
pkgs: AnalyzedPackage[],
): AnalyzedPackage {
const [key, value] = text.split(": ");
switch (key) {
case "Package":
curPkg = {
Name: value,
Version: undefined,
Source: undefined,
Provides: [],
Deps: {},
AutoInstalled: undefined,
};
pkgs.push(curPkg);
break;
case "Version":
curPkg.Version = value;
break;
case "Source":
curPkg.Source = value.trim().split(" ")[0];
break;
case "Provides":
for (let name of value.split(",")) {
name = name.trim().split(" ")[0];
curPkg.Provides.push(name);
}
break;
case "Pre-Depends":
case "Depends":
for (const depElem of value.split(",")) {
for (let name of depElem.split("|")) {
name = name.trim().split(" ")[0];
curPkg.Deps[name] = true;
}
}
break;
}
return curPkg;
}
function setAutoInstalledPackages(text: string, pkgs: AnalyzedPackage[]) {
const autoPkgs = parseExtFile(text);
for (const pkg of pkgs) {
if (autoPkgs[pkg.Name]) {
pkg.AutoInstalled = true;
}
}
}
interface PkgMap {
[name: string]: boolean;
}
function parseExtFile(text: string) {
const pkgMap: PkgMap = {};
let curPkgName: any = null;
for (const line of text.split("\n")) {
curPkgName = parseExtLine(line, curPkgName, pkgMap);
}
return pkgMap;
}
function parseExtLine(text: string, curPkgName: string, pkgMap: PkgMap) {
const [key, value] = text.split(": ");
switch (key) {
case "Package":
curPkgName = value;
break;
case "Auto-Installed":
if (parseInt(value, 10) === 1) {
pkgMap[curPkgName] = true;
}
break;
}
return curPkgName;
}