4

I'm trying to use ansible-vault to secure the secret files in my project before I push them to Git. There's loads of advice out there on how to set this up in part, but everything I've read is specifically for diff'ing these files, not how to encrypt them as you put them in - it looks like to initially commit them you need to manually vault them first. Is there a way of doing this vaulting on the fly?

What I have so far: .git/config:

 [diff "ansible-vault"]
 textconv = "ansible-vault view"

ansible.cfg:

 [defaults]
 vault_password_file = .vault

.gitattributes:

key.pem diff=ansible-vault merge=binary

This works fine if I run the following commands:

 ansible-vault encrypt key.pem 
 git add key.pem
 ansible-vault decrypt key.pem 
 git diff --cached

I'd like to automate the ansible-vault encrypt/decrypt commands within git. Any ideas?

2
  • Thinking about this, am I using ansible-vault for the wrong purpose here? I guess generally you'd have a playbook reading the vaulted files, so the files being vaulted is what you want here. What I'm trying to do here is use vault just as an encryption tool. (Would still be nice to be able to do this, though) Commented Jul 20, 2022 at 11:45
  • I think you're looking for something like this, but using ansible-vault instead of gpg.
    – larsks
    Commented Jul 21, 2022 at 13:45

1 Answer 1

5

I just had the same want for my personal learning experience (home-lab). What I found was the .git/hooks/pre-commit would help. I have not automated the process, so for your inspiration here are the parts I have.

The .git/hooks/pre-commit is a bash script. The FILE_PATTERN variable determines the files I want to find and warn about are not ansible-vault encrypted. FOr me that would be all yaml files containing variables I don't want to share.

#!/bin/sh
#
# Ansible Vault Secrets Git Hook
#
# Hook to check if an un-encrypted FILE_PATTERN file is being commited. Useful if secrets 
# are retained in ansible vault encrypted file(s) that should never be committed to the repository
# un-encrypted. Contact a repository owner for the ansible vault password.
#
# Put this file in .git/hooks/pre-commit

# set -o xtrace
set -o nounset

FILE_PATTERN="my_secrets_file.yaml\|vars/"
ENCRYPTED_PATTERN="\$ANSIBLE_VAULT"

is_encrypted() {
  local file=$1
  if ! git show :"$file" | grep --quiet "^${ENCRYPTED_PATTERN}"; then
    echo "Located a staged file that should be encrypted:\n> ${file}\n"
    echo "Please un-stage this file. If you are adding or updating this file, please encrypt it before staging."
    echo "Alternatively, you can git checkout the latest encrypted version of the file before committing.\n"
    echo "Remember... Only YOU Can Prevent Secret Leakage."
    exit 1
  fi
}

echo "Running pre-commit checks..."
git diff --cached --name-only | grep "${FILE_PATTERN}" | while IFS= read -r line; do
  is_encrypted "${line}"
done

This solves part 1 - i.e. letting me know that I have secrets about to get committed and stopping the misery right there. A simple "git commit" will get this caught.~

The 2nd part is encrypting the necessary files. This is simply a matter of again finding the relevant files and encrypting these. I have made this script to put some convenience into this. The 'files' variable contains the (same) patterns to look for the files.

#!/bin/bash

# If number of arguments is 0
if [ $# -eq 0 ]
  then
    echo "This script will encrypt of decrypt all files containing secrets."
    echo "There are all files in vars as well as all secrets.yaml files under each service."
    echo "Specify 'decrypt' or 'encrypt' as argument"
    echo "If you put the vault password in a password file named .vault_password, the script will not ask for a password."
    exit 1
fi

files=`find . -type f -name "me_secrets_file.yaml"`
files="$files vars/*"

password_type=--ask-vault-password
if [ -f ".vault_password" ]
  then
    if [ `stat -c %a .vault_password` != "600" ]
      then
        echo ".vault_password file has bad permissions; fixing this to 600"
        chmod 600 .vault_password
    fi
    password_type="--vault-password-file .vault_password"
fi

if [ $1 == "encrypt" ]
  then
    ansible-vault encrypt $password_type $files
    for value in $files; do
        echo $value;
    done

elif [ $1 == "decrypt" ]
  then
    ansible-vault decrypt $password_type $files
    for value in $files; do
        echo $value;
    done
else
    echo "Wrong argument supplied.  Run without arguments to see allowed ones."
fi

Used as:

./vault.sh {encrypt|decrypt}

This solves part 2 - encryption/decryption of the necessary files.

I am sure these two parts can be combined so that encryption happens as part of the pre-commit hook on any file which is not already encrypted. Improve by putting -´.vault_password in ~/.vault_password and so on.

The pre-commit script is not originally of my doing, but I did not save the reference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.