diff --git a/ansible-vault-tools.py b/ansible-vault-tools.py index b9b963d..cfbe33e 100755 --- a/ansible-vault-tools.py +++ b/ansible-vault-tools.py @@ -17,7 +17,7 @@ subparsers = parser.add_subparsers(title="commands", dest="command", required=Tr # Encrypt arguments parser_encrypt = subparsers.add_parser( "encrypt", - help="Encrypt a string using ansible-vault", + help="Encrypt a string or file using ansible-vault", ) encrypt_flags = parser_encrypt.add_mutually_exclusive_group(required=True) encrypt_flags.add_argument( @@ -35,13 +35,16 @@ encrypt_flags.add_argument( # Decrypt arguments parser_decrypt = subparsers.add_parser( "decrypt", - help="Print a variable of one or multiple hosts and decrypt it if necessary", + help="Decrypt a string or file using ansible-vault", ) decrypt_flags = parser_decrypt.add_mutually_exclusive_group(required=True) decrypt_flags.add_argument( "-H", "--host", - help="Host name from Ansible inventory for which you want to get the variable", + help=( + "Host name from Ansible inventory for which you want to get a specific variable." + "Also supports 'all'" + ), dest="decrypt_host", ) decrypt_flags.add_argument( @@ -56,6 +59,20 @@ parser_decrypt.add_argument( help="Variable you want to print", dest="decrypt_var", ) +# All variables +parser_allvars = subparsers.add_parser( + "allvars", + help="Print all variables of a host", +) +parser_allvars.add_argument( + "-H", + "--host", + help=( + "Host name from Ansible inventory for which you want to get all variables." + "Also supports 'all'" + ), + dest="allvars_host", +) def convert_ansible_errors(error: str) -> str: @@ -85,7 +102,7 @@ def ask_for_confirm(question: str) -> bool: return answer == "y" -def encrypt_string(password): +def encrypt_string(password: str) -> str: """Encrypt string with ansible-vault""" result = subprocess.run( ["ansible-vault", "encrypt_string"], @@ -136,6 +153,34 @@ def decrypt_file(filename: str) -> str: return f"File '{filename}' was not changed" +def allvars(host: str) -> str: + """Decrypt/print all variables from one or multiple hosts""" + # Run ansible var for all host vars as seen from localhost + # Send return as JSON + ansible_command = ["ansible", "localhost", "-m", "debug", "-a", "var=hostvars"] + ansible_env = { + "ANSIBLE_LOAD_CALLBACK_PLUGINS": "1", + "ANSIBLE_STDOUT_CALLBACK": "json", + } + result = subprocess.run( + ansible_command, env=ansible_env, capture_output=True, text=True, check=False + ) + + # Reduce JSON + ansible_output = json.loads(result.stdout)["plays"][0]["tasks"][0]["hosts"]["localhost"][ + "hostvars" + ] + + # If only a specific host was requested, reduce the output to that host + if host != "all": + try: + ansible_output = ansible_output[host] + except KeyError: + sys.exit(f"ERROR: Host '{host}' not found.") + + return json.dumps(ansible_output, indent=2) + + def encrypt_file(filename: str) -> str: """Encrypt a file with ansible-vault""" @@ -204,6 +249,10 @@ def main(): elif args.decrypt_file: filename = input("Enter filename: ") if not args.decrypt_file else args.decrypt_file output = decrypt_file(filename) + # ALLVARS + elif args.command == "allvars": + host = input("Enter host: ") if not args.allvars_host else args.allvars_host + output = allvars(host) if output: print(output)