Merge "Add fernet keys purging based no t-h-t parameter"

This commit is contained in:
Jenkins 2017-06-16 16:35:00 +00:00 committed by Gerrit Code Review
commit 5852482c20
2 changed files with 89 additions and 12 deletions

View File

@ -263,11 +263,14 @@ class GetPasswordsAction(base.TripleOAction):
parameter_defaults = env.get('parameter_defaults', {})
passwords = env.get('passwords', {})
return self._get_overriden_passwords(passwords, parameter_defaults)
def _get_overriden_passwords(self, env_passwords, parameter_defaults):
for name in constants.PASSWORD_PARAMETER_NAMES:
if name in parameter_defaults:
passwords[name] = parameter_defaults[name]
return passwords
env_passwords[name] = parameter_defaults[name]
return env_passwords
class GenerateFencingParametersAction(base.TripleOAction):
@ -479,14 +482,14 @@ class RotateFernetKeysAction(GetPasswordsAction):
return mistral_workflow_utils.Result(error=err_msg)
parameter_defaults = env.get('parameter_defaults', {})
passwords = env.get('passwords', {})
for name in constants.PASSWORD_PARAMETER_NAMES:
if name in parameter_defaults:
passwords[name] = parameter_defaults[name]
passwords = self._get_overriden_passwords(env.get('passwords', {}),
parameter_defaults)
next_index = self.get_next_index(passwords['KeystoneFernetKeys'])
keys_map = self.rotate_keys(passwords['KeystoneFernetKeys'],
next_index)
max_keys = self.get_max_keys_value(parameter_defaults)
keys_map = self.purge_excess_keys(max_keys, keys_map)
env['passwords']['KeystoneFernetKeys'] = keys_map
@ -503,14 +506,20 @@ class RotateFernetKeysAction(GetPasswordsAction):
return keys_map
@staticmethod
def get_key_index_from_path(path):
return int(path[path.rfind('/') + 1:])
def get_next_index(self, keys_map):
def get_index(path):
return int(path[path.rfind('/') + 1:])
return get_index(max(keys_map, key=get_index)) + 1
return self.get_key_index_from_path(
max(keys_map, key=self.get_key_index_from_path)) + 1
def get_key_path(self, index):
return password_utils.KEYSTONE_FERNET_REPO + str(index)
def rotate_keys(self, keys_map, next_index):
next_index_path = password_utils.KEYSTONE_FERNET_REPO + str(next_index)
zero_index_path = password_utils.KEYSTONE_FERNET_REPO + '0'
next_index_path = self.get_key_path(next_index)
zero_index_path = self.get_key_path(0)
# promote staged key to be new primary
keys_map[next_index_path] = keys_map[zero_index_path]
@ -518,3 +527,20 @@ class RotateFernetKeysAction(GetPasswordsAction):
keys_map[zero_index_path] = {
'content': password_utils.create_keystone_credential()}
return keys_map
def get_max_keys_value(self, parameter_defaults):
# The number of max keys should always be positive. The minimum amount
# of keys is 3.
return max(parameter_defaults.get('KeystoneFernetMaxActiveKeys', 5), 3)
def purge_excess_keys(self, max_keys, keys_map):
current_repo_size = len(keys_map)
if current_repo_size <= max_keys:
return keys_map
key_paths = sorted(keys_map.keys(), key=self.get_key_index_from_path)
keys_to_be_purged = current_repo_size - max_keys
for key_path in key_paths[1:keys_to_be_purged + 1]:
del keys_map[key_path]
return keys_map

View File

@ -917,3 +917,54 @@ class RotateFernetKeysActionTest(base.TestCase):
# primary key should be the previous staged key
self.assertEqual('Some key',
new_keys_map[new_primary_key_index]['content'])
def test_purge_excess_keys_should_purge(self):
action = parameters.RotateFernetKeysAction()
keys_map = {
password_utils.KEYSTONE_FERNET_REPO + '0': {
'content': 'key0'},
password_utils.KEYSTONE_FERNET_REPO + '1': {
'content': 'key1'},
password_utils.KEYSTONE_FERNET_REPO + '2': {
'content': 'key2'},
password_utils.KEYSTONE_FERNET_REPO + '3': {
'content': 'key3'},
password_utils.KEYSTONE_FERNET_REPO + '4': {
'content': 'key4'},
}
max_keys = 3
keys_map = action.purge_excess_keys(max_keys, keys_map)
self.assertEqual(max_keys, len(keys_map))
# It should keep index 0, 3 and 4
self.assertIn(password_utils.KEYSTONE_FERNET_REPO + '0', keys_map)
self.assertIn(password_utils.KEYSTONE_FERNET_REPO + '3', keys_map)
self.assertIn(password_utils.KEYSTONE_FERNET_REPO + '4', keys_map)
# It sould have removed index 1 and 2
self.assertNotIn(password_utils.KEYSTONE_FERNET_REPO + '1', keys_map)
self.assertNotIn(password_utils.KEYSTONE_FERNET_REPO + '2', keys_map)
def test_purge_excess_keys_should_not_purge_if_equal_to_max(self):
action = parameters.RotateFernetKeysAction()
keys_map = {
password_utils.KEYSTONE_FERNET_REPO + '0': {
'content': 'key0'},
password_utils.KEYSTONE_FERNET_REPO + '1': {
'content': 'key1'},
password_utils.KEYSTONE_FERNET_REPO + '2': {
'content': 'key2'},
}
max_keys = 3
keys_map = action.purge_excess_keys(max_keys, keys_map)
self.assertEqual(max_keys, len(keys_map))
def test_purge_excess_keys_should_not_purge_if_less_than_max(self):
action = parameters.RotateFernetKeysAction()
keys_map = {
password_utils.KEYSTONE_FERNET_REPO + '0': {
'content': 'key0'},
password_utils.KEYSTONE_FERNET_REPO + '1': {
'content': 'key1'},
}
max_keys = 3
keys_map = action.purge_excess_keys(max_keys, keys_map)
self.assertEqual(2, len(keys_map))