diff options
author | Adrian Likins <alikins@redhat.com> | 2017-04-18 19:09:02 +0200 |
---|---|---|
committer | Brian Coca <bcoca@users.noreply.github.com> | 2017-04-18 19:09:02 +0200 |
commit | ae3d7fb29ed3aac413aea05384dd60eacc5f738c (patch) | |
tree | a691173aed946b88b0c9746efab7259a51a63715 | |
parent | When become_method is su, self._play_context.prompt is a function. Fixes #23689 (diff) | |
download | ansible-ae3d7fb29ed3aac413aea05384dd60eacc5f738c.tar.xz ansible-ae3d7fb29ed3aac413aea05384dd60eacc5f738c.zip |
Fix vault reading from stdin (avoid realpath() on non-links) (#23583)
* Fix vault reading from stdin (avoid realpath() on non-links)
os.path.realpath() is used to find the target of file paths that
are symlinks so vault operations happen directly on the target.
However, in addition to resolving symlinks, realpath() also returns
a full path. when reading from stdin, vault cli uses '-' as a special
file path so VaultEditor() will replace with stdin.
realpath() was expanding '-' with the CWD to something like
'/home/user/playbooks/-' causing errors like:
ERROR! [Errno 2] No such file or directory: u'/home/user/ansible/-'
Fix is to specialcase '-' to not use realpath()
Fixes #23567
* to_text decrypt output when writing to stdout
-rw-r--r-- | lib/ansible/parsing/vault/__init__.py | 19 | ||||
-rwxr-xr-x | test/integration/targets/vault/runme.sh | 7 | ||||
-rw-r--r-- | test/units/parsing/vault/test_vault_editor.py | 26 |
3 files changed, 47 insertions, 5 deletions
diff --git a/lib/ansible/parsing/vault/__init__.py b/lib/ansible/parsing/vault/__init__.py index 1ccc47e775..0c424e2684 100644 --- a/lib/ansible/parsing/vault/__init__.py +++ b/lib/ansible/parsing/vault/__init__.py @@ -402,6 +402,14 @@ class VaultEditor: # shuffle tmp file into place self.shuffle_files(tmp_path, filename) + def _real_path(self, filename): + # '-' is special to VaultEditor, dont expand it. + if filename == '-': + return filename + + real_path = os.path.realpath(filename) + return real_path + def encrypt_bytes(self, b_plaintext): check_prereqs() @@ -417,7 +425,7 @@ class VaultEditor: # so treat the contents as a byte string. # follow the symlink - filename = os.path.realpath(filename) + filename = self._real_path(filename) b_plaintext = self.read_data(filename) b_ciphertext = self.vault.encrypt(b_plaintext) @@ -428,7 +436,7 @@ class VaultEditor: check_prereqs() # follow the symlink - filename = os.path.realpath(filename) + filename = self._real_path(filename) ciphertext = self.read_data(filename) @@ -455,7 +463,7 @@ class VaultEditor: check_prereqs() # follow the symlink - filename = os.path.realpath(filename) + filename = self._real_path(filename) ciphertext = self.read_data(filename) @@ -487,7 +495,7 @@ class VaultEditor: check_prereqs() # follow the symlink - filename = os.path.realpath(filename) + filename = self._real_path(filename) prev = os.stat(filename) ciphertext = self.read_data(filename) @@ -536,7 +544,8 @@ class VaultEditor: b_file_data = to_bytes(data, errors='strict') if filename == '-': - sys.stdout.write(b_file_data) + file_data = to_text(b_file_data, encoding='utf-8', errors='strict', nonstring='strict') + sys.stdout.write(file_data) else: if os.path.isfile(filename): if shred: diff --git a/test/integration/targets/vault/runme.sh b/test/integration/targets/vault/runme.sh index 7fc14d7196..05603ee747 100755 --- a/test/integration/targets/vault/runme.sh +++ b/test/integration/targets/vault/runme.sh @@ -9,6 +9,8 @@ trap 'rm -rf "${MYTMPDIR}"' EXIT TEST_FILE="${MYTMPDIR}/test_file" echo "This is a test file" > "${TEST_FILE}" +TEST_FILE_OUTPUT="${MYTMPDIR}/test_file_output" + # encrypt it ansible-vault encrypt "$@" --vault-password-file vault-password "${TEST_FILE}" @@ -28,6 +30,11 @@ ansible-vault view "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" "${TEST_FI ansible-vault decrypt "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" "${TEST_FILE}" +# reading/writing to/from stdin/stdin (See https://github.com/ansible/ansible/issues/23567) +ansible-vault encrypt "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" --output="${TEST_FILE_OUTPUT}" < "${TEST_FILE}" +ansible-vault view "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" - < "${TEST_FILE_OUTPUT}" +ansible-vault decrypt "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" --output=- < "${TEST_FILE_OUTPUT}" + ansible-vault encrypt_string "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" "a test string" ansible-vault encrypt_string "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" --name "blippy" "a test string names blippy" diff --git a/test/units/parsing/vault/test_vault_editor.py b/test/units/parsing/vault/test_vault_editor.py index 51b8301a0d..259761ba35 100644 --- a/test/units/parsing/vault/test_vault_editor.py +++ b/test/units/parsing/vault/test_vault_editor.py @@ -516,3 +516,29 @@ class TestVaultEditor(unittest.TestCase): assert vl.cipher_name == "AES256", "wrong cipher name set after rekey: %s" % vl.cipher_name assert error_hit is False, "error decrypting migrated 1.0 file" assert dec_data.strip() == b"foo", "incorrect decryption of rekeyed/migrated file: %s" % dec_data + + def test_real_path_dash(self): + filename = '-' + ve = vault.VaultEditor('password') + + res = ve._real_path(filename) + self.assertEqual(res, '-') + + def test_real_path_dev_null(self): + filename = '/dev/null' + ve = vault.VaultEditor('password') + + res = ve._real_path(filename) + self.assertEqual(res, '/dev/null') + + def test_real_path_symlink(self): + self._test_dir = self._create_test_dir() + file_path = self._create_file(self._test_dir, 'test_file', content=b'this is a test file') + file_link_path = os.path.join(self._test_dir, 'a_link_to_test_file') + + os.symlink(file_path, file_link_path) + + ve = vault.VaultEditor('password') + + res = ve._real_path(file_link_path) + self.assertEqual(res, file_path) |