Skip to content

Instantly share code, notes, and snippets.

@vitalvas
Last active May 18, 2021 07:53
Show Gist options
  • Select an option

  • Save vitalvas/fe9bea72f495f36dd6aca80b5270f20a to your computer and use it in GitHub Desktop.

Select an option

Save vitalvas/fe9bea72f495f36dd6aca80b5270f20a to your computer and use it in GitHub Desktop.
terraform vault state storage

Terraform state in Vault

Configure vault

vault auth enable approle
vault secrets enable -path=secrets/infra/terraform kv-v2
vault write secrets/infra/terraform/config max_versions=100
vault write auth/approle/role/${role_name} token_policies="${policy_name}" token_ttl=10m token_max_ttl=1h

Example policy

path "secrets/infra/terraform/data/abstractproject/abstractkey" {
  capabilities = [ "create", "read", "update" ]
}

Example gitlab ci

variables:
  PLAN: plan.tfplan
  VAULT_KV_PATH: secrets/infra/terraform/abstractproject/abstractkey

plan:
  stage: build
  script:
    - ./vault_state.sh download
    - terraform plan -lock=false -out=$PLAN
....

apply:
  stage: deploy
  environment:
    name: production
  script:
    - ./vault_state.sh download
    - terraform apply -input=false $PLAN
    - ./vault_state.sh upload
....

Configure CI

Required env

  • VAULT_ROLE_ID
  • VAULT_SECRET_ID
  • VAULT_KV_PATH
#!/usr/bin/env bash
## Written by: Vitaliy Vasilenko - [email protected]
TF_STATE=${2:-terraform.tfstate}
export VAULT_TOKEN=$(vault write -format=json auth/approle/login role_id="${VAULT_ROLE_ID}" secret_id="${VAULT_SECRET_ID}" | jq -r '.auth.client_token')
function hashsum () {
file=$1
if [ $(uname -s) == "Darwin" ]; then
echo $(md5 ${file} | awk '{print $NF}' | tr -d '\n')
else
echo $(md5sum ${file} | awk '{print $1}' | tr -d '\n')
fi
}
case $1 in
download)
if tf_state_b64=$(vault kv get -field=state ${VAULT_KV_PATH}) 2>/dev/null ; then
echo ${tf_state_b64} | base64 -d | gzip -d > ${TF_STATE}
fi
;;
validate)
if [ -f "${TF_STATE}" ]; then
tf_state_hashsum=$(hashsum ${TF_STATE})
if vault_state_hashsum=$(vault kv get -field=hashsum ${VAULT_KV_PATH}) 2>/dev/null ; then
if [ "${vault_state_hashsum}" == "${tf_state_hashsum}" ]; then
echo "State was not changed"
else
echo "The state has changed"
fi
else
echo "No state in vault"
fi
else
echo "No state file"
fi
;;
upload)
if [ -f "${TF_STATE}" ]; then
tf_state_b64=$(cat ${TF_STATE} | gzip -9 | base64 | tr -d '\n')
tf_state_hashsum=$(hashsum ${TF_STATE})
if vault_state_hashsum=$(vault kv get -field=hashsum ${VAULT_KV_PATH}) 2>/dev/null ; then
if [ "${vault_state_hashsum}" == "${tf_state_hashsum}" ]; then
echo "State was not changed"
exit 0
fi
fi
vault kv put ${VAULT_KV_PATH} state=${tf_state_b64} hashsum=${tf_state_hashsum} time=$(date +%s)
else
echo "No state file to upload"
fi
;;
*)
echo "Unknown action"
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment