Return binary data from gpg renderer

If we receive binary data, we should respond with binary data.
This commit is contained in:
Wayne Werner 2019-03-22 14:52:19 -05:00
parent 32aafab79a
commit 604b671ef9
No known key found for this signature in database
GPG key ID: C36D3A8D5BEF0935
2 changed files with 64 additions and 16 deletions

View file

@ -228,7 +228,11 @@ from salt.ext import six
log = logging.getLogger(__name__)
GPG_CIPHERTEXT = re.compile(
r'-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----', re.DOTALL)
salt.utils.stringutils.to_bytes(
r'-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----'
),
re.DOTALL,
)
def _get_gpg_exec():
@ -281,37 +285,37 @@ def _decrypt_ciphertext(cipher):
proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False)
decrypted_data, decrypt_error = proc.communicate(input=cipher)
if not decrypted_data:
try:
cipher = salt.utils.stringutils.to_unicode(cipher)
except UnicodeDecodeError:
# decrypted data contains undecodable binary data
pass
log.warning(
'Could not decrypt cipher %s, received: %s',
'Could not decrypt cipher %r, received: %r',
cipher,
decrypt_error
)
return cipher
else:
try:
decrypted_data = salt.utils.stringutils.to_unicode(decrypted_data)
except UnicodeDecodeError:
# decrypted data contains undecodable binary data
pass
return decrypted_data
def _decrypt_ciphertexts(cipher, translate_newlines=False):
cipher = salt.utils.stringutils.to_bytes(cipher)
if translate_newlines:
cipher = cipher.replace(r'\n', '\n')
ret, num = GPG_CIPHERTEXT.subn(lambda m: _decrypt_ciphertext(m.group()), cipher)
cipher = cipher.replace(rb'\n', b'\n')
def replace(match):
result = salt.utils.stringutils.to_bytes(_decrypt_ciphertext(match.group()))
return result
ret, num = GPG_CIPHERTEXT.subn(replace, salt.utils.stringutils.to_bytes(cipher))
if num > 0:
# Remove trailing newlines. Without if crypted value initially specified as a YAML multiline
# it will conain unexpected trailing newline.
return ret.rstrip('\n')
ret = ret.rstrip(b'\n')
else:
return cipher
ret = cipher
try:
ret = salt.utils.stringutils.to_unicode(ret)
except UnicodeDecodeError:
# decrypted data contains some sort of binary data - not our problem
pass
return ret
def _decrypt_object(obj, translate_newlines=False):
'''

View file

@ -3,6 +3,8 @@
# Import Python Libs
from __future__ import absolute_import, print_function, unicode_literals
from textwrap import dedent
# Import Salt Testing libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import skipIf, TestCase
@ -100,3 +102,45 @@ class GPGTestCase(TestCase, LoaderModuleMockMixin):
with patch('salt.renderers.gpg._get_key_dir', MagicMock(return_value=key_dir)):
with patch('salt.renderers.gpg._decrypt_object', MagicMock(return_value=secret)):
self.assertEqual(gpg.render(crypted), secret)
def test_multi_render(self):
key_dir = '/etc/salt/gpgkeys'
secret = 'Use more salt.'
expected = '\n'.join([secret]*3)
crypted = dedent('''\
-----BEGIN PGP MESSAGE-----
!@#$%^&*()_+
-----END PGP MESSAGE-----
-----BEGIN PGP MESSAGE-----
!@#$%^&*()_+
-----END PGP MESSAGE-----
-----BEGIN PGP MESSAGE-----
!@#$%^&*()_+
-----END PGP MESSAGE-----
''')
with patch('salt.renderers.gpg._get_gpg_exec', MagicMock(return_value=True)):
with patch('salt.renderers.gpg._get_key_dir', MagicMock(return_value=key_dir)):
with patch('salt.renderers.gpg._decrypt_ciphertext', MagicMock(return_value=secret)):
self.assertEqual(gpg.render(crypted), expected)
def test_render_with_binary_data_should_return_binary_data(self):
key_dir = '/etc/salt/gpgkeys'
secret = b'Use\x8b more\x8b salt.'
expected = b'\n'.join([secret]*3)
crypted = dedent('''\
-----BEGIN PGP MESSAGE-----
!@#$%^&*()_+
-----END PGP MESSAGE-----
-----BEGIN PGP MESSAGE-----
!@#$%^&*()_+
-----END PGP MESSAGE-----
-----BEGIN PGP MESSAGE-----
!@#$%^&*()_+
-----END PGP MESSAGE-----
''')
with patch('salt.renderers.gpg._get_gpg_exec', MagicMock(return_value=True)):
with patch('salt.renderers.gpg._get_key_dir', MagicMock(return_value=key_dir)):
with patch('salt.renderers.gpg._decrypt_ciphertext', MagicMock(return_value=secret)):
self.assertEqual(gpg.render(crypted), expected)