Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix vault reading from stdin (avoid realpath() on non-links) #23583

Merged
merged 2 commits into from
Apr 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 14 additions & 5 deletions lib/ansible/parsing/vault/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,14 @@ def _edit_file_helper(self, filename, existing_data=None, force_save=False):
# 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()

Expand All @@ -417,7 +425,7 @@ def encrypt_file(self, filename, output_file=None):
# 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)
Expand All @@ -428,7 +436,7 @@ def decrypt_file(self, filename, output_file=None):
check_prereqs()

# follow the symlink
filename = os.path.realpath(filename)
filename = self._real_path(filename)

ciphertext = self.read_data(filename)

Expand All @@ -455,7 +463,7 @@ def edit_file(self, filename):
check_prereqs()

# follow the symlink
filename = os.path.realpath(filename)
filename = self._real_path(filename)

ciphertext = self.read_data(filename)

Expand Down Expand Up @@ -487,7 +495,7 @@ def rekey_file(self, filename, b_new_password):
check_prereqs()

# follow the symlink
filename = os.path.realpath(filename)
filename = self._real_path(filename)

prev = os.stat(filename)
ciphertext = self.read_data(filename)
Expand Down Expand Up @@ -536,7 +544,8 @@ def write_data(self, data, filename, shred=True):
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:
Expand Down
7 changes: 7 additions & 0 deletions test/integration/targets/vault/runme.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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}"

Expand All @@ -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"
Expand Down
26 changes: 26 additions & 0 deletions test/units/parsing/vault/test_vault_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,3 +516,29 @@ def test_rekey_migration(self):
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)