diff --git a/scripts/commands/dec.sh b/scripts/commands/dec.sh index b711c61ef..1c2a5b636 100644 --- a/scripts/commands/dec.sh +++ b/scripts/commands/dec.sh @@ -21,21 +21,21 @@ EOF } decrypt_helper() { - file="${1}" + encrypted_file="${1}" - if [ ! -f "$file" ]; then - printf 'File does not exist: %s\n' "${file}" + if ! encrypted_file_path=$(_file_get "${encrypted_file}"); then + printf '[helm-secrets] File does not exist: %s\n' "${encrypted_file}" exit 1 fi - if ! driver_is_file_encrypted "${file}"; then + if ! driver_is_file_encrypted "${encrypted_file_path}"; then return 1 fi - file_dec="$(file_dec_name "${file}")" + encrypted_file_dec="$(_file_dec_name "${encrypted_file_path}")" - if ! driver_decrypt_file "yaml" "${file}" "${file_dec}"; then - printf 'Error while decrypting file: %s\n' "${file}" + if ! driver_decrypt_file "yaml" "${encrypted_file_path}" "${encrypted_file_dec}"; then + printf '[helm-secrets] Error while decrypting file: %s\n' "${file}" exit 1 fi @@ -50,11 +50,6 @@ dec() { file="$1" - if [ ! -f "${file}" ]; then - printf 'File does not exist: %s\n' "${file}" - exit 1 - else - printf 'Decrypting %s\n' "${file}" - decrypt_helper "${file}" - fi + printf '[helm-secrets] Decrypting %s\n' "${file}" + decrypt_helper "${file}" } diff --git a/scripts/commands/enc.sh b/scripts/commands/enc.sh index afbaf72f5..357338035 100644 --- a/scripts/commands/enc.sh +++ b/scripts/commands/enc.sh @@ -33,7 +33,7 @@ encrypt_helper() { printf 'File does not exist: %s\n' "${dir}/${file}" exit 1 fi - file_dec="$(file_dec_name "${file}")" + file_dec="$(_file_dec_name "${file}")" if [ ! -f "${file_dec}" ]; then file_dec="${file}" diff --git a/scripts/commands/helm.sh b/scripts/commands/helm.sh index d0795ea88..f8e68db04 100644 --- a/scripts/commands/helm.sh +++ b/scripts/commands/helm.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -set -eu +set -eux # shellcheck disable=SC1090 . "${SCRIPT_DIR}/commands/dec.sh" @@ -24,8 +24,8 @@ Typical usage: EOF } -helm_wrapper_cleanup() { - if [ -s "${decrypted_files}" ]; then +_trap_hook() { + if [ -n "${decrypted_files+x}" ]; then if [ "${QUIET}" = "false" ]; then echo >&2 # shellcheck disable=SC2016 @@ -33,9 +33,9 @@ helm_wrapper_cleanup() { else xargs -0 rm >&2 <"${decrypted_files}" fi - fi - rm "${decrypted_files}" + rm "${decrypted_files}" + fi } helm_wrapper() { @@ -44,9 +44,6 @@ helm_wrapper() { argc=$# j=0 - #cleanup on-the-fly decrypted files - trap helm_wrapper_cleanup EXIT - while [ $j -lt $argc ]; do case "$1" in --) @@ -71,7 +68,12 @@ helm_wrapper() { ;; esac - file_dec="$(file_dec_name "${file}")" + if ! real_file=$(_file_get "${file}"); then + printf '[helm-secrets] File does not exist: %s\n' "${file}" + exit 1 + fi + + file_dec="$(_file_dec_name "${real_file}")" if [ -f "${file_dec}" ]; then set -- "$@" "$file_dec" @@ -79,7 +81,7 @@ helm_wrapper() { printf '[helm-secrets] Decrypt skipped: %s' "${file}" >&2 fi else - if decrypt_helper "${file}"; then + if decrypt_helper "${real_file}"; then set -- "$@" "$file_dec" printf '%s\0' "${file_dec}" >>"${decrypted_files}" diff --git a/scripts/commands/view.sh b/scripts/commands/view.sh index a4cf382cb..a54788eeb 100644 --- a/scripts/commands/view.sh +++ b/scripts/commands/view.sh @@ -17,12 +17,14 @@ EOF view_helper() { file="$1" - if [ ! -f "${file}" ]; then + if ! _file_exists "$file"; then printf 'File does not exist: %s\n' "${file}" exit 1 fi - driver_decrypt_file "yaml" "${file}" + real_file=$(_file_get "${file}") + + driver_decrypt_file "yaml" "${real_file}" } view() { diff --git a/scripts/install.sh b/scripts/install.sh index dda9654ca..4e8e29089 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -2,6 +2,12 @@ set -eu +# Path to current directory +SCRIPT_DIR="$(dirname "$0")" + +# shellcheck source=lib/http.sh +. "${SCRIPT_DIR}/lib/http.sh" + SOPS_DEFAULT_VERSION="v3.6.1" SOPS_VERSION="${SOPS_VERSION:-$SOPS_DEFAULT_VERSION}" SOPS_LINUX_URL="${SOPS_LINUX_URL:-"https://github.com/mozilla/sops/releases/download/${SOPS_VERSION}/sops-${SOPS_VERSION}.linux"}" @@ -13,16 +19,6 @@ RED='\033[0;31m' #YELLOW='\033[1;33m' NOC='\033[0m' -download() { - if command -v curl >/dev/null; then - curl -sSfL "$1" - elif command -v wget >/dev/null; then - wget -q -O- "$1" - else - return 1 - fi -} - get_sha_256() { if command -v sha256sum >/dev/null; then res=$(sha256sum "$1") diff --git a/scripts/lib/file.sh b/scripts/lib/file.sh new file mode 100644 index 000000000..4dc4088b5 --- /dev/null +++ b/scripts/lib/file.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env sh + +# shellcheck source=lib/file/local.sh +. "${SCRIPT_DIR}/lib/file/local.sh" + +# shellcheck source=lib/file/http.sh +. "${SCRIPT_DIR}/lib/file/http.sh" + +# shellcheck source=lib/file/custom.sh +. "${SCRIPT_DIR}/lib/file/custom.sh" + +_file_get_protocol() { + case "$1" in + /* | \*) + echo "local" + ;; + http*) + echo "http" + ;; + *) + echo "custom" + ;; + esac +} + +_file_exists() { + file_type=$(_file_get_protocol "${1}") + + _file_"${file_type}"_exists "$@" +} + +_file_get() { + file_type=$(_file_get_protocol "${1}") + + _file_"${file_type}"_get "$@" +} + +_file_put() { + file_type=$(_file_get_protocol "${1}") + + _file_"${file_type}"_put "$@" +} + +_file_dec_name() { + if [ "${DEC_DIR}" != "" ]; then + printf '%s' "${DEC_DIR}/$(basename "${1}" ".yaml")${DEC_SUFFIX}" + else + printf '%s' "$(dirname "${1}")/$(basename "${1}" ".yaml")${DEC_SUFFIX}" + fi +} diff --git a/scripts/lib/file/custom.sh b/scripts/lib/file/custom.sh new file mode 100644 index 000000000..86abee800 --- /dev/null +++ b/scripts/lib/file/custom.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh + +_file_custom_exists() { + _file_custom_get "$@" >/dev/null +} + +_file_custom_get() { + _tmp_file=$(mktemp) + helm template "${SCRIPT_DIR}/lib/file/helm-values-getter" -f "${1}" >"${_tmp_file}" + printf '%s' "${_tmp_file}" +} + +_file_custom_put() { + echo "Can't write to remote files!" + exit 1 +} diff --git a/scripts/lib/file/helm-values-getter/Chart.yaml b/scripts/lib/file/helm-values-getter/Chart.yaml new file mode 100644 index 000000000..fea58ff85 --- /dev/null +++ b/scripts/lib/file/helm-values-getter/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: helm-values-getter +version: 1.0.0 diff --git a/scripts/lib/file/helm-values-getter/templates/values.yaml b/scripts/lib/file/helm-values-getter/templates/values.yaml new file mode 100644 index 000000000..4bdbf9db6 --- /dev/null +++ b/scripts/lib/file/helm-values-getter/templates/values.yaml @@ -0,0 +1 @@ +{{- .Values | toYaml -}} diff --git a/scripts/lib/file/helm-values-getter/values.yaml b/scripts/lib/file/helm-values-getter/values.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/lib/file/http.sh b/scripts/lib/file/http.sh new file mode 100644 index 000000000..374e229bd --- /dev/null +++ b/scripts/lib/file/http.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh + +_file_http_exists() { + _file_http_get "$@" >/dev/null +} + +_file_http_get() { + _tmp_file=$(mktemp) + download "${1}" >"${_tmp_file}" + printf '%s' "${_tmp_file}" +} + +_file_http_put() { + echo "Can't write to remote files!" + exit 1 +} diff --git a/scripts/lib/file/local.sh b/scripts/lib/file/local.sh new file mode 100644 index 000000000..3cccb39f7 --- /dev/null +++ b/scripts/lib/file/local.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env sh + +_file_local_exists() { + [ -f "${1}" ] +} + +_file_local_get() { + _file_local_exists "$@" + printf '%s' "${1}" +} + +_file_local_put() { + cat - >"${1}" +} diff --git a/scripts/lib/http.sh b/scripts/lib/http.sh new file mode 100644 index 000000000..bdb8abea2 --- /dev/null +++ b/scripts/lib/http.sh @@ -0,0 +1,9 @@ +download() { + if command -v curl >/dev/null; then + curl -sSfL "$1" + elif command -v wget >/dev/null; then + wget -q -O- "$1" + else + return 1 + fi +} diff --git a/scripts/run.sh b/scripts/run.sh index 16be25cc9..ea88dd8e4 100755 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -5,6 +5,9 @@ set -eu # Path to current directory SCRIPT_DIR="$(dirname "$0")" +# Create temporary directory +TMPDIR="${HELM_SECRETS_DEC_TMP_DIR:-$(mktemp -d)}" + # Output debug infos QUIET="${HELM_SECRETS_QUIET:-false}" @@ -19,6 +22,24 @@ DEC_DIR="${HELM_SECRETS_DEC_DIR:-}" # Make sure HELM_BIN is set (normally by the helm command) HELM_BIN="${HELM_BIN:-helm}" +# shellcheck source=lib/file.sh +. "${SCRIPT_DIR}/lib/file.sh" + +# shellcheck source=lib/http.sh +. "${SCRIPT_DIR}/lib/http.sh" + +_trap_hook() { + true +} + +_trap() { + rm -rf "${TMPDIR}" + + _trap_hook +} + +trap _trap EXIT + usage() { cat <&1 + assert_success + assert_output --partial "[helm-secrets] Decrypt: ${FILE}" + assert_output --partial "port: 81" + assert_output --partial "[helm-secrets] Removed: " + assert [ ! -f "${FILE}.dec" ] +} diff --git a/tests/it/install.bats b/tests/it/install.bats index 3742f3d51..4ad876891 100755 --- a/tests/it/install.bats +++ b/tests/it/install.bats @@ -257,3 +257,20 @@ load '../bats/extensions/bats-file/load' assert_success assert_output --partial "port: 81" } + +@test "install: helm install w/ chart + secrets.yaml + http://" { + FILE="https://raw.githubusercontent.com/jkroepke/helm-secrets/master/tests/assets/values/sops/secrets.yaml" + RELEASE="install-$(date +%s)-${SEED}" + create_chart "${TEST_TEMP_DIR}" + + run helm secrets install "${RELEASE}" "${TEST_TEMP_DIR}/chart" --no-hooks -f "${FILE}" 2>&1 + assert_success + assert_output --partial "[helm-secrets] Decrypt: ${FILE}" + assert_output --partial "STATUS: deployed" + assert_output --partial "[helm-secrets] Removed: " + assert [ ! -f "${FILE}.dec" ] + + run kubectl get svc -o yaml -l "app.kubernetes.io/name=chart,app.kubernetes.io/instance=${RELEASE}" + assert_success + assert_output --partial "port: 81" +} diff --git a/tests/it/upgrade.bats b/tests/it/upgrade.bats index cd75df986..601b47504 100755 --- a/tests/it/upgrade.bats +++ b/tests/it/upgrade.bats @@ -256,3 +256,20 @@ load '../bats/extensions/bats-file/load' assert_success assert_output --partial "port: 81" } + +@test "upgrade: helm upgrade w/ chart + secrets.yaml + http://" { + FILE="https://raw.githubusercontent.com/jkroepke/helm-secrets/master/tests/assets/values/sops/secrets.yaml" + RELEASE="upgrade-$(date +%s)-${SEED}" + create_chart "${TEST_TEMP_DIR}" + + run helm secrets upgrade -i "${RELEASE}" "${TEST_TEMP_DIR}/chart" --no-hooks -f "${FILE}" 2>&1 + assert_success + assert_output --partial "[helm-secrets] Decrypt: ${FILE}" + assert_output --partial "STATUS: deployed" + assert_output --partial "[helm-secrets] Removed: " + assert [ ! -f "${FILE}.dec" ] + + run kubectl get svc -o yaml -l "app.kubernetes.io/name=chart,app.kubernetes.io/instance=${RELEASE}" + assert_success + assert_output --partial "port: 81" +} diff --git a/tests/lib/helper.bash b/tests/lib/helper.bash index 3f31abbf7..28b68661d 100644 --- a/tests/lib/helper.bash +++ b/tests/lib/helper.bash @@ -133,12 +133,19 @@ helm_plugin_install() { if ! env APPDATA="${HELM_CACHE}/home/" HOME="${HELM_CACHE}/home/" helm plugin list | grep -q "${1}"; then case "${1}" in kubeval) - env APPDATA="${HELM_CACHE}/home/" HOME="${HELM_CACHE}/home/" helm plugin install https://github.com/instrumenta/helm-kubeval + URL="https://github.com/instrumenta/helm-kubeval" ;; diff) - env APPDATA="${HELM_CACHE}/home/" HOME="${HELM_CACHE}/home/" helm plugin install https://github.com/databus23/helm-diff + URL="https://github.com/databus23/helm-diff" + ;; + git) + # See: https://github.com/aslafy-z/helm-git/pull/120 + #URL="https://github.com/aslafy-z/helm-git" + URL="https://github.com/diwakar-s-maurya/helm-git" ;; esac + + env APPDATA="${HELM_CACHE}/home/" HOME="${HELM_CACHE}/home/" helm plugin install "${URL}" fi cp -r "${HELM_CACHE}/home/." "${HOME}" diff --git a/tests/unit/dec.bats b/tests/unit/dec.bats index 71367329c..b65412dd0 100755 --- a/tests/unit/dec.bats +++ b/tests/unit/dec.bats @@ -28,7 +28,7 @@ load '../bats/extensions/bats-file/load' run helm secrets dec "${FILE}" assert_success - assert_output "Decrypting ${FILE}" + assert_output "[helm-secrets] Decrypting ${FILE}" assert_file_exist "${FILE}.dec" run cat "${FILE}.dec" @@ -42,7 +42,7 @@ load '../bats/extensions/bats-file/load' run helm secrets dec "${FILE}" assert_success - assert_output "Decrypting ${FILE}" + assert_output "[helm-secrets] Decrypting ${FILE}" assert_file_exist "${FILE}.dec" run cat "${FILE}.dec" @@ -60,7 +60,7 @@ load '../bats/extensions/bats-file/load' run helm secrets dec "${FILE}" assert_success - assert_output "Decrypting ${FILE}" + assert_output "[helm-secrets] Decrypting ${FILE}" assert_file_exist "${FILE}.dec" run cat "${FILE}.dec" @@ -77,7 +77,7 @@ load '../bats/extensions/bats-file/load' run helm secrets dec "${FILE}" assert_success - assert_output "Decrypting ${FILE}" + assert_output "[helm-secrets] Decrypting ${FILE}" assert [ -e "${FILE}.test" ] run cat "${FILE}.test" @@ -94,7 +94,7 @@ load '../bats/extensions/bats-file/load' run helm secrets dec "${FILE}" assert_success - assert_output "Decrypting ${FILE}" + assert_output "[helm-secrets] Decrypting ${FILE}" assert_file_exist "${HELM_SECRETS_DEC_DIR}/secrets.yaml.dec" run cat "${HELM_SECRETS_DEC_DIR}/secrets.yaml.dec" @@ -102,3 +102,21 @@ load '../bats/extensions/bats-file/load' assert_output --partial 'global_secret: ' assert_output --partial 'global_bar' } + +@test "dec: Decrypt secrets.yaml + http://" { + FILE="https://raw.githubusercontent.com/jkroepke/helm-secrets/master/tests/assets/values/sops/secrets.yaml" + + run helm secrets dec "${FILE}" + assert_success + assert_output "[helm-secrets] Decrypting ${FILE}" +} + +@test "dec: Decrypt secrets.yaml + git://" { + helm_plugin_install "git" + #FILE="git+https://github.com/jkroepke/helm-secrets@assets/values/sops/secrets.yaml?ref=master" + FILE="github://jkroepke/helm-secrets:master/tests/assets/values/sops/secrets.yaml" + + run helm secrets dec "${FILE}" + assert_success + assert_output "[helm-secrets] Decrypting ${FILE}" +} diff --git a/tests/unit/template.bats b/tests/unit/template.bats index 5de68fbe1..39c6a820b 100755 --- a/tests/unit/template.bats +++ b/tests/unit/template.bats @@ -237,3 +237,29 @@ load '../bats/extensions/bats-file/load' assert_success assert_output --partial "port: 81" } + +@test "template: helm template w/ chart + secrets.yaml + http://" { + FILE="https://raw.githubusercontent.com/jkroepke/helm-secrets/master/tests/assets/values/sops/secrets.yaml" + + create_chart "${TEST_TEMP_DIR}" + + run helm secrets template "${TEST_TEMP_DIR}/chart" -f "${FILE}" 2>&1 + assert_success + assert_output --partial "[helm-secrets] Decrypt: ${FILE}" + assert_output --partial "port: 81" + assert_output --partial "[helm-secrets] Removed: " +} + +@test "template: helm template w/ chart + secrets.yaml + git://" { + helm_plugin_install "git" + #FILE="git+https://github.com/jkroepke/helm-secrets@assets/values/sops/secrets.yaml?ref=master" + FILE="github://jkroepke/helm-secrets:master/tests/assets/values/sops/secrets.yaml" + + create_chart "${TEST_TEMP_DIR}" + + run helm secrets template "${TEST_TEMP_DIR}/chart" -f "${FILE}" 2>&1 + assert_success + assert_output --partial "[helm-secrets] Decrypt: ${FILE}" + assert_output --partial "port: 81" + assert_output --partial "[helm-secrets] Removed: " +}