Files
terraform-provider-gpgvault…/scripts/e2e.sh
T
unkinben f56bb6be29
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Add terraform-provider-gpgvaultsecret
A terraform-plugin-framework provider for the vault-plugin-secrets-gpg engine,
managing engine mounts and OpenPGP keys on Vault/OpenBao.

- gpg_secret_backend resource: mount the engine (+ optional plugin catalog
  registration when a sha256 is given; deregisters on destroy).
- gpg_key resource: create/configure a key (algorithm, identity, exportable,
  deletion_allowed, min_decryption_version); computed public_key/fingerprint/
  key_id/latest_version; destroy auto-enables deletion; import <backend>/<name>.
- gpg_key data source: read a key's metadata + armored public key.
- Talks to Vault/OpenBao via hashicorp/vault/api; address/token fall back to
  VAULT_ADDR/VAULT_TOKEN. Unit tests plus an e2e running real terraform
  apply/destroy against a Vault dev server + the gpg plugin. Release publishes a
  zip to the artifactapi terraform-unkin registry on v* tags.
2026-07-16 23:33:04 +10:00

99 lines
3.7 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# End-to-end test for terraform-provider-gpgvaultsecret. Boots a Vault dev server
# running the vault-plugin-secrets-gpg engine, then applies real terraform that
# registers + mounts the backend, creates a key, and reads it via the data
# source. Verifies the outputs and that the mounted engine actually works, then
# destroys and confirms cleanup.
#
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PLUGIN_BIN="${PLUGIN_BIN:-${ROOT_DIR}/../vault-plugin-secrets-gpg/dist/vault-plugin-secrets-gpg}"
red() { printf '\033[31m%s\033[0m\n' "$*"; }
green() { printf '\033[32m%s\033[0m\n' "$*"; }
blue() { printf '\033[34m==> %s\033[0m\n' "$*"; }
fail() { red "FAIL: $*"; exit 1; }
command -v vault >/dev/null || fail "vault binary not found"
command -v terraform >/dev/null || fail "terraform binary not found"
[ -x "${PLUGIN_BIN}" ] || fail "plugin binary not found at ${PLUGIN_BIN} (build it: make -C ../vault-plugin-secrets-gpg build)"
WORK="$(mktemp -d)"
PLUGIN_DIR="${WORK}/plugins"
mkdir -p "${PLUGIN_DIR}"
cp "${PLUGIN_BIN}" "${PLUGIN_DIR}/vault-plugin-secrets-gpg"
PLUGIN_SHA="$(sha256sum "${PLUGIN_DIR}/vault-plugin-secrets-gpg" | awk '{print $1}')"
export VAULT_ADDR="http://127.0.0.1:8282"
export VAULT_TOKEN="root"
cleanup() {
[ -n "${VAULT_PID:-}" ] && kill "${VAULT_PID}" 2>/dev/null || true
rm -rf "${WORK}"
}
trap cleanup EXIT
blue "Building provider"
make -C "${ROOT_DIR}" build >/dev/null
PROVIDER_BIN="${ROOT_DIR}/terraform-provider-gpgvaultsecret"
blue "Starting Vault dev server (plugin_directory=${PLUGIN_DIR})"
vault server -dev -dev-root-token-id=root -dev-listen-address=127.0.0.1:8282 \
-dev-plugin-dir="${PLUGIN_DIR}" >"${WORK}/vault.log" 2>&1 &
VAULT_PID=$!
for i in $(seq 1 30); do
vault status >/dev/null 2>&1 && break
sleep 0.5
[ "$i" = 30 ] && fail "vault did not become ready"
done
green "vault ready"
# Dev override so terraform uses the freshly built provider binary directly.
cat > "${WORK}/dev.tfrc" <<EOF
provider_installation {
dev_overrides {
"git.unkin.net/unkin/gpgvaultsecret" = "$(dirname "${PROVIDER_BIN}")"
}
direct {}
}
EOF
export TF_CLI_CONFIG_FILE="${WORK}/dev.tfrc"
TFDIR="${ROOT_DIR}/test/e2e"
export TF_IN_AUTOMATION=1
tfvars=(-var "address=${VAULT_ADDR}" -var "token=root" -var "plugin_sha256=${PLUGIN_SHA}")
blue "terraform apply"
# dev_overrides skips init; apply directly.
terraform -chdir="${TFDIR}" apply -auto-approve "${tfvars[@]}" >/dev/null
green "apply succeeded"
fpr="$(terraform -chdir="${TFDIR}" output -raw resource_fingerprint)"
pub="$(terraform -chdir="${TFDIR}" output -raw data_public_key)"
ver="$(terraform -chdir="${TFDIR}" output -raw latest_version)"
[ -n "${fpr}" ] || fail "no fingerprint output"
printf '%s' "${pub}" | grep -q 'BEGIN PGP PUBLIC KEY BLOCK' || fail "data source public_key not armored"
[ "${ver}" = "1" ] || fail "latest_version != 1 (got ${ver})"
green "outputs OK: version=${ver} fpr=${fpr:0:16}..."
blue "engine is live: encrypt + decrypt via the mounted backend"
ct="$(vault write -field=ciphertext gpg/encrypt/app plaintext="$(printf 'tf-secret' | base64)")"
pt="$(vault write -field=plaintext gpg/decrypt/app ciphertext="${ct}" | base64 -d)"
[ "${pt}" = "tf-secret" ] || fail "encrypt/decrypt through the tf-managed engine failed"
green "encrypt/decrypt OK"
blue "terraform destroy"
terraform -chdir="${TFDIR}" destroy -auto-approve "${tfvars[@]}" >/dev/null
if vault secrets list -format=json 2>/dev/null | grep -q '"gpg/"'; then
fail "mount still present after destroy"
fi
green "destroy removed the mount + key"
# tidy generated state so the tree stays clean
rm -f "${TFDIR}"/terraform.tfstate* "${TFDIR}"/.terraform.lock.hcl
rm -rf "${TFDIR}"/.terraform
green "ALL PROVIDER END-TO-END CHECKS PASSED"