diff --git a/README.md b/README.md index 20877f6..8b48995 100644 --- a/README.md +++ b/README.md @@ -122,13 +122,44 @@ steps: path: 'plan.tfplanjson' ``` +### Directory Scanning + +Add the following to your `pipeline.yml`, the plugin will scan a directory. + +```yaml +steps: + - label: "Scan Directory" + command: ls . + env: + - WIZ_API_ID: "" + plugins: + - wiz#v1.3.3: + scan-type: 'dir' + path: 'main.tf' +``` + +By default, `path` parameter will be the root of your repository, and scan all files in the local directory. +To change the directory, add the following to your `pipeline.yml`, the plugin will scan the chosen directory. + +```yaml +steps: + - label: "Scan Files in different Directory" + command: ls my-dir + env: + - WIZ_API_ID: "" + plugins: + - wiz#v1.3.3: + scan-type: 'dir' + path: 'my-dir' +``` + ## Configuration ### `api-secret-env` (Optional, string) The environment variable that the Wiz API Secret is stored in. Defaults to using `WIZ_API_SECRET`. Refer to the [documentation](https://buildkite.com/docs/pipelines/secrets#using-a-secrets-storage-service) for more information about managing secrets on your Buildkite agents. -### `scan-type` (Required, string) : 'docker | iac' +### `scan-type` (Required, string) : `dir | docker | iac' The type of resource to be scanned. @@ -141,6 +172,11 @@ Used when `scan-type` is `iac`. The path to image file, if the `scan-type` is `docker`. +### `output-format` (Optional, string): `human | json | sarif` + +Scans output format. +Defaults to: `human` + ### `parameter-files` (Optional, string) Comma separated list of globs of external parameter files to include while scanning e.g., `variables.tf` @@ -149,7 +185,12 @@ Used when `scan-type` is `iac`. ### `path` (Optional, string) The file or directory to scan, defaults to the root directory of repository. -Used when `scan-type` is `iac`. +Used when `scan-type` is `dir` or `iac`. + +### `show-secret-snippets` (Optional, bool) + +Enable snippets in secrets. +Defaults to: `false` ## Developing diff --git a/hooks/post-command b/hooks/post-command index 9927ea1..2d9b065 100755 --- a/hooks/post-command +++ b/hooks/post-command @@ -7,14 +7,16 @@ SCAN_TYPE="${BUILDKITE_PLUGIN_WIZ_SCAN_TYPE:-}" FILE_PATH="${BUILDKITE_PLUGIN_WIZ_PATH:-}" PARAMETER_FILES="${BUILDKITE_PLUGIN_WIZ_PARAMETER_FILES:-}" IAC_TYPE="${BUILDKITE_PLUGIN_WIZ_IAC_TYPE:-}" +OUTPUT_FORMAT="${BUILDKITE_PLUGIN_WIZ_OUTPUT_FORMAT:=human}" +SHOW_SECRET_SNIPPETS="${BUILDKITE_PLUGIN_WIZ_SHOW_SECRET_SNIPPETS:=false}" if [[ -z "${SCAN_TYPE}" ]]; then - echo "Missing scan type. Possible values: 'iac', 'docker'" + echo "+++ 🚨 Missing scan type. Possible values: 'iac', 'docker', 'dir'" exit 1 fi -if [ "${SCAN_TYPE}" = "docker" ] && [[ -z "${BUILDKITE_PLUGIN_WIZ_IMAGE_ADDRESS:-}" ]]; then - echo "Missing image address, docker scans require an adress to pull the image" +if [[ "${SCAN_TYPE}" == "docker" && -z "${BUILDKITE_PLUGIN_WIZ_IMAGE_ADDRESS:-}" ]]; then + echo "+++ 🚨 Missing image address, docker scans require an address to pull the image" exit 1 fi @@ -31,12 +33,32 @@ fi args=() -if [[ -n "${IAC_TYPE}" ]]; then - args+=("--types=${IAC_TYPE}") +## Global Parameters + +if [[ "${SHOW_SECRET_SNIPPETS}" == "true" ]]; then + args+=("--show-secret-snippets") fi -if [[ -n "${PARAMETER_FILES}" ]]; then - args+=("--parameter-files=${PARAMETER_FILES}") +output_formats=("human" "json" "sarif") +if [[ ${output_formats[*]} =~ ${OUTPUT_FORMAT} ]]; then + args+=("--format=${OUTPUT_FORMAT}") +else + echo "+++ 🚨 Invalid Output Format: ${OUTPUT_FORMAT}" + echo "Valid Formats: ${output_formats[*]}" + exit 1 +fi + +## IAC Scanning Parameters + +if [[ "${SCAN_TYPE}" == "iac" ]]; then + + if [[ -n "${IAC_TYPE}" ]]; then + args+=("--types=${IAC_TYPE}") + fi + + if [[ -n "${PARAMETER_FILES}" ]]; then + args+=("--parameter-files=${PARAMETER_FILES}") + fi fi # Get the architecture of the machine for running the container image due to "latest" not being multi-architecture @@ -110,8 +132,8 @@ dockerImageScan() { "${wiz_cli_container}" \ docker scan --image "$IMAGE" \ --policy-hits-only \ - -f human \ - -o /scan/result,human,true + -o /scan/result,human,true ${args:+"${args[@]}"} + exit_code="$?" image_name=$(echo "$IMAGE" | cut -d "/" -f 2) # FIXME: Linktree Specific Env. Var. @@ -135,7 +157,6 @@ iacScan() { --mount type=bind,src="$PWD",dst=/scan \ "${wiz_cli_container}" \ iac scan \ - -f human \ -o /scan/result/output,human \ --name "$BUILDKITE_JOB_ID" \ --path "/scan/$FILE_PATH" ${args:+"${args[@]}"} @@ -156,6 +177,34 @@ iacScan() { exit $exit_code } +dirScan() { + mkdir -p result + docker run \ + --rm -it \ + --mount type=bind,src="$WIZ_DIR",dst=/cli,readonly \ + --mount type=bind,src="$PWD",dst=/scan \ + "${wiz_cli_container}" \ + dir scan \ + -o /scan/result/output,human \ + --name "$BUILDKITE_JOB_ID" \ + --path "/scan/$FILE_PATH" ${args:+"${args[@]}"} + + exit_code="$?" + case $exit_code in + 0) + buildAnnotation "dir" "$BUILDKITE_LABEL" true "result/output" | buildkite-agent annotate --append --context 'ctx-wiz-dir-success' --style 'success' + ;; + *) + buildAnnotation "dir" "$BUILDKITE_LABEL" false "result/output" | buildkite-agent annotate --append --context 'ctx-wiz-dir-warning' --style 'warning' + ;; + esac + # buildkite-agent artifact upload "result/**/*" --log-level info + # this post step will be used in template to check the step was run + echo "${BUILDKITE_BUILD_ID}" >check-file && buildkite-agent artifact upload check-file + + exit $exit_code +} + case "${SCAN_TYPE}" in iac) setupWiz @@ -165,4 +214,8 @@ docker) setupWiz dockerImageScan ;; +dir) + setupWiz + dirScan + ;; esac diff --git a/plugin.yml b/plugin.yml index 69478c4..00592da 100644 --- a/plugin.yml +++ b/plugin.yml @@ -10,6 +10,13 @@ configuration: type: string image-address: type: string + output-format: + type: string + enum: + - human + - json + - sarif + default: human parameter-files: type: string path: @@ -17,8 +24,12 @@ configuration: scan-type: type: string enum: + - dir - docker - - iac + - iac + show-secret-snippets: + type: boolean + default: false iac-type: type: string enum: diff --git a/tests/post-command.bats b/tests/post-command.bats index 521cc7d..c614fd7 100755 --- a/tests/post-command.bats +++ b/tests/post-command.bats @@ -5,8 +5,7 @@ load "$BATS_PLUGIN_PATH/load.bash" # Uncomment the following line to debug stub failures # export BUILDKITE_AGENT_STUB_DEBUG=/dev/tty - -setup () { +setup() { export BUILDKITE_PLUGIN_WIZ_SCAN_TYPE="docker" export BUILDKITE_PLUGIN_WIZ_IMAGE_ADDRESS="ubuntu:22.04" export WIZ_DIR="$HOME/.wiz" @@ -67,11 +66,11 @@ setup () { @test "No Wiz API Secret password found in \$WIZ_API_SECRET" { export WIZ_API_ID="test" - export WIZ_API_SECRET="" + unset WIZ_API_SECRET run "$PWD/hooks/post-command" - assert_output --partial "No Wiz API Secret password found in $WIZ_API_SECRET" + assert_output "+++ 🚨 No Wiz API Secret password found in \$WIZ_API_SECRET" assert_failure } @@ -82,7 +81,7 @@ setup () { run "$PWD/hooks/post-command" - assert_output --partial "No Wiz API Secret password found in $CUSTOM_WIZ_API_SECRET_ENV" + assert_output "+++ 🚨 No Wiz API Secret password found in \$CUSTOM_WIZ_API_SECRET_ENV" assert_failure } @@ -90,6 +89,27 @@ setup () { export BUILDKITE_PLUGIN_WIZ_SCAN_TYPE="" run "$PWD/hooks/post-command" - assert_output "Missing scan type. Possible values: 'iac', 'docker'" + assert_output "+++ 🚨 Missing scan type. Possible values: 'iac', 'docker', 'dir'" + assert_failure +} + +@test "Docker Scan without BUILDKITE_PLUGIN_WIZ_IMAGE_ADDRESS" { + export WIZ_API_ID="test" + export WIZ_API_SECRET="secret" + unset BUILDKITE_PLUGIN_WIZ_IMAGE_ADDRESS + + run "$PWD/hooks/post-command" + assert_output "+++ 🚨 Missing image address, docker scans require an address to pull the image" + assert_failure } + +@test "Invalid Output Format" { + export WIZ_API_SECRET="secret" + export BUILDKITE_PLUGIN_WIZ_OUTPUT_FORMAT="wrong-format" + + run "$PWD/hooks/post-command" + assert_output --partial "+++ 🚨 Invalid Output Format: $BUILDKITE_PLUGIN_WIZ_OUTPUT_FORMAT" + + assert_failure +} \ No newline at end of file