diff --git a/README.md b/README.md index 1eb0f9207e8fed49296292fd84f30312715e5587..d4c74a90f95d9fcb6b9bc630a819c3529e6a9dcd 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,18 @@ Host *.ffs03 ProxyCommand ssh ffs03 -W 10.0.3.$(( $(echo %n | sed -e 's/.ffs03//') - 3000 )):22 ``` +### Vault + +The ansible vault password can be stored in the system keyring using the `vault-keyring-client.py` script. + +To set the vault password initally, run: + +``` +./vault-keyring-client.py --vault-id ansible-ffs --set +``` + +The Password can be found in Vaultwarden. + ## Usage To deploy everything everywhere: diff --git a/group_vars/test_vault b/group_vars/test_vault new file mode 100644 index 0000000000000000000000000000000000000000..1fc7a03c25459178115c7a23ba9ee92dd9d4aa59 --- /dev/null +++ b/group_vars/test_vault @@ -0,0 +1,6 @@ +$ANSIBLE_VAULT;1.2;AES256;ansible-ffs +33643536396363666263633837646231633033356661363531636463363832303739663033653838 +3333623864643333633366313663343533313737643461330a353537663761383963323162616463 +64306430373938356166323538393337336431336666326437313838383063653861623164663338 +3333316262653735360a336132383838616532393232386637643336393332316633653566646262 +38626663616630643831656564616535316630373164616261303831393163346163 diff --git a/vault-keyring-client.py b/vault-keyring-client.py new file mode 100755 index 0000000000000000000000000000000000000000..ec684c0ba48540f5545a11f2da50729812153b7b --- /dev/null +++ b/vault-keyring-client.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# (c) 2014, Matt Martz <matt@sivel.net> +# (c) 2016, Justin Mayer <https://justinmayer.com/> +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# +# ============================================================================= +# +# This script is to be used with ansible-vault's --vault-id arg +# to retrieve the vault password via your OS's native keyring application. +# +# This file *MUST* be saved with executable permissions. Otherwise, Ansible +# will try to parse as a password file and display: "ERROR! Decryption failed" +# +# The `keyring` Python module is required: https://pypi.org/project/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' +# +# In useage like: +# +# ansible-vault --vault-id keyring_id@contrib/vault/vault-keyring-client.py view some_encrypted_file +# +# --vault-id will call this script like: +# +# contrib/vault/vault-keyring-client.py --vault-id keyring_id +# +# That will retrieve the password from users keyring for the +# keyring service 'keyring_id'. The equivalent of: +# +# keyring get keyring_id $USER +# +# If no vault-id name is specified to ansible command line, the vault-keyring-client.py +# script will be called without a '--vault-id' and will default to the keyring service 'ansible' +# This is equivalent to: +# +# keyring get ansible $USER +# +# You can configure the `vault_password_file` option in ansible.cfg: +# +# [defaults] +# ... +# vault_password_file = /path/to/vault-keyring-client.py +# ... +# +# To set your password, `cd` to your project directory and run: +# +# # will use default keyring service / vault-id of 'ansible' +# /path/to/vault-keyring-client.py --set +# +# or to specify the keyring service / vault-id of 'my_ansible_secret': +# +# /path/to/vault-keyring-client.py --vault-id my_ansible_secret --set +# +# 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-id=keyring_id@/path/to/vault-keyring-client.py site.yml + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import argparse +import sys +import getpass +import keyring + +from ansible.config.manager import ConfigManager, get_ini_config_value + +KEYNAME_UNKNOWN_RC = 2 + + +def build_arg_parser(): + parser = argparse.ArgumentParser(description='Get a vault password from user keyring') + + parser.add_argument('--vault-id', action='store', default=None, + dest='vault_id', + help='name of the vault secret to get from keyring') + parser.add_argument('--username', action='store', default=None, + help='the username whose keyring is queried') + parser.add_argument('--set', action='store_true', default=False, + dest='set_password', + help='set the password instead of getting it') + return parser + + +def main(): + # Set default values + username = getpass.getuser() + keyname = 'ansible' + + # Try to load values from config if one exists + config = ConfigManager() + if config._config_file: + username = get_ini_config_value( + config._parsers[config._config_file], + dict(section='vault', key='username') + ) or username + + keyname = get_ini_config_value( + config._parsers[config._config_file], + dict(section='vault', key='keyname') + ) or keyname + + # Read values from command line (which override the previous if given) + arg_parser = build_arg_parser() + args = arg_parser.parse_args() + + username = args.username or username + keyname = args.vault_id or keyname + + if args.set_password: + 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(keyname, username, password) + else: + sys.stderr.write('Passwords do not match\n') + sys.exit(1) + else: + secret = keyring.get_password(keyname, username) + if secret is None: + sys.stderr.write('vault-keyring-client could not find key="%s" for user="%s" via backend="%s"\n' % + (keyname, username, keyring.get_keyring().name)) + sys.exit(KEYNAME_UNKNOWN_RC) + + # print('secret: %s' % secret) + sys.stdout.write('%s\n' % secret) + + sys.exit(0) + + +if __name__ == '__main__': + main()