From 920a49cfa055733d575282973e23558c33087a4a Mon Sep 17 00:00:00 2001 From: RHE Date: Fri, 24 Nov 2017 13:54:26 +0100 Subject: remove keystone-moon Change-Id: I80d7c9b669f19d5f6607e162de8e0e55c2f80fdd Signed-off-by: RHE --- keystone-moon/keystone/contrib/revoke/__init__.py | 0 .../keystone/contrib/revoke/backends/__init__.py | 0 .../keystone/contrib/revoke/backends/kvs.py | 74 ---- .../keystone/contrib/revoke/backends/sql.py | 28 -- .../keystone/contrib/revoke/controllers.py | 44 --- keystone-moon/keystone/contrib/revoke/core.py | 262 --------------- .../contrib/revoke/migrate_repo/__init__.py | 0 .../contrib/revoke/migrate_repo/migrate.cfg | 25 -- .../migrate_repo/versions/001_revoke_table.py | 17 - .../002_add_audit_id_and_chain_to_revoke_table.py | 17 - .../revoke/migrate_repo/versions/__init__.py | 0 keystone-moon/keystone/contrib/revoke/model.py | 371 --------------------- keystone-moon/keystone/contrib/revoke/routers.py | 31 -- 13 files changed, 869 deletions(-) delete mode 100644 keystone-moon/keystone/contrib/revoke/__init__.py delete mode 100644 keystone-moon/keystone/contrib/revoke/backends/__init__.py delete mode 100644 keystone-moon/keystone/contrib/revoke/backends/kvs.py delete mode 100644 keystone-moon/keystone/contrib/revoke/backends/sql.py delete mode 100644 keystone-moon/keystone/contrib/revoke/controllers.py delete mode 100644 keystone-moon/keystone/contrib/revoke/core.py delete mode 100644 keystone-moon/keystone/contrib/revoke/migrate_repo/__init__.py delete mode 100644 keystone-moon/keystone/contrib/revoke/migrate_repo/migrate.cfg delete mode 100644 keystone-moon/keystone/contrib/revoke/migrate_repo/versions/001_revoke_table.py delete mode 100644 keystone-moon/keystone/contrib/revoke/migrate_repo/versions/002_add_audit_id_and_chain_to_revoke_table.py delete mode 100644 keystone-moon/keystone/contrib/revoke/migrate_repo/versions/__init__.py delete mode 100644 keystone-moon/keystone/contrib/revoke/model.py delete mode 100644 keystone-moon/keystone/contrib/revoke/routers.py (limited to 'keystone-moon/keystone/contrib/revoke') diff --git a/keystone-moon/keystone/contrib/revoke/__init__.py b/keystone-moon/keystone/contrib/revoke/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/keystone-moon/keystone/contrib/revoke/backends/__init__.py b/keystone-moon/keystone/contrib/revoke/backends/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/keystone-moon/keystone/contrib/revoke/backends/kvs.py b/keystone-moon/keystone/contrib/revoke/backends/kvs.py deleted file mode 100644 index 086becb0..00000000 --- a/keystone-moon/keystone/contrib/revoke/backends/kvs.py +++ /dev/null @@ -1,74 +0,0 @@ -# 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 datetime - -from oslo_config import cfg -from oslo_log import versionutils -from oslo_utils import timeutils - -from keystone.common import kvs -from keystone.contrib import revoke -from keystone import exception - - -CONF = cfg.CONF - -_EVENT_KEY = 'os-revoke-events' -_KVS_BACKEND = 'openstack.kvs.Memory' - - -class Revoke(revoke.RevokeDriverV8): - - @versionutils.deprecated( - versionutils.deprecated.JUNO, - in_favor_of='keystone.contrib.revoke.backends.sql', - remove_in=+1, - what='keystone.contrib.revoke.backends.kvs') - def __init__(self, **kwargs): - super(Revoke, self).__init__() - self._store = kvs.get_key_value_store('os-revoke-driver') - self._store.configure(backing_store=_KVS_BACKEND, **kwargs) - - def _list_events(self): - try: - return self._store.get(_EVENT_KEY) - except exception.NotFound: - return [] - - def list_events(self, last_fetch=None): - results = [] - - with self._store.get_lock(_EVENT_KEY): - events = self._list_events() - - for event in events: - revoked_at = event.revoked_at - if last_fetch is None or revoked_at > last_fetch: - results.append(event) - return results - - def revoke(self, event): - pruned = [] - expire_delta = datetime.timedelta(seconds=CONF.token.expiration) - oldest = timeutils.utcnow() - expire_delta - - with self._store.get_lock(_EVENT_KEY) as lock: - events = self._list_events() - if event: - events.append(event) - - for event in events: - revoked_at = event.revoked_at - if revoked_at > oldest: - pruned.append(event) - self._store.set(_EVENT_KEY, pruned, lock) diff --git a/keystone-moon/keystone/contrib/revoke/backends/sql.py b/keystone-moon/keystone/contrib/revoke/backends/sql.py deleted file mode 100644 index 0bf493ae..00000000 --- a/keystone-moon/keystone/contrib/revoke/backends/sql.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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. - -from oslo_log import versionutils - -from keystone.revoke.backends import sql - - -_OLD = "keystone.contrib.revoke.backends.sql.Revoke" -_NEW = "sql" - - -class Revoke(sql.Revoke): - - @versionutils.deprecated(versionutils.deprecated.MITAKA, - in_favor_of=_NEW, - what=_OLD) - def __init__(self, *args, **kwargs): - super(Revoke, self).__init__(*args, **kwargs) diff --git a/keystone-moon/keystone/contrib/revoke/controllers.py b/keystone-moon/keystone/contrib/revoke/controllers.py deleted file mode 100644 index 40151bae..00000000 --- a/keystone-moon/keystone/contrib/revoke/controllers.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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. - -from oslo_utils import timeutils - -from keystone.common import controller -from keystone.common import dependency -from keystone import exception -from keystone.i18n import _ - - -@dependency.requires('revoke_api') -class RevokeController(controller.V3Controller): - @controller.protected() - def list_revoke_events(self, context): - since = context['query_string'].get('since') - last_fetch = None - if since: - try: - last_fetch = timeutils.normalize_time( - timeutils.parse_isotime(since)) - except ValueError: - raise exception.ValidationError( - message=_('invalid date format %s') % since) - events = self.revoke_api.list_events(last_fetch=last_fetch) - # Build the links by hand as the standard controller calls require ids - response = {'events': [event.to_dict() for event in events], - 'links': { - 'next': None, - 'self': RevokeController.base_url( - context, - path=context['path']), - 'previous': None} - } - return response diff --git a/keystone-moon/keystone/contrib/revoke/core.py b/keystone-moon/keystone/contrib/revoke/core.py deleted file mode 100644 index 3b108c9e..00000000 --- a/keystone-moon/keystone/contrib/revoke/core.py +++ /dev/null @@ -1,262 +0,0 @@ -# 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. - -"""Main entry point into the Revoke service.""" - -import abc -import datetime - -from oslo_config import cfg -from oslo_log import log -from oslo_log import versionutils -from oslo_utils import timeutils -import six - -from keystone.common import cache -from keystone.common import dependency -from keystone.common import extension -from keystone.common import manager -from keystone.contrib.revoke import model -from keystone import exception -from keystone.i18n import _ -from keystone import notifications - - -CONF = cfg.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) - -MEMOIZE = cache.get_memoization_decorator(section='revoke') - - -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') -class Manager(manager.Manager): - """Default pivot point for the Revoke backend. - - Performs common logic for recording revocations. - - See :mod:`keystone.common.manager.Manager` for more details on - how this dynamically calls the backend. - - """ - - driver_namespace = 'keystone.revoke' - - def __init__(self): - super(Manager, self).__init__(CONF.revoke.driver) - self._register_listeners() - self.model = model - - def _user_callback(self, service, resource_type, operation, - payload): - self.revoke_by_user(payload['resource_info']) - - def _role_callback(self, service, resource_type, operation, - payload): - self.revoke( - model.RevokeEvent(role_id=payload['resource_info'])) - - def _project_callback(self, service, resource_type, operation, - payload): - self.revoke( - model.RevokeEvent(project_id=payload['resource_info'])) - - def _domain_callback(self, service, resource_type, operation, - payload): - self.revoke( - model.RevokeEvent(domain_id=payload['resource_info'])) - - def _trust_callback(self, service, resource_type, operation, - payload): - self.revoke( - model.RevokeEvent(trust_id=payload['resource_info'])) - - def _consumer_callback(self, service, resource_type, operation, - payload): - self.revoke( - model.RevokeEvent(consumer_id=payload['resource_info'])) - - def _access_token_callback(self, service, resource_type, operation, - payload): - self.revoke( - model.RevokeEvent(access_token_id=payload['resource_info'])) - - def _role_assignment_callback(self, service, resource_type, operation, - payload): - info = payload['resource_info'] - self.revoke_by_grant(role_id=info['role_id'], user_id=info['user_id'], - domain_id=info.get('domain_id'), - project_id=info.get('project_id')) - - def _register_listeners(self): - callbacks = { - notifications.ACTIONS.deleted: [ - ['OS-TRUST:trust', self._trust_callback], - ['OS-OAUTH1:consumer', self._consumer_callback], - ['OS-OAUTH1:access_token', self._access_token_callback], - ['role', self._role_callback], - ['user', self._user_callback], - ['project', self._project_callback], - ['role_assignment', self._role_assignment_callback] - ], - notifications.ACTIONS.disabled: [ - ['user', self._user_callback], - ['project', self._project_callback], - ['domain', self._domain_callback], - ], - notifications.ACTIONS.internal: [ - [notifications.INVALIDATE_USER_TOKEN_PERSISTENCE, - self._user_callback], - ] - } - - for event, cb_info in callbacks.items(): - for resource_type, callback_fns in cb_info: - notifications.register_event_callback(event, resource_type, - callback_fns) - - def revoke_by_user(self, user_id): - return self.revoke(model.RevokeEvent(user_id=user_id)) - - def _assert_not_domain_and_project_scoped(self, domain_id=None, - project_id=None): - if domain_id is not None and project_id is not None: - msg = _('The revoke call must not have both domain_id and ' - 'project_id. This is a bug in the Keystone server. The ' - 'current request is aborted.') - raise exception.UnexpectedError(exception=msg) - - @versionutils.deprecated(as_of=versionutils.deprecated.JUNO, - remove_in=0) - def revoke_by_expiration(self, user_id, expires_at, - domain_id=None, project_id=None): - - self._assert_not_domain_and_project_scoped(domain_id=domain_id, - project_id=project_id) - - self.revoke( - model.RevokeEvent(user_id=user_id, - expires_at=expires_at, - domain_id=domain_id, - project_id=project_id)) - - def revoke_by_audit_id(self, audit_id): - self.revoke(model.RevokeEvent(audit_id=audit_id)) - - def revoke_by_audit_chain_id(self, audit_chain_id, project_id=None, - domain_id=None): - - self._assert_not_domain_and_project_scoped(domain_id=domain_id, - project_id=project_id) - - self.revoke(model.RevokeEvent(audit_chain_id=audit_chain_id, - domain_id=domain_id, - project_id=project_id)) - - 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)) - - def revoke_by_user_and_project(self, user_id, project_id): - self.revoke( - model.RevokeEvent(project_id=project_id, user_id=user_id)) - - def revoke_by_project_role_assignment(self, project_id, role_id): - self.revoke(model.RevokeEvent(project_id=project_id, role_id=role_id)) - - def revoke_by_domain_role_assignment(self, domain_id, role_id): - self.revoke(model.RevokeEvent(domain_id=domain_id, role_id=role_id)) - - @MEMOIZE - def _get_revoke_tree(self): - events = self.driver.list_events() - revoke_tree = model.RevokeTree(revoke_events=events) - - return revoke_tree - - 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')) - - def revoke(self, event): - self.driver.revoke(event) - self._get_revoke_tree.invalidate(self) - - -@six.add_metaclass(abc.ABCMeta) -class RevokeDriverV8(object): - """Interface for recording and reporting revocation events.""" - - @abc.abstractmethod - def list_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() # pragma: no cover - - @abc.abstractmethod - def revoke(self, event): - """register a revocation event - - :param event: An instance of - keystone.contrib.revoke.model.RevocationEvent - - """ - raise exception.NotImplemented() # pragma: no cover - - -Driver = manager.create_legacy_driver(RevokeDriverV8) diff --git a/keystone-moon/keystone/contrib/revoke/migrate_repo/__init__.py b/keystone-moon/keystone/contrib/revoke/migrate_repo/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/keystone-moon/keystone/contrib/revoke/migrate_repo/migrate.cfg b/keystone-moon/keystone/contrib/revoke/migrate_repo/migrate.cfg deleted file mode 100644 index 0e61bcaa..00000000 --- a/keystone-moon/keystone/contrib/revoke/migrate_repo/migrate.cfg +++ /dev/null @@ -1,25 +0,0 @@ -[db_settings] -# Used to identify which repository this database is versioned under. -# You can use the name of your project. -repository_id=revoke - -# The name of the database table used to track the schema version. -# This name shouldn't already be used by your project. -# If this is changed once a database is under version control, you'll need to -# change the table name in each database too. -version_table=migrate_version - -# When committing a change script, Migrate will attempt to generate the -# sql for all supported databases; normally, if one of them fails - probably -# because you don't have that database installed - it is ignored and the -# commit continues, perhaps ending successfully. -# Databases in this list MUST compile successfully during a commit, or the -# entire commit will fail. List the databases your application will actually -# be using to ensure your updates to that database work properly. -# This must be a list; example: ['postgres','sqlite'] -required_dbs=[] - -# When creating new change scripts, Migrate will stamp the new script with -# a version number. By default this is latest_version + 1. You can set this -# to 'true' to tell Migrate to use the UTC timestamp instead. -use_timestamp_numbering=False diff --git a/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/001_revoke_table.py b/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/001_revoke_table.py deleted file mode 100644 index 81c535e1..00000000 --- a/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/001_revoke_table.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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. - -from keystone import exception - - -def upgrade(migrate_engine): - raise exception.MigrationMovedFailure(extension='revoke') diff --git a/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/002_add_audit_id_and_chain_to_revoke_table.py b/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/002_add_audit_id_and_chain_to_revoke_table.py deleted file mode 100644 index 81c535e1..00000000 --- a/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/002_add_audit_id_and_chain_to_revoke_table.py +++ /dev/null @@ -1,17 +0,0 @@ -# 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. - -from keystone import exception - - -def upgrade(migrate_engine): - raise exception.MigrationMovedFailure(extension='revoke') diff --git a/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/__init__.py b/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/keystone-moon/keystone/contrib/revoke/model.py b/keystone-moon/keystone/contrib/revoke/model.py deleted file mode 100644 index e677bfb5..00000000 --- a/keystone-moon/keystone/contrib/revoke/model.py +++ /dev/null @@ -1,371 +0,0 @@ -# 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. - -from oslo_utils import timeutils -from six.moves import map - -from keystone.common import utils - - -# The set of attributes common between the RevokeEvent -# and the dictionaries created from the token Data. -_NAMES = ['trust_id', - 'consumer_id', - 'access_token_id', - 'audit_id', - 'audit_chain_id', - 'expires_at', - 'domain_id', - 'project_id', - 'user_id', - 'role_id'] - - -# Additional arguments for creating a RevokeEvent -_EVENT_ARGS = ['issued_before', 'revoked_at'] - -# Names of attributes in the RevocationEvent, including "virtual" attributes. -# Virtual attributes are those added based on other values. -_EVENT_NAMES = _NAMES + ['domain_scope_id'] - -# Values that will be in the token data but not in the event. -# These will compared with event values that have different names. -# For example: both trustor_id and trustee_id are compared against user_id -_TOKEN_KEYS = ['identity_domain_id', - 'assignment_domain_id', - 'issued_at', - 'trustor_id', - 'trustee_id'] - -# Alternative names to be checked in token for every field in -# revoke tree. -ALTERNATIVES = { - 'user_id': ['user_id', 'trustor_id', 'trustee_id'], - 'domain_id': ['identity_domain_id', 'assignment_domain_id'], - # For a domain-scoped token, the domain is in assignment_domain_id. - 'domain_scope_id': ['assignment_domain_id', ], -} - - -REVOKE_KEYS = _NAMES + _EVENT_ARGS - - -def blank_token_data(issued_at): - token_data = dict() - for name in _NAMES: - token_data[name] = None - for name in _TOKEN_KEYS: - token_data[name] = None - # required field - token_data['issued_at'] = issued_at - return token_data - - -class RevokeEvent(object): - def __init__(self, **kwargs): - for k in REVOKE_KEYS: - v = kwargs.get(k, None) - setattr(self, k, v) - - if self.domain_id and self.expires_at: - # This is revoking a domain-scoped token. - self.domain_scope_id = self.domain_id - self.domain_id = None - else: - # This is revoking all tokens for a domain. - self.domain_scope_id = None - - if self.expires_at is not None: - # Trim off the expiration time because MySQL timestamps are only - # accurate to the second. - self.expires_at = self.expires_at.replace(microsecond=0) - - if self.revoked_at is None: - self.revoked_at = timeutils.utcnow() - if self.issued_before is None: - self.issued_before = self.revoked_at - - def to_dict(self): - keys = ['user_id', - 'role_id', - 'domain_id', - 'domain_scope_id', - 'project_id', - 'audit_id', - 'audit_chain_id', - ] - event = {key: self.__dict__[key] for key in keys - if self.__dict__[key] is not None} - if self.trust_id is not None: - event['OS-TRUST:trust_id'] = self.trust_id - if self.consumer_id is not None: - event['OS-OAUTH1:consumer_id'] = self.consumer_id - if self.consumer_id is not None: - event['OS-OAUTH1:access_token_id'] = self.access_token_id - if self.expires_at is not None: - event['expires_at'] = utils.isotime(self.expires_at) - if self.issued_before is not None: - event['issued_before'] = utils.isotime(self.issued_before, - subsecond=True) - return event - - def key_for_name(self, name): - return "%s=%s" % (name, getattr(self, name) or '*') - - -def attr_keys(event): - return list(map(event.key_for_name, _EVENT_NAMES)) - - -class RevokeTree(object): - """Fast Revocation Checking Tree Structure - - The Tree is an index to quickly match tokens against events. - Each node is a hashtable of key=value combinations from revocation events. - The - - """ - - def __init__(self, revoke_events=None): - self.revoke_map = dict() - self.add_events(revoke_events) - - def add_event(self, event): - """Updates the tree based on a revocation event. - - Creates any necessary internal nodes in the tree corresponding to the - fields of the revocation event. The leaf node will always be set to - the latest 'issued_before' for events that are otherwise identical. - - :param: Event to add to the tree - - :returns: the event that was passed in. - - """ - revoke_map = self.revoke_map - for key in attr_keys(event): - revoke_map = revoke_map.setdefault(key, {}) - revoke_map['issued_before'] = max( - event.issued_before, revoke_map.get( - 'issued_before', event.issued_before)) - return event - - def remove_event(self, event): - """Update the tree based on the removal of a Revocation Event - - Removes empty nodes from the tree from the leaf back to the root. - - If multiple events trace the same path, but have different - 'issued_before' values, only the last is ever stored in the tree. - So only an exact match on 'issued_before' ever triggers a removal - - :param: Event to remove from the tree - - """ - stack = [] - revoke_map = self.revoke_map - for name in _EVENT_NAMES: - key = event.key_for_name(name) - nxt = revoke_map.get(key) - if nxt is None: - break - stack.append((revoke_map, key, nxt)) - revoke_map = nxt - else: - if event.issued_before == revoke_map['issued_before']: - revoke_map.pop('issued_before') - for parent, key, child in reversed(stack): - if not any(child): - del parent[key] - - def add_events(self, revoke_events): - return list(map(self.add_event, revoke_events or [])) - - @staticmethod - def _next_level_keys(name, token_data): - """Generate keys based on current field name and token data - - Generate all keys to look for in the next iteration of revocation - event tree traversal. - """ - yield '*' - if name == 'role_id': - # Roles are very special since a token has a list of them. - # If the revocation event matches any one of them, - # revoke the token. - for role_id in token_data.get('roles', []): - yield role_id - else: - # For other fields we try to get any branch that concur - # with any alternative field in the token. - for alt_name in ALTERNATIVES.get(name, [name]): - yield token_data[alt_name] - - def _search(self, revoke_map, names, token_data): - """Search for revocation event by token_data - - Traverse the revocation events tree looking for event matching token - data issued after the token. - """ - if not names: - # The last (leaf) level is checked in a special way because we - # verify issued_at field differently. - try: - return revoke_map['issued_before'] >= token_data['issued_at'] - except KeyError: - return False - - name, remaining_names = names[0], names[1:] - - for key in self._next_level_keys(name, token_data): - subtree = revoke_map.get('%s=%s' % (name, key)) - if subtree and self._search(subtree, remaining_names, token_data): - return True - - # If we made it out of the loop then no element in revocation tree - # corresponds to our token and it is good. - return False - - def is_revoked(self, token_data): - """Check if a token matches the revocation event - - Compare the values for each level of the tree with the values from - the token, accounting for attributes that have alternative - keys, and for wildcard matches. - if there is a match, continue down the tree. - if there is no match, exit early. - - token_data is a map based on a flattened view of token. - The required fields are: - - 'expires_at','user_id', 'project_id', 'identity_domain_id', - 'assignment_domain_id', 'trust_id', 'trustor_id', 'trustee_id' - 'consumer_id', 'access_token_id' - - """ - return self._search(self.revoke_map, _EVENT_NAMES, token_data) - - -def build_token_values_v2(access, default_domain_id): - token_data = access['token'] - - token_expires_at = timeutils.parse_isotime(token_data['expires']) - - # Trim off the microseconds because the revocation event only has - # expirations accurate to the second. - token_expires_at = token_expires_at.replace(microsecond=0) - - token_values = { - 'expires_at': timeutils.normalize_time(token_expires_at), - 'issued_at': timeutils.normalize_time( - timeutils.parse_isotime(token_data['issued_at'])), - 'audit_id': token_data.get('audit_ids', [None])[0], - 'audit_chain_id': token_data.get('audit_ids', [None])[-1], - } - - token_values['user_id'] = access.get('user', {}).get('id') - - project = token_data.get('tenant') - if project is not None: - token_values['project_id'] = project['id'] - else: - token_values['project_id'] = None - - token_values['identity_domain_id'] = default_domain_id - token_values['assignment_domain_id'] = default_domain_id - - trust = token_data.get('trust') - if trust is None: - token_values['trust_id'] = None - token_values['trustor_id'] = None - token_values['trustee_id'] = None - else: - token_values['trust_id'] = trust['id'] - token_values['trustor_id'] = trust['trustor_id'] - token_values['trustee_id'] = trust['trustee_id'] - - token_values['consumer_id'] = None - token_values['access_token_id'] = None - - role_list = [] - # Roles are by ID in metadata and by name in the user section - roles = access.get('metadata', {}).get('roles', []) - for role in roles: - role_list.append(role) - token_values['roles'] = role_list - return token_values - - -def build_token_values(token_data): - - token_expires_at = timeutils.parse_isotime(token_data['expires_at']) - - # Trim off the microseconds because the revocation event only has - # expirations accurate to the second. - token_expires_at = token_expires_at.replace(microsecond=0) - - token_values = { - 'expires_at': timeutils.normalize_time(token_expires_at), - 'issued_at': timeutils.normalize_time( - timeutils.parse_isotime(token_data['issued_at'])), - 'audit_id': token_data.get('audit_ids', [None])[0], - 'audit_chain_id': token_data.get('audit_ids', [None])[-1], - } - - user = token_data.get('user') - if user is not None: - token_values['user_id'] = user['id'] - # Federated users do not have a domain, be defensive and get the user - # domain set to None in the federated user case. - token_values['identity_domain_id'] = user.get('domain', {}).get('id') - else: - token_values['user_id'] = None - token_values['identity_domain_id'] = None - - project = token_data.get('project', token_data.get('tenant')) - if project is not None: - token_values['project_id'] = project['id'] - token_values['assignment_domain_id'] = project['domain']['id'] - else: - token_values['project_id'] = None - - domain = token_data.get('domain') - if domain is not None: - token_values['assignment_domain_id'] = domain['id'] - else: - token_values['assignment_domain_id'] = None - - role_list = [] - roles = token_data.get('roles') - if roles is not None: - for role in roles: - role_list.append(role['id']) - token_values['roles'] = role_list - - trust = token_data.get('OS-TRUST:trust') - if trust is None: - token_values['trust_id'] = None - token_values['trustor_id'] = None - token_values['trustee_id'] = None - else: - token_values['trust_id'] = trust['id'] - token_values['trustor_id'] = trust['trustor_user']['id'] - token_values['trustee_id'] = trust['trustee_user']['id'] - - oauth1 = token_data.get('OS-OAUTH1') - if oauth1 is None: - token_values['consumer_id'] = None - token_values['access_token_id'] = None - else: - token_values['consumer_id'] = oauth1['consumer_id'] - token_values['access_token_id'] = oauth1['access_token_id'] - return token_values diff --git a/keystone-moon/keystone/contrib/revoke/routers.py b/keystone-moon/keystone/contrib/revoke/routers.py deleted file mode 100644 index a44c6194..00000000 --- a/keystone-moon/keystone/contrib/revoke/routers.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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. - -from oslo_log import log -from oslo_log import versionutils - -from keystone.common import wsgi -from keystone.i18n import _ - - -LOG = log.getLogger(__name__) - - -class RevokeExtension(wsgi.Middleware): - - def __init__(self, *args, **kwargs): - super(RevokeExtension, self).__init__(*args, **kwargs) - msg = _("Remove revoke_extension from the paste pipeline, the " - "revoke extension is now always available. Update the " - "[pipeline:api_v3] section in keystone-paste.ini accordingly, " - "as it will be removed in the O release.") - versionutils.report_deprecated_feature(LOG, msg) -- cgit 1.2.3-korg