configs/ansible-vault_reencrypt.sh
2025-05-09 23:25:40 +02:00

173 lines
5.6 KiB
Bash
Executable file

#!/bin/sh
# Usage: $0 [ -f old_password_file | -i old_vault_id ] [ -F new_password_file | -I new_vault_id ] vars_file.yaml
usage() {
printf '%s\n' "USAGE: $0 [ -f old_password_file | -i old_vault_id ] [ -F new_password_file | -I new_vault_id ] <vars_file.yaml>"
printf '%s\n' "Example: $0 -f old.passphrase -I other/ansible-vault/default@pass-client.sh inventory/group_vars/all.yaml"
}
hasold=0
hasnew=0
if [ $# -ge 1 ]; then
while getopts 'f:i:F:I:h' opt; do
case $opt in
f) OLD_PASSWORD_FILE=$OPTARG
OLD_PASS_OPT="--vault-password-file ${OLD_PASSWORD_FILE}"
hasold=1 ;;
i) OLD_VAULT_ID=$OPTARG
OLD_PASS_OPT="--vault-id ${OLD_VAULT_ID}"
hasold=1 ;;
F) NEW_PASSWORD_FILE=$OPTARG
NEW_PASS_OPT="--vault-password-file ${NEW_PASSWORD_FILE}"
REKEY_NEW_PASS_OPT="--new-vault-password-file ${NEW_PASSWORD_FILE}"
hasnew=1 ;;
I) NEW_VAULT_ID=$OPTARG
NEW_PASS_OPT="--vault-id ${NEW_VAULT_ID}"
REKEY_NEW_PASS_OPT="--new-vault-id ${NEW_VAULT_ID}"
hasnew=1 ;;
h) usage && exit 0;;
esac
done
fi;
shift $(($OPTIND-1))
if [ "x$OLD_PASSWORD_FILE" != "x" ] && [ "x$OLD_VAULT_ID" != "x" ]; then
printf '%s\n' "ERROR: Both old_password_file and old_vault_id provided."
usage && exit 1;
fi
if [ "x$NEW_PASSWORD_FILE" != "x" ] && [ "x$NEW_VAULT_ID" != "x" ]; then
printf '%s\n' "ERROR: Both new_password_file and new_vault_id provided."
usage && exit 1;
fi
if [ $# -eq 1 ] && [ $hasold -eq 1 ] && [ $hasnew -eq 1 ] ; then
VARS_FILE="$1"
else
usage && exit 1;
fi;
FILE=$(cat "$VARS_FILE")
# Read file line by line
# when line is of type ^[^(: )]: !vault |$
# get variable name
# go to vault mode
# if next line begins with a ' ', stay in vault mode and get the number of spaces before '$ANSIBLE_VAULT;(.*)'
# else, exit vault mode
# if next line begins with a ' ' (number of spaces matching indentation), stay in vault mode
# else, exit vault mode
isvault=0
isvault_data=0
n=0
prevline=''
while IFS= read -r line; do
if [ $isvault -eq 0 ]; then
# if the previous line exists and is a "normal" line,
# print it
if [ $n -gt 0 ]; then
# printf '%s\n' "$n $prevline"
printf '%s\n' "$prevline"
fi
# if we are not in a vault yet, check if the current line
# looks like a vaulted var
printf '%s\n' "$line" | grep -q '^[^#:]*: !vault |$'
if [ $? -eq 0 ]; then
# if the line looks like a vaulted var, save its name
var_name=$(printf '%s\n' "$line" | cut -d':' -f1)
isvault=1
else
# if the line doesn't look like a vaulted var, do nothing
isvault=0
fi
else
# the previous line was a vault line
if [ $isvault_data -eq 0 ]; then
# if we are not in vaulted data yet, check if the line
# starts with a space
printf '%s\n' "$line" | grep -q '^ .*'
if [ $? -eq 0 ]; then
# if this is the first line of vaulted data,
# save the line indentation
data_indent=$(printf '%s\n' "$line" | grep -o '^ *')
# and print the var name
# printf '%s\n' "var_name: $var_name"
isvault_data=1
# printf '%s\n' "${data_indent}nothing"
# printf '%s\n' "ANSIBLE_CALLBACK_RESULT_FORMAT=yaml ansible localhost -m debug -a var=${var_name} -e @${VARS_FILE} ${OLD_PASS_OPT} 2>/dev/null | grep -v 'localhost | .* =>' | sed s/'^ *'//g" >&2
var_value_plain=$( ANSIBLE_CALLBACK_RESULT_FORMAT=yaml ansible localhost -m debug -a var=${var_name} -e @${VARS_FILE} ${OLD_PASS_OPT} 2>/dev/null | grep -v 'localhost | .* =>' | sed s/'^[^:]*: '//g )
if [ $? -eq 0 ]; then
# and print the var name and its plain data
# printf '%s\n' "var_name: $var_name" >&2
# printf '%s\n' "$var_value_plain"
# printf '%s\n' "ansible-vault encrypt_string \"${var_value_plain}\" --name ${var_name} ${NEW_PASS_OPT}" >&2
ansible-vault encrypt_string "${var_value_plain}" --name ${var_name} ${NEW_PASS_OPT} 2>/dev/null
printf '\n'
else
printf '%s\n' "Error when decrypting data for variable ${var_name}. Skipping." >&2
fi
else
# if this is not the first line of vaulted data,
# we are not in a vault
isvault=0
isvault_data=0
# reset vault-related variables
var_name=''
data_indent=''
# # exit with an error
# printf '%s\n' "ERROR: No vault data found at line $n, exiting." >&2
# exit 2
# check if the current line
# looks like a vaulted var
printf '%s\n' "$line" | grep -q '^[^#: ]*: !vault |$'
if [ $? -eq 0 ]; then
# if the line looks like a vaulted var, save its name
var_name=$(printf '%s\n' "$line" | cut -d':' -f1)
isvault=1
else
# if the line doesn't look like a vaulted var, do nothing
isvault=0
fi
fi
else
# if we are in the vaulted data section, check if the line
# starts with the same indentation as the first
# echo "${data_indent}plop"
# printf '%s\n' "$line"
printf '%s\n' "$line" | grep -qE "^${data_indent}[^ ]+"
if [ $? -eq 0 ]; then
# if we are still in the vaulted data section, do nothing
# printf '%s\n' "${data_indent}nothing"
:
else
# if we are out of the vaulted data section, register it
isvault_data=0
isvault=0
# reset vault-related variables
var_name=''
data_indent=''
# check if the current line
# looks like a vaulted var
printf '%s\n' "$line" | grep -q '^[^#: ]*: !vault |$'
if [ $? -eq 0 ]; then
# if the line looks like a vaulted var, save its name
var_name=$(printf '%s\n' "$line" | cut -d':' -f1)
isvault=1
else
# if the line doesn't look like a vaulted var, do nothing
isvault=0
fi
fi
fi
fi
prevline="$line"
n=$(( $n + 1 ))
done <<EOF
$FILE
EOF
# print the last line
# printf '%s\n' "$n $prevline"
printf '%s\n' "$prevline"