From 2e7b4f2027a1147ca28301e4f88adf8274b39a1f Mon Sep 17 00:00:00 2001 From: DUVAL Thomas Date: Thu, 9 Jun 2016 09:11:50 +0200 Subject: Update Keystone core to Mitaka. Change-Id: Ia10d6add16f4a9d25d1f42d420661c46332e69db --- keystone-moon/keystone/v2_crud/__init__.py | 0 keystone-moon/keystone/v2_crud/admin_crud.py | 240 +++++++++++++++++++++++++++ keystone-moon/keystone/v2_crud/user_crud.py | 134 +++++++++++++++ 3 files changed, 374 insertions(+) create mode 100644 keystone-moon/keystone/v2_crud/__init__.py create mode 100644 keystone-moon/keystone/v2_crud/admin_crud.py create mode 100644 keystone-moon/keystone/v2_crud/user_crud.py (limited to 'keystone-moon/keystone/v2_crud') diff --git a/keystone-moon/keystone/v2_crud/__init__.py b/keystone-moon/keystone/v2_crud/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/keystone-moon/keystone/v2_crud/admin_crud.py b/keystone-moon/keystone/v2_crud/admin_crud.py new file mode 100644 index 00000000..86ccfcd8 --- /dev/null +++ b/keystone-moon/keystone/v2_crud/admin_crud.py @@ -0,0 +1,240 @@ +# Copyright 2012 OpenStack Foundation +# +# 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 keystone import assignment +from keystone import catalog +from keystone.common import extension +from keystone.common import wsgi +from keystone import identity +from keystone import resource + + +extension.register_admin_extension( + 'OS-KSADM', { + 'name': 'OpenStack Keystone Admin', + 'namespace': 'http://docs.openstack.org/identity/api/ext/' + 'OS-KSADM/v1.0', + 'alias': 'OS-KSADM', + 'updated': '2013-07-11T17:14:00-00:00', + 'description': 'OpenStack extensions to Keystone v2.0 API ' + 'enabling Administrative Operations.', + 'links': [ + { + 'rel': 'describedby', + 'type': 'text/html', + 'href': 'http://developer.openstack.org/' + 'api-ref-identity-v2-ext.html', + } + ]}) + + +class Router(wsgi.ComposableRouter): + """Previously known as the OS-KSADM extension. + + Provides a bunch of CRUD operations for internal data types. + + """ + + def add_routes(self, mapper): + tenant_controller = resource.controllers.Tenant() + assignment_tenant_controller = ( + assignment.controllers.TenantAssignment()) + user_controller = identity.controllers.User() + role_controller = assignment.controllers.Role() + assignment_role_controller = assignment.controllers.RoleAssignmentV2() + service_controller = catalog.controllers.Service() + endpoint_controller = catalog.controllers.Endpoint() + + # Tenant Operations + mapper.connect( + '/tenants', + controller=tenant_controller, + action='create_project', + conditions=dict(method=['POST'])) + mapper.connect( + '/tenants/{tenant_id}', + controller=tenant_controller, + action='update_project', + conditions=dict(method=['PUT', 'POST'])) + mapper.connect( + '/tenants/{tenant_id}', + controller=tenant_controller, + action='delete_project', + conditions=dict(method=['DELETE'])) + mapper.connect( + '/tenants/{tenant_id}/users', + controller=assignment_tenant_controller, + action='get_project_users', + conditions=dict(method=['GET'])) + + # User Operations + mapper.connect( + '/users', + controller=user_controller, + action='get_users', + conditions=dict(method=['GET'])) + mapper.connect( + '/users', + controller=user_controller, + action='create_user', + conditions=dict(method=['POST'])) + # NOTE(termie): not in diablo + mapper.connect( + '/users/{user_id}', + controller=user_controller, + action='update_user', + conditions=dict(method=['PUT'])) + mapper.connect( + '/users/{user_id}', + controller=user_controller, + action='delete_user', + conditions=dict(method=['DELETE'])) + + # COMPAT(diablo): the copy with no OS-KSADM is from diablo + mapper.connect( + '/users/{user_id}/password', + controller=user_controller, + action='set_user_password', + conditions=dict(method=['PUT'])) + mapper.connect( + '/users/{user_id}/OS-KSADM/password', + controller=user_controller, + action='set_user_password', + conditions=dict(method=['PUT'])) + + # COMPAT(diablo): the copy with no OS-KSADM is from diablo + mapper.connect( + '/users/{user_id}/tenant', + controller=user_controller, + action='update_user', + conditions=dict(method=['PUT'])) + mapper.connect( + '/users/{user_id}/OS-KSADM/tenant', + controller=user_controller, + action='update_user', + conditions=dict(method=['PUT'])) + + # COMPAT(diablo): the copy with no OS-KSADM is from diablo + mapper.connect( + '/users/{user_id}/enabled', + controller=user_controller, + action='set_user_enabled', + conditions=dict(method=['PUT'])) + mapper.connect( + '/users/{user_id}/OS-KSADM/enabled', + controller=user_controller, + action='set_user_enabled', + conditions=dict(method=['PUT'])) + + # User Roles + mapper.connect( + '/users/{user_id}/roles/OS-KSADM/{role_id}', + controller=assignment_role_controller, + action='add_role_to_user', + conditions=dict(method=['PUT'])) + mapper.connect( + '/users/{user_id}/roles/OS-KSADM/{role_id}', + controller=assignment_role_controller, + action='remove_role_from_user', + conditions=dict(method=['DELETE'])) + + # COMPAT(diablo): User Roles + mapper.connect( + '/users/{user_id}/roleRefs', + controller=assignment_role_controller, + action='get_role_refs', + conditions=dict(method=['GET'])) + mapper.connect( + '/users/{user_id}/roleRefs', + controller=assignment_role_controller, + action='create_role_ref', + conditions=dict(method=['POST'])) + mapper.connect( + '/users/{user_id}/roleRefs/{role_ref_id}', + controller=assignment_role_controller, + action='delete_role_ref', + conditions=dict(method=['DELETE'])) + + # User-Tenant Roles + mapper.connect( + '/tenants/{tenant_id}/users/{user_id}/roles/OS-KSADM/{role_id}', + controller=assignment_role_controller, + action='add_role_to_user', + conditions=dict(method=['PUT'])) + mapper.connect( + '/tenants/{tenant_id}/users/{user_id}/roles/OS-KSADM/{role_id}', + controller=assignment_role_controller, + action='remove_role_from_user', + conditions=dict(method=['DELETE'])) + + # Service Operations + mapper.connect( + '/OS-KSADM/services', + controller=service_controller, + action='get_services', + conditions=dict(method=['GET'])) + mapper.connect( + '/OS-KSADM/services', + controller=service_controller, + action='create_service', + conditions=dict(method=['POST'])) + mapper.connect( + '/OS-KSADM/services/{service_id}', + controller=service_controller, + action='delete_service', + conditions=dict(method=['DELETE'])) + mapper.connect( + '/OS-KSADM/services/{service_id}', + controller=service_controller, + action='get_service', + conditions=dict(method=['GET'])) + + # Endpoint Templates + mapper.connect( + '/endpoints', + controller=endpoint_controller, + action='get_endpoints', + conditions=dict(method=['GET'])) + mapper.connect( + '/endpoints', + controller=endpoint_controller, + action='create_endpoint', + conditions=dict(method=['POST'])) + mapper.connect( + '/endpoints/{endpoint_id}', + controller=endpoint_controller, + action='delete_endpoint', + conditions=dict(method=['DELETE'])) + + # Role Operations + mapper.connect( + '/OS-KSADM/roles', + controller=role_controller, + action='create_role', + conditions=dict(method=['POST'])) + mapper.connect( + '/OS-KSADM/roles', + controller=role_controller, + action='get_roles', + conditions=dict(method=['GET'])) + mapper.connect( + '/OS-KSADM/roles/{role_id}', + controller=role_controller, + action='get_role', + conditions=dict(method=['GET'])) + mapper.connect( + '/OS-KSADM/roles/{role_id}', + controller=role_controller, + action='delete_role', + conditions=dict(method=['DELETE'])) diff --git a/keystone-moon/keystone/v2_crud/user_crud.py b/keystone-moon/keystone/v2_crud/user_crud.py new file mode 100644 index 00000000..9da7f31f --- /dev/null +++ b/keystone-moon/keystone/v2_crud/user_crud.py @@ -0,0 +1,134 @@ +# Copyright 2012 Red Hat, Inc +# +# 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. + +import copy +import uuid + +from oslo_log import log + +from keystone.common import dependency +from keystone.common import extension +from keystone.common import wsgi +from keystone import exception +from keystone import identity +from keystone.models import token_model + + +LOG = log.getLogger(__name__) + + +extension.register_public_extension( + 'OS-KSCRUD', { + 'name': 'OpenStack Keystone User CRUD', + 'namespace': 'http://docs.openstack.org/identity/api/ext/' + 'OS-KSCRUD/v1.0', + 'alias': 'OS-KSCRUD', + 'updated': '2013-07-07T12:00:0-00:00', + 'description': 'OpenStack extensions to Keystone v2.0 API ' + 'enabling User Operations.', + 'links': [ + { + 'rel': 'describedby', + 'type': 'text/html', + 'href': 'http://developer.openstack.org/' + 'api-ref-identity-v2-ext.html', + } + ]}) + + +@dependency.requires('catalog_api', 'identity_api', 'resource_api', + 'token_provider_api') +class UserController(identity.controllers.User): + def set_user_password(self, context, user_id, user): + token_id = context.get('token_id') + original_password = user.get('original_password') + + token_data = self.token_provider_api.validate_token(token_id) + token_ref = token_model.KeystoneToken(token_id=token_id, + token_data=token_data) + + if token_ref.user_id != user_id: + raise exception.Forbidden('Token belongs to another user') + if original_password is None: + raise exception.ValidationError(target='user', + attribute='original password') + + try: + user_ref = self.identity_api.authenticate( + context, + user_id=token_ref.user_id, + password=original_password) + if not user_ref.get('enabled', True): + # NOTE(dolph): why can't you set a disabled user's password? + raise exception.Unauthorized('User is disabled') + except AssertionError: + raise exception.Unauthorized() + + update_dict = {'password': user['password'], 'id': user_id} + + admin_context = copy.copy(context) + admin_context['is_admin'] = True + super(UserController, self).set_user_password(admin_context, + user_id, + update_dict) + + # Issue a new token based upon the original token data. This will + # always be a V2.0 token. + + # TODO(morganfainberg): Add a mechanism to issue a new token directly + # from a token model so that this code can go away. This is likely + # not the norm as most cases do not need to yank apart a token to + # issue a new one. + new_token_ref = {} + metadata_ref = {} + roles_ref = None + + new_token_ref['user'] = user_ref + if token_ref.bind: + new_token_ref['bind'] = token_ref.bind + if token_ref.project_id: + new_token_ref['tenant'] = self.resource_api.get_project( + token_ref.project_id) + if token_ref.role_names: + roles_ref = [dict(name=value) + for value in token_ref.role_names] + if token_ref.role_ids: + metadata_ref['roles'] = token_ref.role_ids + if token_ref.trust_id: + metadata_ref['trust'] = { + 'id': token_ref.trust_id, + 'trustee_user_id': token_ref.trustee_user_id} + new_token_ref['metadata'] = metadata_ref + new_token_ref['id'] = uuid.uuid4().hex + + catalog_ref = self.catalog_api.get_catalog(user_id, + token_ref.project_id) + + new_token_id, new_token_data = self.token_provider_api.issue_v2_token( + token_ref=new_token_ref, roles_ref=roles_ref, + catalog_ref=catalog_ref) + LOG.debug('TOKEN_REF %s', new_token_data) + return new_token_data + + +class Router(wsgi.ComposableRouter): + """Provides a subset of CRUD operations for internal data types.""" + + def add_routes(self, mapper): + user_controller = UserController() + + mapper.connect('/OS-KSCRUD/users/{user_id}', + controller=user_controller, + action='set_user_password', + conditions=dict(method=['PATCH'])) -- cgit 1.2.3-korg