Skip to content

Commit

Permalink
refactor: move ActionInputs to a class
Browse files Browse the repository at this point in the history
  • Loading branch information
tembleking committed Jul 30, 2024
1 parent 55113c7 commit cada804
Show file tree
Hide file tree
Showing 8 changed files with 439 additions and 339 deletions.
326 changes: 194 additions & 132 deletions dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

17 changes: 7 additions & 10 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as core from '@actions/core';
import fs from 'fs';
import { generateSARIFReport } from './src/sarif';
import { cliScannerName, cliScannerResult, cliScannerURL, composeFlags, executeScan, numericPriorityForSeverity, pullScanner, ScanExecutionResult, vmMode } from './src/scanner';
import { ActionInputs, defaultSecureEndpoint, parseActionInputs, printOptions, validateInput } from './src/action';
import { cliScannerName, cliScannerResult, cliScannerURL, executeScan, numericPriorityForSeverity, pullScanner, ScanExecutionResult, vmMode } from './src/scanner';
import { ActionInputs, defaultSecureEndpoint } from './src/action';
import { generateSummary } from './src/summary';
import { Report } from './src/report';

Expand All @@ -20,10 +20,9 @@ function writeReport(reportData: string) {
export async function run() {

try {
let opts = parseActionInputs();
validateInput(opts)
printOptions(opts);
let scanFlags = composeFlags(opts); // FIXME(fede) this also modifies the opts.cliScannerURL, which is something we don't want
let opts = ActionInputs.parseActionInputs();
opts.printOptions();
let scanFlags = opts.composeFlags();

let scanResult: ScanExecutionResult;
// Download CLI Scanner from 'cliScannerURL'
Expand All @@ -35,7 +34,8 @@ export async function run() {
retCode = scanResult.ReturnCode;
if (retCode == 0 || retCode == 1) {
// Transform Scan Results to other formats such as SARIF
if (opts.mode && opts.mode == vmMode) {

if (opts.mode == vmMode) {
await processScanResult(scanResult, opts);
}
} else {
Expand Down Expand Up @@ -103,11 +103,8 @@ export async function processScanResult(result: ScanExecutionResult, opts: Actio
}

export {
parseActionInputs,
validateInput,
cliScannerURL,
defaultSecureEndpoint,
composeFlags,
pullScanner,
cliScannerName,
executeScan,
Expand Down
271 changes: 211 additions & 60 deletions src/action.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as core from '@actions/core';
import { cliScannerURL, iacMode, vmMode } from './scanner';
import { cliScannerResult, cliScannerURL, ComposeFlags, iacMode, scannerURLForVersion, vmMode } from './scanner';

export const defaultSecureEndpoint = "https://secure.sysdig.com/"

export interface ActionInputs {
interface ActionInputParameters {
cliScannerURL: string;
cliScannerVersion: string;
registryUser: string;
Expand All @@ -29,89 +29,240 @@ export interface ActionInputs {
iacScanPath: string;
}

export function parseActionInputs() : ActionInputs {
return {
cliScannerURL: core.getInput('cli-scanner-url') || cliScannerURL,
cliScannerVersion: core.getInput('cli-scanner-version'),
registryUser: core.getInput('registry-user'),
registryPassword: core.getInput('registry-password'),
stopOnFailedPolicyEval: core.getInput('stop-on-failed-policy-eval') == 'true',
stopOnProcessingError: core.getInput('stop-on-processing-error') == 'true',
standalone: core.getInput('standalone') == 'true',
dbPath: core.getInput('db-path'),
skipUpload: core.getInput('skip-upload') == 'true',
skipSummary: core.getInput('skip-summary') == 'true',
usePolicies: core.getInput('use-policies'),
overridePullString: core.getInput('override-pullstring'),
imageTag: core.getInput('image-tag'),
sysdigSecureToken: core.getInput('sysdig-secure-token'),
sysdigSecureURL: core.getInput('sysdig-secure-url') || defaultSecureEndpoint,
sysdigSkipTLS: core.getInput('sysdig-skip-tls') == 'true',
severityAtLeast: core.getInput('severity-at-least') || undefined,
groupByPackage: core.getInput('group-by-package') == 'true',
extraParameters: core.getInput('extra-parameters'),
mode: core.getInput('mode') || vmMode,
recursive: core.getInput('recursive') == 'true',
minimumSeverity: core.getInput('minimum-severity'),
iacScanPath: core.getInput('iac-scan-path') || './'
export class ActionInputs {
private readonly _params: ActionInputParameters;
public get params(): ActionInputParameters {
return this._params;
}
private constructor(params: ActionInputParameters) {
ActionInputs.validateInputs(params);
this._params = params;
}
}

export function validateInput(opts: ActionInputs) {
if (!opts.standalone && !opts.sysdigSecureToken) {
core.setFailed("Sysdig Secure Token is required for standard execution, please set your token or remove the standalone input.");
throw new Error("Sysdig Secure Token is required for standard execution, please set your token or remove the standalone input.");
static from(any: any): ActionInputs {
return new ActionInputs(any as ActionInputParameters);
}

if (opts.mode && opts.mode == vmMode && !opts.imageTag) {
core.setFailed("image-tag is required for VM mode.");
throw new Error("image-tag is required for VM mode.");
static fromJSON(jsonContents: string): ActionInputs {
return ActionInputs.from(JSON.parse(jsonContents))
}

if (opts.mode && opts.mode == iacMode && opts.iacScanPath == "") {
core.setFailed("iac-scan-path can't be empty, please specify the path you want to scan your manifest resources.");
throw new Error("iac-scan-path can't be empty, please specify the path you want to scan your manifest resources.");
static parseActionInputs(): ActionInputs {
return ActionInputs.overridingParsedActionInputs({});
}
}

export function printOptions(opts: ActionInputs) {
if (opts.standalone) {
core.info(`[!] Running in Standalone Mode.`);
static overridingParsedActionInputs(overrides: { [key: string]: any }) {

const params: ActionInputParameters = {
cliScannerURL: core.getInput('cli-scanner-url') || cliScannerURL,
cliScannerVersion: core.getInput('cli-scanner-version'),
registryUser: core.getInput('registry-user'),
registryPassword: core.getInput('registry-password'),
stopOnFailedPolicyEval: core.getInput('stop-on-failed-policy-eval') == 'true',
stopOnProcessingError: core.getInput('stop-on-processing-error') == 'true',
standalone: core.getInput('standalone') == 'true',
dbPath: core.getInput('db-path'),
skipUpload: core.getInput('skip-upload') == 'true',
skipSummary: core.getInput('skip-summary') == 'true',
usePolicies: core.getInput('use-policies'),
overridePullString: core.getInput('override-pullstring'),
imageTag: core.getInput('image-tag'),
sysdigSecureToken: core.getInput('sysdig-secure-token'),
sysdigSecureURL: core.getInput('sysdig-secure-url') || defaultSecureEndpoint,
sysdigSkipTLS: core.getInput('sysdig-skip-tls') == 'true',
severityAtLeast: core.getInput('severity-at-least') || undefined,
groupByPackage: core.getInput('group-by-package') == 'true',
extraParameters: core.getInput('extra-parameters'),
mode: core.getInput('mode') || vmMode,
recursive: core.getInput('recursive') == 'true',
minimumSeverity: core.getInput('minimum-severity'),
iacScanPath: core.getInput('iac-scan-path') || './',
};

const overridenParams = {
...params,
...overrides,
};


return ActionInputs.from(overridenParams);
}

if (opts.sysdigSecureURL) {
core.info('Sysdig Secure URL: ' + opts.sysdigSecureURL);
get cliScannerURL(): string {
return this.params.cliScannerURL
}

if (opts.registryUser && opts.registryPassword) {
core.info(`Using specified Registry credentials.`);
get mode() {
return this.params.mode || vmMode;
}

core.info(`Stop on Failed Policy Evaluation: ${opts.stopOnFailedPolicyEval}`);
get stopOnProcessingError() {
return this.params.stopOnProcessingError
}

core.info(`Stop on Processing Error: ${opts.stopOnProcessingError}`);
get standalone() {
return this.params.standalone
}

if (opts.skipUpload) {
core.info(`Skipping scan results upload to Sysdig Secure...`);
get stopOnFailedPolicyEval() {
return this.params.stopOnFailedPolicyEval
}

if (opts.dbPath) {
core.info(`DB Path: ${opts.dbPath}`);
get skipSummary() {
return this.params.skipSummary
}

core.info(`Sysdig skip TLS: ${opts.sysdigSkipTLS}`);
get groupByPackage(): boolean {
return this.params.groupByPackage
}

if (opts.severityAtLeast) {
core.info(`Severity level: ${opts.severityAtLeast}`);
get severityAtLeast() {
return this.params.severityAtLeast
}

core.info('Analyzing image: ' + opts.imageTag);
get imageTag() {
return this.params.imageTag
}

if (opts.overridePullString) {
core.info(` * Image PullString will be overwritten as ${opts.overridePullString}`);
get overridePullString() {
return this.params.overridePullString
}

if (opts.skipSummary) {
core.info("This run will NOT generate a SUMMARY.");
private static validateInputs(params: ActionInputParameters) {
if (!params.standalone && !params.sysdigSecureToken) {
core.setFailed("Sysdig Secure Token is required for standard execution, please set your token or remove the standalone input.");
throw new Error("Sysdig Secure Token is required for standard execution, please set your token or remove the standalone input.");
}

if (params.mode && params.mode == vmMode && !params.imageTag) {
core.setFailed("image-tag is required for VM mode.");
throw new Error("image-tag is required for VM mode.");
}

if (params.mode && params.mode == iacMode && params.iacScanPath == "") {
core.setFailed("iac-scan-path can't be empty, please specify the path you want to scan your manifest resources.");
throw new Error("iac-scan-path can't be empty, please specify the path you want to scan your manifest resources.");
}
}

// FIXME(fede) this also modifies the opts.cliScannerURL, which is something we don't want
public composeFlags(): ComposeFlags {
if (this.params.cliScannerVersion && this.params.cliScannerURL == cliScannerURL) {
this.params.cliScannerURL = scannerURLForVersion(this.params.cliScannerVersion)
}

let envvars: { [key: string]: string } = {}
envvars['SECURE_API_TOKEN'] = this.params.sysdigSecureToken || "";

let flags = ""

if (this.params.registryUser) {
envvars['REGISTRY_USER'] = this.params.registryUser;
}

if (this.params.registryPassword) {
envvars['REGISTRY_PASSWORD'] = this.params.registryPassword;
}

if (this.params.standalone) {
flags += " --standalone";
}

if (this.params.sysdigSecureURL) {
flags += ` --apiurl ${this.params.sysdigSecureURL}`;
}

if (this.params.dbPath) {
flags += ` --dbpath=${this.params.dbPath}`;
}

if (this.params.skipUpload) {
flags += ' --skipupload';
}

if (this.params.usePolicies) {
flags += ` --policy=${this.params.usePolicies}`;
}

if (this.params.sysdigSkipTLS) {
flags += ` --skiptlsverify`;
}

if (this.params.overridePullString) {
flags += ` --override-pullstring=${this.params.overridePullString}`;
}

if (this.params.extraParameters) {
flags += ` ${this.params.extraParameters}`;
}

if (this.params.mode && this.params.mode == iacMode) {
flags += ` --iac`;
}

if (this.params.recursive && this.params.mode == iacMode) {
flags += ` -r`;
}

if (this.params.minimumSeverity && this.params.mode == iacMode) {
flags += ` -f=${this.params.minimumSeverity}`;
}

if (this.params.mode && this.params.mode == vmMode) {
flags += ` --json-scan-result=${cliScannerResult}`
flags += ` ${this.params.imageTag}`;
}

if (this.params.mode && this.params.mode == iacMode) {
flags += ` ${this.params.iacScanPath}`;
}

return {
envvars: envvars,
flags: flags
}
}

public printOptions() {
if (this.params.standalone) {
core.info(`[!] Running in Standalone Mode.`);
}

if (this.params.sysdigSecureURL) {
core.info('Sysdig Secure URL: ' + this.params.sysdigSecureURL);
}

if (this.params.registryUser && this.params.registryPassword) {
core.info(`Using specified Registry credentials.`);
}

core.info(`Stop on Failed Policy Evaluation: ${this.params.stopOnFailedPolicyEval}`);

core.info(`Stop on Processing Error: ${this.params.stopOnProcessingError}`);

if (this.params.skipUpload) {
core.info(`Skipping scan results upload to Sysdig Secure...`);
}

if (this.params.dbPath) {
core.info(`DB Path: ${this.params.dbPath}`);
}

core.info(`Sysdig skip TLS: ${this.params.sysdigSkipTLS}`);

if (this.params.severityAtLeast) {
core.info(`Severity level: ${this.params.severityAtLeast}`);
}

core.info('Analyzing image: ' + this.params.imageTag);

if (this.params.overridePullString) {
core.info(` * Image PullString will be overwritten as ${this.params.overridePullString}`);
}

if (this.params.skipSummary) {
core.info("This run will NOT generate a SUMMARY.");
}
}
}

6 changes: 3 additions & 3 deletions src/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface Metadata {
size: number
os: string
architecture: string
labels?: {[key: string]: string}
labels?: { [key: string]: string }
layersCount: number
createdAt: string
}
Expand Down Expand Up @@ -77,7 +77,7 @@ export interface Vuln {
exploitable: boolean
fixedInVersion?: string
publishDateByVendor: PublishDateByVendor
annotations?: {[key: string]: string}
annotations?: { [key: string]: string }
acceptedRisks?: AcceptedRisk[]
}

Expand Down Expand Up @@ -126,7 +126,7 @@ export interface Vulns {
negligible?: number
}

export interface RunningVulns {}
export interface RunningVulns { }

export interface BaseImage {
pullstrings: string[]
Expand Down
Loading

0 comments on commit cada804

Please sign in to comment.