From fda131504b571b4bb2fe3dafe9291e18d00a3ca6 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Wed, 12 Oct 2016 10:57:41 -0600 Subject: [PATCH] Support multiple vault passwords in keyring script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows users to specify a key name in a given project’s `ansible.cfg` file and thus handle keyring integration with vaults with different passwords. If no key name is specified, the original default `ansible` key name will be used. Other improvements: * `username` is now optional; defaults to user that invokes the script * change string interpolation to new `.format()` style * clean up and expand upon documentation * enforce PEP 8 compliance --- contrib/vault/vault-keyring.py | 61 ++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/contrib/vault/vault-keyring.py b/contrib/vault/vault-keyring.py index b8394da10e9..8a51e6486f0 100755 --- a/contrib/vault/vault-keyring.py +++ b/contrib/vault/vault-keyring.py @@ -1,8 +1,9 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # (c) 2014, Matt Martz +# (c) 2016, Justin Mayer # -# This file is part of Ansible +# This file is part of Ansible. # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,30 +18,42 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . # +# ============================================================================= # -# Script to be used with vault_password_file or --vault-password-file -# to retrieve the vault password via your OSes native keyring application +# This script is to be used with vault_password_file or --vault-password-file +# to retrieve the vault password via your OS's native keyring application. # -# This script requires the ``keyring`` python module +# This file *MUST* be saved with executable permissions. Otherwise, Ansible +# will try to parse as a password file and display: "ERROR! Decryption failed" # -# Add a [vault] section to your ansible.cfg file, -# the only option is 'username'. Example: +# The `keyring` Python module is required: https://pypi.python.org/pypi/keyring +# +# By default, this script will store the specified password in the keyring of +# the user that invokes the script. To specify a user keyring, add a [vault] +# section to your ansible.cfg file with a 'username' option. Example: # # [vault] -# username = 'ansible_vault' +# username = 'ansible-vault' +# +# Another optional setting is for the key name, which allows you to use this +# script to handle multiple project vaults with different passwords: # -# Additionally, it would be a good idea to configure vault_password_file in -# ansible.cfg +# [vault] +# keyname = 'ansible-vault-yourproject' +# +# You can configure the `vault_password_file` option in ansible.cfg: # # [defaults] # ... # vault_password_file = /path/to/vault-keyring.py # ... # -# To set your password: python /path/to/vault-keyring.py set +# To set your password, `cd` to your project directory and run: +# +# python /path/to/vault-keyring.py set # -# If you choose to not configure the path to vault_password_file in ansible.cfg -# your ansible-playbook command may look like: +# If you choose not to configure the path to `vault_password_file` in +# ansible.cfg, your `ansible-playbook` command might look like: # # ansible-playbook --vault-password-file=/path/to/vault-keyring.py site.yml @@ -51,29 +64,35 @@ ANSIBLE_METADATA = {'status': ['preview'], import sys import getpass import keyring -import ConfigParser - import ansible.constants as C + def main(): - (parser,config_path) = C.load_config_file() - try: + (parser, config_path) = C.load_config_file() + if parser.has_option('vault', 'username'): username = parser.get('vault', 'username') - except ConfigParser.NoSectionError: - sys.stderr.write('No [vault] section configured in config file: %s\n' % config_path) - sys.exit(1) + else: + username = getpass.getuser() + + if parser.has_option('vault', 'keyname'): + keyname = parser.get('vault', 'keyname') + else: + keyname = 'ansible' if len(sys.argv) == 2 and sys.argv[1] == 'set': + intro = 'Storing password in "{}" user keyring using key name: {}\n' + sys.stdout.write(intro.format(username, keyname)) password = getpass.getpass() confirm = getpass.getpass('Confirm password: ') if password == confirm: - keyring.set_password('ansible', username, password) + keyring.set_password(keyname, username, password) else: sys.stderr.write('Passwords do not match\n') sys.exit(1) else: - sys.stdout.write('%s\n' % keyring.get_password('ansible', username)) + sys.stdout.write('{}\n'.format(keyring.get_password(keyname, + username))) sys.exit(0)