Fix 'New Vault password' on vault 'edit' (#35923)

* Fix 'New Vault password' on vault 'edit'

ffe0ddea96 introduce a
change on 'ansible-vault edit' that tried to check
for --encrypt-vault-id in that mode. But '--encrypt-vault-id'
is not intended for 'edit' since the 'edit' should always
reuse the vault secret that was used to decrypt the text.

Change cli to not check for --encrypt-vault-id on 'edit'.

VaultLib.decrypt_and_get_vault_id() was change to return
the vault secret used to decrypt (in addition to vault_id
and the plaintext).

VaultEditor.edit_file() will now use 'vault_secret_used'
as returned from decrypt_and_get_vault_id() so that
an edited file always gets reencrypted with the same
secret, regardless of any vault id configuration or
cli options.

Fixes #35834
This commit is contained in:
Adrian Likins 2018-03-27 14:12:21 -04:00 committed by GitHub
parent cbe2915ba5
commit 6e737c8cb6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 20 deletions

View file

@ -657,7 +657,7 @@ class VaultLib:
:returns: a byte string containing the decrypted data and the vault-id that was used
'''
plaintext, vault_id = self.decrypt_and_get_vault_id(vaulttext, filename=filename)
plaintext, vault_id, vault_secret = self.decrypt_and_get_vault_id(vaulttext, filename=filename)
return plaintext
def decrypt_and_get_vault_id(self, vaulttext, filename=None):
@ -668,7 +668,7 @@ class VaultLib:
:kwarg filename: a filename that the data came from. This is only
used to make better error messages in case the data cannot be
decrypted.
:returns: a byte string containing the decrypted data and the vault-id that was used
:returns: a byte string containing the decrypted data and the vault-id vault-secret that was used
"""
b_vaulttext = to_bytes(vaulttext, errors='strict', encoding='utf-8')
@ -709,6 +709,7 @@ class VaultLib:
vault_id_matchers = []
vault_id_used = None
vault_secret_used = None
if vault_id:
display.vvvvv('Found a vault_id (%s) in the vaulttext' % (vault_id))
@ -737,6 +738,7 @@ class VaultLib:
b_plaintext = this_cipher.decrypt(b_vaulttext, vault_secret)
if b_plaintext is not None:
vault_id_used = vault_secret_id
vault_secret_used = vault_secret
file_slug = ''
if filename:
file_slug = ' of "%s"' % filename
@ -765,7 +767,7 @@ class VaultLib:
msg += " on %s" % to_native(filename)
raise AnsibleError(msg)
return b_plaintext, vault_id_used
return b_plaintext, vault_id_used, vault_secret_used
class VaultEditor:
@ -931,7 +933,8 @@ class VaultEditor:
self._edit_file_helper(filename, secret, vault_id=vault_id)
def edit_file(self, filename):
vault_id_used = None
vault_secret_used = None
# follow the symlink
filename = self._real_path(filename)
@ -943,7 +946,7 @@ class VaultEditor:
try:
# vaulttext gets converted back to bytes, but alas
# TODO: return the vault_id that worked?
plaintext, vault_id_used = self.vault.decrypt_and_get_vault_id(vaulttext)
plaintext, vault_id_used, vault_secret_used = self.vault.decrypt_and_get_vault_id(vaulttext)
except AnsibleError as e:
raise AnsibleError("%s for %s" % (to_bytes(e), to_bytes(filename)))
@ -956,21 +959,14 @@ class VaultEditor:
# as when the edited file has no vault-id but is decrypted by non-default id in secrets
# (vault_id=default, while a different vault-id decrypted)
# if we could decrypt, the vault_id should be in secrets or we use vault_id_used
# though we could have multiple secrets for a given vault_id, pick the first one
secrets = match_secrets(self.vault.secrets, [vault_id_used, vault_id])
if not secrets:
raise AnsibleVaultError('Attempting to encrypt "%s" but no vault secrets were found for vault ids "%s" or "%s"' %
(filename, vault_id, vault_id_used))
secret = secrets[0][1]
# Keep the same vault-id (and version) as in the header
if cipher_name not in CIPHER_WRITE_WHITELIST:
# we want to get rid of files encrypted with the AES cipher
self._edit_file_helper(filename, secret, existing_data=plaintext, force_save=True, vault_id=vault_id)
self._edit_file_helper(filename, vault_secret_used, existing_data=plaintext,
force_save=True, vault_id=vault_id)
else:
self._edit_file_helper(filename, secret, existing_data=plaintext, force_save=False, vault_id=vault_id)
self._edit_file_helper(filename, vault_secret_used, existing_data=plaintext,
force_save=False, vault_id=vault_id)
def plaintext(self, filename):
@ -996,7 +992,7 @@ class VaultEditor:
display.vvvvv('Rekeying file "%s" to with new vault-id "%s" and vault secret %s' %
(filename, new_vault_id, new_vault_secret))
try:
plaintext, vault_id_used = self.vault.decrypt_and_get_vault_id(vaulttext)
plaintext, vault_id_used, _dummy = self.vault.decrypt_and_get_vault_id(vaulttext)
except AnsibleError as e:
raise AnsibleError("%s for %s" % (to_bytes(e), to_bytes(filename)))