-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: decouple image analyzers and introduce static scanning opts
Decouple the way we retrieve package manager files (e.g. APK DB file), which is currently done with Docker run, from the logic that processes the file content. This will allow reusing the logic of processing a file that was acquired in different ways (e.g. statically or dynamically with Docker) while still supporting the existing functionality. Additionally introduced static stanning options which serve as hints that the caller wants a static analysis. The code now branches at the entrypoint "inspect()" for the two new paths: static analysis and dynamic (Docker) analysis.
- Loading branch information
1 parent
d0473b6
commit 780919a
Showing
18 changed files
with
318 additions
and
193 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import * as Debug from "debug"; | ||
import { DockerOptions } from "../docker"; | ||
import * as dockerFile from "../docker-file"; | ||
import * as binariesAnalyzer from "./binaries-analyzer"; | ||
import * as imageInspector from "./image-inspector"; | ||
import * as osReleaseDetector from "./os-release-detector"; | ||
|
||
import apkInputDocker = require("../inputs/apk/docker"); | ||
import aptInputDocker = require("../inputs/apt/docker"); | ||
import rpmInputDocker = require("../inputs/rpm/docker"); | ||
import apkAnalyzer = require("./package-manager/apk"); | ||
import aptAnalyzer = require("./package-manager/apt"); | ||
import rpmAnalyzer = require("./package-manager/rpm"); | ||
|
||
const debug = Debug("snyk"); | ||
|
||
export async function analyze( | ||
targetImage: string, | ||
dockerfileAnalysis?: dockerFile.DockerFileAnalysis, | ||
options?: DockerOptions, | ||
) { | ||
const [imageInspection, osRelease] = await Promise.all([ | ||
imageInspector.detect(targetImage, options), | ||
osReleaseDetector.detect(targetImage, dockerfileAnalysis, options), | ||
]); | ||
|
||
const [ | ||
apkDbFileContent, | ||
aptDbFileContent, | ||
rpmDbFileContent, | ||
] = await Promise.all([ | ||
apkInputDocker.getApkDbFileContent(targetImage, options), | ||
aptInputDocker.getAptDbFileContent(targetImage, options), | ||
rpmInputDocker.getRpmDbFileContent(targetImage, options), | ||
]); | ||
|
||
const results = await Promise.all([ | ||
apkAnalyzer.analyze(targetImage, apkDbFileContent), | ||
aptAnalyzer.analyze(targetImage, aptDbFileContent), | ||
rpmAnalyzer.analyze(targetImage, rpmDbFileContent), | ||
]).catch((err) => { | ||
debug(`Error while running analyzer: '${err.stderr}'`); | ||
throw new Error("Failed to detect installed OS packages"); | ||
}); | ||
|
||
const { installedPackages, pkgManager } = getInstalledPackages( | ||
results as any[], | ||
); | ||
let binaries; | ||
try { | ||
binaries = await binariesAnalyzer.analyze( | ||
targetImage, | ||
installedPackages, | ||
pkgManager, | ||
options, | ||
); | ||
} catch (err) { | ||
debug(`Error while running binaries analyzer: '${err}'`); | ||
throw new Error("Failed to detect binaries versions"); | ||
} | ||
|
||
return { | ||
imageId: imageInspection.Id, | ||
osRelease, | ||
results, | ||
binaries, | ||
imageLayers: imageInspection.RootFS && imageInspection.RootFS.Layers, | ||
}; | ||
} | ||
|
||
function getInstalledPackages( | ||
results: any[], | ||
): { installedPackages: string[]; pkgManager?: string } { | ||
const dockerAnalysis = results.find((res) => { | ||
return res.Analysis && res.Analysis.length > 0; | ||
}); | ||
|
||
if (!dockerAnalysis) { | ||
return { installedPackages: [] }; | ||
} | ||
const installedPackages = dockerAnalysis.Analysis.map((pkg) => pkg.Name); | ||
let pkgManager = dockerAnalysis.AnalyzeType; | ||
if (pkgManager) { | ||
pkgManager = pkgManager.toLowerCase(); | ||
} | ||
return { installedPackages, pkgManager }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,4 @@ | ||
import * as Debug from "debug"; | ||
import { DockerOptions } from "../docker"; | ||
import * as dockerFile from "../docker-file"; | ||
import * as apkAnalyzer from "./apk-analyzer"; | ||
import * as aptAnalyzer from "./apt-analyzer"; | ||
import * as binariesAnalyzer from "./binaries-analyzer"; | ||
import * as imageInspector from "./image-inspector"; | ||
import * as osReleaseDetector from "./os-release-detector"; | ||
import * as rpmAnalyzer from "./rpm-analyzer"; | ||
import { analyze as analyzeDynamically } from "./docker-analyzer"; | ||
import { analyze as analyzeStatically } from "./static-analyzer"; | ||
|
||
export { analyze }; | ||
|
||
const debug = Debug("snyk"); | ||
|
||
async function analyze( | ||
targetImage: string, | ||
dockerfileAnalysis?: dockerFile.DockerFileAnalysis, | ||
options?: DockerOptions, | ||
) { | ||
const [imageInspection, osRelease] = await Promise.all([ | ||
imageInspector.detect(targetImage, options), | ||
osReleaseDetector.detect(targetImage, dockerfileAnalysis, options), | ||
]); | ||
|
||
const results = await Promise.all([ | ||
apkAnalyzer.analyze(targetImage, options), | ||
aptAnalyzer.analyze(targetImage, options), | ||
rpmAnalyzer.analyze(targetImage, options), | ||
]).catch((err) => { | ||
debug(`Error while running analyzer: '${err.stderr}'`); | ||
throw new Error("Failed to detect installed OS packages"); | ||
}); | ||
|
||
const { installedPackages, pkgManager } = getInstalledPackages( | ||
results as any[], | ||
); | ||
let binaries; | ||
try { | ||
binaries = await binariesAnalyzer.analyze( | ||
targetImage, | ||
installedPackages, | ||
pkgManager, | ||
options, | ||
); | ||
} catch (err) { | ||
debug(`Error while running binaries analyzer: '${err}'`); | ||
throw new Error("Failed to detect binaries versions"); | ||
} | ||
|
||
return { | ||
imageId: imageInspection.Id, | ||
osRelease, | ||
results, | ||
binaries, | ||
imageLayers: imageInspection.RootFS && imageInspection.RootFS.Layers, | ||
}; | ||
} | ||
|
||
function getInstalledPackages( | ||
results: any[], | ||
): { installedPackages: string[]; pkgManager?: string } { | ||
const dockerAnalysis = results.find((res) => { | ||
return res.Analysis && res.Analysis.length > 0; | ||
}); | ||
|
||
if (!dockerAnalysis) { | ||
return { installedPackages: [] }; | ||
} | ||
const installedPackages = dockerAnalysis.Analysis.map((pkg) => pkg.Name); | ||
let pkgManager = dockerAnalysis.AnalyzeType; | ||
if (pkgManager) { | ||
pkgManager = pkgManager.toLowerCase(); | ||
} | ||
return { installedPackages, pkgManager }; | ||
} | ||
export { analyzeDynamically, analyzeStatically }; |
21 changes: 8 additions & 13 deletions
21
lib/analyzer/apk-analyzer.ts → lib/analyzer/package-manager/apk.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 11 additions & 9 deletions
20
lib/analyzer/apt-analyzer.ts → lib/analyzer/package-manager/apt.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { AnalyzerPkg } from "../types"; | ||
|
||
export { analyze }; | ||
|
||
async function analyze(targetImage: string, rpmDbFilecontent: string) { | ||
return { | ||
Image: targetImage, | ||
AnalyzeType: "Rpm", | ||
Analysis: parseOutput(rpmDbFilecontent), | ||
}; | ||
} | ||
|
||
function parseOutput(output: string) { | ||
const pkgs: AnalyzerPkg[] = []; | ||
for (const line of output.split("\n")) { | ||
parseLine(line, pkgs); | ||
} | ||
return pkgs; | ||
} | ||
|
||
function parseLine(text: string, pkgs: AnalyzerPkg[]) { | ||
const [name, version, size] = text.split("\t"); | ||
if (name && version && size) { | ||
const pkg: AnalyzerPkg = { | ||
Name: name, | ||
Version: version, | ||
Source: undefined, | ||
Provides: [], | ||
Deps: {}, | ||
AutoInstalled: undefined, | ||
}; | ||
pkgs.push(pkg); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { StaticAnalysisOptions } from "../types"; | ||
|
||
export async function analyze( | ||
targetImage: string, | ||
options: StaticAnalysisOptions, | ||
): Promise<never> { | ||
throw new Error("Not yet implemented!"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.