keystone  18.0.0
About: OpenStack Keystone (Core Service: Identity) provides an authentication and authorization service for other OpenStack services. Provides a catalog of endpoints for all OpenStack services.
The "Victoria" series (maintained release).
  Fossies Dox: keystone-18.0.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

core.py
Go to the documentation of this file.
1 # Copyright 2012 OpenStack Foundation
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14 
15 """Main entry point into the Trust service."""
16 
17 from keystone.common import manager
18 from keystone.common import provider_api
19 import keystone.conf
20 from keystone import exception
21 from keystone.i18n import _
22 from keystone import notifications
23 
24 
25 CONF = keystone.conf.CONF
26 PROVIDERS = provider_api.ProviderAPIs
27 
28 
29 class Manager(manager.Manager):
30  """Default pivot point for the Trust backend.
31 
32  See :mod:`keystone.common.manager.Manager` for more details on how this
33  dynamically calls the backend.
34 
35  """
36 
37  driver_namespace = 'keystone.trust'
38  _provides_api = 'trust_api'
39 
40  _TRUST = "OS-TRUST:trust"
41 
42  def __init__(self):
43  super(Manager, self).__init__(CONF.trust.driver)
44  notifications.register_event_callback(
45  notifications.ACTIONS.deleted, 'user',
46  self._on_user_delete)
47 
48  def _on_user_delete(self, service, resource_type, operation,
49  payload):
50  # NOTE(davechen): Only delete the user that is maintained by
51  # keystone will delete the related trust, since we don't know
52  # when a LDAP user or federation user is deleted.
53  user_id = payload['resource_info']
54  trusts = self.driver.list_trusts_for_trustee(user_id)
55  trusts = trusts + self.driver.list_trusts_for_trustor(user_id)
56  for trust in trusts:
57  self.driver.delete_trust(trust['id'])
58 
59  @staticmethod
60  def _validate_redelegation(redelegated_trust, trust):
61  # Validate against:
62  # 0 < redelegation_count <= max_redelegation_count
63  max_redelegation_count = CONF.trust.max_redelegation_count
64  redelegation_depth = redelegated_trust.get('redelegation_count', 0)
65  if not (0 < redelegation_depth <= max_redelegation_count):
66  raise exception.Forbidden(
67  _('Remaining redelegation depth of %(redelegation_depth)d'
68  ' out of allowed range of [0..%(max_count)d]') %
69  {'redelegation_depth': redelegation_depth,
70  'max_count': max_redelegation_count})
71 
72  # remaining_uses is None
73  remaining_uses = trust.get('remaining_uses')
74  if remaining_uses is not None:
75  raise exception.Forbidden(
76  _('Field "remaining_uses" is set to %(value)s'
77  ' while it must not be set in order to redelegate a trust'),
78  value=remaining_uses)
79 
80  # expiry times
81  trust_expiry = trust.get('expires_at')
82  redelegated_expiry = redelegated_trust['expires_at']
83  if trust_expiry:
84  # redelegated trust is from backend and has no tzinfo
85  if redelegated_expiry < trust_expiry.replace(tzinfo=None):
86  raise exception.Forbidden(
87  _('Requested expiration time is more '
88  'than redelegated trust can provide'))
89  else:
90  trust['expires_at'] = redelegated_expiry
91 
92  # trust roles is a subset of roles of the redelegated trust
93  parent_roles = set(role['id']
94  for role in redelegated_trust['roles'])
95  if not all(role['id'] in parent_roles for role in trust['roles']):
96  raise exception.Forbidden(
97  _('Some of requested roles are not in redelegated trust'))
98 
99  # forbid to create a trust (with impersonation set to true) from a
100  # redelegated trust (with impersonation set to false)
101  if not redelegated_trust['impersonation'] and trust['impersonation']:
102  raise exception.Forbidden(
103  _('Impersonation is not allowed because redelegated trust '
104  'does not specify impersonation. Redelegated trust id: %s') %
105  redelegated_trust['id'])
106 
107  def get_trust_pedigree(self, trust_id):
108  trust = self.driver.get_trust(trust_id)
109  trust_chain = [trust]
110  while trust and trust.get('redelegated_trust_id'):
111  trust = self.driver.get_trust(trust['redelegated_trust_id'])
112  trust_chain.append(trust)
113 
114  return trust_chain
115 
116  def get_trust(self, trust_id, deleted=False):
117  trust = self.driver.get_trust(trust_id, deleted)
118 
119  if trust and trust.get('redelegated_trust_id') and not deleted:
120  trust_chain = self.get_trust_pedigree(trust_id)
121 
122  for parent, child in zip(trust_chain[1:], trust_chain):
123  self._validate_redelegation(parent, child)
124  try:
125  PROVIDERS.identity_api.assert_user_enabled(
126  parent['trustee_user_id'])
127  except (AssertionError, exception.NotFound):
128  raise exception.Forbidden(
129  _('One of the trust agents is disabled or deleted'))
130 
131  return trust
132 
133  def create_trust(self, trust_id, trust, roles, redelegated_trust=None,
134  initiator=None):
135  """Create a new trust.
136 
137  :returns: a new trust
138  """
139  # Default for initial trust in chain is max_redelegation_count
140  max_redelegation_count = CONF.trust.max_redelegation_count
141  requested_count = trust.get('redelegation_count')
142  redelegatable = (trust.pop('allow_redelegation', False)
143  and requested_count != 0)
144  if not redelegatable:
145  trust['redelegation_count'] = requested_count = 0
146  remaining_uses = trust.get('remaining_uses')
147  if remaining_uses is not None and remaining_uses <= 0:
148  msg = _('remaining_uses must be a positive integer or null.')
149  raise exception.ValidationError(msg)
150  else:
151  # Validate requested redelegation depth
152  if requested_count and requested_count > max_redelegation_count:
153  raise exception.Forbidden(
154  _('Requested redelegation depth of %(requested_count)d '
155  'is greater than allowed %(max_count)d') %
156  {'requested_count': requested_count,
157  'max_count': max_redelegation_count})
158  # Decline remaining_uses
159  if trust.get('remaining_uses') is not None:
161  _('remaining_uses must not be set if redelegation is '
162  'allowed'))
163 
164  if redelegated_trust:
165  trust['redelegated_trust_id'] = redelegated_trust['id']
166  remaining_count = redelegated_trust['redelegation_count'] - 1
167 
168  # Validate depth consistency
169  if (redelegatable and requested_count and
170  requested_count != remaining_count):
171  msg = _('Modifying "redelegation_count" upon redelegation is '
172  'forbidden. Omitting this parameter is advised.')
173  raise exception.Forbidden(msg)
174  trust.setdefault('redelegation_count', remaining_count)
175 
176  # Check entire trust pedigree validity
177  pedigree = self.get_trust_pedigree(redelegated_trust['id'])
178  for t in pedigree:
179  self._validate_redelegation(t, trust)
180 
181  trust.setdefault('redelegation_count', max_redelegation_count)
182  ref = self.driver.create_trust(trust_id, trust, roles)
183 
184  notifications.Audit.created(self._TRUST, trust_id, initiator=initiator)
185 
186  return ref
187 
188  def delete_trust(self, trust_id, initiator=None):
189  """Remove a trust.
190 
191  :raises keystone.exception.TrustNotFound: If the trust doesn't exist.
192 
193  Recursively remove given and redelegated trusts
194  """
195  trust = self.driver.get_trust(trust_id)
196  trusts = self.driver.list_trusts_for_trustor(
197  trust['trustor_user_id'])
198 
199  for t in trusts:
200  if t.get('redelegated_trust_id') == trust_id:
201  # recursive call to make sure all notifications are sent
202  try:
203  self.delete_trust(t['id'])
204  except exception.TrustNotFound: # nosec
205  # if trust was deleted by concurrent process
206  # consistency must not suffer
207  pass
208 
209  # end recursion
210  self.driver.delete_trust(trust_id)
211 
212  notifications.Audit.deleted(self._TRUST, trust_id, initiator)
keystone.trust.core.Manager._validate_redelegation
def _validate_redelegation(redelegated_trust, trust)
Definition: core.py:60
keystone.exception.NotFound
Definition: exception.py:395
keystone.trust.core.Manager.delete_trust
def delete_trust(self, trust_id, initiator=None)
Definition: core.py:188
keystone.trust.core.Manager.create_trust
def create_trust(self, trust_id, trust, roles, redelegated_trust=None, initiator=None)
Definition: core.py:134
keystone.trust.core.Manager
Definition: core.py:29
keystone.exception.ValidationError
Definition: exception.py:98
keystone.trust.core.Manager.__init__
def __init__(self)
Definition: core.py:42
keystone.trust.core.Manager.get_trust_pedigree
def get_trust_pedigree(self, trust_id)
Definition: core.py:107
keystone.trust.core.Manager._on_user_delete
def _on_user_delete(self, service, resource_type, operation, payload)
Definition: core.py:49
keystone.exception.TrustNotFound
Definition: exception.py:481
keystone.exception.Forbidden
Definition: exception.py:352
keystone.conf
Definition: __init__.py:1
keystone.i18n._
_
Definition: i18n.py:29
keystone.common
Definition: __init__.py:1
keystone.i18n
Definition: i18n.py:1
keystone.trust.core.Manager.get_trust
def get_trust(self, trust_id, deleted=False)
Definition: core.py:116
keystone.trust.core.Manager._TRUST
string _TRUST
Definition: core.py:40