-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: container static scanning in test command
The CLI no longer scans container images by using Docker. Distroless scanning is also enabled by default. This is enabled for both "snyk test --docker" and "snyk container test". Additionally, clean up the code by moving ecosystems.ts and splitting to its own module. Allows to better organize it as the module is going to grow with more functionality (currently has test but next up is monitor). Additional changes: - extract types from ecosystems module - move ecosystems plugins to their own file - move ecosystem test in its own file
- Loading branch information
1 parent
db2dec6
commit 800b57b
Showing
18 changed files
with
716 additions
and
311 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
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 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,31 @@ | ||
import { Options } from '../types'; | ||
import { Ecosystem } from './types'; | ||
|
||
export { testEcosystem } from './test'; | ||
export { getPlugin } from './plugins'; | ||
|
||
/** | ||
* Ecosystems are listed here if you opt in to the new plugin test flow. | ||
* This is a breaking change to the old plugin formats, so only a select few | ||
* plugins currently work with it. | ||
* | ||
* Currently container scanning is not yet ready to work with this flow, | ||
* hence this is in a separate function from getEcosystem(). | ||
*/ | ||
export function getEcosystemForTest(options: Options): Ecosystem | null { | ||
if (options.source) { | ||
return 'cpp'; | ||
} | ||
return null; | ||
} | ||
|
||
export function getEcosystem(options: Options): Ecosystem | null { | ||
if (options.source) { | ||
return 'cpp'; | ||
} | ||
|
||
if (options.docker) { | ||
return 'docker'; | ||
} | ||
return null; | ||
} |
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,15 @@ | ||
import * as cppPlugin from 'snyk-cpp-plugin'; | ||
import * as dockerPlugin from 'snyk-docker-plugin'; | ||
import { Ecosystem, EcosystemPlugin } from './types'; | ||
|
||
const EcosystemPlugins: { | ||
readonly [ecosystem in Ecosystem]: EcosystemPlugin; | ||
} = { | ||
cpp: cppPlugin, | ||
// TODO: not any | ||
docker: dockerPlugin as any, | ||
}; | ||
|
||
export function getPlugin(ecosystem: Ecosystem): EcosystemPlugin { | ||
return EcosystemPlugins[ecosystem]; | ||
} |
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,33 @@ | ||
import * as path from 'path'; | ||
|
||
import { SupportedPackageManagers } from '../package-managers'; | ||
import { findAndLoadPolicy } from '../policy'; | ||
import { Options, PolicyOptions } from '../types'; | ||
import { ScanResult } from './types'; | ||
|
||
export async function findAndLoadPolicyForScanResult( | ||
scanResult: ScanResult, | ||
options: Options & PolicyOptions, | ||
): Promise<object | undefined> { | ||
const targetFileRelativePath = scanResult.identity.targetFile | ||
? path.join(path.resolve(`${options.path}`), scanResult.identity.targetFile) | ||
: undefined; | ||
const targetFileDir = targetFileRelativePath | ||
? path.parse(targetFileRelativePath).dir | ||
: undefined; | ||
const scanType = options.docker | ||
? 'docker' | ||
: (scanResult.identity.type as SupportedPackageManagers); | ||
// TODO: fix this and send only send when we used resolve-deps for node | ||
// it should be a ExpandedPkgTree type instead | ||
const packageExpanded = undefined; | ||
|
||
const policy = (await findAndLoadPolicy( | ||
options.path, | ||
scanType, | ||
options, | ||
packageExpanded, | ||
targetFileDir, | ||
)) as object | undefined; // TODO: findAndLoadPolicy() does not return a string! | ||
return policy; | ||
} |
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,89 @@ | ||
import * as snyk from '../index'; | ||
import * as config from '../config'; | ||
import { isCI } from '../is-ci'; | ||
import { makeRequest } from '../request/promise'; | ||
import { Options } from '../types'; | ||
import { TestCommandResult } from '../../cli/commands/types'; | ||
import * as spinner from '../../lib/spinner'; | ||
import { Ecosystem, ScanResult, TestResult } from './types'; | ||
import { getPlugin } from './plugins'; | ||
import { TestDependenciesResponse } from '../snyk-test/legacy'; | ||
import { assembleQueryString } from '../snyk-test/common'; | ||
|
||
export async function testEcosystem( | ||
ecosystem: Ecosystem, | ||
paths: string[], | ||
options: Options, | ||
): Promise<TestCommandResult> { | ||
const plugin = getPlugin(ecosystem); | ||
const scanResultsByPath: { [dir: string]: ScanResult[] } = {}; | ||
for (const path of paths) { | ||
options.path = path; | ||
const pluginResponse = await plugin.scan(options); | ||
scanResultsByPath[path] = pluginResponse.scanResults; | ||
} | ||
const [testResults, errors] = await testDependencies( | ||
scanResultsByPath, | ||
options, | ||
); | ||
const stringifiedData = JSON.stringify(testResults, null, 2); | ||
if (options.json) { | ||
return TestCommandResult.createJsonTestCommandResult(stringifiedData); | ||
} | ||
const emptyResults: ScanResult[] = []; | ||
const scanResults = emptyResults.concat(...Object.values(scanResultsByPath)); | ||
const readableResult = await plugin.display( | ||
scanResults, | ||
testResults, | ||
errors, | ||
options, | ||
); | ||
|
||
return TestCommandResult.createHumanReadableTestCommandResult( | ||
readableResult, | ||
stringifiedData, | ||
); | ||
} | ||
|
||
async function testDependencies( | ||
scans: { | ||
[dir: string]: ScanResult[]; | ||
}, | ||
options: Options, | ||
): Promise<[TestResult[], string[]]> { | ||
const results: TestResult[] = []; | ||
const errors: string[] = []; | ||
for (const [path, scanResults] of Object.entries(scans)) { | ||
await spinner(`Testing dependencies in ${path}`); | ||
for (const scanResult of scanResults) { | ||
const payload = { | ||
method: 'POST', | ||
url: `${config.API}/test-dependencies`, | ||
json: true, | ||
headers: { | ||
'x-is-ci': isCI(), | ||
authorization: 'token ' + snyk.api, | ||
}, | ||
body: { | ||
scanResult, | ||
}, | ||
qs: assembleQueryString(options), | ||
}; | ||
try { | ||
const response = await makeRequest<TestDependenciesResponse>(payload); | ||
results.push({ | ||
issues: response.result.issues, | ||
issuesData: response.result.issuesData, | ||
depGraphData: response.result.depGraphData, | ||
}); | ||
} catch (error) { | ||
if (error.code >= 400 && error.code < 500) { | ||
throw new Error(error.message); | ||
} | ||
errors.push('Could not test dependencies in ' + path); | ||
} | ||
} | ||
} | ||
spinner.clearAll(); | ||
return [results, errors]; | ||
} |
Oops, something went wrong.