From 309f54b709d489114841530663642b7f3ad262ec Mon Sep 17 00:00:00 2001 From: Adrian Likins Date: Mon, 31 Oct 2016 12:56:18 -0400 Subject: [PATCH] Fix 'vault rekey' with vault secret env var if ANSIBLE_VAULT_PASSWORD_FILE is set, 'ansible-vault rekey myvault.yml' will fail to prompt for the new vault password file, and will use None. Fix is to split out 'ask_vault_passwords' into 'ask_vault_passwords' and 'ask_new_vault_passwords' to make the logic simpler. And then make sure new_vault_pass is always set for 'rekey', and if not, then call ask_new_vault_passwords() to set it. ask_vault_passwords() would return values for vault_pass and new vault_pass, and vault cli previously would not prompt for new_vault_pass if there was a vault_pass set via a vault password file. Fixes #18247 --- lib/ansible/cli/__init__.py | 30 +++++++++++++++------------ lib/ansible/cli/adhoc.py | 2 +- lib/ansible/cli/playbook.py | 2 +- lib/ansible/cli/vault.py | 16 +++++++------- lib/ansible/parsing/vault/__init__.py | 4 ++++ 5 files changed, 32 insertions(+), 22 deletions(-) diff --git a/lib/ansible/cli/__init__.py b/lib/ansible/cli/__init__.py index 827124b8f3..84cc99132f 100644 --- a/lib/ansible/cli/__init__.py +++ b/lib/ansible/cli/__init__.py @@ -161,33 +161,37 @@ class CLI(with_metaclass(ABCMeta, object)): display.display(u"No config file found; using defaults") @staticmethod - def ask_vault_passwords(ask_new_vault_pass=False, rekey=False): + def ask_vault_passwords(): ''' prompt for vault password and/or password change ''' vault_pass = None - new_vault_pass = None try: - if rekey or not ask_new_vault_pass: - vault_pass = getpass.getpass(prompt="Vault password: ") + vault_pass = getpass.getpass(prompt="Vault password: ") - if ask_new_vault_pass: - new_vault_pass = getpass.getpass(prompt="New Vault password: ") - new_vault_pass2 = getpass.getpass(prompt="Confirm New Vault password: ") - if new_vault_pass != new_vault_pass2: - raise AnsibleError("Passwords do not match") except EOFError: pass # enforce no newline chars at the end of passwords if vault_pass: vault_pass = to_bytes(vault_pass, errors='strict', nonstring='simplerepr').strip() + + return vault_pass + + @staticmethod + def ask_new_vault_passwords(): + new_vault_pass = None + try: + new_vault_pass = getpass.getpass(prompt="New Vault password: ") + new_vault_pass2 = getpass.getpass(prompt="Confirm New Vault password: ") + if new_vault_pass != new_vault_pass2: + raise AnsibleError("Passwords do not match") + except EOFError: + pass + if new_vault_pass: new_vault_pass = to_bytes(new_vault_pass, errors='strict', nonstring='simplerepr').strip() - if ask_new_vault_pass and not rekey: - vault_pass = new_vault_pass - - return vault_pass, new_vault_pass + return new_vault_pass def ask_passwords(self): ''' prompt for connection and become passwords if needed ''' diff --git a/lib/ansible/cli/adhoc.py b/lib/ansible/cli/adhoc.py index 94113f710e..45e357109a 100644 --- a/lib/ansible/cli/adhoc.py +++ b/lib/ansible/cli/adhoc.py @@ -118,7 +118,7 @@ class AdHocCLI(CLI): vault_pass = CLI.read_vault_password_file(self.options.vault_password_file, loader=loader) loader.set_vault_password(vault_pass) elif self.options.ask_vault_pass: - vault_pass = self.ask_vault_passwords()[0] + vault_pass = self.ask_vault_passwords() loader.set_vault_password(vault_pass) variable_manager = VariableManager() diff --git a/lib/ansible/cli/playbook.py b/lib/ansible/cli/playbook.py index 645b74b337..544e588465 100644 --- a/lib/ansible/cli/playbook.py +++ b/lib/ansible/cli/playbook.py @@ -116,7 +116,7 @@ class PlaybookCLI(CLI): vault_pass = CLI.read_vault_password_file(self.options.vault_password_file, loader=loader) loader.set_vault_password(vault_pass) elif self.options.ask_vault_pass: - vault_pass = self.ask_vault_passwords()[0] + vault_pass = self.ask_vault_passwords() loader.set_vault_password(vault_pass) # create the variable manager, which will be shared throughout diff --git a/lib/ansible/cli/vault.py b/lib/ansible/cli/vault.py index 5ca0169d51..cdf282ef9d 100644 --- a/lib/ansible/cli/vault.py +++ b/lib/ansible/cli/vault.py @@ -101,21 +101,23 @@ class VaultCLI(CLI): if self.options.vault_password_file: # read vault_pass from a file self.vault_pass = CLI.read_vault_password_file(self.options.vault_password_file, loader) - else: - newpass = False - rekey = False - if not self.options.new_vault_password_file: - newpass = (self.action in ['create', 'rekey', 'encrypt']) - rekey = (self.action == 'rekey') - self.vault_pass, self.new_vault_pass = self.ask_vault_passwords(ask_new_vault_pass=newpass, rekey=rekey) if self.options.new_vault_password_file: # for rekey only self.new_vault_pass = CLI.read_vault_password_file(self.options.new_vault_password_file, loader) + if not self.vault_pass or self.options.ask_vault_pass: + self.vault_pass = self.ask_vault_passwords() + if not self.vault_pass: raise AnsibleOptionsError("A password is required to use Ansible's Vault") + if self.action == 'rekey': + if not self.new_vault_pass: + self.new_vault_pass = self.ask_new_vault_passwords() + if not self.new_vault_pass: + raise AnsibleOptionsError("A password is required to rekey Ansible's Vault") + self.editor = VaultEditor(self.vault_pass) self.execute() diff --git a/lib/ansible/parsing/vault/__init__.py b/lib/ansible/parsing/vault/__init__.py index e86889ddc3..ff3dafa26d 100644 --- a/lib/ansible/parsing/vault/__init__.py +++ b/lib/ansible/parsing/vault/__init__.py @@ -486,6 +486,10 @@ class VaultEditor: except AnsibleError as e: raise AnsibleError("%s for %s" % (to_bytes(e),to_bytes(filename))) + # This is more or less an assert, see #18247 + if new_password is None: + raise AnsibleError('The value for the new_password to rekey %s with is not valid' % filename) + new_vault = VaultLib(new_password) new_ciphertext = new_vault.encrypt(plaintext)