diff options
author | Ruan HE <ruan.he@orange.com> | 2016-06-09 08:12:34 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@172.30.200.206> | 2016-06-09 08:12:34 +0000 |
commit | 4bc079a2664f9a407e332291f34d174625a9d5ea (patch) | |
tree | 7481cd5d0a9b3ce37c44c797a1e0d39881221cbe /keystone-moon/keystone/contrib | |
parent | 2f179c5790fbbf6144205d3c6e5089e6eb5f048a (diff) | |
parent | 2e7b4f2027a1147ca28301e4f88adf8274b39a1f (diff) |
Merge "Update Keystone core to Mitaka."
Diffstat (limited to 'keystone-moon/keystone/contrib')
43 files changed, 359 insertions, 2319 deletions
diff --git a/keystone-moon/keystone/contrib/admin_crud/core.py b/keystone-moon/keystone/contrib/admin_crud/core.py index 5d69d249..739cc0ff 100644 --- a/keystone-moon/keystone/contrib/admin_crud/core.py +++ b/keystone-moon/keystone/contrib/admin_crud/core.py @@ -12,230 +12,21 @@ # 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', - # TODO(dolph): link needs to be revised after - # bug 928059 merges - 'type': 'text/html', - 'href': 'https://github.com/openstack/identity-api', - } - ]}) - - -class CrudExtension(wsgi.ExtensionRouter): - """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() +from oslo_log import log +from oslo_log import versionutils - # 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'])) +from keystone.common import wsgi +from keystone.i18n import _ - # 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'])) +LOG = log.getLogger(__name__) - # 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'])) +class CrudExtension(wsgi.Middleware): + def __init__(self, application): + super(CrudExtension, self).__init__(application) + msg = _("Remove admin_crud_extension from the paste pipeline, the " + "admin_crud extension is now always available. Update" + "the [pipeline:admin_api] section in keystone-paste.ini " + "accordingly, as it will be removed in the O release.") + versionutils.report_deprecated_feature(LOG, msg) diff --git a/keystone-moon/keystone/contrib/ec2/controllers.py b/keystone-moon/keystone/contrib/ec2/controllers.py index 78172ec9..c0f6067e 100644 --- a/keystone-moon/keystone/contrib/ec2/controllers.py +++ b/keystone-moon/keystone/contrib/ec2/controllers.py @@ -17,7 +17,7 @@ This service allows the creation of access/secret credentials used for the ec2 interop layer of OpenStack. -A user can create as many access/secret pairs, each of which map to a +A user can create as many access/secret pairs, each of which is mapped to a specific project. This is required because OpenStack supports a user belonging to multiple projects, whereas the signatures created on ec2-style requests don't allow specification of which project the user wishes to act @@ -47,6 +47,8 @@ from keystone.common import wsgi from keystone import exception from keystone.i18n import _ +CRED_TYPE_EC2 = 'ec2' + @dependency.requires('assignment_api', 'catalog_api', 'credential_api', 'identity_api', 'resource_api', 'role_api', @@ -75,13 +77,14 @@ class Ec2ControllerCommon(object): signature): return True raise exception.Unauthorized( - message='Invalid EC2 signature.') + message=_('Invalid EC2 signature.')) else: raise exception.Unauthorized( - message='EC2 signature not supplied.') + message=_('EC2 signature not supplied.')) # Raise the exception when credentials.get('signature') is None else: - raise exception.Unauthorized(message='EC2 signature not supplied.') + raise exception.Unauthorized( + message=_('EC2 signature not supplied.')) @abc.abstractmethod def authenticate(self, context, credentials=None, ec2Credentials=None): @@ -111,7 +114,6 @@ class Ec2ControllerCommon(object): :returns: user_ref, tenant_ref, metadata_ref, roles_ref, catalog_ref """ - # FIXME(ja): validate that a service token was used! # NOTE(termie): backwards compat hack @@ -119,7 +121,8 @@ class Ec2ControllerCommon(object): credentials = ec2credentials if 'access' not in credentials: - raise exception.Unauthorized(message='EC2 signature not supplied.') + raise exception.Unauthorized( + message=_('EC2 signature not supplied.')) creds_ref = self._get_credentials(credentials['access']) self.check_signature(creds_ref, credentials) @@ -152,7 +155,8 @@ class Ec2ControllerCommon(object): roles = metadata_ref.get('roles', []) if not roles: - raise exception.Unauthorized(message='User not valid for tenant.') + raise exception.Unauthorized( + message=_('User not valid for tenant.')) roles_ref = [self.role_api.get_role(role_id) for role_id in roles] catalog_ref = self.catalog_api.get_catalog( @@ -171,7 +175,6 @@ class Ec2ControllerCommon(object): :param tenant_id: id of tenant :returns: credential: dict of ec2 credential """ - self.identity_api.get_user(user_id) self.resource_api.get_project(tenant_id) trust_id = self._get_trust_id_for_request(context) @@ -183,7 +186,7 @@ class Ec2ControllerCommon(object): 'project_id': tenant_id, 'blob': jsonutils.dumps(blob), 'id': credential_id, - 'type': 'ec2'} + 'type': CRED_TYPE_EC2} self.credential_api.create_credential(credential_id, cred_ref) return {'credential': self._convert_v3_to_ec2_credential(cred_ref)} @@ -193,10 +196,9 @@ class Ec2ControllerCommon(object): :param user_id: id of user :returns: credentials: list of ec2 credential dicts """ - self.identity_api.get_user(user_id) credential_refs = self.credential_api.list_credentials_for_user( - user_id) + user_id, type=CRED_TYPE_EC2) return {'credentials': [self._convert_v3_to_ec2_credential(credential) for credential in credential_refs]} @@ -210,7 +212,6 @@ class Ec2ControllerCommon(object): :param credential_id: access key for credentials :returns: credential: dict of ec2 credential """ - self.identity_api.get_user(user_id) return {'credential': self._get_credentials(credential_id)} @@ -223,7 +224,6 @@ class Ec2ControllerCommon(object): :param credential_id: access key for credentials :returns: bool: success """ - self.identity_api.get_user(user_id) self._get_credentials(credential_id) ec2_credential_id = utils.hash_access_key(credential_id) @@ -249,20 +249,22 @@ class Ec2ControllerCommon(object): """Return credentials from an ID. :param credential_id: id of credential - :raises exception.Unauthorized: when credential id is invalid + :raises keystone.exception.Unauthorized: when credential id is invalid + or when the credential type is not ec2 :returns: credential: dict of ec2 credential. """ ec2_credential_id = utils.hash_access_key(credential_id) - creds = self.credential_api.get_credential(ec2_credential_id) - if not creds: - raise exception.Unauthorized(message='EC2 access key not found.') - return self._convert_v3_to_ec2_credential(creds) + cred = self.credential_api.get_credential(ec2_credential_id) + if not cred or cred['type'] != CRED_TYPE_EC2: + raise exception.Unauthorized( + message=_('EC2 access key not found.')) + return self._convert_v3_to_ec2_credential(cred) @dependency.requires('policy_api', 'token_provider_api') class Ec2Controller(Ec2ControllerCommon, controller.V2Controller): - @controller.v2_deprecated + @controller.v2_ec2_deprecated def authenticate(self, context, credentials=None, ec2Credentials=None): (user_ref, tenant_ref, metadata_ref, roles_ref, catalog_ref) = self._authenticate(credentials=credentials, @@ -282,27 +284,27 @@ class Ec2Controller(Ec2ControllerCommon, controller.V2Controller): auth_token_data, roles_ref, catalog_ref) return token_data - @controller.v2_deprecated + @controller.v2_ec2_deprecated def get_credential(self, context, user_id, credential_id): if not self._is_admin(context): self._assert_identity(context, user_id) return super(Ec2Controller, self).get_credential(user_id, credential_id) - @controller.v2_deprecated + @controller.v2_ec2_deprecated def get_credentials(self, context, user_id): if not self._is_admin(context): self._assert_identity(context, user_id) return super(Ec2Controller, self).get_credentials(user_id) - @controller.v2_deprecated + @controller.v2_ec2_deprecated def create_credential(self, context, user_id, tenant_id): if not self._is_admin(context): self._assert_identity(context, user_id) return super(Ec2Controller, self).create_credential(context, user_id, tenant_id) - @controller.v2_deprecated + @controller.v2_ec2_deprecated def delete_credential(self, context, user_id, credential_id): if not self._is_admin(context): self._assert_identity(context, user_id) @@ -315,7 +317,7 @@ class Ec2Controller(Ec2ControllerCommon, controller.V2Controller): :param context: standard context :param user_id: id of user - :raises exception.Forbidden: when token is invalid + :raises keystone.exception.Forbidden: when token is invalid """ token_ref = utils.get_token_ref(context) @@ -343,7 +345,7 @@ class Ec2Controller(Ec2ControllerCommon, controller.V2Controller): :param user_id: expected credential owner :param credential_id: id of credential object - :raises exception.Forbidden: on failure + :raises keystone.exception.Forbidden: on failure """ ec2_credential_id = utils.hash_access_key(credential_id) diff --git a/keystone-moon/keystone/contrib/ec2/core.py b/keystone-moon/keystone/contrib/ec2/core.py index 77857af8..7bba8cab 100644 --- a/keystone-moon/keystone/contrib/ec2/core.py +++ b/keystone-moon/keystone/contrib/ec2/core.py @@ -25,9 +25,9 @@ EXTENSION_DATA = { 'links': [ { 'rel': 'describedby', - # TODO(ayoung): needs a description 'type': 'text/html', - 'href': 'https://github.com/openstack/identity-api', + 'href': 'http://developer.openstack.org/' + 'api-ref-identity-v2-ext.html', } ]} extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) diff --git a/keystone-moon/keystone/contrib/ec2/routers.py b/keystone-moon/keystone/contrib/ec2/routers.py index 7b6bf115..97c68cf7 100644 --- a/keystone-moon/keystone/contrib/ec2/routers.py +++ b/keystone-moon/keystone/contrib/ec2/routers.py @@ -23,10 +23,6 @@ build_resource_relation = functools.partial( json_home.build_v3_extension_resource_relation, extension_name='OS-EC2', extension_version='1.0') -build_parameter_relation = functools.partial( - json_home.build_v3_extension_parameter_relation, extension_name='OS-EC2', - extension_version='1.0') - class Ec2Extension(wsgi.ExtensionRouter): def add_routes(self, mapper): @@ -90,6 +86,6 @@ class Ec2ExtensionV3(wsgi.V3ExtensionRouter): rel=build_resource_relation(resource_name='user_credential'), path_vars={ 'credential_id': - build_parameter_relation(parameter_name='credential_id'), + json_home.build_v3_parameter_relation('credential_id'), 'user_id': json_home.Parameters.USER_ID, }) diff --git a/keystone-moon/keystone/contrib/endpoint_filter/__init__.py b/keystone-moon/keystone/contrib/endpoint_filter/__init__.py index 72508c3e..e69de29b 100644 --- a/keystone-moon/keystone/contrib/endpoint_filter/__init__.py +++ b/keystone-moon/keystone/contrib/endpoint_filter/__init__.py @@ -1,15 +0,0 @@ -# Copyright 2013 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.contrib.endpoint_filter.core import * # noqa diff --git a/keystone-moon/keystone/contrib/endpoint_filter/backends/catalog_sql.py b/keystone-moon/keystone/contrib/endpoint_filter/backends/catalog_sql.py index 22d5796a..ad39d045 100644 --- a/keystone-moon/keystone/contrib/endpoint_filter/backends/catalog_sql.py +++ b/keystone-moon/keystone/contrib/endpoint_filter/backends/catalog_sql.py @@ -17,52 +17,52 @@ from oslo_config import cfg from keystone.catalog.backends import sql from keystone.catalog import core as catalog_core from keystone.common import dependency -from keystone import exception CONF = cfg.CONF -@dependency.requires('endpoint_filter_api') +@dependency.requires('catalog_api') class EndpointFilterCatalog(sql.Catalog): def get_v3_catalog(self, user_id, project_id): substitutions = dict(CONF.items()) - substitutions.update({'tenant_id': project_id, 'user_id': user_id}) + substitutions.update({ + 'tenant_id': project_id, + 'project_id': project_id, + 'user_id': user_id, + }) services = {} - refs = self.endpoint_filter_api.list_endpoints_for_project(project_id) + dict_of_endpoint_refs = (self.catalog_api. + list_endpoints_for_project(project_id)) - if (not refs and + if (not dict_of_endpoint_refs and CONF.endpoint_filter.return_all_endpoints_if_no_filter): return super(EndpointFilterCatalog, self).get_v3_catalog( user_id, project_id) - for entry in refs: - try: - endpoint = self.get_endpoint(entry['endpoint_id']) - if not endpoint['enabled']: - # Skip disabled endpoints. - continue - service_id = endpoint['service_id'] - services.setdefault( - service_id, - self.get_service(service_id)) - service = services[service_id] - del endpoint['service_id'] - del endpoint['enabled'] - del endpoint['legacy_endpoint_id'] - endpoint['url'] = catalog_core.format_url( - endpoint['url'], substitutions) - # populate filtered endpoints - if 'endpoints' in services[service_id]: - service['endpoints'].append(endpoint) - else: - service['endpoints'] = [endpoint] - except exception.EndpointNotFound: - # remove bad reference from association - self.endpoint_filter_api.remove_endpoint_from_project( - entry['endpoint_id'], project_id) + for endpoint_id, endpoint in dict_of_endpoint_refs.items(): + if not endpoint['enabled']: + # Skip disabled endpoints. + continue + service_id = endpoint['service_id'] + services.setdefault( + service_id, + self.get_service(service_id)) + service = services[service_id] + del endpoint['service_id'] + del endpoint['enabled'] + del endpoint['legacy_endpoint_id'] + # Include deprecated region for backwards compatibility + endpoint['region'] = endpoint['region_id'] + endpoint['url'] = catalog_core.format_url( + endpoint['url'], substitutions) + # populate filtered endpoints + if 'endpoints' in services[service_id]: + service['endpoints'].append(endpoint) + else: + service['endpoints'] = [endpoint] # format catalog catalog = [] @@ -70,6 +70,7 @@ class EndpointFilterCatalog(sql.Catalog): formatted_service = {} formatted_service['id'] = service['id'] formatted_service['type'] = service['type'] + formatted_service['name'] = service['name'] formatted_service['endpoints'] = service['endpoints'] catalog.append(formatted_service) diff --git a/keystone-moon/keystone/contrib/endpoint_filter/backends/sql.py b/keystone-moon/keystone/contrib/endpoint_filter/backends/sql.py index cf904268..484934bb 100644 --- a/keystone-moon/keystone/contrib/endpoint_filter/backends/sql.py +++ b/keystone-moon/keystone/contrib/endpoint_filter/backends/sql.py @@ -12,214 +12,19 @@ # License for the specific language governing permissions and limitations # under the License. -from keystone.common import sql -from keystone.contrib import endpoint_filter -from keystone import exception -from keystone.i18n import _ +from oslo_log import versionutils +from keystone.catalog.backends import sql -class ProjectEndpoint(sql.ModelBase, sql.ModelDictMixin): - """project-endpoint relationship table.""" - __tablename__ = 'project_endpoint' - attributes = ['endpoint_id', 'project_id'] - endpoint_id = sql.Column(sql.String(64), - primary_key=True, - nullable=False) - project_id = sql.Column(sql.String(64), - primary_key=True, - nullable=False) +_OLD = 'keystone.contrib.endpoint_filter.backends.sql.EndpointFilter' +_NEW = 'sql' -class EndpointGroup(sql.ModelBase, sql.ModelDictMixin): - """Endpoint Groups table.""" - __tablename__ = 'endpoint_group' - attributes = ['id', 'name', 'description', 'filters'] - mutable_attributes = frozenset(['name', 'description', 'filters']) - id = sql.Column(sql.String(64), primary_key=True) - name = sql.Column(sql.String(255), nullable=False) - description = sql.Column(sql.Text, nullable=True) - filters = sql.Column(sql.JsonBlob(), nullable=False) - - -class ProjectEndpointGroupMembership(sql.ModelBase, sql.ModelDictMixin): - """Project to Endpoint group relationship table.""" - __tablename__ = 'project_endpoint_group' - attributes = ['endpoint_group_id', 'project_id'] - endpoint_group_id = sql.Column(sql.String(64), - sql.ForeignKey('endpoint_group.id'), - nullable=False) - project_id = sql.Column(sql.String(64), nullable=False) - __table_args__ = (sql.PrimaryKeyConstraint('endpoint_group_id', - 'project_id'), {}) - - -class EndpointFilter(endpoint_filter.EndpointFilterDriverV8): - - @sql.handle_conflicts(conflict_type='project_endpoint') - def add_endpoint_to_project(self, endpoint_id, project_id): - session = sql.get_session() - with session.begin(): - endpoint_filter_ref = ProjectEndpoint(endpoint_id=endpoint_id, - project_id=project_id) - session.add(endpoint_filter_ref) - - def _get_project_endpoint_ref(self, session, endpoint_id, project_id): - endpoint_filter_ref = session.query(ProjectEndpoint).get( - (endpoint_id, project_id)) - if endpoint_filter_ref is None: - msg = _('Endpoint %(endpoint_id)s not found in project ' - '%(project_id)s') % {'endpoint_id': endpoint_id, - 'project_id': project_id} - raise exception.NotFound(msg) - return endpoint_filter_ref - - def check_endpoint_in_project(self, endpoint_id, project_id): - session = sql.get_session() - self._get_project_endpoint_ref(session, endpoint_id, project_id) - - def remove_endpoint_from_project(self, endpoint_id, project_id): - session = sql.get_session() - endpoint_filter_ref = self._get_project_endpoint_ref( - session, endpoint_id, project_id) - with session.begin(): - session.delete(endpoint_filter_ref) - - def list_endpoints_for_project(self, project_id): - session = sql.get_session() - query = session.query(ProjectEndpoint) - query = query.filter_by(project_id=project_id) - endpoint_filter_refs = query.all() - return [ref.to_dict() for ref in endpoint_filter_refs] - - def list_projects_for_endpoint(self, endpoint_id): - session = sql.get_session() - query = session.query(ProjectEndpoint) - query = query.filter_by(endpoint_id=endpoint_id) - endpoint_filter_refs = query.all() - return [ref.to_dict() for ref in endpoint_filter_refs] - - def delete_association_by_endpoint(self, endpoint_id): - session = sql.get_session() - with session.begin(): - query = session.query(ProjectEndpoint) - query = query.filter_by(endpoint_id=endpoint_id) - query.delete(synchronize_session=False) - - def delete_association_by_project(self, project_id): - session = sql.get_session() - with session.begin(): - query = session.query(ProjectEndpoint) - query = query.filter_by(project_id=project_id) - query.delete(synchronize_session=False) - - def create_endpoint_group(self, endpoint_group_id, endpoint_group): - session = sql.get_session() - with session.begin(): - endpoint_group_ref = EndpointGroup.from_dict(endpoint_group) - session.add(endpoint_group_ref) - return endpoint_group_ref.to_dict() - - def _get_endpoint_group(self, session, endpoint_group_id): - endpoint_group_ref = session.query(EndpointGroup).get( - endpoint_group_id) - if endpoint_group_ref is None: - raise exception.EndpointGroupNotFound( - endpoint_group_id=endpoint_group_id) - return endpoint_group_ref - - def get_endpoint_group(self, endpoint_group_id): - session = sql.get_session() - endpoint_group_ref = self._get_endpoint_group(session, - endpoint_group_id) - return endpoint_group_ref.to_dict() - - def update_endpoint_group(self, endpoint_group_id, endpoint_group): - session = sql.get_session() - with session.begin(): - endpoint_group_ref = self._get_endpoint_group(session, - endpoint_group_id) - old_endpoint_group = endpoint_group_ref.to_dict() - old_endpoint_group.update(endpoint_group) - new_endpoint_group = EndpointGroup.from_dict(old_endpoint_group) - for attr in EndpointGroup.mutable_attributes: - setattr(endpoint_group_ref, attr, - getattr(new_endpoint_group, attr)) - return endpoint_group_ref.to_dict() - - def delete_endpoint_group(self, endpoint_group_id): - session = sql.get_session() - endpoint_group_ref = self._get_endpoint_group(session, - endpoint_group_id) - with session.begin(): - self._delete_endpoint_group_association_by_endpoint_group( - session, endpoint_group_id) - session.delete(endpoint_group_ref) - - def get_endpoint_group_in_project(self, endpoint_group_id, project_id): - session = sql.get_session() - ref = self._get_endpoint_group_in_project(session, - endpoint_group_id, - project_id) - return ref.to_dict() - - @sql.handle_conflicts(conflict_type='project_endpoint_group') - def add_endpoint_group_to_project(self, endpoint_group_id, project_id): - session = sql.get_session() - - with session.begin(): - # Create a new Project Endpoint group entity - endpoint_group_project_ref = ProjectEndpointGroupMembership( - endpoint_group_id=endpoint_group_id, project_id=project_id) - session.add(endpoint_group_project_ref) - - def _get_endpoint_group_in_project(self, session, - endpoint_group_id, project_id): - endpoint_group_project_ref = session.query( - ProjectEndpointGroupMembership).get((endpoint_group_id, - project_id)) - if endpoint_group_project_ref is None: - msg = _('Endpoint Group Project Association not found') - raise exception.NotFound(msg) - else: - return endpoint_group_project_ref - - def list_endpoint_groups(self): - session = sql.get_session() - query = session.query(EndpointGroup) - endpoint_group_refs = query.all() - return [e.to_dict() for e in endpoint_group_refs] - - def list_endpoint_groups_for_project(self, project_id): - session = sql.get_session() - query = session.query(ProjectEndpointGroupMembership) - query = query.filter_by(project_id=project_id) - endpoint_group_refs = query.all() - return [ref.to_dict() for ref in endpoint_group_refs] - - def remove_endpoint_group_from_project(self, endpoint_group_id, - project_id): - session = sql.get_session() - endpoint_group_project_ref = self._get_endpoint_group_in_project( - session, endpoint_group_id, project_id) - with session.begin(): - session.delete(endpoint_group_project_ref) - - def list_projects_associated_with_endpoint_group(self, endpoint_group_id): - session = sql.get_session() - query = session.query(ProjectEndpointGroupMembership) - query = query.filter_by(endpoint_group_id=endpoint_group_id) - endpoint_group_refs = query.all() - return [ref.to_dict() for ref in endpoint_group_refs] - - def _delete_endpoint_group_association_by_endpoint_group( - self, session, endpoint_group_id): - query = session.query(ProjectEndpointGroupMembership) - query = query.filter_by(endpoint_group_id=endpoint_group_id) - query.delete() - - def delete_endpoint_group_association_by_project(self, project_id): - session = sql.get_session() - with session.begin(): - query = session.query(ProjectEndpointGroupMembership) - query = query.filter_by(project_id=project_id) - query.delete() +class EndpointFilter(sql.Catalog): + @versionutils.deprecated( + as_of=versionutils.deprecated.MITAKA, + in_favor_of=_NEW, + what=_OLD, + remove_in=2) + def __init__(self, *args, **kwargs): + super(EndpointFilter, self).__init__(*args, **kwargs) diff --git a/keystone-moon/keystone/contrib/endpoint_filter/migrate_repo/versions/001_add_endpoint_filtering_table.py b/keystone-moon/keystone/contrib/endpoint_filter/migrate_repo/versions/001_add_endpoint_filtering_table.py index 2aa93a86..ac0a30cc 100644 --- a/keystone-moon/keystone/contrib/endpoint_filter/migrate_repo/versions/001_add_endpoint_filtering_table.py +++ b/keystone-moon/keystone/contrib/endpoint_filter/migrate_repo/versions/001_add_endpoint_filtering_table.py @@ -12,27 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - # Upgrade operations go here. Don't create your own engine; bind - # migrate_engine to your metadata - meta = sql.MetaData() - meta.bind = migrate_engine - - endpoint_filtering_table = sql.Table( - 'project_endpoint', - meta, - sql.Column( - 'endpoint_id', - sql.String(64), - primary_key=True, - nullable=False), - sql.Column( - 'project_id', - sql.String(64), - primary_key=True, - nullable=False)) - - endpoint_filtering_table.create(migrate_engine, checkfirst=True) + raise exception.MigrationMovedFailure(extension='endpoint_filter') diff --git a/keystone-moon/keystone/contrib/endpoint_filter/migrate_repo/versions/002_add_endpoint_groups.py b/keystone-moon/keystone/contrib/endpoint_filter/migrate_repo/versions/002_add_endpoint_groups.py index 2c218b0d..ac5aa5b3 100644 --- a/keystone-moon/keystone/contrib/endpoint_filter/migrate_repo/versions/002_add_endpoint_groups.py +++ b/keystone-moon/keystone/contrib/endpoint_filter/migrate_repo/versions/002_add_endpoint_groups.py @@ -12,30 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - # Upgrade operations go here. Don't create your own engine; bind - # migrate_engine to your metadata - meta = sql.MetaData() - meta.bind = migrate_engine - - endpoint_group_table = sql.Table( - 'endpoint_group', - meta, - sql.Column('id', sql.String(64), primary_key=True), - sql.Column('name', sql.String(255), nullable=False), - sql.Column('description', sql.Text, nullable=True), - sql.Column('filters', sql.Text(), nullable=False)) - endpoint_group_table.create(migrate_engine, checkfirst=True) - - project_endpoint_group_table = sql.Table( - 'project_endpoint_group', - meta, - sql.Column('endpoint_group_id', sql.String(64), - sql.ForeignKey('endpoint_group.id'), nullable=False), - sql.Column('project_id', sql.String(64), nullable=False), - sql.PrimaryKeyConstraint('endpoint_group_id', - 'project_id')) - project_endpoint_group_table.create(migrate_engine, checkfirst=True) + raise exception.MigrationMovedFailure(extension='endpoint_filter') diff --git a/keystone-moon/keystone/contrib/endpoint_filter/routers.py b/keystone-moon/keystone/contrib/endpoint_filter/routers.py index 285b9df2..f75110f9 100644 --- a/keystone-moon/keystone/contrib/endpoint_filter/routers.py +++ b/keystone-moon/keystone/contrib/endpoint_filter/routers.py @@ -12,151 +12,22 @@ # License for the specific language governing permissions and limitations # under the License. -import functools +from oslo_log import log +from oslo_log import versionutils -from keystone.common import json_home from keystone.common import wsgi -from keystone.contrib.endpoint_filter import controllers +from keystone.i18n import _ -build_resource_relation = functools.partial( - json_home.build_v3_extension_resource_relation, - extension_name='OS-EP-FILTER', extension_version='1.0') +LOG = log.getLogger(__name__) -build_parameter_relation = functools.partial( - json_home.build_v3_extension_parameter_relation, - extension_name='OS-EP-FILTER', extension_version='1.0') -ENDPOINT_GROUP_PARAMETER_RELATION = build_parameter_relation( - parameter_name='endpoint_group_id') +class EndpointFilterExtension(wsgi.Middleware): - -class EndpointFilterExtension(wsgi.V3ExtensionRouter): - """API Endpoints for the Endpoint Filter extension. - - The API looks like:: - - PUT /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} - GET /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} - HEAD /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} - DELETE /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} - GET /OS-EP-FILTER/endpoints/{endpoint_id}/projects - GET /OS-EP-FILTER/projects/{project_id}/endpoints - GET /OS-EP-FILTER/projects/{project_id}/endpoint_groups - - GET /OS-EP-FILTER/endpoint_groups - POST /OS-EP-FILTER/endpoint_groups - GET /OS-EP-FILTER/endpoint_groups/{endpoint_group_id} - HEAD /OS-EP-FILTER/endpoint_groups/{endpoint_group_id} - PATCH /OS-EP-FILTER/endpoint_groups/{endpoint_group_id} - DELETE /OS-EP-FILTER/endpoint_groups/{endpoint_group_id} - - GET /OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects - GET /OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/endpoints - - PUT /OS-EP-FILTER/endpoint_groups/{endpoint_group}/projects/ - {project_id} - GET /OS-EP-FILTER/endpoint_groups/{endpoint_group}/projects/ - {project_id} - HEAD /OS-EP-FILTER/endpoint_groups/{endpoint_group}/projects/ - {project_id} - DELETE /OS-EP-FILTER/endpoint_groups/{endpoint_group}/projects/ - {project_id} - - """ - PATH_PREFIX = '/OS-EP-FILTER' - PATH_PROJECT_ENDPOINT = '/projects/{project_id}/endpoints/{endpoint_id}' - PATH_ENDPOINT_GROUPS = '/endpoint_groups/{endpoint_group_id}' - PATH_ENDPOINT_GROUP_PROJECTS = PATH_ENDPOINT_GROUPS + ( - '/projects/{project_id}') - - def add_routes(self, mapper): - endpoint_filter_controller = controllers.EndpointFilterV3Controller() - endpoint_group_controller = controllers.EndpointGroupV3Controller() - project_endpoint_group_controller = ( - controllers.ProjectEndpointGroupV3Controller()) - - self._add_resource( - mapper, endpoint_filter_controller, - path=self.PATH_PREFIX + '/endpoints/{endpoint_id}/projects', - get_action='list_projects_for_endpoint', - rel=build_resource_relation(resource_name='endpoint_projects'), - path_vars={ - 'endpoint_id': json_home.Parameters.ENDPOINT_ID, - }) - self._add_resource( - mapper, endpoint_filter_controller, - path=self.PATH_PREFIX + self.PATH_PROJECT_ENDPOINT, - get_head_action='check_endpoint_in_project', - put_action='add_endpoint_to_project', - delete_action='remove_endpoint_from_project', - rel=build_resource_relation(resource_name='project_endpoint'), - path_vars={ - 'endpoint_id': json_home.Parameters.ENDPOINT_ID, - 'project_id': json_home.Parameters.PROJECT_ID, - }) - self._add_resource( - mapper, endpoint_filter_controller, - path=self.PATH_PREFIX + '/projects/{project_id}/endpoints', - get_action='list_endpoints_for_project', - rel=build_resource_relation(resource_name='project_endpoints'), - path_vars={ - 'project_id': json_home.Parameters.PROJECT_ID, - }) - self._add_resource( - mapper, endpoint_group_controller, - path=self.PATH_PREFIX + '/projects/{project_id}/endpoint_groups', - get_action='list_endpoint_groups_for_project', - rel=build_resource_relation( - resource_name='project_endpoint_groups'), - path_vars={ - 'project_id': json_home.Parameters.PROJECT_ID, - }) - self._add_resource( - mapper, endpoint_group_controller, - path=self.PATH_PREFIX + '/endpoint_groups', - get_action='list_endpoint_groups', - post_action='create_endpoint_group', - rel=build_resource_relation(resource_name='endpoint_groups')) - self._add_resource( - mapper, endpoint_group_controller, - path=self.PATH_PREFIX + self.PATH_ENDPOINT_GROUPS, - get_head_action='get_endpoint_group', - patch_action='update_endpoint_group', - delete_action='delete_endpoint_group', - rel=build_resource_relation(resource_name='endpoint_group'), - path_vars={ - 'endpoint_group_id': ENDPOINT_GROUP_PARAMETER_RELATION - }) - self._add_resource( - mapper, project_endpoint_group_controller, - path=self.PATH_PREFIX + self.PATH_ENDPOINT_GROUP_PROJECTS, - get_head_action='get_endpoint_group_in_project', - put_action='add_endpoint_group_to_project', - delete_action='remove_endpoint_group_from_project', - rel=build_resource_relation( - resource_name='endpoint_group_to_project_association'), - path_vars={ - 'project_id': json_home.Parameters.PROJECT_ID, - 'endpoint_group_id': ENDPOINT_GROUP_PARAMETER_RELATION - }) - self._add_resource( - mapper, endpoint_group_controller, - path=self.PATH_PREFIX + self.PATH_ENDPOINT_GROUPS + ( - '/projects'), - get_action='list_projects_associated_with_endpoint_group', - rel=build_resource_relation( - resource_name='projects_associated_with_endpoint_group'), - path_vars={ - 'endpoint_group_id': ENDPOINT_GROUP_PARAMETER_RELATION - }) - self._add_resource( - mapper, endpoint_group_controller, - path=self.PATH_PREFIX + self.PATH_ENDPOINT_GROUPS + ( - '/endpoints'), - get_action='list_endpoints_associated_with_endpoint_group', - rel=build_resource_relation( - resource_name='endpoints_in_endpoint_group'), - path_vars={ - 'endpoint_group_id': ENDPOINT_GROUP_PARAMETER_RELATION - }) + def __init__(self, *args, **kwargs): + super(EndpointFilterExtension, self).__init__(*args, **kwargs) + msg = _("Remove endpoint_filter_extension from the paste pipeline, " + "the endpoint filter extension is now always available. " + "Update the [pipeline:api_v3] section in keystone-paste.ini " + "accordingly as it will be removed in the O release.") + versionutils.report_deprecated_feature(LOG, msg) diff --git a/keystone-moon/keystone/contrib/endpoint_policy/backends/sql.py b/keystone-moon/keystone/contrib/endpoint_policy/backends/sql.py index 54792f30..93331779 100644 --- a/keystone-moon/keystone/contrib/endpoint_policy/backends/sql.py +++ b/keystone-moon/keystone/contrib/endpoint_policy/backends/sql.py @@ -10,14 +10,10 @@ # License for the specific language governing permissions and limitations # under the License. -import logging - from oslo_log import versionutils from keystone.endpoint_policy.backends import sql -LOG = logging.getLogger(__name__) - _OLD = 'keystone.contrib.endpoint_policy.backends.sql.EndpointPolicy' _NEW = 'keystone.endpoint_policy.backends.sql.EndpointPolicy' diff --git a/keystone-moon/keystone/contrib/endpoint_policy/migrate_repo/versions/001_add_endpoint_policy_table.py b/keystone-moon/keystone/contrib/endpoint_policy/migrate_repo/versions/001_add_endpoint_policy_table.py index 5c22f169..32bdabdd 100644 --- a/keystone-moon/keystone/contrib/endpoint_policy/migrate_repo/versions/001_add_endpoint_policy_table.py +++ b/keystone-moon/keystone/contrib/endpoint_policy/migrate_repo/versions/001_add_endpoint_policy_table.py @@ -12,29 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - # Upgrade operations go here. Don't create your own engine; bind - # migrate_engine to your metadata - meta = sql.MetaData() - meta.bind = migrate_engine - - endpoint_policy_table = sql.Table( - 'policy_association', - meta, - sql.Column('id', sql.String(64), primary_key=True), - sql.Column('policy_id', sql.String(64), - nullable=False), - sql.Column('endpoint_id', sql.String(64), - nullable=True), - sql.Column('service_id', sql.String(64), - nullable=True), - sql.Column('region_id', sql.String(64), - nullable=True), - sql.UniqueConstraint('endpoint_id', 'service_id', 'region_id'), - mysql_engine='InnoDB', - mysql_charset='utf8') - - endpoint_policy_table.create(migrate_engine, checkfirst=True) + raise exception.MigrationMovedFailure(extension='endpoint_policy') diff --git a/keystone-moon/keystone/contrib/endpoint_policy/routers.py b/keystone-moon/keystone/contrib/endpoint_policy/routers.py index 714d1663..c8f7f154 100644 --- a/keystone-moon/keystone/contrib/endpoint_policy/routers.py +++ b/keystone-moon/keystone/contrib/endpoint_policy/routers.py @@ -10,14 +10,10 @@ # License for the specific language governing permissions and limitations # under the License. -import logging - from oslo_log import versionutils from keystone.common import wsgi -LOG = logging.getLogger(__name__) - _OLD = 'keystone.contrib.endpoint_policy.routers.EndpointPolicyExtension' _NEW = 'keystone.endpoint_policy.routers.Routers' diff --git a/keystone-moon/keystone/contrib/federation/__init__.py b/keystone-moon/keystone/contrib/federation/__init__.py index 57c9e42c..e69de29b 100644 --- a/keystone-moon/keystone/contrib/federation/__init__.py +++ b/keystone-moon/keystone/contrib/federation/__init__.py @@ -1,15 +0,0 @@ -# Copyright 2014 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.contrib.federation.core import * # noqa diff --git a/keystone-moon/keystone/contrib/federation/backends/sql.py b/keystone-moon/keystone/contrib/federation/backends/sql.py index dbd17025..3c24d9c0 100644 --- a/keystone-moon/keystone/contrib/federation/backends/sql.py +++ b/keystone-moon/keystone/contrib/federation/backends/sql.py @@ -12,355 +12,18 @@ # License for the specific language governing permissions and limitations # under the License. -from oslo_serialization import jsonutils +from oslo_log import versionutils -from keystone.common import sql -from keystone.contrib.federation import core -from keystone import exception -from sqlalchemy import orm +from keystone.federation.backends import sql +_OLD = "keystone.contrib.federation.backends.sql.Federation" +_NEW = "sql" -class FederationProtocolModel(sql.ModelBase, sql.DictBase): - __tablename__ = 'federation_protocol' - attributes = ['id', 'idp_id', 'mapping_id'] - mutable_attributes = frozenset(['mapping_id']) - id = sql.Column(sql.String(64), primary_key=True) - idp_id = sql.Column(sql.String(64), sql.ForeignKey('identity_provider.id', - ondelete='CASCADE'), primary_key=True) - mapping_id = sql.Column(sql.String(64), nullable=False) +class Federation(sql.Federation): - @classmethod - def from_dict(cls, dictionary): - new_dictionary = dictionary.copy() - return cls(**new_dictionary) - - def to_dict(self): - """Return a dictionary with model's attributes.""" - d = dict() - for attr in self.__class__.attributes: - d[attr] = getattr(self, attr) - return d - - -class IdentityProviderModel(sql.ModelBase, sql.DictBase): - __tablename__ = 'identity_provider' - attributes = ['id', 'enabled', 'description', 'remote_ids'] - mutable_attributes = frozenset(['description', 'enabled', 'remote_ids']) - - id = sql.Column(sql.String(64), primary_key=True) - enabled = sql.Column(sql.Boolean, nullable=False) - description = sql.Column(sql.Text(), nullable=True) - remote_ids = orm.relationship('IdPRemoteIdsModel', - order_by='IdPRemoteIdsModel.remote_id', - cascade='all, delete-orphan') - - @classmethod - def from_dict(cls, dictionary): - new_dictionary = dictionary.copy() - remote_ids_list = new_dictionary.pop('remote_ids', None) - if not remote_ids_list: - remote_ids_list = [] - identity_provider = cls(**new_dictionary) - remote_ids = [] - # NOTE(fmarco76): the remote_ids_list contains only remote ids - # associated with the IdP because of the "relationship" established in - # sqlalchemy and corresponding to the FK in the idp_remote_ids table - for remote in remote_ids_list: - remote_ids.append(IdPRemoteIdsModel(remote_id=remote)) - identity_provider.remote_ids = remote_ids - return identity_provider - - def to_dict(self): - """Return a dictionary with model's attributes.""" - d = dict() - for attr in self.__class__.attributes: - d[attr] = getattr(self, attr) - d['remote_ids'] = [] - for remote in self.remote_ids: - d['remote_ids'].append(remote.remote_id) - return d - - -class IdPRemoteIdsModel(sql.ModelBase, sql.DictBase): - __tablename__ = 'idp_remote_ids' - attributes = ['idp_id', 'remote_id'] - mutable_attributes = frozenset(['idp_id', 'remote_id']) - - idp_id = sql.Column(sql.String(64), - sql.ForeignKey('identity_provider.id', - ondelete='CASCADE')) - remote_id = sql.Column(sql.String(255), - primary_key=True) - - @classmethod - def from_dict(cls, dictionary): - new_dictionary = dictionary.copy() - return cls(**new_dictionary) - - def to_dict(self): - """Return a dictionary with model's attributes.""" - d = dict() - for attr in self.__class__.attributes: - d[attr] = getattr(self, attr) - return d - - -class MappingModel(sql.ModelBase, sql.DictBase): - __tablename__ = 'mapping' - attributes = ['id', 'rules'] - - id = sql.Column(sql.String(64), primary_key=True) - rules = sql.Column(sql.JsonBlob(), nullable=False) - - @classmethod - def from_dict(cls, dictionary): - new_dictionary = dictionary.copy() - new_dictionary['rules'] = jsonutils.dumps(new_dictionary['rules']) - return cls(**new_dictionary) - - def to_dict(self): - """Return a dictionary with model's attributes.""" - d = dict() - for attr in self.__class__.attributes: - d[attr] = getattr(self, attr) - d['rules'] = jsonutils.loads(d['rules']) - return d - - -class ServiceProviderModel(sql.ModelBase, sql.DictBase): - __tablename__ = 'service_provider' - attributes = ['auth_url', 'id', 'enabled', 'description', - 'relay_state_prefix', 'sp_url'] - mutable_attributes = frozenset(['auth_url', 'description', 'enabled', - 'relay_state_prefix', 'sp_url']) - - id = sql.Column(sql.String(64), primary_key=True) - enabled = sql.Column(sql.Boolean, nullable=False) - description = sql.Column(sql.Text(), nullable=True) - auth_url = sql.Column(sql.String(256), nullable=False) - sp_url = sql.Column(sql.String(256), nullable=False) - relay_state_prefix = sql.Column(sql.String(256), nullable=False) - - @classmethod - def from_dict(cls, dictionary): - new_dictionary = dictionary.copy() - return cls(**new_dictionary) - - def to_dict(self): - """Return a dictionary with model's attributes.""" - d = dict() - for attr in self.__class__.attributes: - d[attr] = getattr(self, attr) - return d - - -class Federation(core.FederationDriverV8): - - # Identity Provider CRUD - @sql.handle_conflicts(conflict_type='identity_provider') - def create_idp(self, idp_id, idp): - idp['id'] = idp_id - with sql.transaction() as session: - idp_ref = IdentityProviderModel.from_dict(idp) - session.add(idp_ref) - return idp_ref.to_dict() - - def delete_idp(self, idp_id): - with sql.transaction() as session: - self._delete_assigned_protocols(session, idp_id) - idp_ref = self._get_idp(session, idp_id) - session.delete(idp_ref) - - def _get_idp(self, session, idp_id): - idp_ref = session.query(IdentityProviderModel).get(idp_id) - if not idp_ref: - raise exception.IdentityProviderNotFound(idp_id=idp_id) - return idp_ref - - def _get_idp_from_remote_id(self, session, remote_id): - q = session.query(IdPRemoteIdsModel) - q = q.filter_by(remote_id=remote_id) - try: - return q.one() - except sql.NotFound: - raise exception.IdentityProviderNotFound(idp_id=remote_id) - - def list_idps(self): - with sql.transaction() as session: - idps = session.query(IdentityProviderModel) - idps_list = [idp.to_dict() for idp in idps] - return idps_list - - def get_idp(self, idp_id): - with sql.transaction() as session: - idp_ref = self._get_idp(session, idp_id) - return idp_ref.to_dict() - - def get_idp_from_remote_id(self, remote_id): - with sql.transaction() as session: - ref = self._get_idp_from_remote_id(session, remote_id) - return ref.to_dict() - - def update_idp(self, idp_id, idp): - with sql.transaction() as session: - idp_ref = self._get_idp(session, idp_id) - old_idp = idp_ref.to_dict() - old_idp.update(idp) - new_idp = IdentityProviderModel.from_dict(old_idp) - for attr in IdentityProviderModel.mutable_attributes: - setattr(idp_ref, attr, getattr(new_idp, attr)) - return idp_ref.to_dict() - - # Protocol CRUD - def _get_protocol(self, session, idp_id, protocol_id): - q = session.query(FederationProtocolModel) - q = q.filter_by(id=protocol_id, idp_id=idp_id) - try: - return q.one() - except sql.NotFound: - kwargs = {'protocol_id': protocol_id, - 'idp_id': idp_id} - raise exception.FederatedProtocolNotFound(**kwargs) - - @sql.handle_conflicts(conflict_type='federation_protocol') - def create_protocol(self, idp_id, protocol_id, protocol): - protocol['id'] = protocol_id - protocol['idp_id'] = idp_id - with sql.transaction() as session: - self._get_idp(session, idp_id) - protocol_ref = FederationProtocolModel.from_dict(protocol) - session.add(protocol_ref) - return protocol_ref.to_dict() - - def update_protocol(self, idp_id, protocol_id, protocol): - with sql.transaction() as session: - proto_ref = self._get_protocol(session, idp_id, protocol_id) - old_proto = proto_ref.to_dict() - old_proto.update(protocol) - new_proto = FederationProtocolModel.from_dict(old_proto) - for attr in FederationProtocolModel.mutable_attributes: - setattr(proto_ref, attr, getattr(new_proto, attr)) - return proto_ref.to_dict() - - def get_protocol(self, idp_id, protocol_id): - with sql.transaction() as session: - protocol_ref = self._get_protocol(session, idp_id, protocol_id) - return protocol_ref.to_dict() - - def list_protocols(self, idp_id): - with sql.transaction() as session: - q = session.query(FederationProtocolModel) - q = q.filter_by(idp_id=idp_id) - protocols = [protocol.to_dict() for protocol in q] - return protocols - - def delete_protocol(self, idp_id, protocol_id): - with sql.transaction() as session: - key_ref = self._get_protocol(session, idp_id, protocol_id) - session.delete(key_ref) - - def _delete_assigned_protocols(self, session, idp_id): - query = session.query(FederationProtocolModel) - query = query.filter_by(idp_id=idp_id) - query.delete() - - # Mapping CRUD - def _get_mapping(self, session, mapping_id): - mapping_ref = session.query(MappingModel).get(mapping_id) - if not mapping_ref: - raise exception.MappingNotFound(mapping_id=mapping_id) - return mapping_ref - - @sql.handle_conflicts(conflict_type='mapping') - def create_mapping(self, mapping_id, mapping): - ref = {} - ref['id'] = mapping_id - ref['rules'] = mapping.get('rules') - with sql.transaction() as session: - mapping_ref = MappingModel.from_dict(ref) - session.add(mapping_ref) - return mapping_ref.to_dict() - - def delete_mapping(self, mapping_id): - with sql.transaction() as session: - mapping_ref = self._get_mapping(session, mapping_id) - session.delete(mapping_ref) - - def list_mappings(self): - with sql.transaction() as session: - mappings = session.query(MappingModel) - return [x.to_dict() for x in mappings] - - def get_mapping(self, mapping_id): - with sql.transaction() as session: - mapping_ref = self._get_mapping(session, mapping_id) - return mapping_ref.to_dict() - - @sql.handle_conflicts(conflict_type='mapping') - def update_mapping(self, mapping_id, mapping): - ref = {} - ref['id'] = mapping_id - ref['rules'] = mapping.get('rules') - with sql.transaction() as session: - mapping_ref = self._get_mapping(session, mapping_id) - old_mapping = mapping_ref.to_dict() - old_mapping.update(ref) - new_mapping = MappingModel.from_dict(old_mapping) - for attr in MappingModel.attributes: - setattr(mapping_ref, attr, getattr(new_mapping, attr)) - return mapping_ref.to_dict() - - def get_mapping_from_idp_and_protocol(self, idp_id, protocol_id): - with sql.transaction() as session: - protocol_ref = self._get_protocol(session, idp_id, protocol_id) - mapping_id = protocol_ref.mapping_id - mapping_ref = self._get_mapping(session, mapping_id) - return mapping_ref.to_dict() - - # Service Provider CRUD - @sql.handle_conflicts(conflict_type='service_provider') - def create_sp(self, sp_id, sp): - sp['id'] = sp_id - with sql.transaction() as session: - sp_ref = ServiceProviderModel.from_dict(sp) - session.add(sp_ref) - return sp_ref.to_dict() - - def delete_sp(self, sp_id): - with sql.transaction() as session: - sp_ref = self._get_sp(session, sp_id) - session.delete(sp_ref) - - def _get_sp(self, session, sp_id): - sp_ref = session.query(ServiceProviderModel).get(sp_id) - if not sp_ref: - raise exception.ServiceProviderNotFound(sp_id=sp_id) - return sp_ref - - def list_sps(self): - with sql.transaction() as session: - sps = session.query(ServiceProviderModel) - sps_list = [sp.to_dict() for sp in sps] - return sps_list - - def get_sp(self, sp_id): - with sql.transaction() as session: - sp_ref = self._get_sp(session, sp_id) - return sp_ref.to_dict() - - def update_sp(self, sp_id, sp): - with sql.transaction() as session: - sp_ref = self._get_sp(session, sp_id) - old_sp = sp_ref.to_dict() - old_sp.update(sp) - new_sp = ServiceProviderModel.from_dict(old_sp) - for attr in ServiceProviderModel.mutable_attributes: - setattr(sp_ref, attr, getattr(new_sp, attr)) - return sp_ref.to_dict() - - def get_enabled_service_providers(self): - with sql.transaction() as session: - service_providers = session.query(ServiceProviderModel) - service_providers = service_providers.filter_by(enabled=True) - return service_providers + @versionutils.deprecated(versionutils.deprecated.MITAKA, + in_favor_of=_NEW, + what=_OLD) + def __init__(self, *args, **kwargs): + super(Federation, self).__init__(*args, **kwargs) diff --git a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/001_add_identity_provider_table.py b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/001_add_identity_provider_table.py index 9a4d574b..d9b24a00 100644 --- a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/001_add_identity_provider_table.py +++ b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/001_add_identity_provider_table.py @@ -10,33 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - idp_table = sql.Table( - 'identity_provider', - meta, - sql.Column('id', sql.String(64), primary_key=True), - sql.Column('enabled', sql.Boolean, nullable=False), - sql.Column('description', sql.Text(), nullable=True), - mysql_engine='InnoDB', - mysql_charset='utf8') - - idp_table.create(migrate_engine, checkfirst=True) - - federation_protocol_table = sql.Table( - 'federation_protocol', - meta, - sql.Column('id', sql.String(64), primary_key=True), - sql.Column('idp_id', sql.String(64), - sql.ForeignKey('identity_provider.id', ondelete='CASCADE'), - primary_key=True), - sql.Column('mapping_id', sql.String(64), nullable=True), - mysql_engine='InnoDB', - mysql_charset='utf8') - - federation_protocol_table.create(migrate_engine, checkfirst=True) + raise exception.MigrationMovedFailure(extension='federation') diff --git a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/002_add_mapping_tables.py b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/002_add_mapping_tables.py index 9a155f5c..d9b24a00 100644 --- a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/002_add_mapping_tables.py +++ b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/002_add_mapping_tables.py @@ -10,18 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - mapping_table = sql.Table( - 'mapping', - meta, - sql.Column('id', sql.String(64), primary_key=True), - sql.Column('rules', sql.Text(), nullable=False), - mysql_engine='InnoDB', - mysql_charset='utf8') - mapping_table.create(migrate_engine, checkfirst=True) + raise exception.MigrationMovedFailure(extension='federation') diff --git a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/003_mapping_id_nullable_false.py b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/003_mapping_id_nullable_false.py index 1731b0d3..8ce8c6fa 100644 --- a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/003_mapping_id_nullable_false.py +++ b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/003_mapping_id_nullable_false.py @@ -13,17 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sa +from keystone import exception def upgrade(migrate_engine): - meta = sa.MetaData(bind=migrate_engine) - federation_protocol = sa.Table('federation_protocol', meta, autoload=True) - # NOTE(i159): The column is changed to non-nullable. To prevent - # database errors when the column will be altered, all the existing - # null-records should be filled with not null values. - stmt = (federation_protocol.update(). - where(federation_protocol.c.mapping_id.is_(None)). - values(mapping_id='')) - migrate_engine.execute(stmt) - federation_protocol.c.mapping_id.alter(nullable=False) + raise exception.MigrationMovedFailure(extension='federation') diff --git a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/004_add_remote_id_column.py b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/004_add_remote_id_column.py index 2e0aaf93..d9b24a00 100644 --- a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/004_add_remote_id_column.py +++ b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/004_add_remote_id_column.py @@ -10,14 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -from oslo_db.sqlalchemy import utils -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - idp_table = utils.get_table(migrate_engine, 'identity_provider') - remote_id = sql.Column('remote_id', sql.String(256), nullable=True) - idp_table.create_column(remote_id) + raise exception.MigrationMovedFailure(extension='federation') diff --git a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/005_add_service_provider_table.py b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/005_add_service_provider_table.py index 1594f893..d9b24a00 100644 --- a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/005_add_service_provider_table.py +++ b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/005_add_service_provider_table.py @@ -10,22 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - sp_table = sql.Table( - 'service_provider', - meta, - sql.Column('auth_url', sql.String(256), nullable=True), - sql.Column('id', sql.String(64), primary_key=True), - sql.Column('enabled', sql.Boolean, nullable=False), - sql.Column('description', sql.Text(), nullable=True), - sql.Column('sp_url', sql.String(256), nullable=True), - mysql_engine='InnoDB', - mysql_charset='utf8') - - sp_table.create(migrate_engine, checkfirst=True) + raise exception.MigrationMovedFailure(extension='federation') diff --git a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/006_fixup_service_provider_attributes.py b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/006_fixup_service_provider_attributes.py index dc18f548..d9b24a00 100644 --- a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/006_fixup_service_provider_attributes.py +++ b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/006_fixup_service_provider_attributes.py @@ -10,31 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql - -_SP_TABLE_NAME = 'service_provider' - - -def _update_null_columns(migrate_engine, sp_table): - stmt = (sp_table.update(). - where(sp_table.c.auth_url.is_(None)). - values(auth_url='')) - migrate_engine.execute(stmt) - - stmt = (sp_table.update(). - where(sp_table.c.sp_url.is_(None)). - values(sp_url='')) - migrate_engine.execute(stmt) +from keystone import exception def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - sp_table = sql.Table(_SP_TABLE_NAME, meta, autoload=True) - # The columns are being changed to non-nullable. To prevent - # database errors when both are altered, all the existing - # null-records should be filled with not null values. - _update_null_columns(migrate_engine, sp_table) - - sp_table.c.auth_url.alter(nullable=False) - sp_table.c.sp_url.alter(nullable=False) + raise exception.MigrationMovedFailure(extension='federation') diff --git a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py index 77012aad..d9b24a00 100644 --- a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py +++ b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py @@ -10,34 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as orm +from keystone import exception def upgrade(migrate_engine): - meta = orm.MetaData() - meta.bind = migrate_engine - idp_table = orm.Table('identity_provider', meta, autoload=True) - remote_id_table = orm.Table( - 'idp_remote_ids', - meta, - orm.Column('idp_id', - orm.String(64), - orm.ForeignKey('identity_provider.id', - ondelete='CASCADE')), - orm.Column('remote_id', - orm.String(255), - primary_key=True), - mysql_engine='InnoDB', - mysql_charset='utf8') - - remote_id_table.create(migrate_engine, checkfirst=True) - - select = orm.sql.select([idp_table.c.id, idp_table.c.remote_id]).where( - idp_table.c.remote_id.isnot(None)) - - for identity in migrate_engine.execute(select): - remote_idp_entry = {'idp_id': identity.id, - 'remote_id': identity.remote_id} - remote_id_table.insert(remote_idp_entry).execute() - - idp_table.drop_column('remote_id') + raise exception.MigrationMovedFailure(extension='federation') diff --git a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/008_add_relay_state_to_sp.py b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/008_add_relay_state_to_sp.py index 150dcfed..d9b24a00 100644 --- a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/008_add_relay_state_to_sp.py +++ b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/008_add_relay_state_to_sp.py @@ -10,30 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -from oslo_config import cfg -from oslo_db.sqlalchemy import utils -import sqlalchemy as sql - - -CONF = cfg.CONF -_SP_TABLE_NAME = 'service_provider' -_RELAY_STATE_PREFIX = 'relay_state_prefix' +from keystone import exception def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - idp_table = utils.get_table(migrate_engine, _SP_TABLE_NAME) - relay_state_prefix_default = CONF.saml.relay_state_prefix - relay_state_prefix = sql.Column(_RELAY_STATE_PREFIX, sql.String(256), - nullable=False, - server_default=relay_state_prefix_default) - idp_table.create_column(relay_state_prefix) - - -def downgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - idp_table = utils.get_table(migrate_engine, _SP_TABLE_NAME) - idp_table.drop_column(_RELAY_STATE_PREFIX) + raise exception.MigrationMovedFailure(extension='federation') diff --git a/keystone-moon/keystone/contrib/federation/routers.py b/keystone-moon/keystone/contrib/federation/routers.py index ddf2f61f..d5857ca6 100644 --- a/keystone-moon/keystone/contrib/federation/routers.py +++ b/keystone-moon/keystone/contrib/federation/routers.py @@ -10,242 +10,22 @@ # License for the specific language governing permissions and limitations # under the License. -import functools +from oslo_log import log +from oslo_log import versionutils -from keystone.common import json_home from keystone.common import wsgi -from keystone.contrib.federation import controllers +from keystone.i18n import _ -build_resource_relation = functools.partial( - json_home.build_v3_extension_resource_relation, - extension_name='OS-FEDERATION', extension_version='1.0') +LOG = log.getLogger(__name__) -build_parameter_relation = functools.partial( - json_home.build_v3_extension_parameter_relation, - extension_name='OS-FEDERATION', extension_version='1.0') -IDP_ID_PARAMETER_RELATION = build_parameter_relation(parameter_name='idp_id') -PROTOCOL_ID_PARAMETER_RELATION = build_parameter_relation( - parameter_name='protocol_id') -SP_ID_PARAMETER_RELATION = build_parameter_relation(parameter_name='sp_id') +class FederationExtension(wsgi.Middleware): - -class FederationExtension(wsgi.V3ExtensionRouter): - """API Endpoints for the Federation extension. - - The API looks like:: - - PUT /OS-FEDERATION/identity_providers/{idp_id} - GET /OS-FEDERATION/identity_providers - GET /OS-FEDERATION/identity_providers/{idp_id} - DELETE /OS-FEDERATION/identity_providers/{idp_id} - PATCH /OS-FEDERATION/identity_providers/{idp_id} - - PUT /OS-FEDERATION/identity_providers/ - {idp_id}/protocols/{protocol_id} - GET /OS-FEDERATION/identity_providers/ - {idp_id}/protocols - GET /OS-FEDERATION/identity_providers/ - {idp_id}/protocols/{protocol_id} - PATCH /OS-FEDERATION/identity_providers/ - {idp_id}/protocols/{protocol_id} - DELETE /OS-FEDERATION/identity_providers/ - {idp_id}/protocols/{protocol_id} - - PUT /OS-FEDERATION/mappings - GET /OS-FEDERATION/mappings - PATCH /OS-FEDERATION/mappings/{mapping_id} - GET /OS-FEDERATION/mappings/{mapping_id} - DELETE /OS-FEDERATION/mappings/{mapping_id} - - GET /OS-FEDERATION/projects - GET /OS-FEDERATION/domains - - PUT /OS-FEDERATION/service_providers/{sp_id} - GET /OS-FEDERATION/service_providers - GET /OS-FEDERATION/service_providers/{sp_id} - DELETE /OS-FEDERATION/service_providers/{sp_id} - PATCH /OS-FEDERATION/service_providers/{sp_id} - - GET /OS-FEDERATION/identity_providers/{identity_provider}/ - protocols/{protocol}/auth - POST /OS-FEDERATION/identity_providers/{identity_provider}/ - protocols/{protocol}/auth - GET /auth/OS-FEDERATION/identity_providers/ - {idp_id}/protocols/{protocol_id}/websso - ?origin=https%3A//horizon.example.com - POST /auth/OS-FEDERATION/identity_providers/ - {idp_id}/protocols/{protocol_id}/websso - ?origin=https%3A//horizon.example.com - - - POST /auth/OS-FEDERATION/saml2 - POST /auth/OS-FEDERATION/saml2/ecp - GET /OS-FEDERATION/saml2/metadata - - GET /auth/OS-FEDERATION/websso/{protocol_id} - ?origin=https%3A//horizon.example.com - - POST /auth/OS-FEDERATION/websso/{protocol_id} - ?origin=https%3A//horizon.example.com - - """ - def _construct_url(self, suffix): - return "/OS-FEDERATION/%s" % suffix - - def add_routes(self, mapper): - auth_controller = controllers.Auth() - idp_controller = controllers.IdentityProvider() - protocol_controller = controllers.FederationProtocol() - mapping_controller = controllers.MappingController() - project_controller = controllers.ProjectAssignmentV3() - domain_controller = controllers.DomainV3() - saml_metadata_controller = controllers.SAMLMetadataV3() - sp_controller = controllers.ServiceProvider() - - # Identity Provider CRUD operations - - self._add_resource( - mapper, idp_controller, - path=self._construct_url('identity_providers/{idp_id}'), - get_action='get_identity_provider', - put_action='create_identity_provider', - patch_action='update_identity_provider', - delete_action='delete_identity_provider', - rel=build_resource_relation(resource_name='identity_provider'), - path_vars={ - 'idp_id': IDP_ID_PARAMETER_RELATION, - }) - self._add_resource( - mapper, idp_controller, - path=self._construct_url('identity_providers'), - get_action='list_identity_providers', - rel=build_resource_relation(resource_name='identity_providers')) - - # Protocol CRUD operations - - self._add_resource( - mapper, protocol_controller, - path=self._construct_url('identity_providers/{idp_id}/protocols/' - '{protocol_id}'), - get_action='get_protocol', - put_action='create_protocol', - patch_action='update_protocol', - delete_action='delete_protocol', - rel=build_resource_relation( - resource_name='identity_provider_protocol'), - path_vars={ - 'idp_id': IDP_ID_PARAMETER_RELATION, - 'protocol_id': PROTOCOL_ID_PARAMETER_RELATION, - }) - self._add_resource( - mapper, protocol_controller, - path=self._construct_url('identity_providers/{idp_id}/protocols'), - get_action='list_protocols', - rel=build_resource_relation( - resource_name='identity_provider_protocols'), - path_vars={ - 'idp_id': IDP_ID_PARAMETER_RELATION, - }) - - # Mapping CRUD operations - - self._add_resource( - mapper, mapping_controller, - path=self._construct_url('mappings/{mapping_id}'), - get_action='get_mapping', - put_action='create_mapping', - patch_action='update_mapping', - delete_action='delete_mapping', - rel=build_resource_relation(resource_name='mapping'), - path_vars={ - 'mapping_id': build_parameter_relation( - parameter_name='mapping_id'), - }) - self._add_resource( - mapper, mapping_controller, - path=self._construct_url('mappings'), - get_action='list_mappings', - rel=build_resource_relation(resource_name='mappings')) - - # Service Providers CRUD operations - - self._add_resource( - mapper, sp_controller, - path=self._construct_url('service_providers/{sp_id}'), - get_action='get_service_provider', - put_action='create_service_provider', - patch_action='update_service_provider', - delete_action='delete_service_provider', - rel=build_resource_relation(resource_name='service_provider'), - path_vars={ - 'sp_id': SP_ID_PARAMETER_RELATION, - }) - - self._add_resource( - mapper, sp_controller, - path=self._construct_url('service_providers'), - get_action='list_service_providers', - rel=build_resource_relation(resource_name='service_providers')) - - self._add_resource( - mapper, domain_controller, - path=self._construct_url('domains'), - new_path='/auth/domains', - get_action='list_domains_for_groups', - rel=build_resource_relation(resource_name='domains')) - self._add_resource( - mapper, project_controller, - path=self._construct_url('projects'), - new_path='/auth/projects', - get_action='list_projects_for_groups', - rel=build_resource_relation(resource_name='projects')) - - # Auth operations - self._add_resource( - mapper, auth_controller, - path=self._construct_url('identity_providers/{identity_provider}/' - 'protocols/{protocol}/auth'), - get_post_action='federated_authentication', - rel=build_resource_relation( - resource_name='identity_provider_protocol_auth'), - path_vars={ - 'identity_provider': IDP_ID_PARAMETER_RELATION, - 'protocol': PROTOCOL_ID_PARAMETER_RELATION, - }) - self._add_resource( - mapper, auth_controller, - path='/auth' + self._construct_url('saml2'), - post_action='create_saml_assertion', - rel=build_resource_relation(resource_name='saml2')) - self._add_resource( - mapper, auth_controller, - path='/auth' + self._construct_url('saml2/ecp'), - post_action='create_ecp_assertion', - rel=build_resource_relation(resource_name='ecp')) - self._add_resource( - mapper, auth_controller, - path='/auth' + self._construct_url('websso/{protocol_id}'), - get_post_action='federated_sso_auth', - rel=build_resource_relation(resource_name='websso'), - path_vars={ - 'protocol_id': PROTOCOL_ID_PARAMETER_RELATION, - }) - self._add_resource( - mapper, auth_controller, - path='/auth' + self._construct_url( - 'identity_providers/{idp_id}/protocols/{protocol_id}/websso'), - get_post_action='federated_idp_specific_sso_auth', - rel=build_resource_relation(resource_name='identity_providers'), - path_vars={ - 'idp_id': IDP_ID_PARAMETER_RELATION, - 'protocol_id': PROTOCOL_ID_PARAMETER_RELATION, - }) - - # Keystone-Identity-Provider metadata endpoint - self._add_resource( - mapper, saml_metadata_controller, - path=self._construct_url('saml2/metadata'), - get_action='get_metadata', - rel=build_resource_relation(resource_name='metadata')) + def __init__(self, *args, **kwargs): + super(FederationExtension, self).__init__(*args, **kwargs) + msg = _("Remove federation_extension from the paste pipeline, the " + "federation extension is now always available. Update the " + "[pipeline:api_v3] section in keystone-paste.ini accordingly, " + "as it will be removed in the O release.") + versionutils.report_deprecated_feature(LOG, msg) diff --git a/keystone-moon/keystone/contrib/moon/backends/sql.py b/keystone-moon/keystone/contrib/moon/backends/sql.py index 2b7258ea..1ddb474e 100644 --- a/keystone-moon/keystone/contrib/moon/backends/sql.py +++ b/keystone-moon/keystone/contrib/moon/backends/sql.py @@ -324,13 +324,13 @@ class TenantConnector(TenantDriver): base[key] = update[key] def get_tenants_dict(self): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(Tenant) tenants = query.all() return {tenant.id: tenant.tenant for tenant in tenants} def add_tenant_dict(self, tenant_id, tenant_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: new_ref = Tenant.from_dict( { "id": tenant_id, @@ -341,14 +341,14 @@ class TenantConnector(TenantDriver): return {new_ref.id: new_ref.tenant} def del_tenant(self, tenant_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(Tenant) query = query.filter_by(id=tenant_id) tenant = query.first() session.delete(tenant) def set_tenant_dict(self, tenant_id, tenant_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(Tenant) query = query.filter_by(id=tenant_id) ref = query.first() @@ -363,13 +363,13 @@ class IntraExtensionConnector(IntraExtensionDriver): # IntraExtension functions def get_intra_extensions_dict(self): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(IntraExtension) ref_list = query.all() return {_ref.id: _ref.intra_extension for _ref in ref_list} def del_intra_extension(self, intra_extension_id): - with sql.transaction() as session: + with sql.session_for_write() as session: ref = session.query(IntraExtension).get(intra_extension_id) # Must delete all references to that IntraExtension for _object in __all_objects__: @@ -378,11 +378,11 @@ class IntraExtensionConnector(IntraExtensionDriver): _refs = query.all() for _ref in _refs: session.delete(_ref) - session.flush() + # session.flush() session.delete(ref) def set_intra_extension_dict(self, intra_extension_id, intra_extension_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(IntraExtension) query = query.filter_by(id=intra_extension_id) ref = query.first() @@ -399,19 +399,20 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in IntraExtension.attributes: if attr != 'id': setattr(ref, attr, getattr(new_intra_extension, attr)) + # session.flush() return IntraExtension.to_dict(ref) # Getter and Setter for subject_category def get_subject_categories_dict(self, intra_extension_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(SubjectCategory) query = query.filter_by(intra_extension_id=intra_extension_id) ref_list = query.all() return {_ref.id: _ref.subject_category for _ref in ref_list} def set_subject_category_dict(self, intra_extension_id, subject_category_id, subject_category_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(SubjectCategory) query = query.filter_by(intra_extension_id=intra_extension_id, id=subject_category_id) ref = query.first() @@ -429,11 +430,11 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in SubjectCategory.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # # session.flush() return {subject_category_id: SubjectCategory.to_dict(ref)['subject_category']} def del_subject_category(self, intra_extension_id, subject_category_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(SubjectCategory) query = query.filter_by(intra_extension_id=intra_extension_id, id=subject_category_id) ref = query.first() @@ -443,14 +444,14 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for object_category def get_object_categories_dict(self, intra_extension_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(ObjectCategory) query = query.filter_by(intra_extension_id=intra_extension_id) ref_list = query.all() return {_ref.id: _ref.object_category for _ref in ref_list} def set_object_category_dict(self, intra_extension_id, object_category_id, object_category_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(ObjectCategory) query = query.filter_by(intra_extension_id=intra_extension_id, id=object_category_id) ref = query.first() @@ -468,11 +469,11 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in ObjectCategory.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return {object_category_id: ObjectCategory.to_dict(ref)['object_category']} def del_object_category(self, intra_extension_id, object_category_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(ObjectCategory) query = query.filter_by(intra_extension_id=intra_extension_id, id=object_category_id) ref = query.first() @@ -482,14 +483,14 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for action_category def get_action_categories_dict(self, intra_extension_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(ActionCategory) query = query.filter_by(intra_extension_id=intra_extension_id) ref_list = query.all() return {_ref.id: _ref.action_category for _ref in ref_list} def set_action_category_dict(self, intra_extension_id, action_category_id, action_category_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(ActionCategory) query = query.filter_by(intra_extension_id=intra_extension_id, id=action_category_id) ref = query.first() @@ -507,11 +508,11 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in ActionCategory.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return {action_category_id: ActionCategory.to_dict(ref)['action_category']} def del_action_category(self, intra_extension_id, action_category_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(ActionCategory) query = query.filter_by(intra_extension_id=intra_extension_id, id=action_category_id) ref = query.first() @@ -521,14 +522,14 @@ class IntraExtensionConnector(IntraExtensionDriver): # Perimeter def get_subjects_dict(self, intra_extension_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(Subject) query = query.filter_by(intra_extension_id=intra_extension_id) ref_list = query.all() return {_ref.id: _ref.subject for _ref in ref_list} def set_subject_dict(self, intra_extension_id, subject_id, subject_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(Subject) query = query.filter_by(intra_extension_id=intra_extension_id, id=subject_id) ref = query.first() @@ -548,25 +549,25 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in Subject.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return {subject_id: Subject.to_dict(ref)['subject']} def del_subject(self, intra_extension_id, subject_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(Subject) query = query.filter_by(intra_extension_id=intra_extension_id, id=subject_id) ref = query.first() session.delete(ref) def get_objects_dict(self, intra_extension_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(Object) query = query.filter_by(intra_extension_id=intra_extension_id) ref_list = query.all() return {_ref.id: _ref.object for _ref in ref_list} def set_object_dict(self, intra_extension_id, object_id, object_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(Object) query = query.filter_by(intra_extension_id=intra_extension_id, id=object_id) ref = query.first() @@ -584,25 +585,25 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in Object.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return {object_id: Object.to_dict(ref)['object']} def del_object(self, intra_extension_id, object_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(Object) query = query.filter_by(intra_extension_id=intra_extension_id, id=object_id) ref = query.first() session.delete(ref) def get_actions_dict(self, intra_extension_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(Action) query = query.filter_by(intra_extension_id=intra_extension_id) ref_list = query.all() return {_ref.id: _ref.action for _ref in ref_list} def set_action_dict(self, intra_extension_id, action_id, action_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(Action) query = query.filter_by(intra_extension_id=intra_extension_id, id=action_id) ref = query.first() @@ -620,11 +621,11 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in Action.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return {action_id: Action.to_dict(ref)['action']} def del_action(self, intra_extension_id, action_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(Action) query = query.filter_by(intra_extension_id=intra_extension_id, id=action_id) ref = query.first() @@ -633,14 +634,14 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for subject_scope def get_subject_scopes_dict(self, intra_extension_id, subject_category_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(SubjectScope) query = query.filter_by(intra_extension_id=intra_extension_id, subject_category_id=subject_category_id) ref_list = query.all() return {_ref.id: _ref.subject_scope for _ref in ref_list} def set_subject_scope_dict(self, intra_extension_id, subject_category_id, subject_scope_id, subject_scope_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(SubjectScope) query = query.filter_by(intra_extension_id=intra_extension_id, subject_category_id=subject_category_id, id=subject_scope_id) ref = query.first() @@ -659,11 +660,11 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in Subject.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return {subject_scope_id: SubjectScope.to_dict(ref)['subject_scope']} def del_subject_scope(self, intra_extension_id, subject_category_id, subject_scope_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(SubjectScope) if not subject_category_id or not subject_scope_id: query = query.filter_by(intra_extension_id=intra_extension_id) @@ -677,14 +678,14 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for object_category_scope def get_object_scopes_dict(self, intra_extension_id, object_category_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(ObjectScope) query = query.filter_by(intra_extension_id=intra_extension_id, object_category_id=object_category_id) ref_list = query.all() return {_ref.id: _ref.object_scope for _ref in ref_list} def set_object_scope_dict(self, intra_extension_id, object_category_id, object_scope_id, object_scope_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(ObjectScope) query = query.filter_by(intra_extension_id=intra_extension_id, object_category_id=object_category_id, id=object_scope_id) ref = query.first() @@ -703,11 +704,11 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in Object.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return {object_scope_id: ObjectScope.to_dict(ref)['object_scope']} def del_object_scope(self, intra_extension_id, object_category_id, object_scope_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(ObjectScope) if not object_category_id or not object_scope_id: query = query.filter_by(intra_extension_id=intra_extension_id) @@ -721,14 +722,14 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for action_scope def get_action_scopes_dict(self, intra_extension_id, action_category_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(ActionScope) query = query.filter_by(intra_extension_id=intra_extension_id, action_category_id=action_category_id) ref_list = query.all() return {_ref.id: _ref.action_scope for _ref in ref_list} def set_action_scope_dict(self, intra_extension_id, action_category_id, action_scope_id, action_scope_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(ActionScope) query = query.filter_by(intra_extension_id=intra_extension_id, action_category_id=action_category_id, id=action_scope_id) ref = query.first() @@ -747,11 +748,11 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in Action.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return {action_scope_id: ActionScope.to_dict(ref)['action_scope']} def del_action_scope(self, intra_extension_id, action_category_id, action_scope_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(ActionScope) if not action_category_id or not action_scope_id: query = query.filter_by(intra_extension_id=intra_extension_id) @@ -765,7 +766,7 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for subject_category_assignment def get_subject_assignment_list(self, intra_extension_id, subject_id, subject_category_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(SubjectAssignment) if not subject_id or not subject_category_id or not subject_category_id: query = query.filter_by(intra_extension_id=intra_extension_id) @@ -779,7 +780,7 @@ class IntraExtensionConnector(IntraExtensionDriver): return list(ref.subject_assignment) def set_subject_assignment_list(self, intra_extension_id, subject_id, subject_category_id, subject_assignment_list=[]): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(SubjectAssignment) query = query.filter_by(intra_extension_id=intra_extension_id, subject_id=subject_id, subject_category_id=subject_category_id) ref = query.first() @@ -799,7 +800,7 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in SubjectAssignment.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return subject_assignment_list def add_subject_assignment_list(self, intra_extension_id, subject_id, subject_category_id, subject_scope_id): @@ -810,9 +811,10 @@ class IntraExtensionConnector(IntraExtensionDriver): def del_subject_assignment(self, intra_extension_id, subject_id, subject_category_id, subject_scope_id): if not subject_id or not subject_category_id or not subject_category_id: - with sql.transaction() as session: + with sql.session_for_write() as session: for ref in self.get_subject_assignment_list(intra_extension_id, None, None): session.delete(ref) + session.flush() return new_subject_assignment_list = self.get_subject_assignment_list(intra_extension_id, subject_id, subject_category_id) new_subject_assignment_list.remove(subject_scope_id) @@ -821,7 +823,7 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for object_category_assignment def get_object_assignment_list(self, intra_extension_id, object_id, object_category_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(ObjectAssignment) if not object_id or not object_category_id or not object_category_id: query = query.filter_by(intra_extension_id=intra_extension_id) @@ -835,7 +837,7 @@ class IntraExtensionConnector(IntraExtensionDriver): return list(ref.object_assignment) def set_object_assignment_list(self, intra_extension_id, object_id, object_category_id, object_assignment_list=[]): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(ObjectAssignment) query = query.filter_by(intra_extension_id=intra_extension_id, object_id=object_id, object_category_id=object_category_id) ref = query.first() @@ -854,7 +856,7 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in ObjectAssignment.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return self.get_object_assignment_list(intra_extension_id, object_id, object_category_id) def add_object_assignment_list(self, intra_extension_id, object_id, object_category_id, object_scope_id): @@ -865,9 +867,10 @@ class IntraExtensionConnector(IntraExtensionDriver): def del_object_assignment(self, intra_extension_id, object_id, object_category_id, object_scope_id): if not object_id or not object_category_id or not object_category_id: - with sql.transaction() as session: + with sql.session_for_write() as session: for ref in self.get_object_assignment_list(intra_extension_id, None, None): session.delete(ref) + session.flush() return new_object_assignment_list = self.get_object_assignment_list(intra_extension_id, object_id, object_category_id) new_object_assignment_list.remove(object_scope_id) @@ -876,7 +879,7 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for action_category_assignment def get_action_assignment_list(self, intra_extension_id, action_id, action_category_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(ActionAssignment) if not action_id or not action_category_id or not action_category_id: query = query.filter_by(intra_extension_id=intra_extension_id) @@ -890,7 +893,7 @@ class IntraExtensionConnector(IntraExtensionDriver): return list(ref.action_assignment) def set_action_assignment_list(self, intra_extension_id, action_id, action_category_id, action_assignment_list=[]): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(ActionAssignment) query = query.filter_by(intra_extension_id=intra_extension_id, action_id=action_id, action_category_id=action_category_id) ref = query.first() @@ -909,7 +912,7 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in ActionAssignment.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return self.get_action_assignment_list(intra_extension_id, action_id, action_category_id) def add_action_assignment_list(self, intra_extension_id, action_id, action_category_id, action_scope_id): @@ -920,9 +923,10 @@ class IntraExtensionConnector(IntraExtensionDriver): def del_action_assignment(self, intra_extension_id, action_id, action_category_id, action_scope_id): if not action_id or not action_category_id or not action_category_id: - with sql.transaction() as session: + with sql.session_for_write() as session: for ref in self.get_action_assignment_list(intra_extension_id, None, None): session.delete(ref) + session.flush() return new_action_assignment_list = self.get_action_assignment_list(intra_extension_id, action_id, action_category_id) new_action_assignment_list.remove(action_scope_id) @@ -931,7 +935,7 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for sub_meta_rule def get_aggregation_algorithm_id(self, intra_extension_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(IntraExtension) query = query.filter_by(id=intra_extension_id) ref = query.first() @@ -941,18 +945,18 @@ class IntraExtensionConnector(IntraExtensionDriver): return "" def set_aggregation_algorithm_id(self, intra_extension_id, aggregation_algorithm_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(IntraExtension) query = query.filter_by(id=intra_extension_id) ref = query.first() intra_extension_dict = dict(ref.intra_extension) intra_extension_dict["aggregation_algorithm"] = aggregation_algorithm_id setattr(ref, "intra_extension", intra_extension_dict) - session.flush() + # session.flush() return {"aggregation_algorithm": ref.intra_extension["aggregation_algorithm"]} def del_aggregation_algorithm(self, intra_extension_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(IntraExtension) query = query.filter_by(id=intra_extension_id) ref = query.first() @@ -964,14 +968,14 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for sub_meta_rule def get_sub_meta_rules_dict(self, intra_extension_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(SubMetaRule) query = query.filter_by(intra_extension_id=intra_extension_id) ref_list = query.all() return {_ref.id: _ref.sub_meta_rule for _ref in ref_list} def set_sub_meta_rule_dict(self, intra_extension_id, sub_meta_rule_id, sub_meta_rule_dict): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(SubMetaRule) query = query.filter_by(intra_extension_id=intra_extension_id, id=sub_meta_rule_id) ref = query.first() @@ -991,11 +995,11 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in SubMetaRule.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return self.get_sub_meta_rules_dict(intra_extension_id) def del_sub_meta_rule(self, intra_extension_id, sub_meta_rule_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(SubMetaRule) query = query.filter_by(intra_extension_id=intra_extension_id, id=sub_meta_rule_id) ref = query.first() @@ -1004,14 +1008,14 @@ class IntraExtensionConnector(IntraExtensionDriver): # Getter and Setter for rules def get_rules_dict(self, intra_extension_id, sub_meta_rule_id): - with sql.transaction() as session: + with sql.session_for_read() as session: query = session.query(Rule) query = query.filter_by(intra_extension_id=intra_extension_id, sub_meta_rule_id=sub_meta_rule_id) ref_list = query.all() return {_ref.id: _ref.rule for _ref in ref_list} def set_rule_dict(self, intra_extension_id, sub_meta_rule_id, rule_id, rule_list): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(Rule) query = query.filter_by(intra_extension_id=intra_extension_id, sub_meta_rule_id=sub_meta_rule_id, id=rule_id) ref = query.first() @@ -1030,11 +1034,11 @@ class IntraExtensionConnector(IntraExtensionDriver): for attr in Rule.attributes: if attr != 'id': setattr(ref, attr, getattr(new_ref, attr)) - session.flush() + # session.flush() return {rule_id: ref.rule} def del_rule(self, intra_extension_id, sub_meta_rule_id, rule_id): - with sql.transaction() as session: + with sql.session_for_write() as session: query = session.query(Rule) query = query.filter_by(intra_extension_id=intra_extension_id, sub_meta_rule_id=sub_meta_rule_id, id=rule_id) ref = query.first() @@ -1074,19 +1078,19 @@ class IntraExtensionConnector(IntraExtensionDriver): # class InterExtensionConnector(InterExtensionDriver): # # def get_inter_extensions(self): -# with sql.transaction() as session: +# with sql.session_for_read() as session: # query = session.query(InterExtension.id) # interextensions = query.all() # return [interextension.id for interextension in interextensions] # # def create_inter_extensions(self, inter_id, inter_extension): -# with sql.transaction() as session: +# with sql.session_for_read() as session: # ie_ref = InterExtension.from_dict(inter_extension) # session.add(ie_ref) # return InterExtension.to_dict(ie_ref) # # def get_inter_extension(self, uuid): -# with sql.transaction() as session: +# with sql.session_for_read() as session: # query = session.query(InterExtension) # query = query.filter_by(id=uuid) # ref = query.first() @@ -1095,7 +1099,7 @@ class IntraExtensionConnector(IntraExtensionDriver): # return ref.to_dict() # # def delete_inter_extensions(self, inter_extension_id): -# with sql.transaction() as session: +# with sql.session_for_read() as session: # ref = session.query(InterExtension).get(inter_extension_id) # session.delete(ref) diff --git a/keystone-moon/keystone/contrib/moon/core.py b/keystone-moon/keystone/contrib/moon/core.py index 53b81574..83657317 100644 --- a/keystone-moon/keystone/contrib/moon/core.py +++ b/keystone-moon/keystone/contrib/moon/core.py @@ -325,7 +325,7 @@ class ConfigurationManager(manager.Manager): @enforce("read", "sub_meta_rule_algorithms") def get_sub_meta_rule_algorithm_id_from_name(self, sub_meta_rule_algorithm_name): - sub_meta_rule_algorithms_dict = self.driver.get_sub_meta_rule_algorithms_dict() + sub_meta_rule_algorithms_dict = self.configuration_api.get_sub_meta_rule_algorithms_dict() for sub_meta_rule_algorithm_id in sub_meta_rule_algorithms_dict: if sub_meta_rule_algorithms_dict[sub_meta_rule_algorithm_id]['name'] == sub_meta_rule_algorithm_name: return sub_meta_rule_algorithm_id @@ -1218,6 +1218,7 @@ class IntraExtensionManager(manager.Manager): ie_dict["genre"] = "admin" ie_dict["description"] = "policy_root" ref = self.driver.set_intra_extension_dict(ie_dict['id'], ie_dict) + logging.debug("Creation of root IE: {}".format(ref)) self.moonlog_api.debug("Creation of root IE: {}".format(ref)) # read the template given by "model" and populate default variables @@ -2025,6 +2026,8 @@ class IntraExtensionManager(manager.Manager): @enforce(("read", "write"), "sub_meta_rules") @enforce("write", "rules") def add_sub_meta_rule_dict(self, user_id, intra_extension_id, sub_meta_rule_dict): + LOG.info("add_sub_meta_rule_dict = {}".format(self.driver.get_sub_meta_rules_dict(intra_extension_id))) + LOG.info("add_sub_meta_rule_dict = {}".format(sub_meta_rule_dict)) sub_meta_rules_dict = self.driver.get_sub_meta_rules_dict(intra_extension_id) for _sub_meta_rule_id in sub_meta_rules_dict: if sub_meta_rule_dict['name'] == sub_meta_rules_dict[_sub_meta_rule_id]["name"]: @@ -2065,6 +2068,8 @@ class IntraExtensionManager(manager.Manager): @enforce(("read", "write"), "sub_meta_rules") @enforce("write", "rules") def set_sub_meta_rule_dict(self, user_id, intra_extension_id, sub_meta_rule_id, sub_meta_rule_dict): + LOG.info("set_sub_meta_rule_dict = {}".format(self.driver.get_sub_meta_rules_dict(intra_extension_id))) + LOG.info("set_sub_meta_rule_dict = {} {}".format(sub_meta_rule_id, sub_meta_rule_dict)) if sub_meta_rule_id not in self.driver.get_sub_meta_rules_dict(intra_extension_id): raise SubMetaRuleUnknown() for attribute in sub_meta_rule_dict.keys(): diff --git a/keystone-moon/keystone/contrib/oauth1/__init__.py b/keystone-moon/keystone/contrib/oauth1/__init__.py index 8cab2498..e69de29b 100644 --- a/keystone-moon/keystone/contrib/oauth1/__init__.py +++ b/keystone-moon/keystone/contrib/oauth1/__init__.py @@ -1,15 +0,0 @@ -# Copyright 2013 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.contrib.oauth1.core import * # noqa diff --git a/keystone-moon/keystone/contrib/oauth1/backends/sql.py b/keystone-moon/keystone/contrib/oauth1/backends/sql.py index a7876756..31b6ce3b 100644 --- a/keystone-moon/keystone/contrib/oauth1/backends/sql.py +++ b/keystone-moon/keystone/contrib/oauth1/backends/sql.py @@ -12,261 +12,19 @@ # License for the specific language governing permissions and limitations # under the License. -import datetime -import random as _random -import uuid +from oslo_log import versionutils -from oslo_serialization import jsonutils -from oslo_utils import timeutils +from keystone.oauth1.backends import sql -from keystone.common import sql -from keystone.common import utils -from keystone.contrib.oauth1 import core -from keystone import exception -from keystone.i18n import _ +_OLD = "keystone.contrib.oauth1.backends.sql.OAuth1" +_NEW = "sql" -random = _random.SystemRandom() +class OAuth1(sql.OAuth1): -class Consumer(sql.ModelBase, sql.DictBase): - __tablename__ = 'consumer' - attributes = ['id', 'description', 'secret'] - id = sql.Column(sql.String(64), primary_key=True, nullable=False) - description = sql.Column(sql.String(64), nullable=True) - secret = sql.Column(sql.String(64), nullable=False) - extra = sql.Column(sql.JsonBlob(), nullable=False) - - -class RequestToken(sql.ModelBase, sql.DictBase): - __tablename__ = 'request_token' - attributes = ['id', 'request_secret', - 'verifier', 'authorizing_user_id', 'requested_project_id', - 'role_ids', 'consumer_id', 'expires_at'] - id = sql.Column(sql.String(64), primary_key=True, nullable=False) - request_secret = sql.Column(sql.String(64), nullable=False) - verifier = sql.Column(sql.String(64), nullable=True) - authorizing_user_id = sql.Column(sql.String(64), nullable=True) - requested_project_id = sql.Column(sql.String(64), nullable=False) - role_ids = sql.Column(sql.Text(), nullable=True) - consumer_id = sql.Column(sql.String(64), sql.ForeignKey('consumer.id'), - nullable=False, index=True) - expires_at = sql.Column(sql.String(64), nullable=True) - - @classmethod - def from_dict(cls, user_dict): - return cls(**user_dict) - - def to_dict(self): - return dict(self.items()) - - -class AccessToken(sql.ModelBase, sql.DictBase): - __tablename__ = 'access_token' - attributes = ['id', 'access_secret', 'authorizing_user_id', - 'project_id', 'role_ids', 'consumer_id', - 'expires_at'] - id = sql.Column(sql.String(64), primary_key=True, nullable=False) - access_secret = sql.Column(sql.String(64), nullable=False) - authorizing_user_id = sql.Column(sql.String(64), nullable=False, - index=True) - project_id = sql.Column(sql.String(64), nullable=False) - role_ids = sql.Column(sql.Text(), nullable=False) - consumer_id = sql.Column(sql.String(64), sql.ForeignKey('consumer.id'), - nullable=False) - expires_at = sql.Column(sql.String(64), nullable=True) - - @classmethod - def from_dict(cls, user_dict): - return cls(**user_dict) - - def to_dict(self): - return dict(self.items()) - - -class OAuth1(object): - def _get_consumer(self, session, consumer_id): - consumer_ref = session.query(Consumer).get(consumer_id) - if consumer_ref is None: - raise exception.NotFound(_('Consumer not found')) - return consumer_ref - - def get_consumer_with_secret(self, consumer_id): - session = sql.get_session() - consumer_ref = self._get_consumer(session, consumer_id) - return consumer_ref.to_dict() - - def get_consumer(self, consumer_id): - return core.filter_consumer( - self.get_consumer_with_secret(consumer_id)) - - def create_consumer(self, consumer): - consumer['secret'] = uuid.uuid4().hex - if not consumer.get('description'): - consumer['description'] = None - session = sql.get_session() - with session.begin(): - consumer_ref = Consumer.from_dict(consumer) - session.add(consumer_ref) - return consumer_ref.to_dict() - - def _delete_consumer(self, session, consumer_id): - consumer_ref = self._get_consumer(session, consumer_id) - session.delete(consumer_ref) - - def _delete_request_tokens(self, session, consumer_id): - q = session.query(RequestToken) - req_tokens = q.filter_by(consumer_id=consumer_id) - req_tokens_list = set([x.id for x in req_tokens]) - for token_id in req_tokens_list: - token_ref = self._get_request_token(session, token_id) - session.delete(token_ref) - - def _delete_access_tokens(self, session, consumer_id): - q = session.query(AccessToken) - acc_tokens = q.filter_by(consumer_id=consumer_id) - acc_tokens_list = set([x.id for x in acc_tokens]) - for token_id in acc_tokens_list: - token_ref = self._get_access_token(session, token_id) - session.delete(token_ref) - - def delete_consumer(self, consumer_id): - session = sql.get_session() - with session.begin(): - self._delete_request_tokens(session, consumer_id) - self._delete_access_tokens(session, consumer_id) - self._delete_consumer(session, consumer_id) - - def list_consumers(self): - session = sql.get_session() - cons = session.query(Consumer) - return [core.filter_consumer(x.to_dict()) for x in cons] - - def update_consumer(self, consumer_id, consumer): - session = sql.get_session() - with session.begin(): - consumer_ref = self._get_consumer(session, consumer_id) - old_consumer_dict = consumer_ref.to_dict() - old_consumer_dict.update(consumer) - new_consumer = Consumer.from_dict(old_consumer_dict) - consumer_ref.description = new_consumer.description - consumer_ref.extra = new_consumer.extra - return core.filter_consumer(consumer_ref.to_dict()) - - def create_request_token(self, consumer_id, project_id, token_duration, - request_token_id=None, request_token_secret=None): - if request_token_id is None: - request_token_id = uuid.uuid4().hex - if request_token_secret is None: - request_token_secret = uuid.uuid4().hex - expiry_date = None - if token_duration: - now = timeutils.utcnow() - future = now + datetime.timedelta(seconds=token_duration) - expiry_date = utils.isotime(future, subsecond=True) - - ref = {} - ref['id'] = request_token_id - ref['request_secret'] = request_token_secret - ref['verifier'] = None - ref['authorizing_user_id'] = None - ref['requested_project_id'] = project_id - ref['role_ids'] = None - ref['consumer_id'] = consumer_id - ref['expires_at'] = expiry_date - session = sql.get_session() - with session.begin(): - token_ref = RequestToken.from_dict(ref) - session.add(token_ref) - return token_ref.to_dict() - - def _get_request_token(self, session, request_token_id): - token_ref = session.query(RequestToken).get(request_token_id) - if token_ref is None: - raise exception.NotFound(_('Request token not found')) - return token_ref - - def get_request_token(self, request_token_id): - session = sql.get_session() - token_ref = self._get_request_token(session, request_token_id) - return token_ref.to_dict() - - def authorize_request_token(self, request_token_id, user_id, - role_ids): - session = sql.get_session() - with session.begin(): - token_ref = self._get_request_token(session, request_token_id) - token_dict = token_ref.to_dict() - token_dict['authorizing_user_id'] = user_id - token_dict['verifier'] = ''.join(random.sample(core.VERIFIER_CHARS, - 8)) - token_dict['role_ids'] = jsonutils.dumps(role_ids) - - new_token = RequestToken.from_dict(token_dict) - for attr in RequestToken.attributes: - if (attr == 'authorizing_user_id' or attr == 'verifier' - or attr == 'role_ids'): - setattr(token_ref, attr, getattr(new_token, attr)) - - return token_ref.to_dict() - - def create_access_token(self, request_token_id, token_duration, - access_token_id=None, access_token_secret=None): - if access_token_id is None: - access_token_id = uuid.uuid4().hex - if access_token_secret is None: - access_token_secret = uuid.uuid4().hex - session = sql.get_session() - with session.begin(): - req_token_ref = self._get_request_token(session, request_token_id) - token_dict = req_token_ref.to_dict() - - expiry_date = None - if token_duration: - now = timeutils.utcnow() - future = now + datetime.timedelta(seconds=token_duration) - expiry_date = utils.isotime(future, subsecond=True) - - # add Access Token - ref = {} - ref['id'] = access_token_id - ref['access_secret'] = access_token_secret - ref['authorizing_user_id'] = token_dict['authorizing_user_id'] - ref['project_id'] = token_dict['requested_project_id'] - ref['role_ids'] = token_dict['role_ids'] - ref['consumer_id'] = token_dict['consumer_id'] - ref['expires_at'] = expiry_date - token_ref = AccessToken.from_dict(ref) - session.add(token_ref) - - # remove request token, it's been used - session.delete(req_token_ref) - - return token_ref.to_dict() - - def _get_access_token(self, session, access_token_id): - token_ref = session.query(AccessToken).get(access_token_id) - if token_ref is None: - raise exception.NotFound(_('Access token not found')) - return token_ref - - def get_access_token(self, access_token_id): - session = sql.get_session() - token_ref = self._get_access_token(session, access_token_id) - return token_ref.to_dict() - - def list_access_tokens(self, user_id): - session = sql.get_session() - q = session.query(AccessToken) - user_auths = q.filter_by(authorizing_user_id=user_id) - return [core.filter_token(x.to_dict()) for x in user_auths] - - def delete_access_token(self, user_id, access_token_id): - session = sql.get_session() - with session.begin(): - token_ref = self._get_access_token(session, access_token_id) - token_dict = token_ref.to_dict() - if token_dict['authorizing_user_id'] != user_id: - raise exception.Unauthorized(_('User IDs do not match')) - - session.delete(token_ref) + @versionutils.deprecated(versionutils.deprecated.MITAKA, + in_favor_of=_NEW, + what=_OLD) + def __init__(self, *args, **kwargs): + super(OAuth1, self).__init__(*args, **kwargs) diff --git a/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/001_add_oauth_tables.py b/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/001_add_oauth_tables.py index e0305351..fe0212d7 100644 --- a/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/001_add_oauth_tables.py +++ b/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/001_add_oauth_tables.py @@ -12,46 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - # Upgrade operations go here. Don't create your own engine; bind - # migrate_engine to your metadata - meta = sql.MetaData() - meta.bind = migrate_engine - - consumer_table = sql.Table( - 'consumer', - meta, - sql.Column('id', sql.String(64), primary_key=True, nullable=False), - sql.Column('description', sql.String(64), nullable=False), - sql.Column('secret', sql.String(64), nullable=False), - sql.Column('extra', sql.Text(), nullable=False)) - consumer_table.create(migrate_engine, checkfirst=True) - - request_token_table = sql.Table( - 'request_token', - meta, - sql.Column('id', sql.String(64), primary_key=True, nullable=False), - sql.Column('request_secret', sql.String(64), nullable=False), - sql.Column('verifier', sql.String(64), nullable=True), - sql.Column('authorizing_user_id', sql.String(64), nullable=True), - sql.Column('requested_project_id', sql.String(64), nullable=False), - sql.Column('requested_roles', sql.Text(), nullable=False), - sql.Column('consumer_id', sql.String(64), nullable=False, index=True), - sql.Column('expires_at', sql.String(64), nullable=True)) - request_token_table.create(migrate_engine, checkfirst=True) - - access_token_table = sql.Table( - 'access_token', - meta, - sql.Column('id', sql.String(64), primary_key=True, nullable=False), - sql.Column('access_secret', sql.String(64), nullable=False), - sql.Column('authorizing_user_id', sql.String(64), - nullable=False, index=True), - sql.Column('project_id', sql.String(64), nullable=False), - sql.Column('requested_roles', sql.Text(), nullable=False), - sql.Column('consumer_id', sql.String(64), nullable=False), - sql.Column('expires_at', sql.String(64), nullable=True)) - access_token_table.create(migrate_engine, checkfirst=True) + raise exception.MigrationMovedFailure(extension='oauth1') diff --git a/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/002_fix_oauth_tables_fk.py b/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/002_fix_oauth_tables_fk.py index 174120e8..fe0212d7 100644 --- a/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/002_fix_oauth_tables_fk.py +++ b/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/002_fix_oauth_tables_fk.py @@ -12,26 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql - -from keystone.common.sql import migration_helpers +from keystone import exception def upgrade(migrate_engine): - # Upgrade operations go here. Don't create your own engine; bind - # migrate_engine to your metadata - meta = sql.MetaData() - meta.bind = migrate_engine - - consumer_table = sql.Table('consumer', meta, autoload=True) - request_token_table = sql.Table('request_token', meta, autoload=True) - access_token_table = sql.Table('access_token', meta, autoload=True) - - constraints = [{'table': request_token_table, - 'fk_column': 'consumer_id', - 'ref_column': consumer_table.c.id}, - {'table': access_token_table, - 'fk_column': 'consumer_id', - 'ref_column': consumer_table.c.id}] - if meta.bind != 'sqlite': - migration_helpers.add_constraints(constraints) + raise exception.MigrationMovedFailure(extension='oauth1') diff --git a/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/003_consumer_description_nullalbe.py b/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/003_consumer_description_nullalbe.py index cf6ffb7c..fe0212d7 100644 --- a/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/003_consumer_description_nullalbe.py +++ b/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/003_consumer_description_nullalbe.py @@ -12,11 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - user_table = sql.Table('consumer', meta, autoload=True) - user_table.c.description.alter(nullable=True) + raise exception.MigrationMovedFailure(extension='oauth1') diff --git a/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/004_request_token_roles_nullable.py b/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/004_request_token_roles_nullable.py index 6934eb6f..fe0212d7 100644 --- a/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/004_request_token_roles_nullable.py +++ b/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/004_request_token_roles_nullable.py @@ -12,14 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - request_token_table = sql.Table('request_token', meta, autoload=True) - request_token_table.c.requested_roles.alter(nullable=True) - request_token_table.c.requested_roles.alter(name="role_ids") - access_token_table = sql.Table('access_token', meta, autoload=True) - access_token_table.c.requested_roles.alter(name="role_ids") + raise exception.MigrationMovedFailure(extension='oauth1') diff --git a/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/005_consumer_id_index.py b/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/005_consumer_id_index.py index 0627d21c..a4681e16 100644 --- a/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/005_consumer_id_index.py +++ b/keystone-moon/keystone/contrib/oauth1/migrate_repo/versions/005_consumer_id_index.py @@ -13,23 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sa +from keystone import exception def upgrade(migrate_engine): - - if migrate_engine.name == 'mysql': - meta = sa.MetaData(bind=migrate_engine) - table = sa.Table('access_token', meta, autoload=True) - - # NOTE(i159): MySQL requires indexes on referencing columns, and those - # indexes create automatically. That those indexes will have different - # names, depending on version of MySQL used. We shoud make this naming - # consistent, by reverting index name to a consistent condition. - if any(i for i in table.indexes if - list(i.columns.keys()) == ['consumer_id'] - and i.name != 'consumer_id'): - # NOTE(i159): by this action will be made re-creation of an index - # with the new name. This can be considered as renaming under the - # MySQL rules. - sa.Index('consumer_id', table.c.consumer_id).create() + raise exception.MigrationMovedFailure(extension='oauth1') diff --git a/keystone-moon/keystone/contrib/oauth1/routers.py b/keystone-moon/keystone/contrib/oauth1/routers.py index 4b772eb5..42a26c10 100644 --- a/keystone-moon/keystone/contrib/oauth1/routers.py +++ b/keystone-moon/keystone/contrib/oauth1/routers.py @@ -12,143 +12,22 @@ # License for the specific language governing permissions and limitations # under the License. -import functools +from oslo_log import log +from oslo_log import versionutils -from keystone.common import json_home from keystone.common import wsgi -from keystone.contrib.oauth1 import controllers +from keystone.i18n import _ -build_resource_relation = functools.partial( - json_home.build_v3_extension_resource_relation, - extension_name='OS-OAUTH1', extension_version='1.0') +LOG = log.getLogger(__name__) -build_parameter_relation = functools.partial( - json_home.build_v3_extension_parameter_relation, - extension_name='OS-OAUTH1', extension_version='1.0') -ACCESS_TOKEN_ID_PARAMETER_RELATION = build_parameter_relation( - parameter_name='access_token_id') +class OAuth1Extension(wsgi.Middleware): - -class OAuth1Extension(wsgi.V3ExtensionRouter): - """API Endpoints for the OAuth1 extension. - - The goal of this extension is to allow third-party service providers - to acquire tokens with a limited subset of a user's roles for acting - on behalf of that user. This is done using an oauth-similar flow and - api. - - The API looks like:: - - # Basic admin-only consumer crud - POST /OS-OAUTH1/consumers - GET /OS-OAUTH1/consumers - PATCH /OS-OAUTH1/consumers/{consumer_id} - GET /OS-OAUTH1/consumers/{consumer_id} - DELETE /OS-OAUTH1/consumers/{consumer_id} - - # User access token crud - GET /users/{user_id}/OS-OAUTH1/access_tokens - GET /users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id} - GET /users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}/roles - GET /users/{user_id}/OS-OAUTH1/access_tokens - /{access_token_id}/roles/{role_id} - DELETE /users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id} - - # OAuth interfaces - POST /OS-OAUTH1/request_token # create a request token - PUT /OS-OAUTH1/authorize # authorize a request token - POST /OS-OAUTH1/access_token # create an access token - - """ - - def add_routes(self, mapper): - consumer_controller = controllers.ConsumerCrudV3() - access_token_controller = controllers.AccessTokenCrudV3() - access_token_roles_controller = controllers.AccessTokenRolesV3() - oauth_controller = controllers.OAuthControllerV3() - - # basic admin-only consumer crud - self._add_resource( - mapper, consumer_controller, - path='/OS-OAUTH1/consumers', - get_action='list_consumers', - post_action='create_consumer', - rel=build_resource_relation(resource_name='consumers')) - self._add_resource( - mapper, consumer_controller, - path='/OS-OAUTH1/consumers/{consumer_id}', - get_action='get_consumer', - patch_action='update_consumer', - delete_action='delete_consumer', - rel=build_resource_relation(resource_name='consumer'), - path_vars={ - 'consumer_id': - build_parameter_relation(parameter_name='consumer_id'), - }) - - # user access token crud - self._add_resource( - mapper, access_token_controller, - path='/users/{user_id}/OS-OAUTH1/access_tokens', - get_action='list_access_tokens', - rel=build_resource_relation(resource_name='user_access_tokens'), - path_vars={ - 'user_id': json_home.Parameters.USER_ID, - }) - self._add_resource( - mapper, access_token_controller, - path='/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}', - get_action='get_access_token', - delete_action='delete_access_token', - rel=build_resource_relation(resource_name='user_access_token'), - path_vars={ - 'access_token_id': ACCESS_TOKEN_ID_PARAMETER_RELATION, - 'user_id': json_home.Parameters.USER_ID, - }) - self._add_resource( - mapper, access_token_roles_controller, - path='/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}/' - 'roles', - get_action='list_access_token_roles', - rel=build_resource_relation( - resource_name='user_access_token_roles'), - path_vars={ - 'access_token_id': ACCESS_TOKEN_ID_PARAMETER_RELATION, - 'user_id': json_home.Parameters.USER_ID, - }) - self._add_resource( - mapper, access_token_roles_controller, - path='/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}/' - 'roles/{role_id}', - get_action='get_access_token_role', - rel=build_resource_relation( - resource_name='user_access_token_role'), - path_vars={ - 'access_token_id': ACCESS_TOKEN_ID_PARAMETER_RELATION, - 'role_id': json_home.Parameters.ROLE_ID, - 'user_id': json_home.Parameters.USER_ID, - }) - - # oauth flow calls - self._add_resource( - mapper, oauth_controller, - path='/OS-OAUTH1/request_token', - post_action='create_request_token', - rel=build_resource_relation(resource_name='request_tokens')) - self._add_resource( - mapper, oauth_controller, - path='/OS-OAUTH1/access_token', - post_action='create_access_token', - rel=build_resource_relation(resource_name='access_tokens')) - self._add_resource( - mapper, oauth_controller, - path='/OS-OAUTH1/authorize/{request_token_id}', - path_vars={ - 'request_token_id': - build_parameter_relation(parameter_name='request_token_id') - }, - put_action='authorize_request_token', - rel=build_resource_relation( - resource_name='authorize_request_token')) + def __init__(self, *args, **kwargs): + super(OAuth1Extension, self).__init__(*args, **kwargs) + msg = _("Remove oauth1_extension from the paste pipeline, the " + "oauth1 extension is now always available. Update the " + "[pipeline:api_v3] section in keystone-paste.ini accordingly, " + "as it will be removed in the O release.") + versionutils.report_deprecated_feature(LOG, msg) diff --git a/keystone-moon/keystone/contrib/revoke/__init__.py b/keystone-moon/keystone/contrib/revoke/__init__.py index 58ba68db..e69de29b 100644 --- a/keystone-moon/keystone/contrib/revoke/__init__.py +++ b/keystone-moon/keystone/contrib/revoke/__init__.py @@ -1,13 +0,0 @@ -# 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.contrib.revoke.core import * # noqa diff --git a/keystone-moon/keystone/contrib/revoke/backends/sql.py b/keystone-moon/keystone/contrib/revoke/backends/sql.py index 82e05194..0bf493ae 100644 --- a/keystone-moon/keystone/contrib/revoke/backends/sql.py +++ b/keystone-moon/keystone/contrib/revoke/backends/sql.py @@ -10,95 +10,19 @@ # License for the specific language governing permissions and limitations # under the License. -import uuid +from oslo_log import versionutils -from keystone.common import sql -from keystone.contrib import revoke -from keystone.contrib.revoke import model +from keystone.revoke.backends import sql -class RevocationEvent(sql.ModelBase, sql.ModelDictMixin): - __tablename__ = 'revocation_event' - attributes = model.REVOKE_KEYS +_OLD = "keystone.contrib.revoke.backends.sql.Revoke" +_NEW = "sql" - # The id field is not going to be exposed to the outside world. - # It is, however, necessary for SQLAlchemy. - id = sql.Column(sql.String(64), primary_key=True) - domain_id = sql.Column(sql.String(64)) - project_id = sql.Column(sql.String(64)) - user_id = sql.Column(sql.String(64)) - role_id = sql.Column(sql.String(64)) - trust_id = sql.Column(sql.String(64)) - consumer_id = sql.Column(sql.String(64)) - access_token_id = sql.Column(sql.String(64)) - issued_before = sql.Column(sql.DateTime(), nullable=False) - expires_at = sql.Column(sql.DateTime()) - revoked_at = sql.Column(sql.DateTime(), nullable=False, index=True) - audit_id = sql.Column(sql.String(32)) - audit_chain_id = sql.Column(sql.String(32)) +class Revoke(sql.Revoke): -class Revoke(revoke.RevokeDriverV8): - def _flush_batch_size(self, dialect): - batch_size = 0 - if dialect == 'ibm_db_sa': - # This functionality is limited to DB2, because - # it is necessary to prevent the transaction log - # from filling up, whereas at least some of the - # other supported databases do not support update - # queries with LIMIT subqueries nor do they appear - # to require the use of such queries when deleting - # large numbers of records at once. - batch_size = 100 - # Limit of 100 is known to not fill a transaction log - # of default maximum size while not significantly - # impacting the performance of large token purges on - # systems where the maximum transaction log size has - # been increased beyond the default. - return batch_size - - def _prune_expired_events(self): - oldest = revoke.revoked_before_cutoff_time() - - session = sql.get_session() - dialect = session.bind.dialect.name - batch_size = self._flush_batch_size(dialect) - if batch_size > 0: - query = session.query(RevocationEvent.id) - query = query.filter(RevocationEvent.revoked_at < oldest) - query = query.limit(batch_size).subquery() - delete_query = (session.query(RevocationEvent). - filter(RevocationEvent.id.in_(query))) - while True: - rowcount = delete_query.delete(synchronize_session=False) - if rowcount == 0: - break - else: - query = session.query(RevocationEvent) - query = query.filter(RevocationEvent.revoked_at < oldest) - query.delete(synchronize_session=False) - - session.flush() - - def list_events(self, last_fetch=None): - session = sql.get_session() - query = session.query(RevocationEvent).order_by( - RevocationEvent.revoked_at) - - if last_fetch: - query = query.filter(RevocationEvent.revoked_at > last_fetch) - - events = [model.RevokeEvent(**e.to_dict()) for e in query] - - return events - - def revoke(self, event): - kwargs = dict() - for attr in model.REVOKE_KEYS: - kwargs[attr] = getattr(event, attr) - kwargs['id'] = uuid.uuid4().hex - record = RevocationEvent(**kwargs) - session = sql.get_session() - with session.begin(): - session.add(record) - self._prune_expired_events() + @versionutils.deprecated(versionutils.deprecated.MITAKA, + in_favor_of=_NEW, + what=_OLD) + def __init__(self, *args, **kwargs): + super(Revoke, self).__init__(*args, **kwargs) diff --git a/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/001_revoke_table.py b/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/001_revoke_table.py index 8b59010e..81c535e1 100644 --- a/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/001_revoke_table.py +++ b/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/001_revoke_table.py @@ -10,27 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql +from keystone import exception def upgrade(migrate_engine): - # Upgrade operations go here. Don't create your own engine; bind - # migrate_engine to your metadata - meta = sql.MetaData() - meta.bind = migrate_engine - - service_table = sql.Table( - 'revocation_event', - meta, - sql.Column('id', sql.String(64), primary_key=True), - sql.Column('domain_id', sql.String(64)), - sql.Column('project_id', sql.String(64)), - sql.Column('user_id', sql.String(64)), - sql.Column('role_id', sql.String(64)), - sql.Column('trust_id', sql.String(64)), - sql.Column('consumer_id', sql.String(64)), - sql.Column('access_token_id', sql.String(64)), - sql.Column('issued_before', sql.DateTime(), nullable=False), - sql.Column('expires_at', sql.DateTime()), - sql.Column('revoked_at', sql.DateTime(), index=True, nullable=False)) - service_table.create(migrate_engine, checkfirst=True) + raise exception.MigrationMovedFailure(extension='revoke') diff --git a/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/002_add_audit_id_and_chain_to_revoke_table.py b/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/002_add_audit_id_and_chain_to_revoke_table.py index b6d821d7..81c535e1 100644 --- a/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/002_add_audit_id_and_chain_to_revoke_table.py +++ b/keystone-moon/keystone/contrib/revoke/migrate_repo/versions/002_add_audit_id_and_chain_to_revoke_table.py @@ -10,19 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sql - - -_TABLE_NAME = 'revocation_event' +from keystone import exception def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - event_table = sql.Table(_TABLE_NAME, meta, autoload=True) - audit_id_column = sql.Column('audit_id', sql.String(32), nullable=True) - audit_chain_column = sql.Column('audit_chain_id', sql.String(32), - nullable=True) - event_table.create_column(audit_id_column) - event_table.create_column(audit_chain_column) + raise exception.MigrationMovedFailure(extension='revoke') diff --git a/keystone-moon/keystone/contrib/revoke/routers.py b/keystone-moon/keystone/contrib/revoke/routers.py index 4d2edfc0..a44c6194 100644 --- a/keystone-moon/keystone/contrib/revoke/routers.py +++ b/keystone-moon/keystone/contrib/revoke/routers.py @@ -10,20 +10,22 @@ # License for the specific language governing permissions and limitations # under the License. -from keystone.common import json_home +from oslo_log import log +from oslo_log import versionutils + from keystone.common import wsgi -from keystone.contrib.revoke import controllers +from keystone.i18n import _ + +LOG = log.getLogger(__name__) -class RevokeExtension(wsgi.V3ExtensionRouter): - PATH_PREFIX = '/OS-REVOKE' +class RevokeExtension(wsgi.Middleware): - def add_routes(self, mapper): - revoke_controller = controllers.RevokeController() - self._add_resource( - mapper, revoke_controller, - path=self.PATH_PREFIX + '/events', - get_action='list_revoke_events', - rel=json_home.build_v3_extension_resource_relation( - 'OS-REVOKE', '1.0', 'events')) + def __init__(self, *args, **kwargs): + super(RevokeExtension, self).__init__(*args, **kwargs) + msg = _("Remove revoke_extension from the paste pipeline, the " + "revoke extension is now always available. Update the " + "[pipeline:api_v3] section in keystone-paste.ini accordingly, " + "as it will be removed in the O release.") + versionutils.report_deprecated_feature(LOG, msg) diff --git a/keystone-moon/keystone/contrib/s3/core.py b/keystone-moon/keystone/contrib/s3/core.py index d3e06acc..c497f5d5 100644 --- a/keystone-moon/keystone/contrib/s3/core.py +++ b/keystone-moon/keystone/contrib/s3/core.py @@ -33,6 +33,7 @@ from keystone.common import utils from keystone.common import wsgi from keystone.contrib.ec2 import controllers from keystone import exception +from keystone.i18n import _ EXTENSION_DATA = { @@ -45,9 +46,9 @@ EXTENSION_DATA = { 'links': [ { 'rel': 'describedby', - # TODO(ayoung): needs a description 'type': 'text/html', - 'href': 'https://github.com/openstack/identity-api', + 'href': 'http://developer.openstack.org/' + 'api-ref-identity-v2-ext.html', } ]} extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) @@ -67,16 +68,58 @@ class S3Extension(wsgi.V3ExtensionRouter): class S3Controller(controllers.Ec2Controller): def check_signature(self, creds_ref, credentials): - msg = base64.urlsafe_b64decode(str(credentials['token'])) - key = str(creds_ref['secret']).encode('utf-8') + string_to_sign = base64.urlsafe_b64decode(str(credentials['token'])) + if string_to_sign[0:4] != b'AWS4': + signature = self._calculate_signature_v1(string_to_sign, + creds_ref['secret']) + else: + signature = self._calculate_signature_v4(string_to_sign, + creds_ref['secret']) + + if not utils.auth_str_equal(credentials['signature'], signature): + raise exception.Unauthorized( + message=_('Credential signature mismatch')) + + def _calculate_signature_v1(self, string_to_sign, secret_key): + """Calculates a v1 signature. + + :param bytes string_to_sign: String that contains request params and + is used for calculate signature of request + :param text secret_key: Second auth key of EC2 account that is used to + sign requests + """ + key = str(secret_key).encode('utf-8') if six.PY2: b64_encode = base64.encodestring else: b64_encode = base64.encodebytes + signed = b64_encode(hmac.new(key, string_to_sign, hashlib.sha1) + .digest()).decode('utf-8').strip() + return signed + + def _calculate_signature_v4(self, string_to_sign, secret_key): + """Calculates a v4 signature. + + :param bytes string_to_sign: String that contains request params and + is used for calculate signature of request + :param text secret_key: Second auth key of EC2 account that is used to + sign requests + """ + parts = string_to_sign.split(b'\n') + if len(parts) != 4 or parts[0] != b'AWS4-HMAC-SHA256': + raise exception.Unauthorized(message=_('Invalid EC2 signature.')) + scope = parts[2].split(b'/') + if len(scope) != 4 or scope[2] != b's3' or scope[3] != b'aws4_request': + raise exception.Unauthorized(message=_('Invalid EC2 signature.')) + + def _sign(key, msg): + return hmac.new(key, msg, hashlib.sha256).digest() - signed = b64_encode( - hmac.new(key, msg, hashlib.sha1).digest()).decode('utf-8').strip() + signed = _sign(('AWS4' + secret_key).encode('utf-8'), scope[0]) + signed = _sign(signed, scope[1]) + signed = _sign(signed, scope[2]) + signed = _sign(signed, b'aws4_request') - if not utils.auth_str_equal(credentials['signature'], signed): - raise exception.Unauthorized('Credential signature mismatch') + signature = hmac.new(signed, string_to_sign, hashlib.sha256) + return signature.hexdigest() diff --git a/keystone-moon/keystone/contrib/simple_cert/__init__.py b/keystone-moon/keystone/contrib/simple_cert/__init__.py index b213192e..2e5f9928 100644 --- a/keystone-moon/keystone/contrib/simple_cert/__init__.py +++ b/keystone-moon/keystone/contrib/simple_cert/__init__.py @@ -10,5 +10,4 @@ # License for the specific language governing permissions and limitations # under the License. -from keystone.contrib.simple_cert.core import * # noqa from keystone.contrib.simple_cert.routers import SimpleCertExtension # noqa diff --git a/keystone-moon/keystone/contrib/simple_cert/routers.py b/keystone-moon/keystone/contrib/simple_cert/routers.py index 8c36c2a4..b1d509e7 100644 --- a/keystone-moon/keystone/contrib/simple_cert/routers.py +++ b/keystone-moon/keystone/contrib/simple_cert/routers.py @@ -10,32 +10,24 @@ # License for the specific language governing permissions and limitations # under the License. -import functools +from oslo_log import log +from oslo_log import versionutils -from keystone.common import json_home from keystone.common import wsgi -from keystone.contrib.simple_cert import controllers +from keystone.i18n import _ -build_resource_relation = functools.partial( - json_home.build_v3_extension_resource_relation, - extension_name='OS-SIMPLE-CERT', extension_version='1.0') +LOG = log.getLogger(__name__) -class SimpleCertExtension(wsgi.V3ExtensionRouter): +class SimpleCertExtension(wsgi.Middleware): - PREFIX = 'OS-SIMPLE-CERT' - - def add_routes(self, mapper): - controller = controllers.SimpleCert() - - self._add_resource( - mapper, controller, - path='/%s/ca' % self.PREFIX, - get_action='get_ca_certificate', - rel=build_resource_relation(resource_name='ca_certificate')) - self._add_resource( - mapper, controller, - path='/%s/certificates' % self.PREFIX, - get_action='list_certificates', - rel=build_resource_relation(resource_name='certificates')) + def __init__(self, application): + super(SimpleCertExtension, self).__init__(application) + msg = _("Remove simple_cert from the paste pipeline, the " + "PKI and PKIz token providers are now deprecated and " + "simple_cert was only used insupport of these token " + "providers. Update the [pipeline:api_v3] section in " + "keystone-paste.ini accordingly, as it will be removed in the " + "O release.") + versionutils.report_deprecated_feature(LOG, msg) diff --git a/keystone-moon/keystone/contrib/user_crud/core.py b/keystone-moon/keystone/contrib/user_crud/core.py index dd16d3a5..b37157ea 100644 --- a/keystone-moon/keystone/contrib/user_crud/core.py +++ b/keystone-moon/keystone/contrib/user_crud/core.py @@ -12,123 +12,21 @@ # License for the specific language governing permissions and limitations # under the License. -import copy -import uuid - from oslo_log import log +from oslo_log import versionutils -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 +from keystone.i18n import _ 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', - # TODO(ayoung): needs a description - 'type': 'text/html', - 'href': 'https://github.com/openstack/identity-api', - } - ]}) - - -@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 CrudExtension(wsgi.ExtensionRouter): - """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'])) +class CrudExtension(wsgi.Middleware): + def __init__(self, application): + super(CrudExtension, self).__init__(application) + msg = _("Remove user_crud_extension from the paste pipeline, the " + "user_crud extension is now always available. Update" + "the [pipeline:public_api] section in keystone-paste.ini " + "accordingly, as it will be removed in the O release.") + versionutils.report_deprecated_feature(LOG, msg) |