1#!/usr/local/bin/python3.8
2# -*- coding: utf-8 -*-
3# (c) 2014, Matt Martz <matt@sivel.net>
4# (c) 2016, Justin Mayer <https://justinmayer.com/>
5#
6# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
7#
8# =============================================================================
9#
10# This script is to be used with vault_password_file or --vault-password-file
11# to retrieve the vault password via your OS's native keyring application.
12#
13# This file *MUST* be saved with executable permissions. Otherwise, Ansible
14# will try to parse as a password file and display: "ERROR! Decryption failed"
15#
16# The `keyring` Python module is required: https://pypi.org/project/keyring/
17#
18# By default, this script will store the specified password in the keyring of
19# the user that invokes the script. To specify a user keyring, add a [vault]
20# section to your ansible.cfg file with a 'username' option. Example:
21#
22# [vault]
23# username = 'ansible-vault'
24#
25# Another optional setting is for the key name, which allows you to use this
26# script to handle multiple project vaults with different passwords:
27#
28# [vault]
29# keyname = 'ansible-vault-yourproject'
30#
31# You can configure the `vault_password_file` option in ansible.cfg:
32#
33# [defaults]
34# ...
35# vault_password_file = /path/to/vault-keyring.py
36# ...
37#
38# To set your password, `cd` to your project directory and run:
39#
40# python /path/to/vault-keyring.py set
41#
42# If you choose not to configure the path to `vault_password_file` in
43# ansible.cfg, your `ansible-playbook` command might look like:
44#
45# ansible-playbook --vault-password-file=/path/to/vault-keyring.py site.yml
46
47from __future__ import (absolute_import, division, print_function)
48__metaclass__ = type
49
50import sys
51import getpass
52import keyring
53
54from ansible.config.manager import ConfigManager, get_ini_config_value
55
56
57def main():
58    config = ConfigManager()
59    username = get_ini_config_value(
60        config._parsers[config._config_file],
61        dict(section='vault', key='username')
62    ) or getpass.getuser()
63
64    keyname = get_ini_config_value(
65        config._parsers[config._config_file],
66        dict(section='vault', key='keyname')
67    ) or 'ansible'
68
69    if len(sys.argv) == 2 and sys.argv[1] == 'set':
70        intro = 'Storing password in "{}" user keyring using key name: {}\n'
71        sys.stdout.write(intro.format(username, keyname))
72        password = getpass.getpass()
73        confirm = getpass.getpass('Confirm password: ')
74        if password == confirm:
75            keyring.set_password(keyname, username, password)
76        else:
77            sys.stderr.write('Passwords do not match\n')
78            sys.exit(1)
79    else:
80        sys.stdout.write('{0}\n'.format(keyring.get_password(keyname,
81                                                             username)))
82
83    sys.exit(0)
84
85
86if __name__ == '__main__':
87    main()
88