diff --git a/README.md b/README.md index c129e30..a6aae91 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ The type of scan that the plugin will perform. Currently supported options are ` ### Optional -#### `token-env` (string) +#### `token-env` (string) The environment variable the plugin will reference to set `SNYK_TOKEN`. (default: `SNYK_TOKEN`) #### `org` (string) @@ -29,15 +29,14 @@ Your Snyk Organization slug, sets `SNYK_CFG_ORG`. The image and tag (example: `alpine:latest`) to pass to the container scan tool. #### `annotate` (bool) -Annotate the build according to the scan results. (default: FALSE) +Annotate the build according to the scan results. If set to `false`, no annotation will be created even if vulnerabilities are detected. (default: `false`) #### `block` (bool) -Optionally block the build on vulnerability detection - +Optionally block the build on vulnerability detection. ## Examples -Here are a few examples of using the plugin to scan within your Buildkite pipeline +Here are a few examples of using the plugin to scan within your Buildkite pipeline: ```yaml steps: @@ -47,10 +46,9 @@ steps: - snyk#v0.1.0: scan: 'oss' annotate: true - ``` -### And with other options as well +### And with other options as well: ```yaml steps: @@ -62,7 +60,6 @@ steps: annotate: true ``` - Scanning a docker container image by image name and tag: ```yaml @@ -74,7 +71,6 @@ steps: scan: 'container' annotate: true image: 'alpine:latest' - ``` Block a build when a vulnerability is detected: @@ -105,4 +101,4 @@ bk local run ## 📜 License -The package is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). +The package is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). \ No newline at end of file diff --git a/lib/snyk.sh b/lib/snyk.sh index 911876a..df5d61e 100644 --- a/lib/snyk.sh +++ b/lib/snyk.sh @@ -2,9 +2,8 @@ set -euo pipefail - function configure_plugin() { - + # PLUGIN_DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)/.." # Set token for the SNYK cli (either Service Account or User token) if [ -z "${BUILDKITE_PLUGIN_SNYK_TOKEN_ENV:-}" ]; then @@ -34,7 +33,7 @@ function configure_plugin() { fi # Check for annotate attribute in plugin config - if ! [[ "${BUILDKITE_PLUGIN_SNYK_ANNOTATE}" ]]; then + if [[ "${BUILDKITE_PLUGIN_SNYK_ANNOTATE:-}" == "false" ]]; then annotate=false else annotate=true @@ -59,21 +58,20 @@ function snyk_scan() { } function snyk_oss_test () { - json_output_file="${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_BUILD_NUMBER}-snyk-oss.json" echo "--- Running Snyk OSS scan" # capture the exit code to use for formatting the annotation later (https://docs.snyk.io/snyk-cli/commands/code-test#exit-codes) # and checking if we need to block the build + exit_code=0 snyk test --json-file-output="${json_output_file}" || exit_code=$? - upload_results "${json_output_file}" "oss" # Only create the annotation if annotate: true is added to the plugin config, default is "false" - if [[ "${annotate}" ]]; then + if [[ "${annotate}" == "true" ]]; then annotate_build "${exit_code}" "oss" fi @@ -91,13 +89,12 @@ function snyk_code_test () { # capture the exit code to use for formatting the annotation later (https://docs.snyk.io/snyk-cli/commands/code-test#exit-codes) exit_code=0 snyk code test --json-file-output="${json_output_file}" || exit_code=$? - + # because snyk code doesn't always create a json file, we need to check if one exists if [ -f "${json_output_file}" ]; then upload_results "${json_output_file}" "code" - # Only create the annotation if annotate: true is added to the plugin config, default is "false" - if [[ "${annotate}" ]]; then + if [[ "${annotate}" == "true" ]]; then annotate_build "${exit_code:0}" "code" fi fi @@ -105,7 +102,6 @@ function snyk_code_test () { if [[ "${exit_code}" != 0 && "${BUILDKITE_PLUGIN_SNYK_BLOCK:-}" == true ]]; then block_build fi - } # Run container test against a container image built as part of the job @@ -116,12 +112,12 @@ function snyk_container_test() { if [[ -n "${CONTAINER_IMAGE}" ]]; then exit_code=0 snyk container test "${CONTAINER_IMAGE:-}" --json-file-output="${json_output_file}" || exit_code=$? - - upload_results "${json_output_file}" "container" + upload_results "${json_output_file}" "container" + # Only create the annotation if annotate: true is added to the plugin config, default is "false" - if [[ "${annotate}" ]]; then - annotate_build "${exit_code}" "container" + if [[ "${annotate}" == "true" ]]; then + annotate_build "${exit_code}" "container" fi else echo "no container image provided" @@ -133,7 +129,6 @@ function snyk_container_test() { fi } - # Blocks the build if BUILDKITE_PLUGIN_SNYK_BLOCK=true and vulnerabilities are detected function block_build() { echo "Snyk detected vulnerabilities in the test, blocking build" @@ -144,8 +139,6 @@ function block_build() { EOF } - -# Format the JSON results from the test into nice HTML and add a build artifact function upload_results() { json_result_file=$1 ctx=$2 @@ -159,7 +152,6 @@ function upload_results() { buildkite-agent artifact upload "${html_artifact}" } - # format the output into an annotation with a link to the full report as an artifact function annotate_build() { exit_code=$1 @@ -174,14 +166,13 @@ function annotate_build() { style="success" message="

Snyk test completed and uploaded the results as a build artifact.

" fi - + annotation=$(cat << EOF

Snyk ${ctx} test

${message} View Complete Scan Result EOF ) - + buildkite-agent annotate "${annotation}" --style "${style}" --context "${ctx}" } - diff --git a/tests/snyk.bats b/tests/snyk.bats index aecd757..467f0a0 100644 --- a/tests/snyk.bats +++ b/tests/snyk.bats @@ -20,6 +20,11 @@ setup() { export BUILDKITE_PLUGIN_SNYK_ANNOTATE=false } +teardown() { + unstub snyk || true + unstub snyk-to-html || true + unstub buildkite-agent || true +} @test "missing snyk token causes plugin to fail" { unset BUILDKITE_PLUGIN_SNYK_TOKEN_ENV @@ -32,11 +37,6 @@ setup() { refute_output --partial 'Running plugin' } -@test "setting token env attribute sets snyk token" { - -} - - @test "oss option runs Snyk OSS scan" { BUILDKITE_PLUGIN_SNYK_SCAN='oss' @@ -54,10 +54,6 @@ setup() { assert_success assert_output --partial 'Scanning OSS' - - unstub snyk - unstub snyk-to-html - unstub buildkite-agent } @test "code option runs Snyk code scan" { @@ -70,8 +66,6 @@ setup() { assert_success assert_output --partial 'Scanning Code' - - unstub snyk } @test "container option runs Snyk container scan" { @@ -91,8 +85,46 @@ setup() { assert_success assert_output --partial 'Scanning Container llama' +} + +@test "snyk plugin does not annotate when annotate is false" { + export BUILDKITE_PLUGIN_SNYK_ANNOTATE=false + BUILDKITE_PLUGIN_SNYK_SCAN='oss' - unstub snyk - unstub snyk-to-html - unstub buildkite-agent -} \ No newline at end of file + stub snyk \ + "test --json-file-output=${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_BUILD_NUMBER}-snyk-oss.json : echo 'Scanning OSS'" + + stub snyk-to-html \ + "-i ${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_BUILD_NUMBER}-snyk-oss.json -o ${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_BUILD_NUMBER}-oss.html : echo 'created artifact'" + + stub buildkite-agent \ + "artifact upload ${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_BUILD_NUMBER}-oss.html : exit 0" \ + "annotate \* \* \* \* \* : exit 0" + + run "$PWD"/hooks/post-command + + assert_success + assert_output --partial 'Scanning OSS' + refute_output --partial 'annotate' +} + +@test "snyk plugin annotates when annotate is true" { + export BUILDKITE_PLUGIN_SNYK_ANNOTATE=true + BUILDKITE_PLUGIN_SNYK_SCAN='oss' + + stub snyk \ + "test --json-file-output=${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_BUILD_NUMBER}-snyk-oss.json : echo 'Scanning OSS'" + + stub snyk-to-html \ + "-i ${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_BUILD_NUMBER}-snyk-oss.json -o ${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_BUILD_NUMBER}-oss.html : echo 'created artifact'" + + stub buildkite-agent \ + "artifact upload ${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_BUILD_NUMBER}-oss.html : exit 0" \ + "annotate \* \* \* \* \* : echo 'Annotation created'" + + run "$PWD"/hooks/post-command + + assert_success + assert_output --partial 'Scanning OSS' + assert_output --partial 'Annotation created' +}