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)  

domains.py
Go to the documentation of this file.
1 # Licensed under the Apache License, Version 2.0 (the "License"); you may
2 # not use this file except in compliance with the License. You may obtain
3 # a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 # License for the specific language governing permissions and limitations
11 # under the License.
12 
13 # This file handles all flask-restful resources for /v3/domains
14 
15 import flask
16 import flask_restful
17 import functools
18 import http.client
19 
20 from keystone.common import json_home
21 from keystone.common import provider_api
22 from keystone.common import rbac_enforcer
23 from keystone.common import validation
24 import keystone.conf
25 from keystone import exception
26 from keystone.resource import schema
27 from keystone.server import flask as ks_flask
28 
29 CONF = keystone.conf.CONF
30 ENFORCER = rbac_enforcer.RBACEnforcer
31 PROVIDERS = provider_api.ProviderAPIs
32 
33 
35  target = {}
36  try:
37  target['domain'] = PROVIDERS.resource_api.get_domain(
38  flask.request.view_args.get('domain_id')
39  )
40  except exception.NotFound: # nosec
41  # Defer existence in the event the domain doesn't exist, we'll
42  # check this later anyway.
43  pass
44 
45  return target
46 
47 
48 def _build_enforcement_target(allow_non_existing=False):
49  target = {}
50  if flask.request.view_args:
51  domain_id = flask.request.view_args.get('domain_id', None)
52  if domain_id:
53  target['domain'] = PROVIDERS.resource_api.get_domain(domain_id)
54 
55  role_id = flask.request.view_args.get('role_id', None)
56  if role_id:
57  target['role'] = PROVIDERS.role_api.get_role(role_id)
58 
59  if flask.request.view_args.get('user_id'):
60  try:
61  target['user'] = PROVIDERS.identity_api.get_user(
62  flask.request.view_args['user_id'])
64  if not allow_non_existing:
65  raise
66  else:
67  try:
68  target['group'] = PROVIDERS.identity_api.get_group(
69  flask.request.view_args.get('group_id'))
71  if not allow_non_existing:
72  raise
73  return target
74 
75 
76 class DomainResource(ks_flask.ResourceBase):
77  collection_key = 'domains'
78  member_key = 'domain'
79  get_member_from_driver = PROVIDERS.deferred_provider_lookup(
80  api='resource_api', method='get_domain')
81 
82  def get(self, domain_id=None):
83  """Get domain or list domains.
84 
85  GET/HEAD /v3/domains
86  GET/HEAD /v3/domains/{domain_id}
87  """
88  if domain_id is not None:
89  return self._get_domain(domain_id)
90  return self._list_domains()
91 
92  def _get_domain(self, domain_id):
93  ENFORCER.enforce_call(
94  action='identity:get_domain',
95  build_target=_build_domain_enforcement_target
96  )
97  domain = PROVIDERS.resource_api.get_domain(domain_id)
98  return self.wrap_member(domain)
99 
100  def _list_domains(self):
101  filters = ['name', 'enabled']
102  ENFORCER.enforce_call(action='identity:list_domains',
103  filters=filters)
104  hints = self.build_driver_hints(filters)
105  refs = PROVIDERS.resource_api.list_domains(hints=hints)
106  return self.wrap_collection(refs, hints=hints)
107 
108  def post(self):
109  """Create domain.
110 
111  POST /v3/domains
112  """
113  ENFORCER.enforce_call(action='identity:create_domain')
114  domain = self.request_body_json.get('domain', {})
115  validation.lazy_validate(schema.domain_create, domain)
116 
117  domain_id = domain.get('explicit_domain_id')
118  if domain_id is None:
119  domain = self._assign_unique_id(domain)
120  else:
121  # Domain ID validation provided by PyCADF
122  try:
123  self._validate_id_format(domain_id)
124  except ValueError:
126  domain['id'] = domain_id
127  domain = self._normalize_dict(domain)
128  ref = PROVIDERS.resource_api.create_domain(
129  domain['id'], domain, initiator=self.audit_initiator)
130  return self.wrap_member(ref), http.client.CREATED
131 
132  def patch(self, domain_id):
133  """Update domain.
134 
135  PATCH /v3/domains/{domain_id}
136  """
137  ENFORCER.enforce_call(action='identity:update_domain')
138  domain = self.request_body_json.get('domain', {})
139  validation.lazy_validate(schema.domain_update, domain)
140  PROVIDERS.resource_api.get_domain(domain_id)
141  ref = PROVIDERS.resource_api.update_domain(
142  domain_id, domain, initiator=self.audit_initiator)
143  return self.wrap_member(ref)
144 
145  def delete(self, domain_id):
146  """Delete domain.
147 
148  DELETE /v3/domains/{domain_id}
149  """
150  ENFORCER.enforce_call(action='identity:delete_domain')
151  PROVIDERS.resource_api.delete_domain(
152  domain_id, initiator=self.audit_initiator)
153  return None, http.client.NO_CONTENT
154 
155 
156 class DomainConfigBase(ks_flask.ResourceBase):
157  member_key = 'config'
158 
159  def get(self, domain_id=None, group=None, option=None):
160  """Check if config option exists.
161 
162  GET/HEAD /v3/domains/{domain_id}/config
163  GET/HEAD /v3/domains/{domain_id}/config/{group}
164  GET/HEAD /v3/domains/{domain_id}/config/{group}/{option}
165  """
166  err = None
167  config = {}
168  try:
169  PROVIDERS.resource_api.get_domain(domain_id)
170  except Exception as e: # nosec
171  # We don't raise out here, we raise out after enforcement, this
172  # ensures we do not leak domain existance.
173  err = e
174  finally:
175  if group and group == 'security_compliance':
176  config = self._get_security_compliance_config(
177  domain_id, group, option)
178  else:
179  config = self._get_config(domain_id, group, option)
180  if err is not None:
181  raise err
182  return {self.member_key: config}
183 
184  def _get_config(self, domain_id, group, option):
185  ENFORCER.enforce_call(action='identity:get_domain_config')
186  return PROVIDERS.domain_config_api.get_config(
187  domain_id, group=group, option=option)
188 
189  def _get_security_compliance_config(self, domain_id, group, option):
190  ENFORCER.enforce_call(
191  action='identity:get_security_compliance_domain_config')
192  return PROVIDERS.domain_config_api.get_security_compliance_config(
193  domain_id, group, option=option)
194 
195  def patch(self, domain_id=None, group=None, option=None):
196  """Update domain config option.
197 
198  PATCH /v3/domains/{domain_id}/config
199  PATCH /v3/domains/{domain_id}/config/{group}
200  PATCH /v3/domains/{domain_id}/config/{group}/{option}
201  """
202  ENFORCER.enforce_call(action='identity:update_domain_config')
203  PROVIDERS.resource_api.get_domain(domain_id)
204  config = self.request_body_json.get('config', {})
205  ref = PROVIDERS.domain_config_api.update_config(
206  domain_id, config, group, option=option)
207  return {self.member_key: ref}
208 
209  def delete(self, domain_id=None, group=None, option=None):
210  """Delete domain config.
211 
212  DELETE /v3/domains/{domain_id}/config
213  DELETE /v3/domains/{domain_id}/config/{group}
214  DELETE /v3/domains/{domain_id}/config/{group}/{option}
215  """
216  ENFORCER.enforce_call(action='identity:delete_domain_config')
217  PROVIDERS.resource_api.get_domain(domain_id)
218  PROVIDERS.domain_config_api.delete_config(
219  domain_id, group, option=option)
220  return None, http.client.NO_CONTENT
221 
222 
224  """Provides config routing functionality.
225 
226  This class leans on DomainConfigBase to provide the following APIs:
227 
228  GET/HEAD /v3/domains/{domain_id}/config
229  PATCH /v3/domains/{domain_id}/config
230  DELETE /v3/domains/{domain_id}/config
231  """
232 
233  def put(self, domain_id):
234  """Create domain config.
235 
236  PUT /v3/domains/{domain_id}/config
237  """
238  ENFORCER.enforce_call(action='identity:create_domain_config')
239  PROVIDERS.resource_api.get_domain(domain_id)
240  config = self.request_body_json.get('config', {})
241  original_config = (
242  PROVIDERS.domain_config_api.get_config_with_sensitive_info(
243  domain_id
244  )
245  )
246  ref = PROVIDERS.domain_config_api.create_config(domain_id, config)
247  if original_config:
248  return {self.member_key: ref}
249  else:
250  return {self.member_key: ref}, http.client.CREATED
251 
252 
254  """Provides config group routing functionality.
255 
256  This class leans on DomainConfigBase to provide the following APIs:
257 
258  GET/HEAD /v3/domains/{domain_id}/config/{group}
259  PATCH /v3/domains/{domain_id}/config/{group}
260  DELETE /v3/domains/{domain_id}/config/{group}
261  """
262 
263 
264 class DomainConfigOptionResource(DomainConfigBase):
265  """Provides config option routing functionality.
266 
267  This class leans on DomainConfigBase to provide the following APIs:
268 
269  GET/HEAD /v3/domains/{domain_id}/config/{group}/{option}
270  PATCH /v3/domains/{domain_id}/config/{group}/{option}
271  DELETE /v3/domains/{domain_id}/config/{group}/{option}
272  """
273 
274 
275 class DefaultConfigResource(flask_restful.Resource):
276  def get(self):
277  """Get default domain config.
278 
279  GET/HEAD /v3/domains/config/default
280  """
281  ENFORCER.enforce_call(action='identity:get_domain_config_default')
282  ref = PROVIDERS.domain_config_api.get_config_default()
283  return {'config': ref}
284 
285 
286 class DefaultConfigGroupResource(flask_restful.Resource):
287  def get(self, group=None):
288  """Get default domain group config.
289 
290  GET/HEAD /v3/domains/config/{group}/default
291  """
292  ENFORCER.enforce_call(action='identity:get_domain_config_default')
293  ref = PROVIDERS.domain_config_api.get_config_default(group=group)
294  return {'config': ref}
295 
296 
297 class DefaultConfigOptionResource(flask_restful.Resource):
298  def get(self, group=None, option=None):
299  """Get default domain group option config.
300 
301  GET/HEAD /v3/domains/config/{group}/{option}/default
302  """
303  ENFORCER.enforce_call(action='identity:get_domain_config_default')
304  ref = PROVIDERS.domain_config_api.get_config_default(
305  group=group, option=option)
306  return {'config': ref}
307 
308 
309 class DomainUserListResource(flask_restful.Resource):
310  def get(self, domain_id=None, user_id=None):
311  """Get user grant.
312 
313  GET/HEAD /v3/domains/{domain_id}/users/{user_id}/roles
314  """
315  ENFORCER.enforce_call(
316  action='identity:list_grants',
317  build_target=_build_enforcement_target)
318  refs = PROVIDERS.assignment_api.list_grants(
319  domain_id=domain_id, user_id=user_id,
320  inherited_to_projects=False)
321  return ks_flask.ResourceBase.wrap_collection(
322  refs, collection_name='roles')
323 
324 
325 class DomainUserResource(ks_flask.ResourceBase):
326  member_key = 'grant'
327  collection_key = 'grants'
328 
329  def get(self, domain_id=None, user_id=None, role_id=None):
330  """Check if a user has a specific role on the domain.
331 
332  GET/HEAD /v3/domains/{domain_id}/users/{user_id}/roles/{role_id}
333  """
334  ENFORCER.enforce_call(
335  action='identity:check_grant',
336  build_target=_build_enforcement_target)
337  PROVIDERS.assignment_api.get_grant(
338  role_id, domain_id=domain_id, user_id=user_id,
339  inherited_to_projects=False)
340  return None, http.client.NO_CONTENT
341 
342  def put(self, domain_id=None, user_id=None, role_id=None):
343  """Create a role to a user on a domain.
344 
345  PUT /v3/domains/{domain_id}/users/{user_id}/roles/{role_id}
346  """
347  ENFORCER.enforce_call(
348  action='identity:create_grant',
349  build_target=_build_enforcement_target)
350  PROVIDERS.assignment_api.create_grant(
351  role_id, domain_id=domain_id, user_id=user_id,
352  inherited_to_projects=False, initiator=self.audit_initiator)
353  return None, http.client.NO_CONTENT
354 
355  def delete(self, domain_id=None, user_id=None, role_id=None):
356  """Revoke a role from user on a domain.
357 
358  DELETE /v3/domains/{domain_id}/users/{user_id}/roles/{role_id}
359  """
360  ENFORCER.enforce_call(
361  action='identity:revoke_grant',
362  build_target=functools.partial(_build_enforcement_target,
363  allow_non_existing=True))
364  PROVIDERS.assignment_api.delete_grant(
365  role_id, domain_id=domain_id, user_id=user_id,
366  inherited_to_projects=False, initiator=self.audit_initiator)
367  return None, http.client.NO_CONTENT
368 
369 
370 class DomainGroupListResource(flask_restful.Resource):
371  def get(self, domain_id=None, group_id=None):
372  """List all domain grats for a specific group.
373 
374  GET/HEAD /v3/domains/{domain_id}/groups/{group_id}/roles
375  """
376  ENFORCER.enforce_call(
377  action='identity:list_grants',
378  build_target=_build_enforcement_target)
379  refs = PROVIDERS.assignment_api.list_grants(
380  domain_id=domain_id, group_id=group_id,
381  inherited_to_projects=False)
382  return ks_flask.ResourceBase.wrap_collection(
383  refs, collection_name='roles')
384 
385 
386 class DomainGroupResource(ks_flask.ResourceBase):
387  member_key = 'grant'
388  collection_key = 'grants'
389 
390  def get(self, domain_id=None, group_id=None, role_id=None):
391  """Check if a group has a specific role on a domain.
392 
393  GET/HEAD /v3/domains/{domain_id}/groups/{group_id}/roles/{role_id}
394  """
395  ENFORCER.enforce_call(
396  action='identity:check_grant',
397  build_target=_build_enforcement_target)
398  PROVIDERS.assignment_api.get_grant(
399  role_id, domain_id=domain_id, group_id=group_id,
400  inherited_to_projects=False)
401  return None, http.client.NO_CONTENT
402 
403  def put(self, domain_id=None, group_id=None, role_id=None):
404  """Grant a role to a group on a domain.
405 
406  PUT /v3/domains/{domain_id}/groups/{group_id}/roles/{role_id}
407  """
408  ENFORCER.enforce_call(
409  action='identity:create_grant',
410  build_target=_build_enforcement_target)
411  PROVIDERS.assignment_api.create_grant(
412  role_id, domain_id=domain_id, group_id=group_id,
413  inherited_to_projects=False, initiator=self.audit_initiator)
414  return None, http.client.NO_CONTENT
415 
416  def delete(self, domain_id=None, group_id=None, role_id=None):
417  """Revoke a role from a group on a domain.
418 
419  DELETE /v3/domains/{domain_id}/groups/{group_id}/roles/{role_id}
420  """
421  ENFORCER.enforce_call(
422  action='identity:revoke_grant',
423  build_target=functools.partial(_build_enforcement_target,
424  allow_non_existing=True))
425  PROVIDERS.assignment_api.delete_grant(
426  role_id, domain_id=domain_id, group_id=group_id,
427  inherited_to_projects=False, initiator=self.audit_initiator)
428  return None, http.client.NO_CONTENT
429 
430 
431 class DomainAPI(ks_flask.APIBase):
432  CONFIG_GROUP = json_home.build_v3_parameter_relation('config_group')
433  CONFIG_OPTION = json_home.build_v3_parameter_relation('config_option')
434  _name = 'domains'
435  _import_name = __name__
436  resources = [DomainResource]
437  resource_mapping = [
438  ks_flask.construct_resource_map(
439  resource=DomainConfigResource,
440  url=('/domains/<string:domain_id>/config'),
441  resource_kwargs={},
442  rel='domain_config',
443  path_vars={
444  'domain_id': json_home.Parameters.DOMAIN_ID}),
445  ks_flask.construct_resource_map(
446  resource=DomainConfigGroupResource,
447  url='/domains/<string:domain_id>/config/<string:group>',
448  resource_kwargs={},
449  rel='domain_config_group',
450  path_vars={
451  'domain_id': json_home.Parameters.DOMAIN_ID,
452  'group': CONFIG_GROUP}),
453  ks_flask.construct_resource_map(
454  resource=DomainConfigOptionResource,
455  url=('/domains/<string:domain_id>/config/<string:group>'
456  '/<string:option>'),
457  resource_kwargs={},
458  rel='domain_config_option',
459  path_vars={
460  'domain_id': json_home.Parameters.DOMAIN_ID,
461  'group': CONFIG_GROUP,
462  'option': CONFIG_OPTION}),
463  ks_flask.construct_resource_map(
464  resource=DefaultConfigResource,
465  url=('/domains/config/default'),
466  resource_kwargs={},
467  rel='domain_config_default',
468  path_vars={}),
469  ks_flask.construct_resource_map(
470  resource=DefaultConfigGroupResource,
471  url='/domains/config/<string:group>/default',
472  resource_kwargs={},
473  rel='domain_config_default_group',
474  path_vars={
475  'group': CONFIG_GROUP}),
476  ks_flask.construct_resource_map(
477  resource=DefaultConfigOptionResource,
478  url=('/domains/config/<string:group>'
479  '/<string:option>/default'),
480  resource_kwargs={},
481  rel='domain_config_default_option',
482  path_vars={
483  'group': CONFIG_GROUP,
484  'option': CONFIG_OPTION}),
485  ks_flask.construct_resource_map(
486  resource=DomainUserListResource,
487  url=('/domains/<string:domain_id>/users'
488  '/<string:user_id>/roles'),
489  resource_kwargs={},
490  rel='domain_user_roles',
491  path_vars={
492  'domain_id': json_home.Parameters.DOMAIN_ID,
493  'user_id': json_home.Parameters.USER_ID,
494  }),
495  ks_flask.construct_resource_map(
496  resource=DomainUserResource,
497  url=('/domains/<string:domain_id>/users'
498  '/<string:user_id>/roles/<string:role_id>'),
499  resource_kwargs={},
500  rel='domain_user_role',
501  path_vars={
502  'domain_id': json_home.Parameters.DOMAIN_ID,
503  'user_id': json_home.Parameters.USER_ID,
504  'role_id': json_home.Parameters.ROLE_ID
505  }),
506  ks_flask.construct_resource_map(
507  resource=DomainGroupListResource,
508  url=('/domains/<string:domain_id>/groups'
509  '/<string:group_id>/roles'),
510  resource_kwargs={},
511  rel='domain_group_roles',
512  path_vars={
513  'domain_id': json_home.Parameters.DOMAIN_ID,
514  'group_id': json_home.Parameters.GROUP_ID,
515  }),
516  ks_flask.construct_resource_map(
517  resource=DomainGroupResource,
518  url=('/domains/<string:domain_id>/groups'
519  '/<string:group_id>/roles/<string:role_id>'),
520  resource_kwargs={},
521  rel='domain_group_role',
522  path_vars={
523  'domain_id': json_home.Parameters.DOMAIN_ID,
524  'group_id': json_home.Parameters.GROUP_ID,
525  'role_id': json_home.Parameters.ROLE_ID
526  })
527  ]
528 
529 
530 APIs = (DomainAPI,)
keystone.api.domains.DomainResource._get_domain
def _get_domain(self, domain_id)
Definition: domains.py:92
keystone.api.domains.DomainUserResource.get
def get(self, domain_id=None, user_id=None, role_id=None)
Definition: domains.py:329
keystone.exception.UserNotFound
Definition: exception.py:469
keystone.api.domains.DomainResource._list_domains
def _list_domains(self)
Definition: domains.py:100
keystone.api.domains.DomainResource.patch
def patch(self, domain_id)
Definition: domains.py:132
keystone.api.domains.DomainConfigResource.put
def put(self, domain_id)
Definition: domains.py:233
keystone.api.domains.DefaultConfigGroupResource
Definition: domains.py:286
keystone.api.domains.DomainGroupListResource
Definition: domains.py:370
keystone.api.domains.DefaultConfigGroupResource.get
def get(self, group=None)
Definition: domains.py:287
keystone.exception.NotFound
Definition: exception.py:395
keystone.api.domains.DomainUserResource.put
def put(self, domain_id=None, user_id=None, role_id=None)
Definition: domains.py:342
keystone.api.domains.DomainConfigBase.patch
def patch(self, domain_id=None, group=None, option=None)
Definition: domains.py:195
keystone.api.domains.DomainConfigBase.delete
def delete(self, domain_id=None, group=None, option=None)
Definition: domains.py:209
keystone.api.domains.DomainUserResource.delete
def delete(self, domain_id=None, user_id=None, role_id=None)
Definition: domains.py:355
keystone.api.domains.DefaultConfigOptionResource.get
def get(self, group=None, option=None)
Definition: domains.py:298
keystone.api.domains.DefaultConfigResource
Definition: domains.py:275
keystone.api.domains._build_enforcement_target
def _build_enforcement_target(allow_non_existing=False)
Definition: domains.py:48
keystone.api.domains.DomainConfigBase.member_key
string member_key
Definition: domains.py:157
keystone.api.domains.DomainConfigBase._get_security_compliance_config
def _get_security_compliance_config(self, domain_id, group, option)
Definition: domains.py:189
keystone.api.domains.DomainConfigResource
Definition: domains.py:223
keystone.api.domains.DomainResource
Definition: domains.py:76
keystone.api.domains.DomainUserResource
Definition: domains.py:325
keystone.api.domains.DomainResource.post
def post(self)
Definition: domains.py:108
keystone.api.domains.DomainUserListResource
Definition: domains.py:309
keystone.api.domains._build_domain_enforcement_target
def _build_domain_enforcement_target()
Definition: domains.py:34
keystone.api.domains.DomainResource.delete
def delete(self, domain_id)
Definition: domains.py:145
keystone.api.domains.DomainConfigBase
Definition: domains.py:156
keystone.api.domains.DomainGroupResource
Definition: domains.py:386
keystone.api.domains.DomainGroupResource.get
def get(self, domain_id=None, group_id=None, role_id=None)
Definition: domains.py:390
keystone.api.domains.DomainAPI
Definition: domains.py:431
keystone.exception.DomainIdInvalid
Definition: exception.py:435
keystone.exception.GroupNotFound
Definition: exception.py:473
keystone.api.domains.DomainGroupResource.put
def put(self, domain_id=None, group_id=None, role_id=None)
Definition: domains.py:403
keystone.api.domains.DomainConfigGroupResource
Definition: domains.py:253
keystone.api.domains.DomainGroupResource.delete
def delete(self, domain_id=None, group_id=None, role_id=None)
Definition: domains.py:416
keystone.api.domains.DomainGroupListResource.get
def get(self, domain_id=None, group_id=None)
Definition: domains.py:371
keystone.server
Definition: __init__.py:1
keystone.api.domains.DomainConfigBase._get_config
def _get_config(self, domain_id, group, option)
Definition: domains.py:184
keystone.conf
Definition: __init__.py:1
keystone.api.domains.DefaultConfigResource.get
def get(self)
Definition: domains.py:276
keystone.common
Definition: __init__.py:1
keystone.api.domains.DomainConfigBase.get
def get(self, domain_id=None, group=None, option=None)
Definition: domains.py:159
keystone.api.domains.DomainUserListResource.get
def get(self, domain_id=None, user_id=None)
Definition: domains.py:310
keystone.api.domains.DomainResource.get
def get(self, domain_id=None)
Definition: domains.py:82
keystone.api.domains.DefaultConfigOptionResource
Definition: domains.py:297
keystone.resource
Definition: __init__.py:1