automatically encrypt/decrypt CTinT settings that are stored in memcached

addresses #4246
This commit is contained in:
Ryan Petrello
2017-02-01 11:12:18 -05:00
parent eada4ce83f
commit 557bc8006d
3 changed files with 167 additions and 17 deletions

View File

@@ -13,9 +13,11 @@ from rest_framework import fields
import pytest
from awx.conf import models
from awx.conf.settings import SettingsWrapper, SETTING_CACHE_NOTSET
from awx.conf.settings import SettingsWrapper, EncryptedCacheProxy, SETTING_CACHE_NOTSET
from awx.conf.registry import SettingsRegistry
from awx.main.utils import encrypt_field, decrypt_field
@contextmanager
def apply_patches(_patches):
@@ -262,3 +264,79 @@ def test_read_only_setting_deletion(settings):
with pytest.raises(ImproperlyConfigured):
del settings.AWX_SOME_SETTING
assert settings.AWX_SOME_SETTING == 'DEFAULT'
def test_settings_use_an_encrypted_cache(settings):
settings.registry.register(
'AWX_ENCRYPTED',
field_class=fields.CharField,
category=_('System'),
category_slug='system',
encrypted=True
)
assert isinstance(settings.cache, EncryptedCacheProxy)
assert settings.cache.__dict__['encrypter'] == encrypt_field
assert settings.cache.__dict__['decrypter'] == decrypt_field
def test_sensitive_cache_data_is_encrypted(settings, mocker):
"fields marked as `encrypted` are stored in the cache with encryption"
settings.registry.register(
'AWX_ENCRYPTED',
field_class=fields.CharField,
category=_('System'),
category_slug='system',
encrypted=True
)
def rot13(obj, attribute):
assert obj.pk == 123
return getattr(obj, attribute).encode('rot13')
native_cache = LocMemCache(str(uuid4()), {})
cache = EncryptedCacheProxy(
native_cache,
settings.registry,
encrypter=rot13,
decrypter=rot13
)
# Insert the setting value into the database; the encryption process will
# use its primary key as part of the encryption key
setting_from_db = mocker.Mock(pk=123, key='AWX_ENCRYPTED', value='SECRET!')
mocks = mocker.Mock(**{
'order_by.return_value': mocker.Mock(**{
'__iter__': lambda self: iter([setting_from_db]),
'first.return_value': setting_from_db
}),
})
with mocker.patch('awx.conf.models.Setting.objects.filter', return_value=mocks):
cache.set('AWX_ENCRYPTED', 'SECRET!')
assert cache.get('AWX_ENCRYPTED') == 'SECRET!'
assert native_cache.get('AWX_ENCRYPTED') == 'FRPERG!'
def test_readonly_sensitive_cache_data_is_encrypted(settings):
"readonly fields marked as `encrypted` are stored in the cache with encryption"
settings.registry.register(
'AWX_ENCRYPTED',
field_class=fields.CharField,
category=_('System'),
category_slug='system',
read_only=True,
encrypted=True
)
def rot13(obj, attribute):
assert obj.pk is None
return getattr(obj, attribute).encode('rot13')
native_cache = LocMemCache(str(uuid4()), {})
cache = EncryptedCacheProxy(
native_cache,
settings.registry,
encrypter=rot13,
decrypter=rot13
)
cache.set('AWX_ENCRYPTED', 'SECRET!')
assert cache.get('AWX_ENCRYPTED') == 'SECRET!'
assert native_cache.get('AWX_ENCRYPTED') == 'FRPERG!'