Move revoke extension into core
Remove revoke as an extension and move it to a core resource. For now we leave the database migrations in the extension directory until we have a general policy for merging these into core. DocImpact: update keystone-paste and remove revoke from pipeline Change-Id: I2d6f425a508b7acb4b4d079e4387f25bf7555683 Implements: bp move-extensions
This commit is contained in:
parent
a83b6b29e8
commit
32b70d15c4
|
@ -39,9 +39,6 @@ use = egg:keystone#endpoint_filter_extension
|
|||
[filter:simple_cert_extension]
|
||||
use = egg:keystone#simple_cert_extension
|
||||
|
||||
[filter:revoke_extension]
|
||||
use = egg:keystone#revoke_extension
|
||||
|
||||
[filter:url_normalize]
|
||||
use = egg:keystone#url_normalize
|
||||
|
||||
|
@ -70,7 +67,7 @@ pipeline = sizelimit url_normalize request_id build_auth_context token_auth admi
|
|||
[pipeline:api_v3]
|
||||
# The last item in this pipeline must be service_v3 or an equivalent
|
||||
# application. It cannot be a filter.
|
||||
pipeline = sizelimit url_normalize request_id build_auth_context token_auth admin_token_auth json_body ec2_extension_v3 s3_extension simple_cert_extension revoke_extension endpoint_filter_extension service_v3
|
||||
pipeline = sizelimit url_normalize request_id build_auth_context token_auth admin_token_auth json_body ec2_extension_v3 s3_extension simple_cert_extension endpoint_filter_extension service_v3
|
||||
|
||||
[app:public_version_service]
|
||||
use = egg:keystone#public_version_service
|
||||
|
|
|
@ -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
|
|
@ -10,65 +10,20 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import versionutils
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from keystone.common import kvs
|
||||
from keystone.contrib import revoke
|
||||
from keystone import exception
|
||||
from keystone.revoke.backends import kvs
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
_EVENT_KEY = 'os-revoke-events'
|
||||
_KVS_BACKEND = 'openstack.kvs.Memory'
|
||||
_OLD = 'keystone.contrib.revoke.backends.kvs.Revoke'
|
||||
_NEW = 'kvs'
|
||||
|
||||
|
||||
class Revoke(revoke.RevokeDriverV8):
|
||||
class Revoke(kvs.Revoke):
|
||||
|
||||
@versionutils.deprecated(
|
||||
versionutils.deprecated.JUNO,
|
||||
in_favor_of='keystone.contrib.revoke.backends.sql',
|
||||
remove_in=+1,
|
||||
what='keystone.contrib.revoke.backends.kvs')
|
||||
def __init__(self, **kwargs):
|
||||
super(Revoke, self).__init__()
|
||||
self._store = kvs.get_key_value_store('os-revoke-driver')
|
||||
self._store.configure(backing_store=_KVS_BACKEND, **kwargs)
|
||||
|
||||
def _list_events(self):
|
||||
try:
|
||||
return self._store.get(_EVENT_KEY)
|
||||
except exception.NotFound:
|
||||
return []
|
||||
|
||||
def list_events(self, last_fetch=None):
|
||||
results = []
|
||||
|
||||
with self._store.get_lock(_EVENT_KEY):
|
||||
events = self._list_events()
|
||||
|
||||
for event in events:
|
||||
revoked_at = event.revoked_at
|
||||
if last_fetch is None or revoked_at > last_fetch:
|
||||
results.append(event)
|
||||
return results
|
||||
|
||||
def revoke(self, event):
|
||||
pruned = []
|
||||
expire_delta = datetime.timedelta(seconds=CONF.token.expiration)
|
||||
oldest = timeutils.utcnow() - expire_delta
|
||||
|
||||
with self._store.get_lock(_EVENT_KEY) as lock:
|
||||
events = self._list_events()
|
||||
if event:
|
||||
events.append(event)
|
||||
|
||||
for event in events:
|
||||
revoked_at = event.revoked_at
|
||||
if revoked_at > oldest:
|
||||
pruned.append(event)
|
||||
self._store.set(_EVENT_KEY, pruned, lock)
|
||||
@versionutils.deprecated(versionutils.deprecated.MITAKA,
|
||||
in_favor_of=_NEW,
|
||||
remove_in=2,
|
||||
what=_OLD)
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Revoke, self).__init__(*args, **kwargs)
|
||||
|
|
|
@ -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
|
||||
|
||||
# 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))
|
||||
_OLD = "keystone.contrib.revoke.backends.sql.Revoke"
|
||||
_NEW = "sql"
|
||||
|
||||
|
||||
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
|
||||
class Revoke(sql.Revoke):
|
||||
|
||||
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)
|
||||
|
|
|
@ -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 _
|
||||
|
||||
|
||||
class RevokeExtension(wsgi.V3ExtensionRouter):
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
PATH_PREFIX = '/OS-REVOKE'
|
||||
|
||||
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'))
|
||||
class RevokeExtension(wsgi.Middleware):
|
||||
|
||||
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)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# 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.revoke.core import * # noqa
|
||||
from keystone.revoke.routers import * # noqa
|
|
@ -0,0 +1,74 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import versionutils
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from keystone.common import kvs
|
||||
from keystone import exception
|
||||
from keystone import revoke
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
_EVENT_KEY = 'os-revoke-events'
|
||||
_KVS_BACKEND = 'openstack.kvs.Memory'
|
||||
|
||||
|
||||
class Revoke(revoke.RevokeDriverV8):
|
||||
|
||||
@versionutils.deprecated(
|
||||
versionutils.deprecated.JUNO,
|
||||
in_favor_of='keystone.revoke.backends.sql',
|
||||
remove_in=+1,
|
||||
what='keystone.revoke.backends.kvs')
|
||||
def __init__(self, **kwargs):
|
||||
super(Revoke, self).__init__()
|
||||
self._store = kvs.get_key_value_store('os-revoke-driver')
|
||||
self._store.configure(backing_store=_KVS_BACKEND, **kwargs)
|
||||
|
||||
def _list_events(self):
|
||||
try:
|
||||
return self._store.get(_EVENT_KEY)
|
||||
except exception.NotFound:
|
||||
return []
|
||||
|
||||
def list_events(self, last_fetch=None):
|
||||
results = []
|
||||
|
||||
with self._store.get_lock(_EVENT_KEY):
|
||||
events = self._list_events()
|
||||
|
||||
for event in events:
|
||||
revoked_at = event.revoked_at
|
||||
if last_fetch is None or revoked_at > last_fetch:
|
||||
results.append(event)
|
||||
return results
|
||||
|
||||
def revoke(self, event):
|
||||
pruned = []
|
||||
expire_delta = datetime.timedelta(seconds=CONF.token.expiration)
|
||||
oldest = timeutils.utcnow() - expire_delta
|
||||
|
||||
with self._store.get_lock(_EVENT_KEY) as lock:
|
||||
events = self._list_events()
|
||||
if event:
|
||||
events.append(event)
|
||||
|
||||
for event in events:
|
||||
revoked_at = event.revoked_at
|
||||
if revoked_at > oldest:
|
||||
pruned.append(event)
|
||||
self._store.set(_EVENT_KEY, pruned, lock)
|
|
@ -0,0 +1,104 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import uuid
|
||||
|
||||
from keystone.common import sql
|
||||
from keystone import revoke
|
||||
from keystone.revoke import model
|
||||
|
||||
|
||||
class RevocationEvent(sql.ModelBase, sql.ModelDictMixin):
|
||||
__tablename__ = 'revocation_event'
|
||||
attributes = model.REVOKE_KEYS
|
||||
|
||||
# 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(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()
|
|
@ -25,10 +25,10 @@ from keystone.common import cache
|
|||
from keystone.common import dependency
|
||||
from keystone.common import extension
|
||||
from keystone.common import manager
|
||||
from keystone.contrib.revoke import model
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
from keystone import notifications
|
||||
from keystone.revoke import model
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
@ -240,7 +240,7 @@ class RevokeDriverV8(object):
|
|||
"""return the revocation events, as a list of objects
|
||||
|
||||
:param last_fetch: Time of last fetch. Return all events newer.
|
||||
:returns: A list of keystone.contrib.revoke.model.RevokeEvent
|
||||
:returns: A list of keystone.revoke.model.RevokeEvent
|
||||
newer than `last_fetch.`
|
||||
If no last_fetch is specified, returns all events
|
||||
for tokens issued after the expiration cutoff.
|
||||
|
@ -253,7 +253,7 @@ class RevokeDriverV8(object):
|
|||
"""register a revocation event
|
||||
|
||||
:param event: An instance of
|
||||
keystone.contrib.revoke.model.RevocationEvent
|
||||
keystone.revoke.model.RevocationEvent
|
||||
|
||||
"""
|
||||
raise exception.NotImplemented() # pragma: no cover
|
|
@ -0,0 +1,29 @@
|
|||
# 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.common import json_home
|
||||
from keystone.common import wsgi
|
||||
from keystone.revoke import controllers
|
||||
|
||||
|
||||
class Routers(wsgi.RoutersBase):
|
||||
|
||||
PATH_PREFIX = '/OS-REVOKE'
|
||||
|
||||
def append_v3_routers(self, mapper, routers):
|
||||
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'))
|
|
@ -15,7 +15,6 @@ from keystone import auth
|
|||
from keystone import catalog
|
||||
from keystone.common import cache
|
||||
from keystone.contrib import endpoint_filter
|
||||
from keystone.contrib import revoke
|
||||
from keystone import credential
|
||||
from keystone import endpoint_policy
|
||||
from keystone import federation
|
||||
|
@ -23,6 +22,7 @@ from keystone import identity
|
|||
from keystone import oauth1
|
||||
from keystone import policy
|
||||
from keystone import resource
|
||||
from keystone import revoke
|
||||
from keystone import token
|
||||
from keystone import trust
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ from six.moves import range
|
|||
from testtools import matchers
|
||||
|
||||
from keystone.common import utils
|
||||
from keystone.contrib.revoke import model
|
||||
from keystone import exception
|
||||
from keystone.revoke import model
|
||||
from keystone.tests import unit
|
||||
from keystone.tests.unit import test_backend_sql
|
||||
from keystone.token import provider
|
||||
|
|
|
@ -21,6 +21,7 @@ import uuid
|
|||
from keystoneclient.common import cms
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
from oslo_log import versionutils
|
||||
from oslo_utils import timeutils
|
||||
from six.moves import http_client
|
||||
from six.moves import range
|
||||
|
@ -29,6 +30,7 @@ from testtools import testcase
|
|||
|
||||
from keystone import auth
|
||||
from keystone.common import utils
|
||||
from keystone.contrib.revoke import routers
|
||||
from keystone import exception
|
||||
from keystone.policy.backends import rules
|
||||
from keystone.tests import unit
|
||||
|
@ -1473,11 +1475,19 @@ class TestTokenRevokeByAssignment(TestTokenRevokeById):
|
|||
self.assertIn(project_token, revoked_tokens)
|
||||
|
||||
|
||||
class TestTokenRevokeApi(TestTokenRevokeById):
|
||||
EXTENSION_NAME = 'revoke'
|
||||
EXTENSION_TO_ADD = 'revoke_extension'
|
||||
class RevokeContribTests(test_v3.RestfulTestCase):
|
||||
|
||||
@mock.patch.object(versionutils, 'report_deprecated_feature')
|
||||
def test_exception_happens(self, mock_deprecator):
|
||||
routers.RevokeExtension(mock.ANY)
|
||||
mock_deprecator.assert_called_once_with(mock.ANY, mock.ANY)
|
||||
args, _kwargs = mock_deprecator.call_args
|
||||
self.assertIn("Remove revoke_extension from", args[1])
|
||||
|
||||
|
||||
class TestTokenRevokeApi(TestTokenRevokeById):
|
||||
"""Test token revocation on the v3 Identity API."""
|
||||
|
||||
def config_overrides(self):
|
||||
super(TestTokenRevokeApi, self).config_overrides()
|
||||
self.config_fixture.config(group='revoke', driver='kvs')
|
||||
|
@ -3099,8 +3109,6 @@ class TestTrustChain(test_v3.RestfulTestCase):
|
|||
|
||||
|
||||
class TestTrustAuth(test_v3.RestfulTestCase):
|
||||
EXTENSION_NAME = 'revoke'
|
||||
EXTENSION_TO_ADD = 'revoke_extension'
|
||||
|
||||
def config_overrides(self):
|
||||
super(TestTrustAuth, self).config_overrides()
|
||||
|
|
|
@ -19,7 +19,7 @@ from six.moves import http_client
|
|||
from testtools import matchers
|
||||
|
||||
from keystone.common import utils
|
||||
from keystone.contrib.revoke import model
|
||||
from keystone.revoke import model
|
||||
from keystone.tests.unit import test_v3
|
||||
from keystone.token import provider
|
||||
|
||||
|
@ -31,8 +31,6 @@ def _future_time_string():
|
|||
|
||||
|
||||
class OSRevokeTests(test_v3.RestfulTestCase, test_v3.JsonHomeTestMixin):
|
||||
EXTENSION_NAME = 'revoke'
|
||||
EXTENSION_TO_ADD = 'revoke_extension'
|
||||
|
||||
JSON_HOME_DATA = {
|
||||
'http://docs.openstack.org/api/openstack-identity/3/ext/OS-REVOKE/1.0/'
|
||||
|
|
|
@ -32,6 +32,7 @@ from keystone import identity
|
|||
from keystone import oauth1
|
||||
from keystone import policy
|
||||
from keystone import resource
|
||||
from keystone import revoke
|
||||
from keystone import token
|
||||
from keystone import trust
|
||||
from keystone.version import controllers
|
||||
|
@ -132,6 +133,7 @@ def v3_app_factory(global_conf, **local_conf):
|
|||
identity,
|
||||
policy,
|
||||
resource,
|
||||
revoke,
|
||||
federation,
|
||||
oauth1]
|
||||
|
||||
|
|
|
@ -168,8 +168,8 @@ keystone.oauth1 =
|
|||
sql = keystone.oauth1.backends.sql:OAuth1
|
||||
|
||||
keystone.revoke =
|
||||
kvs = keystone.contrib.revoke.backends.kvs:Revoke
|
||||
sql = keystone.contrib.revoke.backends.sql:Revoke
|
||||
kvs = keystone.revoke.backends.kvs:Revoke
|
||||
sql = keystone.revoke.backends.sql:Revoke
|
||||
|
||||
oslo.config.opts =
|
||||
keystone = keystone.common.config:list_opts
|
||||
|
|
Loading…
Reference in New Issue