Merge pull request #7649 from sivel/vault-password-script
Allow --vault-password-file to work with a script as well as a flat file
This commit is contained in:
commit
4fc8d4b6fe
5 changed files with 40 additions and 25 deletions
13
bin/ansible
13
bin/ansible
|
@ -124,17 +124,8 @@ class Cli(object):
|
||||||
(sshpass, sudopass, su_pass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, ask_sudo_pass=options.ask_sudo_pass, ask_su_pass=options.ask_su_pass, ask_vault_pass=options.ask_vault_pass)
|
(sshpass, sudopass, su_pass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, ask_sudo_pass=options.ask_sudo_pass, ask_su_pass=options.ask_su_pass, ask_vault_pass=options.ask_vault_pass)
|
||||||
|
|
||||||
# read vault_pass from a file
|
# read vault_pass from a file
|
||||||
if options.vault_password_file:
|
if not options.ask_vault_pass and options.vault_password_file:
|
||||||
this_path = os.path.expanduser(options.vault_password_file)
|
vault_pass = utils.read_vault_file(options.vault_password_file)
|
||||||
try:
|
|
||||||
f = open(this_path, "rb")
|
|
||||||
tmp_vault_pass=f.read().strip()
|
|
||||||
f.close()
|
|
||||||
except (OSError, IOError), e:
|
|
||||||
raise errors.AnsibleError("Could not read %s: %s" % (this_path, e))
|
|
||||||
|
|
||||||
if not options.ask_vault_pass:
|
|
||||||
vault_pass = tmp_vault_pass
|
|
||||||
|
|
||||||
inventory_manager = inventory.Inventory(options.inventory, vault_password=vault_pass)
|
inventory_manager = inventory.Inventory(options.inventory, vault_password=vault_pass)
|
||||||
if options.subset:
|
if options.subset:
|
||||||
|
|
|
@ -120,17 +120,9 @@ def main(args):
|
||||||
options.sudo_user = options.sudo_user or C.DEFAULT_SUDO_USER
|
options.sudo_user = options.sudo_user or C.DEFAULT_SUDO_USER
|
||||||
options.su_user = options.su_user or C.DEFAULT_SU_USER
|
options.su_user = options.su_user or C.DEFAULT_SU_USER
|
||||||
|
|
||||||
if options.vault_password_file:
|
# read vault_pass from a file
|
||||||
this_path = os.path.expanduser(options.vault_password_file)
|
if not options.ask_vault_pass and options.vault_password_file:
|
||||||
try:
|
vault_pass = utils.read_vault_file(options.vault_password_file)
|
||||||
f = open(this_path, "rb")
|
|
||||||
tmp_vault_pass=f.read().strip()
|
|
||||||
f.close()
|
|
||||||
except (OSError, IOError), e:
|
|
||||||
raise errors.AnsibleError("Could not read %s: %s" % (this_path, e))
|
|
||||||
|
|
||||||
if not options.ask_vault_pass:
|
|
||||||
vault_pass = tmp_vault_pass
|
|
||||||
|
|
||||||
extra_vars = {}
|
extra_vars = {}
|
||||||
for extra_vars_opt in options.extra_vars:
|
for extra_vars_opt in options.extra_vars:
|
||||||
|
|
|
@ -83,12 +83,16 @@ To run a playbook that contains vault-encrypted data files, you must pass one of
|
||||||
|
|
||||||
This prompt will then be used to decrypt (in memory only) any vault encrypted files that are accessed. Currently this requires that all passwords be encrypted with the same password.
|
This prompt will then be used to decrypt (in memory only) any vault encrypted files that are accessed. Currently this requires that all passwords be encrypted with the same password.
|
||||||
|
|
||||||
Alternatively, passwords can be specified with a file. If this is done, be careful to ensure permissions on the file are such that no one else can access your key, and do not add your key to source control::
|
Alternatively, passwords can be specified with a file or a script. If this is done, be careful to ensure permissions on the file are such that no one else can access your key, and do not add your key to source control::
|
||||||
|
|
||||||
ansible-playbook site.yml --vault-password-file ~/.vault_pass.txt
|
ansible-playbook site.yml --vault-password-file ~/.vault_pass.txt
|
||||||
|
|
||||||
|
ansible-playbook site.yml --vault-password-file ~/.vault_pass.py
|
||||||
|
|
||||||
The password should be a string stored as a single line in the file.
|
The password should be a string stored as a single line in the file.
|
||||||
|
|
||||||
|
If you are using a script instead of a flat file, ensure that it is marked as executable, and that the password is printed to STDOUT. If your script needs to prompt for data, prompts can be sent to STDERR.
|
||||||
|
|
||||||
This is likely something you may wish to do if using Ansible from a continuous integration system like Jenkins.
|
This is likely something you may wish to do if using Ansible from a continuous integration system like Jenkins.
|
||||||
|
|
||||||
(The `--vault-password-file` option can also be used with the :ref:`ansible-pull` command if you wish, though this would require distributing the keys to your nodes, so understand the implications -- vault is more intended for push mode).
|
(The `--vault-password-file` option can also be used with the :ref:`ansible-pull` command if you wish, though this would require distributing the keys to your nodes, so understand the implications -- vault is more intended for push mode).
|
||||||
|
|
|
@ -120,6 +120,7 @@ DEFAULT_SUDO_USER = get_config(p, DEFAULTS, 'sudo_user', 'ANSIBLE
|
||||||
DEFAULT_ASK_SUDO_PASS = get_config(p, DEFAULTS, 'ask_sudo_pass', 'ANSIBLE_ASK_SUDO_PASS', False, boolean=True)
|
DEFAULT_ASK_SUDO_PASS = get_config(p, DEFAULTS, 'ask_sudo_pass', 'ANSIBLE_ASK_SUDO_PASS', False, boolean=True)
|
||||||
DEFAULT_REMOTE_PORT = get_config(p, DEFAULTS, 'remote_port', 'ANSIBLE_REMOTE_PORT', None, integer=True)
|
DEFAULT_REMOTE_PORT = get_config(p, DEFAULTS, 'remote_port', 'ANSIBLE_REMOTE_PORT', None, integer=True)
|
||||||
DEFAULT_ASK_VAULT_PASS = get_config(p, DEFAULTS, 'ask_vault_pass', 'ANSIBLE_ASK_VAULT_PASS', False, boolean=True)
|
DEFAULT_ASK_VAULT_PASS = get_config(p, DEFAULTS, 'ask_vault_pass', 'ANSIBLE_ASK_VAULT_PASS', False, boolean=True)
|
||||||
|
DEFAULT_VAULT_PASSWORD_FILE = shell_expand_path(get_config(p, DEFAULTS, 'vault_password_file', 'ANSIBLE_VAULT_PASSWORD_FILE', None))
|
||||||
DEFAULT_TRANSPORT = get_config(p, DEFAULTS, 'transport', 'ANSIBLE_TRANSPORT', 'smart')
|
DEFAULT_TRANSPORT = get_config(p, DEFAULTS, 'transport', 'ANSIBLE_TRANSPORT', 'smart')
|
||||||
DEFAULT_SCP_IF_SSH = get_config(p, 'ssh_connection', 'scp_if_ssh', 'ANSIBLE_SCP_IF_SSH', False, boolean=True)
|
DEFAULT_SCP_IF_SSH = get_config(p, 'ssh_connection', 'scp_if_ssh', 'ANSIBLE_SCP_IF_SSH', False, boolean=True)
|
||||||
DEFAULT_MANAGED_STR = get_config(p, DEFAULTS, 'ansible_managed', None, 'Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host}')
|
DEFAULT_MANAGED_STR = get_config(p, DEFAULTS, 'ansible_managed', None, 'Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host}')
|
||||||
|
|
|
@ -45,6 +45,7 @@ import traceback
|
||||||
import getpass
|
import getpass
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from vault import VaultLib
|
from vault import VaultLib
|
||||||
|
|
||||||
|
@ -153,6 +154,32 @@ def decrypt(key, msg):
|
||||||
# UTILITY FUNCTIONS FOR COMMAND LINE TOOLS
|
# UTILITY FUNCTIONS FOR COMMAND LINE TOOLS
|
||||||
###############################################################
|
###############################################################
|
||||||
|
|
||||||
|
def read_vault_file(vault_password_file):
|
||||||
|
"""Read a vault password from a file or if executable, execute the script and
|
||||||
|
retrieve password from STDOUT
|
||||||
|
"""
|
||||||
|
if vault_password_file:
|
||||||
|
this_path = os.path.realpath(os.path.expanduser(vault_password_file))
|
||||||
|
if is_executable(this_path):
|
||||||
|
try:
|
||||||
|
# STDERR not captured to make it easier for users to prompt for input in their scripts
|
||||||
|
p = subprocess.Popen(this_path, stdout=subprocess.PIPE)
|
||||||
|
except OSError, e:
|
||||||
|
raise errors.AnsibleError("problem running %s (%s)" % (' '.join(this_path), e))
|
||||||
|
stdout, stderr = p.communicate()
|
||||||
|
vault_pass = stdout.strip('\r\n')
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
f = open(this_path, "rb")
|
||||||
|
vault_pass=f.read().strip()
|
||||||
|
f.close()
|
||||||
|
except (OSError, IOError), e:
|
||||||
|
raise errors.AnsibleError("Could not read %s: %s" % (this_path, e))
|
||||||
|
|
||||||
|
return vault_pass
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def err(msg):
|
def err(msg):
|
||||||
''' print an error message to stderr '''
|
''' print an error message to stderr '''
|
||||||
|
|
||||||
|
@ -797,8 +824,8 @@ def base_parser(constants=C, usage="", output_opts=False, runas_opts=False,
|
||||||
help='ask for su password')
|
help='ask for su password')
|
||||||
parser.add_option('--ask-vault-pass', default=False, dest='ask_vault_pass', action='store_true',
|
parser.add_option('--ask-vault-pass', default=False, dest='ask_vault_pass', action='store_true',
|
||||||
help='ask for vault password')
|
help='ask for vault password')
|
||||||
parser.add_option('--vault-password-file', default=None, dest='vault_password_file',
|
parser.add_option('--vault-password-file', default=constants.DEFAULT_VAULT_PASSWORD_FILE,
|
||||||
help="vault password file")
|
dest='vault_password_file', help="vault password file")
|
||||||
parser.add_option('--list-hosts', dest='listhosts', action='store_true',
|
parser.add_option('--list-hosts', dest='listhosts', action='store_true',
|
||||||
help='outputs a list of matching hosts; does not execute anything else')
|
help='outputs a list of matching hosts; does not execute anything else')
|
||||||
parser.add_option('-M', '--module-path', dest='module_path',
|
parser.add_option('-M', '--module-path', dest='module_path',
|
||||||
|
|
Loading…
Reference in a new issue