summaryrefslogtreecommitdiffstats
path: root/keystone/credential
diff options
context:
space:
mode:
authorAdam Young <ayoung@redhat.com>2013-05-06 14:09:07 -0400
committerAdam Young <ayoung@redhat.com>2013-05-17 11:08:54 -0400
commitd95adc1ac82b34372cd037467d0f60200a6e0a72 (patch)
treebaa82c30f85815e9623d0c1cd3eef6b6494e56b2 /keystone/credential
parent2e15fe428a2393f786852eb28c26bb9fee166bda (diff)
downloadkeystone-d95adc1ac82b34372cd037467d0f60200a6e0a72.tar.gz
keystone-d95adc1ac82b34372cd037467d0f60200a6e0a72.tar.xz
keystone-d95adc1ac82b34372cd037467d0f60200a6e0a72.zip
extracting credentials
Moves the credentials API into its own backend. LDAP was not going to be able to support credentials. Even with a custom schema, many people are using LDAP in read only mode, which means that they would not be able to use the credentials API at all. By splitting it out, we have a workable solution for both SQL and LDAP Identity backends. Drops the Foreign Key constraints off the Credentials table, as there is now no guaranttee that users are stored in the same backend. Blueprint extract-credentials-id Change-Id: I10ad4b36c6f03d1712621eaffcfefa48a5453aff
Diffstat (limited to 'keystone/credential')
-rw-r--r--keystone/credential/__init__.py19
-rw-r--r--keystone/credential/backends/__init__.py0
-rw-r--r--keystone/credential/backends/sql.py96
-rw-r--r--keystone/credential/controllers.py55
-rw-r--r--keystone/credential/core.py87
-rw-r--r--keystone/credential/routers.py26
6 files changed, 283 insertions, 0 deletions
diff --git a/keystone/credential/__init__.py b/keystone/credential/__init__.py
new file mode 100644
index 00000000..bef9c3c7
--- /dev/null
+++ b/keystone/credential/__init__.py
@@ -0,0 +1,19 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# 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.credential import controllers
+from keystone.credential.core import *
+from keystone.credential import routers
diff --git a/keystone/credential/backends/__init__.py b/keystone/credential/backends/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keystone/credential/backends/__init__.py
diff --git a/keystone/credential/backends/sql.py b/keystone/credential/backends/sql.py
new file mode 100644
index 00000000..721cdc6d
--- /dev/null
+++ b/keystone/credential/backends/sql.py
@@ -0,0 +1,96 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# 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 import clean
+from keystone.common import sql
+from keystone.common.sql import migration
+from keystone.common import utils
+from keystone import credential
+from keystone import exception
+
+
+class CredentialModel(sql.ModelBase, sql.DictBase):
+ __tablename__ = 'credential'
+ attributes = ['id', 'user_id', 'project_id', 'blob', 'type']
+ id = sql.Column(sql.String(64), primary_key=True)
+ user_id = sql.Column(sql.String(64),
+ nullable=False)
+ project_id = sql.Column(sql.String(64))
+ blob = sql.Column(sql.JsonBlob(), nullable=False)
+ type = sql.Column(sql.String(255), nullable=False)
+ extra = sql.Column(sql.JsonBlob())
+
+
+class Credential(sql.Base, credential.Driver):
+ # Internal interface to manage the database
+ def db_sync(self):
+ migration.db_sync()
+
+ # credential crud
+
+ @sql.handle_conflicts(type='credential')
+ def create_credential(self, credential_id, credential):
+ session = self.get_session()
+ with session.begin():
+ ref = CredentialModel.from_dict(credential)
+ session.add(ref)
+ session.flush()
+ return ref.to_dict()
+
+ def list_credentials(self):
+ session = self.get_session()
+ refs = session.query(CredentialModel).all()
+ return [ref.to_dict() for ref in refs]
+
+ def get_credential(self, credential_id):
+ session = self.get_session()
+ ref = (session.query(CredentialModel)
+ .filter_by(id=credential_id).first())
+ if ref is None:
+ raise exception.CredentialNotFound(credential_id=credential_id)
+ return ref.to_dict()
+
+ @sql.handle_conflicts(type='credential')
+ def update_credential(self, credential_id, credential):
+ session = self.get_session()
+ with session.begin():
+ ref = (session.query(CredentialModel)
+ .filter_by(id=credential_id).first())
+ if ref is None:
+ raise exception.CredentialNotFound(credential_id=credential_id)
+ old_dict = ref.to_dict()
+ for k in credential:
+ old_dict[k] = credential[k]
+ new_credential = CredentialModel.from_dict(old_dict)
+ for attr in CredentialModel.attributes:
+ if attr != 'id':
+ setattr(ref, attr, getattr(new_credential, attr))
+ ref.extra = new_credential.extra
+ session.flush()
+ return ref.to_dict()
+
+ def delete_credential(self, credential_id):
+ session = self.get_session()
+
+ try:
+ ref = (session.query(CredentialModel)
+ .filter_by(id=credential_id).one())
+ except sql.NotFound:
+ raise exception.CredentialNotFound(credential_id=credential_id)
+
+ with session.begin():
+ session.delete(ref)
+ session.flush()
diff --git a/keystone/credential/controllers.py b/keystone/credential/controllers.py
new file mode 100644
index 00000000..59289de3
--- /dev/null
+++ b/keystone/credential/controllers.py
@@ -0,0 +1,55 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# 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 controller
+
+
+class CredentialV3(controller.V3Controller):
+ collection_name = 'credentials'
+ member_name = 'credential'
+
+ @controller.protected
+ def create_credential(self, context, credential):
+ ref = self._assign_unique_id(self._normalize_dict(credential))
+ ref = self.credential_api.create_credential(context, ref['id'], ref)
+ return CredentialV3.wrap_member(context, ref)
+
+ @controller.protected
+ def list_credentials(self, context):
+ refs = self.credential_api.list_credentials(context)
+ return CredentialV3.wrap_collection(context, refs)
+
+ @controller.protected
+ def get_credential(self, context, credential_id):
+ ref = self.credential_api.get_credential(context, credential_id)
+ return CredentialV3.wrap_member(context, ref)
+
+ @controller.protected
+ def update_credential(self, context, credential_id, credential):
+ self._require_matching_id(credential_id, credential)
+
+ ref = self.credential_api.update_credential(
+ context,
+ credential_id,
+ credential)
+ return CredentialV3.wrap_member(context, ref)
+
+ def _delete_credential(self, context, credential_id):
+ return self.credential_api.delete_credential(context, credential_id)
+
+ @controller.protected
+ def delete_credential(self, context, credential_id):
+ return self._delete_credential(context, credential_id)
diff --git a/keystone/credential/core.py b/keystone/credential/core.py
new file mode 100644
index 00000000..a8921ba0
--- /dev/null
+++ b/keystone/credential/core.py
@@ -0,0 +1,87 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# 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.
+
+"""Main entry point into the Credentials service."""
+
+from keystone.common import dependency
+from keystone.common import logging
+from keystone.common import manager
+from keystone import config
+from keystone import exception
+
+
+CONF = config.CONF
+
+LOG = logging.getLogger(__name__)
+
+
+@dependency.provider('credential_api')
+class Manager(manager.Manager):
+ """Default pivot point for the Credential backend.
+
+ See :mod:`keystone.common.manager.Manager` for more details on how this
+ dynamically calls the backend.
+
+ """
+
+ def __init__(self):
+ super(Manager, self).__init__(CONF.credential.driver)
+
+
+class Driver(object):
+ # credential crud
+
+ def create_credential(self, credential_id, credential):
+ """Creates a new credential.
+
+ :raises: keystone.exception.Conflict
+
+ """
+ raise exception.NotImplemented()
+
+ def list_credentials(self):
+ """List all credentials in the system.
+
+ :returns: a list of credential_refs or an empty list.
+
+ """
+ raise exception.NotImplemented()
+
+ def get_credential(self, credential_id):
+ """Get a credential by ID.
+
+ :returns: credential_ref
+ :raises: keystone.exception.CredentialNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def update_credential(self, credential_id, credential):
+ """Updates an existing credential.
+
+ :raises: keystone.exception.CredentialNotFound,
+ keystone.exception.Conflict
+
+ """
+ raise exception.NotImplemented()
+
+ def delete_credential(self, credential_id):
+ """Deletes an existing credential.
+
+ :raises: keystone.exception.CredentialNotFound
+
+ """
+ raise exception.NotImplemented()
diff --git a/keystone/credential/routers.py b/keystone/credential/routers.py
new file mode 100644
index 00000000..2b27a039
--- /dev/null
+++ b/keystone/credential/routers.py
@@ -0,0 +1,26 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# 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.
+
+"""WSGI Routers for the Credentials service."""
+
+from keystone.common import router
+from keystone.credential import controllers
+
+
+def append_v3_routers(mapper, routers):
+ routers.append(
+ router.Router(controllers.CredentialV3(),
+ 'credentials', 'credential'))