summaryrefslogtreecommitdiffstats
path: root/keystone-moon/keystone/contrib/revoke/backends
diff options
context:
space:
mode:
authorWuKong <rebirthmonkey@gmail.com>2015-06-30 18:47:29 +0200
committerWuKong <rebirthmonkey@gmail.com>2015-06-30 18:47:29 +0200
commitb8c756ecdd7cced1db4300935484e8c83701c82e (patch)
tree87e51107d82b217ede145de9d9d59e2100725bd7 /keystone-moon/keystone/contrib/revoke/backends
parentc304c773bae68fb854ed9eab8fb35c4ef17cf136 (diff)
migrate moon code from github to opnfv
Change-Id: Ice53e368fd1114d56a75271aa9f2e598e3eba604 Signed-off-by: WuKong <rebirthmonkey@gmail.com>
Diffstat (limited to 'keystone-moon/keystone/contrib/revoke/backends')
-rw-r--r--keystone-moon/keystone/contrib/revoke/backends/__init__.py0
-rw-r--r--keystone-moon/keystone/contrib/revoke/backends/kvs.py73
-rw-r--r--keystone-moon/keystone/contrib/revoke/backends/sql.py104
3 files changed, 177 insertions, 0 deletions
diff --git a/keystone-moon/keystone/contrib/revoke/backends/__init__.py b/keystone-moon/keystone/contrib/revoke/backends/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keystone-moon/keystone/contrib/revoke/backends/__init__.py
diff --git a/keystone-moon/keystone/contrib/revoke/backends/kvs.py b/keystone-moon/keystone/contrib/revoke/backends/kvs.py
new file mode 100644
index 00000000..cc41fbee
--- /dev/null
+++ b/keystone-moon/keystone/contrib/revoke/backends/kvs.py
@@ -0,0 +1,73 @@
+# 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_utils import timeutils
+
+from keystone.common import kvs
+from keystone.contrib import revoke
+from keystone import exception
+from keystone.openstack.common import versionutils
+
+
+CONF = cfg.CONF
+
+_EVENT_KEY = 'os-revoke-events'
+_KVS_BACKEND = 'openstack.kvs.Memory'
+
+
+class Revoke(revoke.Driver):
+
+ @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 _prune_expired_events_and_get(self, last_fetch=None, new_event=None):
+ pruned = []
+ results = []
+ expire_delta = datetime.timedelta(seconds=CONF.token.expiration)
+ oldest = timeutils.utcnow() - expire_delta
+ # TODO(ayoung): Store the time of the oldest event so that the
+ # prune process can be skipped if none of the events have timed out.
+ with self._store.get_lock(_EVENT_KEY) as lock:
+ events = self._list_events()
+ if new_event is not None:
+ events.append(new_event)
+
+ for event in events:
+ revoked_at = event.revoked_at
+ if revoked_at > oldest:
+ pruned.append(event)
+ if last_fetch is None or revoked_at > last_fetch:
+ results.append(event)
+ self._store.set(_EVENT_KEY, pruned, lock)
+ return results
+
+ def list_events(self, last_fetch=None):
+ return self._prune_expired_events_and_get(last_fetch=last_fetch)
+
+ def revoke(self, event):
+ self._prune_expired_events_and_get(new_event=event)
diff --git a/keystone-moon/keystone/contrib/revoke/backends/sql.py b/keystone-moon/keystone/contrib/revoke/backends/sql.py
new file mode 100644
index 00000000..1b0cde1e
--- /dev/null
+++ b/keystone-moon/keystone/contrib/revoke/backends/sql.py
@@ -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.contrib import revoke
+from keystone.contrib.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)
+ audit_id = sql.Column(sql.String(32))
+ audit_chain_id = sql.Column(sql.String(32))
+
+
+class Revoke(revoke.Driver):
+ 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):
+ self._prune_expired_events()
+ 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)