diff options
author | RHE <rebirthmonkey@gmail.com> | 2017-11-24 13:54:26 +0100 |
---|---|---|
committer | RHE <rebirthmonkey@gmail.com> | 2017-11-24 13:54:26 +0100 |
commit | 920a49cfa055733d575282973e23558c33087a4a (patch) | |
tree | d371dab34efa5028600dad2e7ca58063626e7ba4 /keystone-moon/keystone/models | |
parent | ef3eefca70d8abb4a00dafb9419ad32738e934b2 (diff) |
remove keystone-moon
Change-Id: I80d7c9b669f19d5f6607e162de8e0e55c2f80fdd
Signed-off-by: RHE <rebirthmonkey@gmail.com>
Diffstat (limited to 'keystone-moon/keystone/models')
-rw-r--r-- | keystone-moon/keystone/models/__init__.py | 0 | ||||
-rw-r--r-- | keystone-moon/keystone/models/revoke_model.py | 373 | ||||
-rw-r--r-- | keystone-moon/keystone/models/token_model.py | 339 |
3 files changed, 0 insertions, 712 deletions
diff --git a/keystone-moon/keystone/models/__init__.py b/keystone-moon/keystone/models/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/keystone-moon/keystone/models/__init__.py +++ /dev/null diff --git a/keystone-moon/keystone/models/revoke_model.py b/keystone-moon/keystone/models/revoke_model.py deleted file mode 100644 index 0fc3e628..00000000 --- a/keystone-moon/keystone/models/revoke_model.py +++ /dev/null @@ -1,373 +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) - 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'] - # The domain_id of projects acting as domains is None - token_values['assignment_domain_id'] = ( - project['domain']['id'] if project['domain'] else None) - 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/models/token_model.py b/keystone-moon/keystone/models/token_model.py deleted file mode 100644 index 32e6b365..00000000 --- a/keystone-moon/keystone/models/token_model.py +++ /dev/null @@ -1,339 +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. - -"""Unified in-memory token model.""" - -from keystoneclient.common import cms -from oslo_config import cfg -from oslo_utils import reflection -from oslo_utils import timeutils -import six - -from keystone import exception -from keystone.federation import constants -from keystone.i18n import _ - -CONF = cfg.CONF -# supported token versions -V2 = 'v2.0' -V3 = 'v3.0' -VERSIONS = frozenset([V2, V3]) - - -def _parse_and_normalize_time(time_data): - if isinstance(time_data, six.string_types): - time_data = timeutils.parse_isotime(time_data) - return timeutils.normalize_time(time_data) - - -class KeystoneToken(dict): - """An in-memory representation that unifies v2 and v3 tokens.""" - - # TODO(morganfainberg): Align this in-memory representation with the - # objects in keystoneclient. This object should be eventually updated - # to be the source of token data with the ability to emit any version - # of the token instead of only consuming the token dict and providing - # property accessors for the underlying data. - - def __init__(self, token_id, token_data): - self.token_data = token_data - if 'access' in token_data: - super(KeystoneToken, self).__init__(**token_data['access']) - self.version = V2 - elif 'token' in token_data and 'methods' in token_data['token']: - super(KeystoneToken, self).__init__(**token_data['token']) - self.version = V3 - else: - raise exception.UnsupportedTokenVersionException() - self.token_id = token_id - self.short_id = cms.cms_hash_token(token_id, - mode=CONF.token.hash_algorithm) - - if self.project_scoped and self.domain_scoped: - raise exception.UnexpectedError(_('Found invalid token: scoped to ' - 'both project and domain.')) - - def __repr__(self): - desc = ('<%(type)s (audit_id=%(audit_id)s, ' - 'audit_chain_id=%(audit_chain_id)s) at %(loc)s>') - self_cls_name = reflection.get_class_name(self, - fully_qualified=False) - return desc % {'type': self_cls_name, - 'audit_id': self.audit_id, - 'audit_chain_id': self.audit_chain_id, - 'loc': hex(id(self))} - - @property - def expires(self): - if self.version is V3: - expires_at = self['expires_at'] - else: - expires_at = self['token']['expires'] - return _parse_and_normalize_time(expires_at) - - @property - def issued(self): - if self.version is V3: - issued_at = self['issued_at'] - else: - issued_at = self['token']['issued_at'] - return _parse_and_normalize_time(issued_at) - - @property - def audit_id(self): - if self.version is V3: - return self.get('audit_ids', [None])[0] - return self['token'].get('audit_ids', [None])[0] - - @property - def audit_chain_id(self): - if self.version is V3: - return self.get('audit_ids', [None])[-1] - return self['token'].get('audit_ids', [None])[-1] - - @property - def auth_token(self): - return self.token_id - - @property - def user_id(self): - return self['user']['id'] - - @property - def user_name(self): - return self['user']['name'] - - @property - def user_domain_name(self): - try: - if self.version == V3: - return self['user']['domain']['name'] - elif 'user' in self: - return "Default" - except KeyError: # nosec - # Do not raise KeyError, raise UnexpectedError - pass - raise exception.UnexpectedError() - - @property - def user_domain_id(self): - try: - if self.version == V3: - return self['user']['domain']['id'] - elif 'user' in self: - return CONF.identity.default_domain_id - except KeyError: # nosec - # Do not raise KeyError, raise UnexpectedError - pass - raise exception.UnexpectedError() - - @property - def domain_id(self): - if self.version is V3: - try: - return self['domain']['id'] - except KeyError: - # Do not raise KeyError, raise UnexpectedError - raise exception.UnexpectedError() - # No domain scoped tokens in V2. - raise NotImplementedError() - - @property - def domain_name(self): - if self.version is V3: - try: - return self['domain']['name'] - except KeyError: - # Do not raise KeyError, raise UnexpectedError - raise exception.UnexpectedError() - # No domain scoped tokens in V2. - raise NotImplementedError() - - @property - def project_id(self): - try: - if self.version is V3: - return self['project']['id'] - else: - return self['token']['tenant']['id'] - except KeyError: - # Do not raise KeyError, raise UnexpectedError - raise exception.UnexpectedError() - - @property - def project_name(self): - try: - if self.version is V3: - return self['project']['name'] - else: - return self['token']['tenant']['name'] - except KeyError: - # Do not raise KeyError, raise UnexpectedError - raise exception.UnexpectedError() - - @property - def project_domain_id(self): - try: - if self.version is V3: - return self['project']['domain']['id'] - elif 'tenant' in self['token']: - return CONF.identity.default_domain_id - except KeyError: # nosec - # Do not raise KeyError, raise UnexpectedError - pass - - raise exception.UnexpectedError() - - @property - def project_domain_name(self): - try: - if self.version is V3: - return self['project']['domain']['name'] - if 'tenant' in self['token']: - return 'Default' - except KeyError: # nosec - # Do not raise KeyError, raise UnexpectedError - pass - - raise exception.UnexpectedError() - - @property - def project_scoped(self): - if self.version is V3: - return 'project' in self - else: - return 'tenant' in self['token'] - - @property - def domain_scoped(self): - if self.version is V3: - return 'domain' in self - return False - - @property - def scoped(self): - return self.project_scoped or self.domain_scoped - - @property - def trust_id(self): - if self.version is V3: - return self.get('OS-TRUST:trust', {}).get('id') - else: - return self.get('trust', {}).get('id') - - @property - def trust_scoped(self): - if self.version is V3: - return 'OS-TRUST:trust' in self - else: - return 'trust' in self - - @property - def trustee_user_id(self): - if self.version is V3: - return self.get( - 'OS-TRUST:trust', {}).get('trustee_user_id') - else: - return self.get('trust', {}).get('trustee_user_id') - - @property - def trustor_user_id(self): - if self.version is V3: - return self.get( - 'OS-TRUST:trust', {}).get('trustor_user_id') - else: - return self.get('trust', {}).get('trustor_user_id') - - @property - def trust_impersonation(self): - if self.version is V3: - return self.get('OS-TRUST:trust', {}).get('impersonation') - else: - return self.get('trust', {}).get('impersonation') - - @property - def oauth_scoped(self): - return 'OS-OAUTH1' in self - - @property - def oauth_access_token_id(self): - if self.version is V3 and self.oauth_scoped: - return self['OS-OAUTH1']['access_token_id'] - return None - - @property - def oauth_consumer_id(self): - if self.version is V3 and self.oauth_scoped: - return self['OS-OAUTH1']['consumer_id'] - return None - - @property - def role_ids(self): - if self.version is V3: - return [r['id'] for r in self.get('roles', [])] - else: - return self.get('metadata', {}).get('roles', []) - - @property - def role_names(self): - if self.version is V3: - return [r['name'] for r in self.get('roles', [])] - else: - return [r['name'] for r in self['user'].get('roles', [])] - - @property - def bind(self): - if self.version is V3: - return self.get('bind') - return self.get('token', {}).get('bind') - - @property - def is_federated_user(self): - try: - return (self.version is V3 and - constants.FEDERATION in self['user']) - except KeyError: - raise exception.UnexpectedError() - - @property - def federation_group_ids(self): - if self.is_federated_user: - if self.version is V3: - try: - groups = self['user'][constants.FEDERATION].get( - 'groups', []) - return [g['id'] for g in groups] - except KeyError: - raise exception.UnexpectedError() - return [] - - @property - def federation_idp_id(self): - if self.version is not V3 or not self.is_federated_user: - return None - return self['user'][constants.FEDERATION]['identity_provider']['id'] - - @property - def federation_protocol_id(self): - if self.version is V3 and self.is_federated_user: - return self['user'][constants.FEDERATION]['protocol']['id'] - return None - - @property - def metadata(self): - return self.get('metadata', {}) - - @property - def methods(self): - if self.version is V3: - return self.get('methods', []) - return [] |