mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
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
This commit is contained in:
parent
f82d95ae28
commit
ae3d7fb29e
3 changed files with 47 additions and 5 deletions
|
@ -402,6 +402,14 @@ class VaultEditor:
|
||||||
# shuffle tmp file into place
|
# shuffle tmp file into place
|
||||||
self.shuffle_files(tmp_path, filename)
|
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):
|
def encrypt_bytes(self, b_plaintext):
|
||||||
check_prereqs()
|
check_prereqs()
|
||||||
|
|
||||||
|
@ -417,7 +425,7 @@ class VaultEditor:
|
||||||
# so treat the contents as a byte string.
|
# so treat the contents as a byte string.
|
||||||
|
|
||||||
# follow the symlink
|
# follow the symlink
|
||||||
filename = os.path.realpath(filename)
|
filename = self._real_path(filename)
|
||||||
|
|
||||||
b_plaintext = self.read_data(filename)
|
b_plaintext = self.read_data(filename)
|
||||||
b_ciphertext = self.vault.encrypt(b_plaintext)
|
b_ciphertext = self.vault.encrypt(b_plaintext)
|
||||||
|
@ -428,7 +436,7 @@ class VaultEditor:
|
||||||
check_prereqs()
|
check_prereqs()
|
||||||
|
|
||||||
# follow the symlink
|
# follow the symlink
|
||||||
filename = os.path.realpath(filename)
|
filename = self._real_path(filename)
|
||||||
|
|
||||||
ciphertext = self.read_data(filename)
|
ciphertext = self.read_data(filename)
|
||||||
|
|
||||||
|
@ -455,7 +463,7 @@ class VaultEditor:
|
||||||
check_prereqs()
|
check_prereqs()
|
||||||
|
|
||||||
# follow the symlink
|
# follow the symlink
|
||||||
filename = os.path.realpath(filename)
|
filename = self._real_path(filename)
|
||||||
|
|
||||||
ciphertext = self.read_data(filename)
|
ciphertext = self.read_data(filename)
|
||||||
|
|
||||||
|
@ -487,7 +495,7 @@ class VaultEditor:
|
||||||
check_prereqs()
|
check_prereqs()
|
||||||
|
|
||||||
# follow the symlink
|
# follow the symlink
|
||||||
filename = os.path.realpath(filename)
|
filename = self._real_path(filename)
|
||||||
|
|
||||||
prev = os.stat(filename)
|
prev = os.stat(filename)
|
||||||
ciphertext = self.read_data(filename)
|
ciphertext = self.read_data(filename)
|
||||||
|
@ -536,7 +544,8 @@ class VaultEditor:
|
||||||
b_file_data = to_bytes(data, errors='strict')
|
b_file_data = to_bytes(data, errors='strict')
|
||||||
|
|
||||||
if filename == '-':
|
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:
|
else:
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
if shred:
|
if shred:
|
||||||
|
|
|
@ -9,6 +9,8 @@ trap 'rm -rf "${MYTMPDIR}"' EXIT
|
||||||
TEST_FILE="${MYTMPDIR}/test_file"
|
TEST_FILE="${MYTMPDIR}/test_file"
|
||||||
echo "This is a test file" > "${TEST_FILE}"
|
echo "This is a test file" > "${TEST_FILE}"
|
||||||
|
|
||||||
|
TEST_FILE_OUTPUT="${MYTMPDIR}/test_file_output"
|
||||||
|
|
||||||
# encrypt it
|
# encrypt it
|
||||||
ansible-vault encrypt "$@" --vault-password-file vault-password "${TEST_FILE}"
|
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}"
|
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}" "a test string"
|
||||||
|
|
||||||
ansible-vault encrypt_string "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" --name "blippy" "a test string names blippy"
|
ansible-vault encrypt_string "$@" --vault-password-file "${NEW_VAULT_PASSWORD}" --name "blippy" "a test string names blippy"
|
||||||
|
|
|
@ -516,3 +516,29 @@ class TestVaultEditor(unittest.TestCase):
|
||||||
assert vl.cipher_name == "AES256", "wrong cipher name set after rekey: %s" % vl.cipher_name
|
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 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
|
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)
|
||||||
|
|
Loading…
Reference in a new issue