**** CubicPower OpenStack Study ****
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import abc
import datetime
import six
from keystone.common import cache
from keystone.common import dependency
from keystone.common import extension
from keystone.common import manager
from keystone import config
from keystone.contrib.revoke import model
from keystone import exception
from keystone import notifications
from keystone.openstack.common.gettextutils import _
from keystone.openstack.common import log
from keystone.openstack.common import timeutils
CONF = config.CONF
LOG = log.getLogger(__name__)
EXTENSION_DATA = {
'name': 'OpenStack Revoke API',
'namespace': 'http://docs.openstack.org/identity/api/ext/'
'OS-REVOKE/v1.0',
'alias': 'OS-REVOKE',
'updated': '2014-02-24T20:51:0-00:00',
'description': 'OpenStack revoked token reporting mechanism.',
'links': [
{
'rel': 'describedby',
'type': 'text/html',
'href': ('https://github.com/openstack/identity-api/blob/master/'
'openstack-identity-api/v3/src/markdown/'
'identity-api-v3-os-revoke-ext.md'),
}
]}
extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA)
extension.register_public_extension(EXTENSION_DATA['alias'], EXTENSION_DATA)
SHOULD_CACHE = cache.should_cache_fn('revoke')
# TODO(ayoung): migrate from the token section
REVOCATION_CACHE_EXPIRATION_TIME = lambda: CONF.token.revocation_cache_time
**** CubicPower OpenStack Study ****
def revoked_before_cutoff_time():
expire_delta = datetime.timedelta(
seconds=CONF.token.expiration + CONF.revoke.expiration_buffer)
oldest = timeutils.utcnow() - expire_delta
return oldest
@dependency.provider('revoke_api')
**** CubicPower OpenStack Study ****
class Manager(manager.Manager):
"""Revoke API Manager.
Performs common logic for recording revocations.
"""
**** CubicPower OpenStack Study ****
def __init__(self):
super(Manager, self).__init__(CONF.revoke.driver)
self._register_listeners()
self.model = model
**** CubicPower OpenStack Study ****
def _user_callback(self, service, resource_type, operation,
payload):
self.revoke_by_user(payload['resource_info'])
**** CubicPower OpenStack Study ****
def _role_callback(self, service, resource_type, operation,
payload):
self.revoke(
model.RevokeEvent(role_id=payload['resource_info']))
**** CubicPower OpenStack Study ****
def _project_callback(self, service, resource_type, operation,
payload):
self.revoke(
model.RevokeEvent(project_id=payload['resource_info']))
**** CubicPower OpenStack Study ****
def _domain_callback(self, service, resource_type, operation,
payload):
self.revoke(
model.RevokeEvent(domain_id=payload['resource_info']))
**** CubicPower OpenStack Study ****
def _trust_callback(self, service, resource_type, operation,
payload):
self.revoke(
model.RevokeEvent(trust_id=payload['resource_info']))
**** CubicPower OpenStack Study ****
def _consumer_callback(self, service, resource_type, operation,
payload):
self.revoke(
model.RevokeEvent(consumer_id=payload['resource_info']))
**** CubicPower OpenStack Study ****
def _access_token_callback(self, service, resource_type, operation,
payload):
self.revoke(
model.RevokeEvent(access_token_id=payload['resource_info']))
**** CubicPower OpenStack Study ****
def _register_listeners(self):
callbacks = [
['deleted', 'OS-TRUST:trust', self._trust_callback],
['deleted', 'OS-OAUTH1:consumer', self._consumer_callback],
['deleted', 'OS-OAUTH1:access_token',
self._access_token_callback],
['deleted', 'role', self._role_callback],
['deleted', 'user', self._user_callback],
['disabled', 'user', self._user_callback],
['deleted', 'project', self._project_callback],
['disabled', 'project', self._project_callback],
['disabled', 'domain', self._domain_callback]]
for cb in callbacks:
notifications.register_event_callback(*cb)
**** CubicPower OpenStack Study ****
def revoke_by_user(self, user_id):
return self.revoke(model.RevokeEvent(user_id=user_id))
**** CubicPower OpenStack Study ****
def revoke_by_expiration(self, user_id, expires_at):
self.revoke(
model.RevokeEvent(user_id=user_id,
expires_at=expires_at))
**** CubicPower OpenStack Study ****
def revoke_by_grant(self, role_id, user_id=None,
domain_id=None, project_id=None):
self.revoke(
model.RevokeEvent(user_id=user_id,
role_id=role_id,
domain_id=domain_id,
project_id=project_id))
**** CubicPower OpenStack Study ****
def revoke_by_user_and_project(self, user_id, project_id):
self.revoke(
model.RevokeEvent(project_id=project_id, user_id=user_id))
**** CubicPower OpenStack Study ****
def revoke_by_project_role_assignment(self, project_id, role_id):
self.revoke(model.RevokeEvent(project_id=project_id, role_id=role_id))
**** CubicPower OpenStack Study ****
def revoke_by_domain_role_assignment(self, domain_id, role_id):
self.revoke(model.RevokeEvent(domain_id=domain_id, role_id=role_id))
@cache.on_arguments(should_cache_fn=SHOULD_CACHE,
expiration_time=REVOCATION_CACHE_EXPIRATION_TIME)
**** CubicPower OpenStack Study ****
def _get_revoke_tree(self):
events = self.driver.get_events()
revoke_tree = model.RevokeTree(revoke_events=events)
return revoke_tree
**** CubicPower OpenStack Study ****
def check_token(self, token_values):
"""Checks the values from a token against the revocation list
:param token_values: dictionary of values from a token,
normalized for differences between v2 and v3. The checked values are a
subset of the attributes of model.TokenEvent
:raises exception.TokenNotFound: if the token is invalid
"""
if self._get_revoke_tree().is_revoked(token_values):
raise exception.TokenNotFound(_('Failed to validate token'))
**** CubicPower OpenStack Study ****
def revoke(self, event):
self.driver.revoke(event)
self._get_revoke_tree.invalidate(self)
@six.add_metaclass(abc.ABCMeta)
**** CubicPower OpenStack Study ****
class Driver(object):
"""Interface for recording and reporting revocation events."""
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def get_events(self, last_fetch=None):
"""return the revocation events, as a list of objects
:param last_fetch: Time of last fetch. Return all events newer.
:returns: A list of keystone.contrib.revoke.model.RevokeEvent
newer than `last_fetch.`
If no last_fetch is specified, returns all events
for tokens issued after the expiration cutoff.
"""
raise exception.NotImplemented()
@abc.abstractmethod
**** CubicPower OpenStack Study ****
def revoke(self, event):
"""register a revocation event
:param event: An instance of
keystone.contrib.revoke.model.RevocationEvent
"""
raise exception.NotImplemented()