diff --git a/README.md b/README.md index d8658a22..439daf64 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,33 @@ You do not have to create a dedicated token. Make sure to use the GitHub's defau ### `fail_action` **Optional** By default ZAP Docker container will fail with an [exit code](https://github.com/zaproxy/zaproxy/blob/efb404d38280dc9ecf8f88c9b0c658385861bdcf/docker/zap-baseline.py#L31), -if it identifies any alerts. Set this option to `true` if you want to fail the status of the GitHub Scan if ZAP identifies any alerts during the scan. +if it identifies any alerts. Set this option to `true** if you want to fail the status of the GitHub Scan if ZAP identifies any alerts during the scan. + +### `force_root` + +**Optional** By default the container will be run using root user. In case a non-root user has to be used (e.g. when using zap with authentication from ictu/zap2docker-weekly), set this parameter to *false*. (note that setting this to false will force to set an accessible reports base dir) + +### `zap_options` + +**Optional** If zap options need to be passed, add the full string here. Zap options are like "key1=value1 key2=value2". This option was added because passing these zap options in cmd_options causes trouble with quotations. +String added here will be prepended with flag *-z*. +E.g., this string: + +```bash +"key1=value1 key2=value2" +``` + +...will be added into the command as: + +```bash +-z "key1=value1 key2=value2" +``` + +### `reports_dir` + +**Optional** Defaults to local dir (i.e. "./"). A different base path can be specified. +If *force_root* was set to false, note that the tool won't have access to the current dir to store the reports, so a new one have to be created. Please, see the examples to find how it can be done. + ## Example usage @@ -87,6 +113,34 @@ jobs: cmd_options: '-a' ``` +** Non root user ** + +``` +on: [push] + +jobs: + zap_scan: + runs-on: ubuntu-latest + name: Scan the webapplication + steps: + - name: Create Reports Dir + run: mkdir ./reports && chmod 777 ./reports + - name: ZAP Scan + uses: zaproxy/action-baseline@v0.4.1 + with: + target: 'https://yourdomain.com' + cmd_options: '-I -j --hook=/zap/auth_hook.py' + zap_options: 'auth.loginurl=https://yourdomain.com/login/ auth.username=username@yourdomain.com auth.password=yoursecretpwd auth.auto=1' + docker_name: ictu/zap2docker-weekly + force_root: false + reports_dir: ./reports + - name: Upload Test results + uses: actions/upload-artifact@master + with: + name: Zap scanning report + path: ${{github.workspace}}/reports +``` + ## Issue Description The following [issue](https://github.com/zaproxy/zaproxy-website/issues/93) shows how the GitHub Baseline Action scans the diff --git a/action.yml b/action.yml index 43863a61..e8216fec 100644 --- a/action.yml +++ b/action.yml @@ -33,6 +33,18 @@ inputs: description: 'The action will file the report to the GitHub issue using the issue_title input' required: false default: true + force_root: + description: 'Whether or not force root user in the container' + required: false + default: false + zap_options: + description: 'zap options, a string like "key=value key2=value2", it will be prepended with flag -z' + required: false + default: '' + reports_dir: + description: 'Base dir to store reports, default to local dir' + required: false + default: './' runs: using: 'node12' main: 'dist/index.js' diff --git a/dist/index.js b/dist/index.js index a3c6b93e..c1494749 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3806,10 +3806,13 @@ async function run() { let target = core.getInput('target'); let rulesFileLocation = core.getInput('rules_file_name'); let cmdOptions = core.getInput('cmd_options'); + let zapOptions = core.getInput('zap_options'); let issueTitle = core.getInput('issue_title'); let failAction = core.getInput('fail_action'); let allowIssueWriting = core.getInput('allow_issue_writing'); let createIssue = true; + let forceRoot = core.getInput('force_root'); + let reportsDir = core.getInput('reports_dir'); if (!(String(failAction).toLowerCase() === 'true' || String(failAction).toLowerCase() === 'false')) { console.log('[WARNING]: \'fail_action\' action input should be either \'true\' or \'false\''); @@ -3818,18 +3821,29 @@ async function run() { if (String(allowIssueWriting).toLowerCase() === 'false') { createIssue = false; } + if (!(String(forceRoot).toLowerCase() === 'true' || String(forceRoot).toLowerCase() === 'false')) { + console.log('[WARNING]: \'force_root\' action input should be either \'true\' or \'false\''); + } console.log('starting the program'); console.log('github run id :' + currentRunnerID); + let reports_dir = './'; + if (reportsDir != '') { + reports_dir = reportsDir + '/' + } + let force_root_param = ''; + if (String(forceRoot).toLowerCase() === 'true') { + force_root_param = '--user root' + } let plugins = []; if (rulesFileLocation) { plugins = await common.helper.processLineByLine(`${workspace}/${rulesFileLocation}`); } await exec.exec(`docker pull ${docker_name} -q`); - let command = (`docker run --user root -v ${workspace}:/zap/wrk/:rw --network="host" ` + - `-t ${docker_name} zap-baseline.py -t ${target} -J ${jsonReportName} -w ${mdReportName} -r ${htmlReportName} ${cmdOptions}`); + let command = (`docker run ${force_root_param} -v ${workspace}:/zap/wrk/:rw --network="host" ` + + `-t ${docker_name} zap-baseline.py -t ${target} -J ${reports_dir}${jsonReportName} -w ${reports_dir}${mdReportName} -r ${reports_dir}${htmlReportName} ${cmdOptions} -z "${zapOptions}"`); if (plugins.length !== 0) { command = command + ` -c ${rulesFileLocation}` @@ -11298,7 +11312,7 @@ exports.create = create; /* 215 */ /***/ (function(module) { -module.exports = {"name":"@octokit/rest","version":"16.43.1","publishConfig":{"access":"public"},"description":"GitHub REST API client for Node.js","keywords":["octokit","github","rest","api-client"],"author":"Gregor Martynus (https://github.com/gr2m)","contributors":[{"name":"Mike de Boer","email":"info@mikedeboer.nl"},{"name":"Fabian Jakobs","email":"fabian@c9.io"},{"name":"Joe Gallo","email":"joe@brassafrax.com"},{"name":"Gregor Martynus","url":"https://github.com/gr2m"}],"repository":"https://github.com/octokit/rest.js","dependencies":{"@octokit/auth-token":"^2.4.0","@octokit/plugin-paginate-rest":"^1.1.1","@octokit/plugin-request-log":"^1.0.0","@octokit/plugin-rest-endpoint-methods":"2.4.0","@octokit/request":"^5.2.0","@octokit/request-error":"^1.0.2","atob-lite":"^2.0.0","before-after-hook":"^2.0.0","btoa-lite":"^1.0.0","deprecation":"^2.0.0","lodash.get":"^4.4.2","lodash.set":"^4.3.2","lodash.uniq":"^4.5.0","octokit-pagination-methods":"^1.1.0","once":"^1.4.0","universal-user-agent":"^4.0.0"},"devDependencies":{"@gimenete/type-writer":"^0.1.3","@octokit/auth":"^1.1.1","@octokit/fixtures-server":"^5.0.6","@octokit/graphql":"^4.2.0","@types/node":"^13.1.0","bundlesize":"^0.18.0","chai":"^4.1.2","compression-webpack-plugin":"^3.1.0","cypress":"^3.0.0","glob":"^7.1.2","http-proxy-agent":"^4.0.0","lodash.camelcase":"^4.3.0","lodash.merge":"^4.6.1","lodash.upperfirst":"^4.3.1","lolex":"^5.1.2","mkdirp":"^1.0.0","mocha":"^7.0.1","mustache":"^4.0.0","nock":"^11.3.3","npm-run-all":"^4.1.2","nyc":"^15.0.0","prettier":"^1.14.2","proxy":"^1.0.0","semantic-release":"^17.0.0","sinon":"^8.0.0","sinon-chai":"^3.0.0","sort-keys":"^4.0.0","string-to-arraybuffer":"^1.0.0","string-to-jsdoc-comment":"^1.0.0","typescript":"^3.3.1","webpack":"^4.0.0","webpack-bundle-analyzer":"^3.0.0","webpack-cli":"^3.0.0"},"types":"index.d.ts","scripts":{"coverage":"nyc report --reporter=html && open coverage/index.html","lint":"prettier --check '{lib,plugins,scripts,test}/**/*.{js,json,ts}' 'docs/*.{js,json}' 'docs/src/**/*' index.js README.md package.json","lint:fix":"prettier --write '{lib,plugins,scripts,test}/**/*.{js,json,ts}' 'docs/*.{js,json}' 'docs/src/**/*' index.js README.md package.json","pretest":"npm run -s lint","test":"nyc mocha test/mocha-node-setup.js \"test/*/**/*-test.js\"","test:browser":"cypress run --browser chrome","build":"npm-run-all build:*","build:ts":"npm run -s update-endpoints:typescript","prebuild:browser":"mkdirp dist/","build:browser":"npm-run-all build:browser:*","build:browser:development":"webpack --mode development --entry . --output-library=Octokit --output=./dist/octokit-rest.js --profile --json > dist/bundle-stats.json","build:browser:production":"webpack --mode production --entry . --plugin=compression-webpack-plugin --output-library=Octokit --output-path=./dist --output-filename=octokit-rest.min.js --devtool source-map","generate-bundle-report":"webpack-bundle-analyzer dist/bundle-stats.json --mode=static --no-open --report dist/bundle-report.html","update-endpoints":"npm-run-all update-endpoints:*","update-endpoints:fetch-json":"node scripts/update-endpoints/fetch-json","update-endpoints:typescript":"node scripts/update-endpoints/typescript","prevalidate:ts":"npm run -s build:ts","validate:ts":"tsc --target es6 --noImplicitAny index.d.ts","postvalidate:ts":"tsc --noEmit --target es6 test/typescript-validate.ts","start-fixtures-server":"octokit-fixtures-server"},"license":"MIT","files":["index.js","index.d.ts","lib","plugins"],"nyc":{"ignore":["test"]},"release":{"publish":["@semantic-release/npm",{"path":"@semantic-release/github","assets":["dist/*","!dist/*.map.gz"]}]},"bundlesize":[{"path":"./dist/octokit-rest.min.js.gz","maxSize":"33 kB"}]}; +module.exports = {"_args":[["@octokit/rest@16.43.1","/app"]],"_from":"@octokit/rest@16.43.1","_id":"@octokit/rest@16.43.1","_inBundle":false,"_integrity":"sha512-gfFKwRT/wFxq5qlNjnW2dh+qh74XgTQ2B179UX5K1HYCluioWj8Ndbgqw2PVqa1NnVJkGHp2ovMpVn/DImlmkw==","_location":"/@octokit/rest","_phantomChildren":{"@octokit/types":"2.8.0","deprecation":"2.3.1","once":"1.4.0","os-name":"3.1.0"},"_requested":{"type":"version","registry":true,"raw":"@octokit/rest@16.43.1","name":"@octokit/rest","escapedName":"@octokit%2frest","scope":"@octokit","rawSpec":"16.43.1","saveSpec":null,"fetchSpec":"16.43.1"},"_requiredBy":["/@actions/github"],"_resolved":"https://registry.npmjs.org/@octokit/rest/-/rest-16.43.1.tgz","_spec":"16.43.1","_where":"/app","author":{"name":"Gregor Martynus","url":"https://github.com/gr2m"},"bugs":{"url":"https://github.com/octokit/rest.js/issues"},"bundlesize":[{"path":"./dist/octokit-rest.min.js.gz","maxSize":"33 kB"}],"contributors":[{"name":"Mike de Boer","email":"info@mikedeboer.nl"},{"name":"Fabian Jakobs","email":"fabian@c9.io"},{"name":"Joe Gallo","email":"joe@brassafrax.com"},{"name":"Gregor Martynus","url":"https://github.com/gr2m"}],"dependencies":{"@octokit/auth-token":"^2.4.0","@octokit/plugin-paginate-rest":"^1.1.1","@octokit/plugin-request-log":"^1.0.0","@octokit/plugin-rest-endpoint-methods":"2.4.0","@octokit/request":"^5.2.0","@octokit/request-error":"^1.0.2","atob-lite":"^2.0.0","before-after-hook":"^2.0.0","btoa-lite":"^1.0.0","deprecation":"^2.0.0","lodash.get":"^4.4.2","lodash.set":"^4.3.2","lodash.uniq":"^4.5.0","octokit-pagination-methods":"^1.1.0","once":"^1.4.0","universal-user-agent":"^4.0.0"},"description":"GitHub REST API client for Node.js","devDependencies":{"@gimenete/type-writer":"^0.1.3","@octokit/auth":"^1.1.1","@octokit/fixtures-server":"^5.0.6","@octokit/graphql":"^4.2.0","@types/node":"^13.1.0","bundlesize":"^0.18.0","chai":"^4.1.2","compression-webpack-plugin":"^3.1.0","cypress":"^3.0.0","glob":"^7.1.2","http-proxy-agent":"^4.0.0","lodash.camelcase":"^4.3.0","lodash.merge":"^4.6.1","lodash.upperfirst":"^4.3.1","lolex":"^5.1.2","mkdirp":"^1.0.0","mocha":"^7.0.1","mustache":"^4.0.0","nock":"^11.3.3","npm-run-all":"^4.1.2","nyc":"^15.0.0","prettier":"^1.14.2","proxy":"^1.0.0","semantic-release":"^17.0.0","sinon":"^8.0.0","sinon-chai":"^3.0.0","sort-keys":"^4.0.0","string-to-arraybuffer":"^1.0.0","string-to-jsdoc-comment":"^1.0.0","typescript":"^3.3.1","webpack":"^4.0.0","webpack-bundle-analyzer":"^3.0.0","webpack-cli":"^3.0.0"},"files":["index.js","index.d.ts","lib","plugins"],"homepage":"https://github.com/octokit/rest.js#readme","keywords":["octokit","github","rest","api-client"],"license":"MIT","name":"@octokit/rest","nyc":{"ignore":["test"]},"publishConfig":{"access":"public"},"release":{"publish":["@semantic-release/npm",{"path":"@semantic-release/github","assets":["dist/*","!dist/*.map.gz"]}]},"repository":{"type":"git","url":"git+https://github.com/octokit/rest.js.git"},"scripts":{"build":"npm-run-all build:*","build:browser":"npm-run-all build:browser:*","build:browser:development":"webpack --mode development --entry . --output-library=Octokit --output=./dist/octokit-rest.js --profile --json > dist/bundle-stats.json","build:browser:production":"webpack --mode production --entry . --plugin=compression-webpack-plugin --output-library=Octokit --output-path=./dist --output-filename=octokit-rest.min.js --devtool source-map","build:ts":"npm run -s update-endpoints:typescript","coverage":"nyc report --reporter=html && open coverage/index.html","generate-bundle-report":"webpack-bundle-analyzer dist/bundle-stats.json --mode=static --no-open --report dist/bundle-report.html","lint":"prettier --check '{lib,plugins,scripts,test}/**/*.{js,json,ts}' 'docs/*.{js,json}' 'docs/src/**/*' index.js README.md package.json","lint:fix":"prettier --write '{lib,plugins,scripts,test}/**/*.{js,json,ts}' 'docs/*.{js,json}' 'docs/src/**/*' index.js README.md package.json","postvalidate:ts":"tsc --noEmit --target es6 test/typescript-validate.ts","prebuild:browser":"mkdirp dist/","pretest":"npm run -s lint","prevalidate:ts":"npm run -s build:ts","start-fixtures-server":"octokit-fixtures-server","test":"nyc mocha test/mocha-node-setup.js \"test/*/**/*-test.js\"","test:browser":"cypress run --browser chrome","update-endpoints":"npm-run-all update-endpoints:*","update-endpoints:fetch-json":"node scripts/update-endpoints/fetch-json","update-endpoints:typescript":"node scripts/update-endpoints/typescript","validate:ts":"tsc --target es6 --noImplicitAny index.d.ts"},"types":"index.d.ts","version":"16.43.1"}; /***/ }), /* 216 */, @@ -18436,7 +18450,7 @@ exports.require = function() { /* 314 */ /***/ (function(module) { -module.exports = {"name":"@octokit/graphql","version":"2.1.3","publishConfig":{"access":"public"},"description":"GitHub GraphQL API client for browsers and Node","main":"index.js","scripts":{"prebuild":"mkdirp dist/","build":"npm-run-all build:*","build:development":"webpack --mode development --entry . --output-library=octokitGraphql --output=./dist/octokit-graphql.js --profile --json > dist/bundle-stats.json","build:production":"webpack --mode production --entry . --plugin=compression-webpack-plugin --output-library=octokitGraphql --output-path=./dist --output-filename=octokit-graphql.min.js --devtool source-map","bundle-report":"webpack-bundle-analyzer dist/bundle-stats.json --mode=static --no-open --report dist/bundle-report.html","coverage":"nyc report --reporter=html && open coverage/index.html","coverage:upload":"nyc report --reporter=text-lcov | coveralls","pretest":"standard","test":"nyc mocha test/*-test.js","test:browser":"cypress run --browser chrome"},"repository":{"type":"git","url":"https://github.com/octokit/graphql.js.git"},"keywords":["octokit","github","api","graphql"],"author":"Gregor Martynus (https://github.com/gr2m)","license":"MIT","bugs":{"url":"https://github.com/octokit/graphql.js/issues"},"homepage":"https://github.com/octokit/graphql.js#readme","dependencies":{"@octokit/request":"^5.0.0","universal-user-agent":"^2.0.3"},"devDependencies":{"chai":"^4.2.0","compression-webpack-plugin":"^2.0.0","coveralls":"^3.0.3","cypress":"^3.1.5","fetch-mock":"^7.3.1","mkdirp":"^0.5.1","mocha":"^6.0.0","npm-run-all":"^4.1.3","nyc":"^14.0.0","semantic-release":"^15.13.3","simple-mock":"^0.8.0","standard":"^12.0.1","webpack":"^4.29.6","webpack-bundle-analyzer":"^3.1.0","webpack-cli":"^3.2.3"},"bundlesize":[{"path":"./dist/octokit-graphql.min.js.gz","maxSize":"5KB"}],"release":{"publish":["@semantic-release/npm",{"path":"@semantic-release/github","assets":["dist/*","!dist/*.map.gz"]}]},"standard":{"globals":["describe","before","beforeEach","afterEach","after","it","expect"]},"files":["lib"]}; +module.exports = {"_args":[["@octokit/graphql@2.1.3","/app"]],"_from":"@octokit/graphql@2.1.3","_id":"@octokit/graphql@2.1.3","_inBundle":false,"_integrity":"sha512-XoXJqL2ondwdnMIW3wtqJWEwcBfKk37jO/rYkoxNPEVeLBDGsGO1TCWggrAlq3keGt/O+C/7VepXnukUxwt5vA==","_location":"/@octokit/graphql","_phantomChildren":{},"_requested":{"type":"version","registry":true,"raw":"@octokit/graphql@2.1.3","name":"@octokit/graphql","escapedName":"@octokit%2fgraphql","scope":"@octokit","rawSpec":"2.1.3","saveSpec":null,"fetchSpec":"2.1.3"},"_requiredBy":["/@actions/github"],"_resolved":"https://registry.npmjs.org/@octokit/graphql/-/graphql-2.1.3.tgz","_spec":"2.1.3","_where":"/app","author":{"name":"Gregor Martynus","url":"https://github.com/gr2m"},"bugs":{"url":"https://github.com/octokit/graphql.js/issues"},"bundlesize":[{"path":"./dist/octokit-graphql.min.js.gz","maxSize":"5KB"}],"dependencies":{"@octokit/request":"^5.0.0","universal-user-agent":"^2.0.3"},"description":"GitHub GraphQL API client for browsers and Node","devDependencies":{"chai":"^4.2.0","compression-webpack-plugin":"^2.0.0","coveralls":"^3.0.3","cypress":"^3.1.5","fetch-mock":"^7.3.1","mkdirp":"^0.5.1","mocha":"^6.0.0","npm-run-all":"^4.1.3","nyc":"^14.0.0","semantic-release":"^15.13.3","simple-mock":"^0.8.0","standard":"^12.0.1","webpack":"^4.29.6","webpack-bundle-analyzer":"^3.1.0","webpack-cli":"^3.2.3"},"files":["lib"],"homepage":"https://github.com/octokit/graphql.js#readme","keywords":["octokit","github","api","graphql"],"license":"MIT","main":"index.js","name":"@octokit/graphql","publishConfig":{"access":"public"},"release":{"publish":["@semantic-release/npm",{"path":"@semantic-release/github","assets":["dist/*","!dist/*.map.gz"]}]},"repository":{"type":"git","url":"git+https://github.com/octokit/graphql.js.git"},"scripts":{"build":"npm-run-all build:*","build:development":"webpack --mode development --entry . --output-library=octokitGraphql --output=./dist/octokit-graphql.js --profile --json > dist/bundle-stats.json","build:production":"webpack --mode production --entry . --plugin=compression-webpack-plugin --output-library=octokitGraphql --output-path=./dist --output-filename=octokit-graphql.min.js --devtool source-map","bundle-report":"webpack-bundle-analyzer dist/bundle-stats.json --mode=static --no-open --report dist/bundle-report.html","coverage":"nyc report --reporter=html && open coverage/index.html","coverage:upload":"nyc report --reporter=text-lcov | coveralls","prebuild":"mkdirp dist/","pretest":"standard","test":"nyc mocha test/*-test.js","test:browser":"cypress run --browser chrome"},"standard":{"globals":["describe","before","beforeEach","afterEach","after","it","expect"]},"version":"2.1.3"}; /***/ }), /* 315 */ diff --git a/index.js b/index.js index 8c51ccc6..f816efd0 100644 --- a/index.js +++ b/index.js @@ -19,10 +19,13 @@ async function run() { let target = core.getInput('target'); let rulesFileLocation = core.getInput('rules_file_name'); let cmdOptions = core.getInput('cmd_options'); + let zapOptions = core.getInput('zap_options'); let issueTitle = core.getInput('issue_title'); let failAction = core.getInput('fail_action'); let allowIssueWriting = core.getInput('allow_issue_writing'); let createIssue = true; + let forceRoot = core.getInput('force_root'); + let reportsDir = core.getInput('reports_dir'); if (!(String(failAction).toLowerCase() === 'true' || String(failAction).toLowerCase() === 'false')) { console.log('[WARNING]: \'fail_action\' action input should be either \'true\' or \'false\''); @@ -31,18 +34,29 @@ async function run() { if (String(allowIssueWriting).toLowerCase() === 'false') { createIssue = false; } + if (!(String(forceRoot).toLowerCase() === 'true' || String(forceRoot).toLowerCase() === 'false')) { + console.log('[WARNING]: \'force_root\' action input should be either \'true\' or \'false\''); + } console.log('starting the program'); console.log('github run id :' + currentRunnerID); + let reports_dir = './'; + if (reportsDir != '') { + reports_dir = reportsDir + '/' + } + let force_root_param = ''; + if (String(forceRoot).toLowerCase() === 'true') { + force_root_param = '--user root' + } let plugins = []; if (rulesFileLocation) { plugins = await common.helper.processLineByLine(`${workspace}/${rulesFileLocation}`); } await exec.exec(`docker pull ${docker_name} -q`); - let command = (`docker run --user root -v ${workspace}:/zap/wrk/:rw --network="host" ` + - `-t ${docker_name} zap-baseline.py -t ${target} -J ${jsonReportName} -w ${mdReportName} -r ${htmlReportName} ${cmdOptions}`); + let command = (`docker run ${force_root_param} -v ${workspace}:/zap/wrk/:rw --network="host" ` + + `-t ${docker_name} zap-baseline.py -t ${target} -J ${reports_dir}${jsonReportName} -w ${reports_dir}${mdReportName} -r ${reports_dir}${htmlReportName} ${cmdOptions} -z "${zapOptions}"`); if (plugins.length !== 0) { command = command + ` -c ${rulesFileLocation}`