-
-
Save exAspArk/97b8924b843a9053d34d3cca8f0ef27a to your computer and use it in GitHub Desktop.
A shell script for merging encrypted Ansible vault files in a git repository
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/sh | |
############################################################################### | |
# USAGE: | |
# > ansible_vault_merge.sh [-p PASSWORD_FILE VAULT_YAML_FILE | |
# This shell script handles conflicts generated by attempts to merge encrypted | |
# Ansible Vault files. Run this command to attempt a merge on the unencrypted | |
# versions of the file. If there are conflicts, you will be given a chance to | |
# correct them in $EDITOR | |
# https://gist.github.com/exAspArk/97b8924b843a9053d34d3cca8f0ef27a | |
############################################################################### | |
# Ensure we are inside the working directory of a git repo | |
GIT_ROOT=`git rev-parse --show-toplevel` | |
if [ $? != 0 ]; then | |
exit $? | |
fi | |
# Allow the user to use custom ansible vault password file with "-p" arg | |
while getopts "p:" opt; do | |
case $opt in | |
p) | |
VAULT_PASSWORD_FILE=$OPTARG | |
;; | |
\?) | |
echo "Invalid option: -$OPTARG" >&2 | |
exit 1 | |
;; | |
esac | |
done | |
shift $(($OPTIND - 1)) | |
# If no vault has been provided, abort! | |
VAULT_FILE=$1 | |
if [ -z $VAULT_FILE ]; then | |
echo "Usage: $0 [-p PASSWORD_FILE] VAULT_YAML_FILE" | |
exit 1 | |
fi | |
# Clean before exit | |
function cleanup { | |
rm -f $NEW_VAULT_PASSWORD_FILE $BASE $CURRENT $OTHER | |
echo "\nCleaning successful" | |
} | |
trap cleanup EXIT | |
# If the password file doesn't exist, we prompt for the password and save it | |
if [ -z "$VAULT_PASSWORD_FILE" ]; then | |
read -s -p "Vault Password: " VAULT_PASSWORD | |
NEW_VAULT_PASSWORD_FILE=`mktemp ${VAULT_FILE}.password.XXXX` | |
VAULT_PASSWORD_FILE=$NEW_VAULT_PASSWORD_FILE | |
echo "\nRemembering password in $VAULT_PASSWORD_FILE" | |
echo $VAULT_PASSWORD > $VAULT_PASSWORD_FILE | |
else | |
echo "Using password saved in $VAULT_PASSWORD_FILE" | |
fi | |
VAULT_OPT="--vault-password-file=$VAULT_PASSWORD_FILE" | |
# Fetch the base (common ancestor) version of the encrypted vault file, save | |
# it to a temporary location, and decrypt it. Hat Tip to the git-merge manual | |
# page for tipping me off to the `git show :1:path` notation | |
BASE=`mktemp ${VAULT_FILE}.base.XXXX` | |
git show :1:${VAULT_FILE} > $BASE 2> /dev/null | |
if [ $? != 0 ]; then | |
echo "Path '${VAULT_FILE}' does not have any conflicts." | |
rm $BASE | |
exit 1 | |
fi | |
ansible-vault decrypt $VAULT_OPT $BASE || exit $? | |
# Do the same with the current (branch we are merging INTO) version of the vault | |
# file | |
CURRENT=`mktemp ${VAULT_FILE}.current.XXXX` | |
git show :2:${VAULT_FILE} > $CURRENT 2> /dev/null | |
ansible-vault decrypt $VAULT_OPT $CURRENT || exit $? | |
# And finally, with the other (branch we a merging FROM) version of the vault | |
OTHER=`mktemp ${VAULT_FILE}.other.XXXX` | |
git show :3:${VAULT_FILE} > $OTHER 2> /dev/null | |
ansible-vault decrypt $VAULT_OPT $OTHER || exit $? | |
# Now that we have all three versions decrypted, ask git to attempt the merge | |
# again. If it fails again due to a conflict, open $EDITOR and let the user | |
# perform a manual merge | |
git merge-file $CURRENT $BASE $OTHER | |
if [ $? == 0 ]; then | |
echo "\nMerge successful" | |
else | |
echo "\nMerge conflict; opening editor to resolve." | |
$EDITOR $CURRENT | |
fi | |
ansible-vault encrypt $VAULT_OPT $CURRENT | |
cp $CURRENT $VAULT_FILE | |
echo "File $VAULT_FILE has been updated!" | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In order to get this to work on Linux I had to change #!/bin/sh to #!/bin/bash (the read option doesn't take -s in sh, and functions don't seem very well supported in sh)