diff options
Diffstat (limited to 'keystone-moon/keystone/trust')
-rw-r--r-- | keystone-moon/keystone/trust/__init__.py | 1 | ||||
-rw-r--r-- | keystone-moon/keystone/trust/backends/sql.py | 78 | ||||
-rw-r--r-- | keystone-moon/keystone/trust/controllers.py | 42 | ||||
-rw-r--r-- | keystone-moon/keystone/trust/core.py | 29 |
4 files changed, 70 insertions, 80 deletions
diff --git a/keystone-moon/keystone/trust/__init__.py b/keystone-moon/keystone/trust/__init__.py index e5ee61fb..bd7297ea 100644 --- a/keystone-moon/keystone/trust/__init__.py +++ b/keystone-moon/keystone/trust/__init__.py @@ -14,4 +14,3 @@ from keystone.trust import controllers # noqa from keystone.trust.core import * # noqa -from keystone.trust import routers # noqa diff --git a/keystone-moon/keystone/trust/backends/sql.py b/keystone-moon/keystone/trust/backends/sql.py index a017056b..cb8446b3 100644 --- a/keystone-moon/keystone/trust/backends/sql.py +++ b/keystone-moon/keystone/trust/backends/sql.py @@ -14,7 +14,6 @@ import time -from oslo_log import log from oslo_utils import timeutils from six.moves import range @@ -23,7 +22,6 @@ from keystone import exception from keystone import trust -LOG = log.getLogger(__name__) # The maximum number of iterations that will be attempted for optimistic # locking on consuming a limited-use trust. MAXIMUM_CONSUME_ATTEMPTS = 10 @@ -45,6 +43,10 @@ class TrustModel(sql.ModelBase, sql.DictBase): expires_at = sql.Column(sql.DateTime) remaining_uses = sql.Column(sql.Integer, nullable=True) extra = sql.Column(sql.JsonBlob()) + __table_args__ = (sql.UniqueConstraint( + 'trustor_user_id', 'trustee_user_id', 'project_id', + 'impersonation', 'expires_at', + name='duplicate_trust_constraint'),) class TrustRole(sql.ModelBase): @@ -57,7 +59,7 @@ class TrustRole(sql.ModelBase): class Trust(trust.TrustDriverV8): @sql.handle_conflicts(conflict_type='trust') def create_trust(self, trust_id, trust, roles): - with sql.transaction() as session: + with sql.session_for_write() as session: ref = TrustModel.from_dict(trust) ref['id'] = trust_id if ref.get('expires_at') and ref['expires_at'].tzinfo is not None: @@ -70,9 +72,9 @@ class Trust(trust.TrustDriverV8): trust_role.role_id = role['id'] added_roles.append({'id': role['id']}) session.add(trust_role) - trust_dict = ref.to_dict() - trust_dict['roles'] = added_roles - return trust_dict + trust_dict = ref.to_dict() + trust_dict['roles'] = added_roles + return trust_dict def _add_roles(self, trust_id, session, trust_dict): roles = [] @@ -84,7 +86,7 @@ class Trust(trust.TrustDriverV8): def consume_use(self, trust_id): for attempt in range(MAXIMUM_CONSUME_ATTEMPTS): - with sql.transaction() as session: + with sql.session_for_write() as session: try: query_result = (session.query(TrustModel.remaining_uses). filter_by(id=trust_id). @@ -130,51 +132,51 @@ class Trust(trust.TrustDriverV8): raise exception.TrustConsumeMaximumAttempt(trust_id=trust_id) def get_trust(self, trust_id, deleted=False): - session = sql.get_session() - query = session.query(TrustModel).filter_by(id=trust_id) - if not deleted: - query = query.filter_by(deleted_at=None) - ref = query.first() - if ref is None: - raise exception.TrustNotFound(trust_id=trust_id) - if ref.expires_at is not None and not deleted: - now = timeutils.utcnow() - if now > ref.expires_at: + with sql.session_for_read() as session: + query = session.query(TrustModel).filter_by(id=trust_id) + if not deleted: + query = query.filter_by(deleted_at=None) + ref = query.first() + if ref is None: raise exception.TrustNotFound(trust_id=trust_id) - # Do not return trusts that can't be used anymore - if ref.remaining_uses is not None and not deleted: - if ref.remaining_uses <= 0: - raise exception.TrustNotFound(trust_id=trust_id) - trust_dict = ref.to_dict() + if ref.expires_at is not None and not deleted: + now = timeutils.utcnow() + if now > ref.expires_at: + raise exception.TrustNotFound(trust_id=trust_id) + # Do not return trusts that can't be used anymore + if ref.remaining_uses is not None and not deleted: + if ref.remaining_uses <= 0: + raise exception.TrustNotFound(trust_id=trust_id) + trust_dict = ref.to_dict() - self._add_roles(trust_id, session, trust_dict) - return trust_dict + self._add_roles(trust_id, session, trust_dict) + return trust_dict @sql.handle_conflicts(conflict_type='trust') def list_trusts(self): - session = sql.get_session() - trusts = session.query(TrustModel).filter_by(deleted_at=None) - return [trust_ref.to_dict() for trust_ref in trusts] + with sql.session_for_read() as session: + trusts = session.query(TrustModel).filter_by(deleted_at=None) + return [trust_ref.to_dict() for trust_ref in trusts] @sql.handle_conflicts(conflict_type='trust') def list_trusts_for_trustee(self, trustee_user_id): - session = sql.get_session() - trusts = (session.query(TrustModel). - filter_by(deleted_at=None). - filter_by(trustee_user_id=trustee_user_id)) - return [trust_ref.to_dict() for trust_ref in trusts] + with sql.session_for_read() as session: + trusts = (session.query(TrustModel). + filter_by(deleted_at=None). + filter_by(trustee_user_id=trustee_user_id)) + return [trust_ref.to_dict() for trust_ref in trusts] @sql.handle_conflicts(conflict_type='trust') def list_trusts_for_trustor(self, trustor_user_id): - session = sql.get_session() - trusts = (session.query(TrustModel). - filter_by(deleted_at=None). - filter_by(trustor_user_id=trustor_user_id)) - return [trust_ref.to_dict() for trust_ref in trusts] + with sql.session_for_read() as session: + trusts = (session.query(TrustModel). + filter_by(deleted_at=None). + filter_by(trustor_user_id=trustor_user_id)) + return [trust_ref.to_dict() for trust_ref in trusts] @sql.handle_conflicts(conflict_type='trust') def delete_trust(self, trust_id): - with sql.transaction() as session: + with sql.session_for_write() as session: trust_ref = session.query(TrustModel).get(trust_id) if not trust_ref: raise exception.TrustNotFound(trust_id=trust_id) diff --git a/keystone-moon/keystone/trust/controllers.py b/keystone-moon/keystone/trust/controllers.py index 39cf0110..00581304 100644 --- a/keystone-moon/keystone/trust/controllers.py +++ b/keystone-moon/keystone/trust/controllers.py @@ -14,9 +14,6 @@ import uuid -from oslo_config import cfg -from oslo_log import log -from oslo_log import versionutils from oslo_utils import timeutils import six @@ -31,11 +28,6 @@ from keystone import notifications from keystone.trust import schema -CONF = cfg.CONF - -LOG = log.getLogger(__name__) - - def _trustor_trustee_only(trust, user_id): if (user_id != trust.get('trustee_user_id') and user_id != trust.get('trustor_user_id')): @@ -47,8 +39,8 @@ def _admin_trustor_only(context, trust, user_id): raise exception.Forbidden() -@dependency.requires('assignment_api', 'identity_api', 'role_api', - 'token_provider_api', 'trust_api') +@dependency.requires('assignment_api', 'identity_api', 'resource_api', + 'role_api', 'token_provider_api', 'trust_api') class TrustV3(controller.V3Controller): collection_name = "trusts" member_name = "trust" @@ -56,7 +48,6 @@ class TrustV3(controller.V3Controller): @classmethod def base_url(cls, context, path=None): """Construct a path and pass it to V3Controller.base_url method.""" - # NOTE(stevemar): Overriding path to /OS-TRUST/trusts so that # V3Controller.base_url handles setting the self link correctly. path = '/OS-TRUST/' + cls.collection_name @@ -113,7 +104,7 @@ class TrustV3(controller.V3Controller): trust_roles.append({'id': all_role_names[rolename]['id']}) else: - raise exception.RoleNotFound("role %s is not defined" % + raise exception.RoleNotFound(_("role %s is not defined") % rolename) else: raise exception.ValidationError(attribute='id or name', @@ -128,7 +119,6 @@ class TrustV3(controller.V3Controller): The user creating the trust must be the trustor. """ - auth_context = context.get('environment', {}).get('KEYSTONE_AUTH_CONTEXT', {}) @@ -178,17 +168,27 @@ class TrustV3(controller.V3Controller): raise exception.Forbidden( _('At least one role should be specified.')) - def _get_user_role(self, trust): + def _get_trustor_roles(self, trust): + original_trust = trust.copy() + while original_trust.get('redelegated_trust_id'): + original_trust = self.trust_api.get_trust( + original_trust['redelegated_trust_id']) + if not self._attribute_is_empty(trust, 'project_id'): - return self.assignment_api.get_roles_for_user_and_project( - trust['trustor_user_id'], trust['project_id']) + self.resource_api.get_project(original_trust['project_id']) + # Get a list of roles including any domain specific roles + assignment_list = self.assignment_api.list_role_assignments( + user_id=original_trust['trustor_user_id'], + project_id=original_trust['project_id'], + effective=True, strip_domain_roles=False) + return list(set([x['role_id'] for x in assignment_list])) else: return [] def _require_trustor_has_role_in_project(self, trust): - user_roles = self._get_user_role(trust) + trustor_roles = self._get_trustor_roles(trust) for trust_role in trust['roles']: - matching_roles = [x for x in user_roles + matching_roles = [x for x in trustor_roles if x == trust_role['id']] if not matching_roles: raise exception.RoleNotFound(role_id=trust_role['id']) @@ -262,12 +262,6 @@ class TrustV3(controller.V3Controller): return {'roles': trust['roles'], 'links': trust['roles_links']} - @versionutils.deprecated( - versionutils.deprecated.KILO, - remove_in=+2) - def check_role_for_trust(self, context, trust_id, role_id): - return self._check_role_for_trust(self, context, trust_id, role_id) - @controller.protected() def get_role_for_trust(self, context, trust_id, role_id): """Get a role that has been assigned to a trust.""" diff --git a/keystone-moon/keystone/trust/core.py b/keystone-moon/keystone/trust/core.py index 7838cb03..43069deb 100644 --- a/keystone-moon/keystone/trust/core.py +++ b/keystone-moon/keystone/trust/core.py @@ -17,7 +17,6 @@ import abc from oslo_config import cfg -from oslo_log import log import six from six.moves import zip @@ -30,8 +29,6 @@ from keystone import notifications CONF = cfg.CONF -LOG = log.getLogger(__name__) - @dependency.requires('identity_api') @dependency.provider('trust_api') @@ -93,14 +90,9 @@ class Manager(manager.Manager): def get_trust_pedigree(self, trust_id): trust = self.driver.get_trust(trust_id) trust_chain = [trust] - if trust and trust.get('redelegated_trust_id'): - trusts = self.driver.list_trusts_for_trustor( - trust['trustor_user_id']) - while trust_chain[-1].get('redelegated_trust_id'): - for t in trusts: - if t['id'] == trust_chain[-1]['redelegated_trust_id']: - trust_chain.append(t) - break + while trust and trust.get('redelegated_trust_id'): + trust = self.driver.get_trust(trust['redelegated_trust_id']) + trust_chain.append(trust) return trust_chain @@ -179,7 +171,7 @@ class Manager(manager.Manager): def delete_trust(self, trust_id, initiator=None): """Remove a trust. - :raises: keystone.exception.TrustNotFound + :raises keystone.exception.TrustNotFound: If the trust doesn't exist. Recursively remove given and redelegated trusts """ @@ -192,7 +184,7 @@ class Manager(manager.Manager): # recursive call to make sure all notifications are sent try: self.delete_trust(t['id']) - except exception.TrustNotFound: + except exception.TrustNotFound: # nosec # if trust was deleted by concurrent process # consistency must not suffer pass @@ -244,11 +236,14 @@ class TrustDriverV8(object): @abc.abstractmethod def consume_use(self, trust_id): - """Consume one use when a trust was created with a limitation on its - uses, provided there are still uses available. + """Consume one use of a trust. + + One use of a trust is consumed when the trust was created with a + limitation on its uses, provided there are still uses available. - :raises: keystone.exception.TrustUseLimitReached, - keystone.exception.TrustNotFound + :raises keystone.exception.TrustUseLimitReached: If no remaining uses + for trust. + :raises keystone.exception.TrustNotFound: If the trust doesn't exist. """ raise exception.NotImplemented() # pragma: no cover |