Merge "Add fernet keys purging based no t-h-t parameter"
This commit is contained in:
commit
5852482c20
@ -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
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user