diff options
Diffstat (limited to 'keystone-moon/keystone/contrib/oauth1')
8 files changed, 32 insertions, 490 deletions
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) |