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]
|
[filter:simple_cert_extension]
|
||||||
use = egg:keystone#simple_cert_extension
|
use = egg:keystone#simple_cert_extension
|
||||||
|
|
||||||
[filter:revoke_extension]
|
|
||||||
use = egg:keystone#revoke_extension
|
|
||||||
|
|
||||||
[filter:url_normalize]
|
[filter:url_normalize]
|
||||||
use = egg:keystone#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]
|
[pipeline:api_v3]
|
||||||
# The last item in this pipeline must be service_v3 or an equivalent
|
# The last item in this pipeline must be service_v3 or an equivalent
|
||||||
# application. It cannot be a filter.
|
# 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]
|
[app:public_version_service]
|
||||||
use = egg:keystone#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
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_log import versionutils
|
from oslo_log import versionutils
|
||||||
from oslo_utils import timeutils
|
|
||||||
|
|
||||||
from keystone.common import kvs
|
from keystone.revoke.backends import kvs
|
||||||
from keystone.contrib import revoke
|
|
||||||
from keystone import exception
|
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
_OLD = 'keystone.contrib.revoke.backends.kvs.Revoke'
|
||||||
|
_NEW = 'kvs'
|
||||||
_EVENT_KEY = 'os-revoke-events'
|
|
||||||
_KVS_BACKEND = 'openstack.kvs.Memory'
|
|
||||||
|
|
||||||
|
|
||||||
class Revoke(revoke.RevokeDriverV8):
|
class Revoke(kvs.Revoke):
|
||||||
|
|
||||||
@versionutils.deprecated(
|
@versionutils.deprecated(versionutils.deprecated.MITAKA,
|
||||||
versionutils.deprecated.JUNO,
|
in_favor_of=_NEW,
|
||||||
in_favor_of='keystone.contrib.revoke.backends.sql',
|
remove_in=2,
|
||||||
remove_in=+1,
|
what=_OLD)
|
||||||
what='keystone.contrib.revoke.backends.kvs')
|
def __init__(self, *args, **kwargs):
|
||||||
def __init__(self, **kwargs):
|
super(Revoke, self).__init__(*args, **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)
|
|
||||||
|
|
|
@ -10,95 +10,19 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import uuid
|
from oslo_log import versionutils
|
||||||
|
|
||||||
from keystone.common import sql
|
from keystone.revoke.backends import sql
|
||||||
from keystone.contrib import revoke
|
|
||||||
from keystone.contrib.revoke import model
|
|
||||||
|
|
||||||
|
|
||||||
class RevocationEvent(sql.ModelBase, sql.ModelDictMixin):
|
_OLD = "keystone.contrib.revoke.backends.sql.Revoke"
|
||||||
__tablename__ = 'revocation_event'
|
_NEW = "sql"
|
||||||
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):
|
class Revoke(sql.Revoke):
|
||||||
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):
|
@versionutils.deprecated(versionutils.deprecated.MITAKA,
|
||||||
oldest = revoke.revoked_before_cutoff_time()
|
in_favor_of=_NEW,
|
||||||
|
what=_OLD)
|
||||||
session = sql.get_session()
|
def __init__(self, *args, **kwargs):
|
||||||
dialect = session.bind.dialect.name
|
super(Revoke, self).__init__(*args, **kwargs)
|
||||||
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()
|
|
||||||
|
|
|
@ -10,20 +10,22 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# 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.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):
|
class RevokeExtension(wsgi.Middleware):
|
||||||
revoke_controller = controllers.RevokeController()
|
|
||||||
self._add_resource(
|
def __init__(self, *args, **kwargs):
|
||||||
mapper, revoke_controller,
|
super(RevokeExtension, self).__init__(*args, **kwargs)
|
||||||
path=self.PATH_PREFIX + '/events',
|
msg = _("Remove revoke_extension from the paste pipeline, the "
|
||||||
get_action='list_revoke_events',
|
"revoke extension is now always available. Update the "
|
||||||
rel=json_home.build_v3_extension_resource_relation(
|
"[pipeline:api_v3] section in keystone-paste.ini accordingly, "
|
||||||
'OS-REVOKE', '1.0', 'events'))
|
"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 dependency
|
||||||
from keystone.common import extension
|
from keystone.common import extension
|
||||||
from keystone.common import manager
|
from keystone.common import manager
|
||||||
from keystone.contrib.revoke import model
|
|
||||||
from keystone import exception
|
from keystone import exception
|
||||||
from keystone.i18n import _
|
from keystone.i18n import _
|
||||||
from keystone import notifications
|
from keystone import notifications
|
||||||
|
from keystone.revoke import model
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
@ -240,7 +240,7 @@ class RevokeDriverV8(object):
|
||||||
"""return the revocation events, as a list of objects
|
"""return the revocation events, as a list of objects
|
||||||
|
|
||||||
:param last_fetch: Time of last fetch. Return all events newer.
|
: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.`
|
newer than `last_fetch.`
|
||||||
If no last_fetch is specified, returns all events
|
If no last_fetch is specified, returns all events
|
||||||
for tokens issued after the expiration cutoff.
|
for tokens issued after the expiration cutoff.
|
||||||
|
@ -253,7 +253,7 @@ class RevokeDriverV8(object):
|
||||||
"""register a revocation event
|
"""register a revocation event
|
||||||
|
|
||||||
:param event: An instance of
|
:param event: An instance of
|
||||||
keystone.contrib.revoke.model.RevocationEvent
|
keystone.revoke.model.RevocationEvent
|
||||||
|
|
||||||
"""
|
"""
|
||||||
raise exception.NotImplemented() # pragma: no cover
|
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 import catalog
|
||||||
from keystone.common import cache
|
from keystone.common import cache
|
||||||
from keystone.contrib import endpoint_filter
|
from keystone.contrib import endpoint_filter
|
||||||
from keystone.contrib import revoke
|
|
||||||
from keystone import credential
|
from keystone import credential
|
||||||
from keystone import endpoint_policy
|
from keystone import endpoint_policy
|
||||||
from keystone import federation
|
from keystone import federation
|
||||||
|
@ -23,6 +22,7 @@ from keystone import identity
|
||||||
from keystone import oauth1
|
from keystone import oauth1
|
||||||
from keystone import policy
|
from keystone import policy
|
||||||
from keystone import resource
|
from keystone import resource
|
||||||
|
from keystone import revoke
|
||||||
from keystone import token
|
from keystone import token
|
||||||
from keystone import trust
|
from keystone import trust
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ from six.moves import range
|
||||||
from testtools import matchers
|
from testtools import matchers
|
||||||
|
|
||||||
from keystone.common import utils
|
from keystone.common import utils
|
||||||
from keystone.contrib.revoke import model
|
|
||||||
from keystone import exception
|
from keystone import exception
|
||||||
|
from keystone.revoke import model
|
||||||
from keystone.tests import unit
|
from keystone.tests import unit
|
||||||
from keystone.tests.unit import test_backend_sql
|
from keystone.tests.unit import test_backend_sql
|
||||||
from keystone.token import provider
|
from keystone.token import provider
|
||||||
|
|
|
@ -21,6 +21,7 @@ import uuid
|
||||||
from keystoneclient.common import cms
|
from keystoneclient.common import cms
|
||||||
import mock
|
import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_log import versionutils
|
||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
|
@ -29,6 +30,7 @@ from testtools import testcase
|
||||||
|
|
||||||
from keystone import auth
|
from keystone import auth
|
||||||
from keystone.common import utils
|
from keystone.common import utils
|
||||||
|
from keystone.contrib.revoke import routers
|
||||||
from keystone import exception
|
from keystone import exception
|
||||||
from keystone.policy.backends import rules
|
from keystone.policy.backends import rules
|
||||||
from keystone.tests import unit
|
from keystone.tests import unit
|
||||||
|
@ -1473,11 +1475,19 @@ class TestTokenRevokeByAssignment(TestTokenRevokeById):
|
||||||
self.assertIn(project_token, revoked_tokens)
|
self.assertIn(project_token, revoked_tokens)
|
||||||
|
|
||||||
|
|
||||||
class TestTokenRevokeApi(TestTokenRevokeById):
|
class RevokeContribTests(test_v3.RestfulTestCase):
|
||||||
EXTENSION_NAME = 'revoke'
|
|
||||||
EXTENSION_TO_ADD = 'revoke_extension'
|
|
||||||
|
|
||||||
|
@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."""
|
"""Test token revocation on the v3 Identity API."""
|
||||||
|
|
||||||
def config_overrides(self):
|
def config_overrides(self):
|
||||||
super(TestTokenRevokeApi, self).config_overrides()
|
super(TestTokenRevokeApi, self).config_overrides()
|
||||||
self.config_fixture.config(group='revoke', driver='kvs')
|
self.config_fixture.config(group='revoke', driver='kvs')
|
||||||
|
@ -3099,8 +3109,6 @@ class TestTrustChain(test_v3.RestfulTestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestTrustAuth(test_v3.RestfulTestCase):
|
class TestTrustAuth(test_v3.RestfulTestCase):
|
||||||
EXTENSION_NAME = 'revoke'
|
|
||||||
EXTENSION_TO_ADD = 'revoke_extension'
|
|
||||||
|
|
||||||
def config_overrides(self):
|
def config_overrides(self):
|
||||||
super(TestTrustAuth, self).config_overrides()
|
super(TestTrustAuth, self).config_overrides()
|
||||||
|
|
|
@ -19,7 +19,7 @@ from six.moves import http_client
|
||||||
from testtools import matchers
|
from testtools import matchers
|
||||||
|
|
||||||
from keystone.common import utils
|
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.tests.unit import test_v3
|
||||||
from keystone.token import provider
|
from keystone.token import provider
|
||||||
|
|
||||||
|
@ -31,8 +31,6 @@ def _future_time_string():
|
||||||
|
|
||||||
|
|
||||||
class OSRevokeTests(test_v3.RestfulTestCase, test_v3.JsonHomeTestMixin):
|
class OSRevokeTests(test_v3.RestfulTestCase, test_v3.JsonHomeTestMixin):
|
||||||
EXTENSION_NAME = 'revoke'
|
|
||||||
EXTENSION_TO_ADD = 'revoke_extension'
|
|
||||||
|
|
||||||
JSON_HOME_DATA = {
|
JSON_HOME_DATA = {
|
||||||
'http://docs.openstack.org/api/openstack-identity/3/ext/OS-REVOKE/1.0/'
|
'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 oauth1
|
||||||
from keystone import policy
|
from keystone import policy
|
||||||
from keystone import resource
|
from keystone import resource
|
||||||
|
from keystone import revoke
|
||||||
from keystone import token
|
from keystone import token
|
||||||
from keystone import trust
|
from keystone import trust
|
||||||
from keystone.version import controllers
|
from keystone.version import controllers
|
||||||
|
@ -132,6 +133,7 @@ def v3_app_factory(global_conf, **local_conf):
|
||||||
identity,
|
identity,
|
||||||
policy,
|
policy,
|
||||||
resource,
|
resource,
|
||||||
|
revoke,
|
||||||
federation,
|
federation,
|
||||||
oauth1]
|
oauth1]
|
||||||
|
|
||||||
|
|
|
@ -168,8 +168,8 @@ keystone.oauth1 =
|
||||||
sql = keystone.oauth1.backends.sql:OAuth1
|
sql = keystone.oauth1.backends.sql:OAuth1
|
||||||
|
|
||||||
keystone.revoke =
|
keystone.revoke =
|
||||||
kvs = keystone.contrib.revoke.backends.kvs:Revoke
|
kvs = keystone.revoke.backends.kvs:Revoke
|
||||||
sql = keystone.contrib.revoke.backends.sql:Revoke
|
sql = keystone.revoke.backends.sql:Revoke
|
||||||
|
|
||||||
oslo.config.opts =
|
oslo.config.opts =
|
||||||
keystone = keystone.common.config:list_opts
|
keystone = keystone.common.config:list_opts
|
||||||
|
|
Loading…
Reference in New Issue