Skip to content

Instantly share code, notes, and snippets.

@leucos
Created May 25, 2015 15:57
Show Gist options
  • Save leucos/405b406b9d6bde0c3d39 to your computer and use it in GitHub Desktop.
Save leucos/405b406b9d6bde0c3d39 to your computer and use it in GitHub Desktop.
Transparent encryption/decryption with pre-commit and post-commit hooks
#!/bin/sh
#
# Post-commit hook that decrypts files containing '$ANSIBLE_VAULT'
#
# File should be .git/hooks/post-commit and executable
CRYPT_TAG='^\$ANSIBLE_VAULT'
EXIT_STATUS=0
wipe="\033[1m\033[0m"
yellow='\033[1;33m'
red='\e[0;31m'
green='\e[0;32m'
# carriage return hack. Leave it on 2 lines.
cr='
'
if [ ! -r '.vault_password_hooks' ]; then
exit 0
fi
for f in $(git diff --name-only HEAD^ HEAD)
do
# test for the presence of the required bit.
MATCH=`head -n4 $f | grep --no-messages -- "$CRYPT_TAG"`
if [ ! -z "$MATCH" ] ; then
# Build the list of unencrypted files if any
UNENCRYPTED_FILES="$f$cr$UNENCRYPTED_FILES"
EXIT_STATUS=1
fi
done
if [ ! $EXIT_STATUS = 0 ] ; then
echo '# POST-COMMIT'
echo '# Looks like crypted ansible files are in repos.'
echo '#'
while read -r line; do
if [ -n "$line" ]; then
echo -e "#\t${yellow}unencrypted: $line${wipe}"
fi
done <<< "$UNENCRYPTED_FILES"
echo '#'
echo "# Decrypting these files now."
echo "#"
while read -r line; do
if [ -n "$line" ]; then
echo -ne "#\t${yellow}decrypting: $line${wipe} => "
if ansible-vault decrypt ${line} --vault-password-file=.vault_password_hooks > /dev/null 2>&1; then
echo -e " ${green}success${wipe}"
else
echo -e " ${red}error${wipe}"
exit 1
fi
fi
done <<< "$UNENCRYPTED_FILES"
echo "#"
echo "# Files decrypted"
echo "#"
echo "# Remove .vault_password_hooks from .gitgnore to prevent transparent decryption"
echo
exit 0
fi
exit $EXIT_STATUS
#!/bin/sh
#
# Pre-commit hook that verifies if all files containing 'vault: true' in it's modeline
# are encrypted.
# If not, commit will fail with an error message
#
# From an idea by Raphael Campardou (@ralovely)
# https://gist.github.com/ralovely/9367737
#
# Adapted for transparent encryption/decryption
#
# File should be .git/hooks/pre-commit and executable
#
# If you want enryption/decryption to be transparent, you must add `.vault_password_hooks`
# in your .gitignore file so the hooks won't delete this file, and reuse it when needed.
#
# Tag to look for
CRYPT_TAG='^#.*mode:.*vault: true'
EXIT_STATUS=0
wipe="\033[1m\033[0m"
yellow='\033[1;33m'
red='\e[0;31m'
green='\e[0;32m'
# carriage return hack. Leave it on 2 lines.
cr='
'
for f in $(git diff --cached --name-only)
do
# test for the presence of the required bit.
MATCH=`head -n4 $f | grep --no-messages -- "$CRYPT_TAG"`
if [ ! -z "$MATCH" ] ; then
# Build the list of unencrypted files if any
UNENCRYPTED_FILES="$f$cr$UNENCRYPTED_FILES"
EXIT_STATUS=1
fi
done
if [ ! $EXIT_STATUS = 0 ] ; then
echo '# COMMIT POSTPONED'
echo '# Looks like unencrypted ansible-vault files are part of the commit:'
echo '#'
while read -r line; do
if [ -n "$line" ]; then
echo -e "#\t${yellow}unencrypted: $line${wipe}"
fi
done <<< "$UNENCRYPTED_FILES"
echo '#'
echo "# Encrypting these files now. Hit <Ctrl+C> to cancel'"
echo "#"
if [ ! -r '.vault_password_hooks' ]; then
echo -n "# Enter vault password:"
exec < /dev/tty
read -s password
echo -en "\n# Confirm vault password:"
read -s password_confirm
echo -e "\n#"
if [ "x${password}" != "x${password_confirm}" ]; then
echo -e "#\n# ${red}Error: passwords do not match !${wipe}"
exit 1
fi
echo $password > .vault_password_hooks
fi
while read -r line; do
if [ -n "$line" ]; then
echo -ne "#\t${yellow}encrypting: $line${wipe} => "
if ansible-vault encrypt ${line} --vault-password-file=.vault_password_hooks > /dev/null 2>&1; then
echo -e " ${green}success${wipe}"
else
echo -e " ${red}error${wipe}"
exit 1
fi
fi
done <<< "$UNENCRYPTED_FILES"
echo "#"
echo "# Files encrypted"
echo "#"
if [ ! -r '.gitignore' ] || ! grep '^.vault_password_hooks$' .gitignore > /dev/null; then
echo -e "# Removing temporary password file.\n# Add .vault_password_hooks to .gitgnore to make it persistent"
rm .vault_password_hooks
fi
exit 0
fi
exit $EXIT_STATUS
@agowa
Copy link

agowa commented Jan 27, 2018

There is an error in the pre-commit script. It encrypts the file, but doesn't add it to the commit, so the file is committed without encryption.
To fix that, simply add after line 70 "git add ${line}"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment