Adds caching of credentials
Allows to cache the credentials as they are currently fetched directly from the database Change-Id: I9a706ac506b0f65402f2433e6fd56097e0830657 Closes-Bug: #1815771
This commit is contained in:
parent
5c5d71cce9
commit
479a2a0afa
@ -46,12 +46,29 @@ share this repository with the repository used to manage keys for Fernet
|
||||
tokens.
|
||||
"""))
|
||||
|
||||
caching = cfg.BoolOpt(
|
||||
'caching',
|
||||
default=True,
|
||||
help=utils.fmt("""
|
||||
Toggle for caching only on retrieval of user credentials. This has no effect
|
||||
unless global caching is enabled.
|
||||
"""))
|
||||
|
||||
cache_time = cfg.IntOpt(
|
||||
'cache_time',
|
||||
help=utils.fmt("""
|
||||
Time to cache credential data in seconds. This has no effect unless global
|
||||
caching is enabled.
|
||||
"""))
|
||||
|
||||
|
||||
GROUP_NAME = __name__.split('.')[-1]
|
||||
ALL_OPTS = [
|
||||
driver,
|
||||
provider,
|
||||
key_repository
|
||||
key_repository,
|
||||
caching,
|
||||
cache_time
|
||||
]
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
import json
|
||||
|
||||
from keystone.common import cache
|
||||
from keystone.common import driver_hints
|
||||
from keystone.common import manager
|
||||
from keystone.common import provider_api
|
||||
@ -24,6 +25,7 @@ from keystone import exception
|
||||
|
||||
|
||||
CONF = keystone.conf.CONF
|
||||
MEMOIZE = cache.get_memoization_decorator(group='credential')
|
||||
PROVIDERS = provider_api.ProviderAPIs
|
||||
|
||||
|
||||
@ -91,21 +93,39 @@ class Manager(manager.Manager):
|
||||
return credentials
|
||||
|
||||
def list_credentials_for_user(self, user_id, type=None):
|
||||
"""List credentials for a specific user."""
|
||||
credentials = self.driver.list_credentials_for_user(user_id, type=type)
|
||||
credentials = self._list_credentials_for_user(user_id, type)
|
||||
for credential in credentials:
|
||||
credential = self._decrypt_credential(credential)
|
||||
return credentials
|
||||
|
||||
@MEMOIZE
|
||||
def _list_credentials_for_user(self, user_id, type):
|
||||
"""List credentials for a specific user."""
|
||||
return self.driver.list_credentials_for_user(user_id, type)
|
||||
|
||||
def get_credential(self, credential_id):
|
||||
"""Return a credential reference."""
|
||||
credential = self.driver.get_credential(credential_id)
|
||||
credential = self._get_credential(credential_id)
|
||||
return self._decrypt_credential(credential)
|
||||
|
||||
@MEMOIZE
|
||||
def _get_credential(self, credential_id):
|
||||
return self.driver.get_credential(credential_id)
|
||||
|
||||
def create_credential(self, credential_id, credential):
|
||||
"""Create a credential."""
|
||||
credential_copy = self._encrypt_credential(credential)
|
||||
ref = self.driver.create_credential(credential_id, credential_copy)
|
||||
if MEMOIZE.should_cache(ref):
|
||||
self._get_credential.set(ref,
|
||||
credential_copy,
|
||||
credential_id)
|
||||
self._list_credentials_for_user.invalidate(self,
|
||||
ref['user_id'],
|
||||
ref['type'])
|
||||
self._list_credentials_for_user.invalidate(self,
|
||||
ref['user_id'],
|
||||
None)
|
||||
ref.pop('key_hash', None)
|
||||
ref.pop('encrypted_blob', None)
|
||||
ref['blob'] = credential['blob']
|
||||
@ -133,6 +153,14 @@ class Manager(manager.Manager):
|
||||
existing_credential = self.get_credential(credential_id)
|
||||
existing_blob = existing_credential['blob']
|
||||
ref = self.driver.update_credential(credential_id, credential_copy)
|
||||
if MEMOIZE.should_cache(ref):
|
||||
self._get_credential.set(ref, self, credential_id)
|
||||
self._list_credentials_for_user.invalidate(self,
|
||||
ref['user_id'],
|
||||
ref['type'])
|
||||
self._list_credentials_for_user.invalidate(self,
|
||||
ref['user_id'],
|
||||
None)
|
||||
ref.pop('key_hash', None)
|
||||
ref.pop('encrypted_blob', None)
|
||||
# If the update request contains a `blob` attribute - we should return
|
||||
@ -143,3 +171,44 @@ class Manager(manager.Manager):
|
||||
else:
|
||||
ref['blob'] = existing_blob
|
||||
return ref
|
||||
|
||||
def delete_credential(self, credential_id):
|
||||
"""Delete a credential."""
|
||||
cred = self.get_credential(credential_id)
|
||||
self.driver.delete_credential(credential_id)
|
||||
self._get_credential.invalidate(self, credential_id)
|
||||
self._list_credentials_for_user.invalidate(self,
|
||||
cred['user_id'],
|
||||
cred['type'])
|
||||
self._list_credentials_for_user.invalidate(self,
|
||||
cred['user_id'],
|
||||
None)
|
||||
|
||||
def delete_credentials_for_project(self, project_id):
|
||||
"""Delete all credentials for a project."""
|
||||
hints = driver_hints.Hints()
|
||||
hints.add_filter('project_id', project_id)
|
||||
creds = self.driver.list_credentials(hints)
|
||||
|
||||
self.driver.delete_credentials_for_project(project_id)
|
||||
for cred in creds:
|
||||
self._get_credential.invalidate(self, cred['id'])
|
||||
self._list_credentials_for_user.invalidate(self,
|
||||
cred['user_id'],
|
||||
cred['type'])
|
||||
self._list_credentials_for_user.invalidate(self,
|
||||
cred['user_id'],
|
||||
None)
|
||||
|
||||
def delete_credentials_for_user(self, user_id):
|
||||
"""Delete all credentials for a user."""
|
||||
creds = self.driver.list_credentials_for_user(user_id)
|
||||
self.driver.delete_credentials_for_user(user_id)
|
||||
for cred in creds:
|
||||
self._get_credential.invalidate(self, cred['id'])
|
||||
self._list_credentials_for_user.invalidate(self,
|
||||
user_id,
|
||||
cred['type'])
|
||||
self._list_credentials_for_user.invalidate(self,
|
||||
cred['user_id'],
|
||||
None)
|
||||
|
7
releasenotes/notes/bug-1815771-ae0e4118c552f01e.yaml
Normal file
7
releasenotes/notes/bug-1815771-ae0e4118c552f01e.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
[`bug 1815771 <https://bugs.launchpad.net/keystone/+bug/1815771>`_]
|
||||
Allows operators to cache credentials to avoid lookups on the database.
|
||||
This operation can be turned on/off through the configuration parameter of
|
||||
keystone.conf [credential] caching.
|
Loading…
Reference in New Issue
Block a user