Created
January 5, 2021 18:13
-
-
Save jeffmccune/3d781c62462813b3fec9772f742ce057 to your computer and use it in GitHub Desktop.
Execute a command with Google Service Account credentials and cleanup after
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/bash | |
# | |
# Execute a command with GOOGLE_APPLICATION_CREDENTIALS set to point to a | |
# Google Service Account key JSON file. The key data is managed by vault and | |
# the lease is released on exit. | |
# | |
# Requires: vault, jq, base64 | |
: "${VAULT_ADDR:=https://vault.example}" | |
: "${DEPLOY_ENV:=dev}" | |
export DEPLOY_ENV | |
rval=100 | |
# Arguments to pass to vault | |
declare -a vault_args | |
while [[ $# -gt 0 ]]; do | |
[[ "$1" == '--' ]] && break | |
vault_args+=("$1") | |
shift | |
done | |
shift | |
usage() { | |
cat <<EOF | |
Usage: $(basename $0) gcp/key/myroleset -- command | |
GOOGLE_APPLICATION_CREDENTIALS is set to the service account key file | |
associated with the Vault roleset myroleset. The vault lease is revoked and | |
the credentials file deleted after command completes. The return value of | |
command is returned. | |
EOF | |
} | |
notoken() { | |
# shellcheck disable=SC2016 | |
echo "Error: VAULT_TOKEN is unset" >&2 | |
echo "Browse to ${VAULT_ADDR} select Copy Token after logging in." | |
} | |
if [[ $# -eq 0 ]]; then | |
usage | |
echo "Error: no command specified" | |
exit 99 | |
fi | |
if [[ -z ${VAULT_TOKEN} ]]; then | |
notoken | |
exit 1 | |
fi | |
tmpdir="$(mktemp -d)" | |
mytemp() { | |
TMPDIR="${tmpdir}" mktemp | |
} | |
renew() { | |
if [[ -n ${LEASE:-} ]]; then | |
vault lease renew "${LEASE}" | |
fi | |
} | |
revoke() { | |
if [[ -n ${LEASE:-} ]]; then | |
vault lease revoke "${LEASE}" >/dev/null | |
fi | |
} | |
finish() { | |
if [[ -e "${tmpdir:-}" ]]; then | |
rm -rf "${tmpdir}" | |
fi | |
revoke | |
exit ${rval:-100} | |
} | |
trap finish EXIT | |
set -eu -o pipefail | |
# Store the vault fields as json | |
json="$(mytemp)" | |
vault read -format=json "${vault_args[@]}" > "$json" | |
# Extract the Google Service Account key JSON into creds | |
creds="$(mytemp)" | |
jq -r .data.private_key_data "${json}" | base64 -d > "${creds}" | |
# Make the credentials available as Application Default Credentials. | |
# See: https://cloud.google.com/docs/authentication/production#passing_variable | |
export GOOGLE_APPLICATION_CREDENTIALS="${creds}" | |
# gcloud variables | |
export CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE="${creds}" | |
# for tools which can't read the filesystem, but can read the environment | |
GOOGLE_CREDENTIALS="$(<"${creds}")" | |
export GOOGLE_CREDENTIALS | |
# Store the lease for later revocation of the key | |
LEASE="$(jq -r .lease_id "${json}")" | |
# Reset VAULT_ADDR and VAULT_TOKEN based on the deployment environment. This | |
# allows credentials from one vault to be used to manage another vault instance | |
# using terraform. | |
eval 'addr=${VAULT_ADDR'_${DEPLOY_ENV}':-}' | |
eval 'tokn=${VAULT_TOKEN'_${DEPLOY_ENV}':-}' | |
if [[ -n "${DEBUG:-}" ]]; then | |
echo "# Identity: $(echo "${GOOGLE_CREDENTIALS}" | jq -r '.client_email')" >&2 | |
fi | |
# Execute the passed command. VAULT_ADDR and VAULT_TOKEN are set in a subshell | |
# to preserve the address and token where the credentials need to be revoked. | |
if [[ -n "${addr:-}" ]] && [[ -n "${tokn:-}" ]]; then | |
(VAULT_ADDR="$addr"; VAULT_TOKEN="$tokn"; "$@") | |
rval=$? | |
else | |
"$@" | |
rval=$? | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage: