OpenStack Identity (Keystone)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

endpoints.py 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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. # This file handles all flask-restful resources for /v3/services
  13. import flask_restful
  14. import functools
  15. from six.moves import http_client
  16. from keystone.catalog import schema
  17. from keystone.common import json_home
  18. from keystone.common import provider_api
  19. from keystone.common import rbac_enforcer
  20. from keystone.common import utils
  21. from keystone.common import validation
  22. from keystone import exception
  23. from keystone.server import flask as ks_flask
  24. ENFORCER = rbac_enforcer.RBACEnforcer
  25. PROVIDERS = provider_api.ProviderAPIs
  26. # TODO(morgan) move the partial functions to a common place so that they
  27. # can be referenced by multiple APIs, such as endpoints and endpoint_policy.
  28. _build_resource_relation = functools.partial(
  29. json_home.build_v3_extension_resource_relation,
  30. extension_name='OS-ENDPOINT-POLICY', extension_version='1.0')
  31. def _filter_endpoint(ref):
  32. ref.pop('legacy_endpoint_id', None)
  33. ref['region'] = ref['region_id']
  34. return ref
  35. class EndpointResource(ks_flask.ResourceBase):
  36. collection_key = 'endpoints'
  37. member_key = 'endpoint'
  38. def __init__(self):
  39. super(EndpointResource, self).__init__()
  40. self.get_member_from_driver = PROVIDERS.catalog_api.get_endpoint
  41. @staticmethod
  42. def _validate_endpoint_region(endpoint):
  43. """Ensure the region for the endpoint exists.
  44. If 'region_id' is used to specify the region, then we will let the
  45. manager/driver take care of this. If, however, 'region' is used,
  46. then for backward compatibility, we will auto-create the region.
  47. """
  48. if (endpoint.get('region_id') is None and
  49. endpoint.get('region') is not None):
  50. # To maintain backward compatibility with clients that are
  51. # using the v3 API in the same way as they used the v2 API,
  52. # create the endpoint region, if that region does not exist
  53. # in keystone.
  54. endpoint['region_id'] = endpoint.pop('region')
  55. try:
  56. PROVIDERS.catalog_api.get_region(endpoint['region_id'])
  57. except exception.RegionNotFound:
  58. region = dict(id=endpoint['region_id'])
  59. PROVIDERS.catalog_api.create_region(
  60. region, initiator=ks_flask.build_audit_initiator())
  61. return endpoint
  62. def _get_endpoint(self, endpoint_id):
  63. ENFORCER.enforce_call(action='identity:get_endpoint')
  64. return self.wrap_member(_filter_endpoint(
  65. PROVIDERS.catalog_api.get_endpoint(endpoint_id)))
  66. def _list_endpoints(self):
  67. filters = ['interface', 'service_id', 'region_id']
  68. ENFORCER.enforce_call(action='identity:list_endpoints',
  69. filters=filters)
  70. hints = self.build_driver_hints(filters)
  71. refs = PROVIDERS.catalog_api.list_endpoints(hints=hints)
  72. return self.wrap_collection([_filter_endpoint(r) for r in refs],
  73. hints=hints)
  74. def get(self, endpoint_id=None):
  75. if endpoint_id is not None:
  76. return self._get_endpoint(endpoint_id)
  77. return self._list_endpoints()
  78. def post(self):
  79. ENFORCER.enforce_call(action='identity:create_endpoint')
  80. endpoint = self.request_body_json.get('endpoint')
  81. validation.lazy_validate(schema.endpoint_create, endpoint)
  82. utils.check_endpoint_url(endpoint['url'])
  83. endpoint = self._assign_unique_id(self._normalize_dict(endpoint))
  84. endpoint = self._validate_endpoint_region(endpoint)
  85. ref = PROVIDERS.catalog_api.create_endpoint(
  86. endpoint['id'], endpoint, initiator=self.audit_initiator)
  87. return self.wrap_member(_filter_endpoint(ref)), http_client.CREATED
  88. def patch(self, endpoint_id):
  89. ENFORCER.enforce_call(action='identity:update_endpoint')
  90. endpoint = self.request_body_json.get('endpoint')
  91. validation.lazy_validate(schema.endpoint_update, endpoint)
  92. self._require_matching_id(endpoint)
  93. endpoint = self._validate_endpoint_region(endpoint)
  94. ref = PROVIDERS.catalog_api.update_endpoint(
  95. endpoint_id, endpoint, initiator=self.audit_initiator)
  96. return self.wrap_member(_filter_endpoint(ref))
  97. def delete(self, endpoint_id):
  98. ENFORCER.enforce_call(action='identity:delete_endpoint')
  99. PROVIDERS.catalog_api.delete_endpoint(endpoint_id,
  100. initiator=self.audit_initiator)
  101. return None, http_client.NO_CONTENT
  102. class EndpointPolicyEndpointResource(flask_restful.Resource):
  103. def get(self, endpoint_id):
  104. ENFORCER.enforce_call(action='identity:get_policy_for_endpoint')
  105. PROVIDERS.catalog_api.get_endpoint(endpoint_id)
  106. ref = PROVIDERS.endpoint_policy_api.get_policy_for_endpoint(
  107. endpoint_id)
  108. return ks_flask.ResourceBase.wrap_member(
  109. ref, collection_name='endpoints', member_name='policy')
  110. class EndpointAPI(ks_flask.APIBase):
  111. _name = 'endpoints'
  112. _import_name = __name__
  113. resources = [EndpointResource]
  114. resource_mapping = [
  115. ks_flask.construct_resource_map(
  116. resource=EndpointPolicyEndpointResource,
  117. url='/endpoints/<string:endpoint_id>/OS-ENDPOINT-POLICY/policy',
  118. resource_kwargs={},
  119. rel='endpoint_policy',
  120. resource_relation_func=_build_resource_relation,
  121. path_vars={'endpoint_id': json_home.Parameters.ENDPOINT_ID})
  122. ]
  123. APIs = (EndpointAPI,)