feat: add option to specify one or more grype config files (#589) · anchore/scan-action@e573fa1

5 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -136,6 +136,7 @@ The inputs `image`, `path`, and `sbom` are mutually exclusive to specify the sou

136136

| `vex` | Specify a list of VEX documents to consider when producing scanning results. | `false` |

137137

| `cache-db` | Cache the Grype DB in GitHub action cache and restore before checking for updates | `false` |

138138

| `grype-version` | An optional Grype version to download, defaults to the pinned version in [GrypeVersion.js](GrypeVersion.js). | |

139+

| `config` | Optional Grype configuration files (newline-separated). Setting this will disable auto-detection of configuration files (e.g. .grype.yaml) - only the specified files will be loaded.. | |

139140
140141

### Action Outputs

141142
Original file line numberDiff line numberDiff line change

@@ -39,13 +39,16 @@ inputs:

3939

by-cve:

4040

description: "Specify whether to orient results by CVE rather than GHSA. Default is false."

4141

required: false

42-

default: "false"

42+

default: "false"

4343

grype-version:

4444

description: "A specific version of Grype to install"

4545

required: false

4646

vex:

4747

description: "Specify a list of VEX documents to consider when producing scanning results."

4848

required: false

49+

config:

50+

description: "Specify one or more Grype configuration files (newline-separated). Setting this will disable auto-detection of configuration files (e.g. .grype.yaml) - only the specified files will be loaded."

51+

required: false

4952

cache-db:

5053

description: "Cache the Grype DB in GitHub action cache and restore before checking for updates"

5154

required: false

Original file line numberDiff line numberDiff line change

@@ -147,6 +147,7 @@ async function run() {

147147

const addCpesIfNone = core.getInput("add-cpes-if-none") || "false";

148148

const byCve = core.getInput("by-cve") || "false";

149149

const vex = core.getInput("vex") || "";

150+

const configFile = core.getInput("config") || "";

150151

const cacheDb = core.getInput("cache-db") || "false";

151152

const outputFile = core.getInput("output-file") || "";

152153

const out = await runScan({

@@ -159,6 +160,7 @@ async function run() {

159160

addCpesIfNone,

160161

byCve,

161162

vex,

163+

configFile,

162164

cacheDb,

163165

});

164166

Object.keys(out).map((key) => {

@@ -309,6 +311,7 @@ async function runScan({

309311

addCpesIfNone,

310312

byCve,

311313

vex,

314+

configFile,

312315

cacheDb,

313316

}) {

314317

const out = {};

@@ -425,6 +428,16 @@ async function runScan({

425428

cmdArgs.push("--vex");

426429

cmdArgs.push(vex);

427430

}

431+

if (configFile) {

432+

const configFiles = configFile

433+

.split("\n")

434+

.map((f) => f.trim())

435+

.filter((f) => f);

436+

for (const cf of configFiles) {

437+

cmdArgs.push("-c");

438+

cmdArgs.push(cf);

439+

}

440+

}

428441

cmdArgs.push(source);

429442
430443

const { exitCode } = await runCommand(grypeCommand, cmdArgs, env);

Original file line numberDiff line numberDiff line change

@@ -133,6 +133,7 @@ async function run() {

133133

const addCpesIfNone = core.getInput("add-cpes-if-none") || "false";

134134

const byCve = core.getInput("by-cve") || "false";

135135

const vex = core.getInput("vex") || "";

136+

const configFile = core.getInput("config") || "";

136137

const cacheDb = core.getInput("cache-db") || "false";

137138

const outputFile = core.getInput("output-file") || "";

138139

const out = await runScan({

@@ -145,6 +146,7 @@ async function run() {

145146

addCpesIfNone,

146147

byCve,

147148

vex,

149+

configFile,

148150

cacheDb,

149151

});

150152

Object.keys(out).map((key) => {

@@ -295,6 +297,7 @@ async function runScan({

295297

addCpesIfNone,

296298

byCve,

297299

vex,

300+

configFile,

298301

cacheDb,

299302

}) {

300303

const out = {};

@@ -411,6 +414,16 @@ async function runScan({

411414

cmdArgs.push("--vex");

412415

cmdArgs.push(vex);

413416

}

417+

if (configFile) {

418+

const configFiles = configFile

419+

.split("\n")

420+

.map((f) => f.trim())

421+

.filter((f) => f);

422+

for (const cf of configFiles) {

423+

cmdArgs.push("-c");

424+

cmdArgs.push(cf);

425+

}

426+

}

414427

cmdArgs.push(source);

415428
416429

const { exitCode } = await runCommand(grypeCommand, cmdArgs, env);

Original file line numberDiff line numberDiff line change

@@ -177,6 +177,60 @@ describe("Grype command args", () => {

177177

"dir:asdf",

178178

]);

179179

});

180+
181+

it("adds single config file if specified", async () => {

182+

const args = await mockRun({

183+

image: "asdf",

184+

"fail-build": "false",

185+

"output-file": "the-output-file",

186+

"output-format": "json",

187+

"severity-cutoff": "low",

188+

"only-fixed": "false",

189+

"add-cpes-if-none": "false",

190+

"by-cve": "false",

191+

config: ".grype-custom.yaml",

192+

});

193+

expect(args).toEqual([

194+

"-v",

195+

"-o",

196+

"json",

197+

"--file",

198+

"the-output-file",

199+

"--fail-on",

200+

"low",

201+

"-c",

202+

".grype-custom.yaml",

203+

"asdf",

204+

]);

205+

});

206+
207+

it("adds multiple config files if specified", async () => {

208+

const args = await mockRun({

209+

image: "asdf",

210+

"fail-build": "false",

211+

"output-file": "the-output-file",

212+

"output-format": "json",

213+

"severity-cutoff": "low",

214+

"only-fixed": "false",

215+

"add-cpes-if-none": "false",

216+

"by-cve": "false",

217+

config: "base.yaml\noverrides.yaml",

218+

});

219+

expect(args).toEqual([

220+

"-v",

221+

"-o",

222+

"json",

223+

"--file",

224+

"the-output-file",

225+

"--fail-on",

226+

"low",

227+

"-c",

228+

"base.yaml",

229+

"-c",

230+

"overrides.yaml",

231+

"asdf",

232+

]);

233+

});

180234

});

181235
182236

async function mockRun(inputs) {