Last active
September 25, 2025 19:16
-
-
Save utoddl/69ff0baa35b4170df8d1eec61563a1ac to your computer and use it in GitHub Desktop.
Report configured Ansible Vault IDs and what vaulted blobs they can decrypt
This file contains hidden or 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
| #!/usr/bin/env bash | |
| # | |
| # Author: Todd Lewis (@utoddl on github.com), 2025-09-25 | |
| # License: CC-By, GNU General Public License v3.0 or later, BSD, Fishing | |
| # | |
| # vault-id-report.sh - Takes no parameters, not even "-h". | |
| # | |
| # Examines ansible-vaulted data in and below the current directory | |
| # and reports which of your configured VAULT_IDENTITY_LIST Vault IDs | |
| # can decrypt them. | |
| shopt -s extglob | |
| # Read configured vault identities from ansible-config | |
| # shellcheck disable=SC2207 | |
| declare -a vault_identity_list=( $(ansible-config dump --only-changed \ | |
| | grep VAULT_IDENTITY_LIST \ | |
| | grep -P -o "'[^']+'" \ | |
| | tr -d "'" | |
| ) | |
| ) | |
| declare -A vault_ids=() | |
| max_vault_id_width=6 | |
| for id in "${vault_identity_list[@]}" ; do | |
| id_key="${id/@*/}" | |
| [ "$max_vault_id_width" -gt "${#id_key}" ] || max_vault_id_width="${#id_key}" | |
| vault_ids["${id/@*/}"]="${id/*@/}" | |
| done | |
| printf "# Configured Vault IDs and Files\n" | |
| for id in "${!vault_ids[@]}" ; do | |
| printf "%-${max_vault_id_width}s %s\n" "$id" "${vault_ids[$id]}" | |
| done | |
| printf "\n# IDs decrypting discovered ANSIBLE_VAULT data\n" | |
| # These exports are necessary to prevent subsequent ansible-vault | |
| # invocations from using all the Vault IDs you normally have configured. | |
| export ANSIBLE_VAULT_IDENTITY='' | |
| export ANSIBLE_VAULT_IDENTITY_LIST='' | |
| # shellcheck disable=SC2016 | |
| vault_header_rx='^( *)(\$ANSIBLE_VAULT;.*)$' | |
| vault_data_rx='^( *)([0-9a]+)$' | |
| vault_blob_init() { | |
| blob_data='' | |
| blob_leading_space='^' | |
| blob_file_name='' | |
| blob_line_no_first=0 | |
| blob_line_no_last=0 | |
| } | |
| vault_blob_test() { | |
| if [ -n "$blob_data" ] ; then | |
| success=0 | |
| for id in "${!vault_ids[@]}" ; do | |
| if ansible-vault decrypt --vault-password-file "${vault_ids[$id]}" > /dev/null 2>&1 < <(printf "%s\n" "$blob_data") ; then | |
| success=$((success + 1)) | |
| printf "%-${max_vault_id_width}s %s:%d-%d %s\n" "$id" "$blob_file_name" "$blob_line_no_first" "$blob_line_no_last" "${blob_data%%$'\n'*}" | |
| fi | |
| done | |
| if [ "$success" -eq 0 ] ; then | |
| printf "%-${max_vault_id_width}s %s:%d-%d\n" "<none>" "$blob_file_name" "$blob_line_no_first" "$blob_line_no_last" | |
| fi | |
| fi | |
| vault_blob_init | |
| } | |
| vault_blob_append() { | |
| if [ "$file_name_in" != "$blob_file_name" ] ; then | |
| vault_blob_test | |
| fi | |
| if [[ "$data_in" =~ $vault_header_rx ]] ; then | |
| vault_blob_test | |
| [[ "$data_in" =~ $vault_header_rx ]] | |
| blob_data="${BASH_REMATCH[2]}"$'\n' | |
| blob_leading_space="${BASH_REMATCH[1]}" | |
| vault_data_rx="^(${blob_leading_space})([0-9a]+)$" | |
| blob_file_name="$file_name_in" | |
| blob_line_no_first="$line_no_in" | |
| blob_line_no_last="$line_no_in" | |
| return | |
| fi | |
| if [ -n "$blob_data" ] && [[ "$data_in" =~ $vault_data_rx ]] ; then | |
| blob_data+="${BASH_REMATCH[2]}"$'\n' | |
| blob_line_no_last="$line_no_in" | |
| else | |
| if [ -n "$vault_blob_data" ] ; then | |
| vault_blob_test | |
| fi | |
| fi | |
| } | |
| # State machine for reading ansible-vault data blobs. | |
| # shellcheck disable=SC2016 | |
| while IFS=':' read -r file_name_in line_no_in data_in ; do | |
| vault_blob_append | |
| done < <(grep -n -r -P '^( *)(\$ANSIBLE_VAULT;.*|[\da]+)$' . 2>/dev/null ) | |
| vault_blob_test |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment