From 785a8d0789c6fc35de2cef6fcfdb374de2fd02c1 Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Wed, 15 Feb 2017 14:05:58 -0500 Subject: [PATCH] Fix an issue where smtplib can't handle unicode strings We probably do get this value as unicode originally but when we store it, due to a recently fixed bug it will come out as *not* unicode. So things were accidentally working because py2 smtplib uses hmac which won't accept unicode. This change adds a flag to encrypt_field that forces it to skip the utf8 fixup from before for narrow use cases. --- awx/main/models/notifications.py | 2 +- awx/main/tests/unit/utils/common/test_common.py | 8 ++++++++ awx/main/utils/common.py | 7 +++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/awx/main/models/notifications.py b/awx/main/models/notifications.py index 8ba92b3782..31b96aa8dd 100644 --- a/awx/main/models/notifications.py +++ b/awx/main/models/notifications.py @@ -75,7 +75,7 @@ class NotificationTemplate(CommonModel): setattr(self, '_saved_{}_{}'.format("config", field), value) self.notification_configuration[field] = '' else: - encrypted = encrypt_field(self, 'notification_configuration', subfield=field) + encrypted = encrypt_field(self, 'notification_configuration', subfield=field, skip_utf8=True) self.notification_configuration[field] = encrypted if 'notification_configuration' not in update_fields: update_fields.append('notification_configuration') diff --git a/awx/main/tests/unit/utils/common/test_common.py b/awx/main/tests/unit/utils/common/test_common.py index a48bbe64b3..6542d64cf0 100644 --- a/awx/main/tests/unit/utils/common/test_common.py +++ b/awx/main/tests/unit/utils/common/test_common.py @@ -29,6 +29,14 @@ def test_encrypt_field_with_unicode_string(): assert common.decrypt_field(field, 'value') == value +def test_encrypt_field_force_disable_unicode(): + value = u"NothingSpecial" + field = Setting(value=value) + encrypted = field.value = common.encrypt_field(field, 'value', skip_utf8=True) + assert "UTF8" not in encrypted + assert common.decrypt_field(field, 'value') == value + + def test_encrypt_subfield(): field = Setting(value={'name': 'ANSIBLE'}) encrypted = field.value = common.encrypt_field(field, 'value', subfield='name') diff --git a/awx/main/utils/common.py b/awx/main/utils/common.py index e49f4d0131..49d92b5f9c 100644 --- a/awx/main/utils/common.py +++ b/awx/main/utils/common.py @@ -183,7 +183,7 @@ def get_encryption_key(field_name, pk=None): return h.digest()[:16] -def encrypt_field(instance, field_name, ask=False, subfield=None): +def encrypt_field(instance, field_name, ask=False, subfield=None, skip_utf8=False): ''' Return content of the given instance and field name encrypted. ''' @@ -192,7 +192,10 @@ def encrypt_field(instance, field_name, ask=False, subfield=None): value = value[subfield] if not value or value.startswith('$encrypted$') or (ask and value == 'ASK'): return value - utf8 = type(value) == six.text_type + if skip_utf8: + utf8 = False + else: + utf8 = type(value) == six.text_type value = smart_str(value) key = get_encryption_key(field_name, getattr(instance, 'pk', None)) cipher = AES.new(key, AES.MODE_ECB)