summaryrefslogtreecommitdiffstats
path: root/keystone/assignment
diff options
context:
space:
mode:
authorHenry Nash <henryn@linux.vnet.ibm.com>2013-07-05 06:04:25 +0100
committerHenry Nash <henryn@linux.vnet.ibm.com>2013-07-10 05:23:00 +0100
commit661cef927e95cf87a96eea7f0f6d840f8bf4adcd (patch)
tree50762c60adead7c8c557696da8b70b2c87da6283 /keystone/assignment
parentfafdf072f5a34ee12ffe9d7651551c83459759bb (diff)
downloadkeystone-661cef927e95cf87a96eea7f0f6d840f8bf4adcd.tar.gz
keystone-661cef927e95cf87a96eea7f0f6d840f8bf4adcd.tar.xz
keystone-661cef927e95cf87a96eea7f0f6d840f8bf4adcd.zip
Rationalize how we get roles after authentication in the controllers
Currently there is a mixture of strategies in the v2 and v3 controllers for how to get the roles assigned for the scope of the requested authentication. This duplicates code, is hard to maintain and in at least once case (where your only roles on a project are due to a group membership) is not actually correct (for v2 tokens). This change does the following: - Standardizes on using the 'get_roles_for_user_and_project()', and its domain equivalent, for how roles are obtained to build a token. This was already the case for v3 tokens. The controllers no longer need to get metadata and extract the roles. - Removes the driver level function to 'authorize_for_project' - this is now handled wihin the controller. The driver simply supports the user authentication. A nice (and planned for) sideffect of the above is that we now hide the schema of how we store roles within the driver layer - i.e. nothing outside of the driver (other than any specific-to-implementation tests) have to know about how roles are stored in the metadata. This paves the way for a re-implementation of the grant tables in IceHouse. This change also fills in missing function definitons in the assignment driver. Implements bp authenticate-role-rationalization Change-Id: I75fc7f5f728649d40ab1c696b33bbcd88ea6edee
Diffstat (limited to 'keystone/assignment')
-rw-r--r--keystone/assignment/backends/kvs.py73
-rw-r--r--keystone/assignment/backends/ldap.py31
-rw-r--r--keystone/assignment/backends/sql.py101
-rw-r--r--keystone/assignment/core.py81
4 files changed, 107 insertions, 179 deletions
diff --git a/keystone/assignment/backends/kvs.py b/keystone/assignment/backends/kvs.py
index 9a09598f..4ed3937b 100644
--- a/keystone/assignment/backends/kvs.py
+++ b/keystone/assignment/backends/kvs.py
@@ -26,22 +26,6 @@ class Assignment(kvs.Base, assignment.Driver):
super(Assignment, self).__init__()
# Public interface
- def authorize_for_project(self, user_ref, tenant_id=None):
- user_id = user_ref['id']
- tenant_ref = None
- metadata_ref = {}
- if tenant_id is not None:
- if tenant_id not in self.get_projects_for_user(user_id):
- raise AssertionError('Invalid tenant')
- try:
- tenant_ref = self.get_project(tenant_id)
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.ProjectNotFound:
- tenant_ref = None
- metadata_ref = {}
- except exception.MetadataNotFound:
- metadata_ref = {}
- return (identity.filter_user(user_ref), tenant_ref, metadata_ref)
def get_project(self, tenant_id):
try:
@@ -79,8 +63,8 @@ class Assignment(kvs.Base, assignment.Driver):
except exception.NotFound:
raise exception.UserNotFound(user_id=user_name)
- def get_metadata(self, user_id=None, tenant_id=None,
- domain_id=None, group_id=None):
+ def _get_metadata(self, user_id=None, tenant_id=None,
+ domain_id=None, group_id=None):
try:
if user_id:
if tenant_id:
@@ -113,21 +97,12 @@ class Assignment(kvs.Base, assignment.Driver):
user_ref = self._get_user(user_id)
return user_ref.get('tenants', [])
- def get_roles_for_user_and_project(self, user_id, tenant_id):
- self.identity_api.get_user(user_id)
- self.get_project(tenant_id)
- try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- return metadata_ref.get('roles', [])
-
def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
self.identity_api.get_user(user_id)
self.get_project(tenant_id)
self.get_role(role_id)
try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
+ metadata_ref = self._get_metadata(user_id, tenant_id)
except exception.MetadataNotFound:
metadata_ref = {}
roles = set(metadata_ref.get('roles', []))
@@ -137,11 +112,11 @@ class Assignment(kvs.Base, assignment.Driver):
raise exception.Conflict(type='role grant', details=msg)
roles.add(role_id)
metadata_ref['roles'] = list(roles)
- self.update_metadata(user_id, tenant_id, metadata_ref)
+ self._update_metadata(user_id, tenant_id, metadata_ref)
def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
+ metadata_ref = self._get_metadata(user_id, tenant_id)
except exception.MetadataNotFound:
metadata_ref = {}
roles = set(metadata_ref.get('roles', []))
@@ -160,7 +135,7 @@ class Assignment(kvs.Base, assignment.Driver):
user_ref['tenants'] = list(tenants)
self.identity_api.update_user(user_id, user_ref)
else:
- self.update_metadata(user_id, tenant_id, metadata_ref)
+ self._update_metadata(user_id, tenant_id, metadata_ref)
def list_role_assignments(self):
"""List the role assignments.
@@ -255,14 +230,14 @@ class Assignment(kvs.Base, assignment.Driver):
self.db.delete('tenant_name-%s' % old_project['name'])
self.db.delete('tenant-%s' % tenant_id)
- def create_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
+ def _create_metadata(self, user_id, tenant_id, metadata,
+ domain_id=None, group_id=None):
- return self.update_metadata(user_id, tenant_id, metadata,
- domain_id, group_id)
+ return self._update_metadata(user_id, tenant_id, metadata,
+ domain_id, group_id)
- def update_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
+ def _update_metadata(self, user_id, tenant_id, metadata,
+ domain_id=None, group_id=None):
if user_id:
if tenant_id:
self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata)
@@ -362,15 +337,15 @@ class Assignment(kvs.Base, assignment.Driver):
self.get_project(project_id)
try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
except exception.MetadataNotFound:
metadata_ref = {}
roles = set(metadata_ref.get('roles', []))
roles.add(role_id)
metadata_ref['roles'] = list(roles)
- self.update_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
+ self._update_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
def list_grants(self, user_id=None, group_id=None,
domain_id=None, project_id=None):
@@ -384,8 +359,8 @@ class Assignment(kvs.Base, assignment.Driver):
self.get_project(project_id)
try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
except exception.MetadataNotFound:
metadata_ref = {}
return [self.get_role(x) for x in metadata_ref.get('roles', [])]
@@ -403,8 +378,8 @@ class Assignment(kvs.Base, assignment.Driver):
self.get_project(project_id)
try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
except exception.MetadataNotFound:
metadata_ref = {}
role_ids = set(metadata_ref.get('roles', []))
@@ -425,8 +400,8 @@ class Assignment(kvs.Base, assignment.Driver):
self.get_project(project_id)
try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
except exception.MetadataNotFound:
metadata_ref = {}
roles = set(metadata_ref.get('roles', []))
@@ -435,8 +410,8 @@ class Assignment(kvs.Base, assignment.Driver):
except KeyError:
raise exception.RoleNotFound(role_id=role_id)
metadata_ref['roles'] = list(roles)
- self.update_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
+ self._update_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
# domain crud
diff --git a/keystone/assignment/backends/ldap.py b/keystone/assignment/backends/ldap.py
index 500f304a..44a479bf 100644
--- a/keystone/assignment/backends/ldap.py
+++ b/keystone/assignment/backends/ldap.py
@@ -26,7 +26,6 @@ from keystone.common import logging
from keystone.common import models
from keystone import config
from keystone import exception
-from keystone import identity
from keystone.identity.backends import ldap as ldap_identity
@@ -70,29 +69,6 @@ class Assignment(assignment.Driver):
#once we remove here. the getter and setter can be removed as well.
self._identity_api.driver.project = self.project
- def authorize_for_project(self, user_ref, tenant_id=None):
- user_id = user_ref['id']
- tenant_ref = None
- metadata_ref = {}
-
- if tenant_id is not None:
- if tenant_id not in self.get_projects_for_user(user_id):
- raise AssertionError('Invalid tenant')
-
- try:
- tenant_ref = self.get_project(tenant_id)
- # TODO(termie): this should probably be made into a
- # get roles call
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.ProjectNotFound:
- tenant_ref = None
- metadata_ref = {}
- except exception.MetadataNotFound:
- metadata_ref = {}
-
- user_ref = self._set_default_domain(identity.filter_user(user_ref))
- return (user_ref, tenant_ref, metadata_ref)
-
def get_project(self, tenant_id):
return self._set_default_domain(self.project.get(tenant_id))
@@ -149,8 +125,9 @@ class Assignment(assignment.Driver):
tenant['name'] = clean.project_name(tenant['name'])
return self._set_default_domain(self.project.update(tenant_id, tenant))
- def get_metadata(self, user_id=None, tenant_id=None,
- domain_id=None, group_id=None):
+ def _get_metadata(self, user_id=None, tenant_id=None,
+ domain_id=None, group_id=None):
+
def _get_roles_for_just_user_and_project(user_id, tenant_id):
self.identity_api.get_user(user_id)
self.get_project(tenant_id)
@@ -216,7 +193,7 @@ class Assignment(assignment.Driver):
user_dn=user_dn,
tenant_dn=tenant_dn)
- def create_metadata(self, user_id, tenant_id, metadata):
+ def _create_metadata(self, user_id, tenant_id, metadata):
return {}
def create_role(self, role_id, role):
diff --git a/keystone/assignment/backends/sql.py b/keystone/assignment/backends/sql.py
index 65d1bbc7..57ca7834 100644
--- a/keystone/assignment/backends/sql.py
+++ b/keystone/assignment/backends/sql.py
@@ -19,7 +19,6 @@ from keystone import clean
from keystone.common import sql
from keystone.common.sql import migration
from keystone import exception
-from keystone import identity
class Assignment(sql.Base, assignment.Driver):
@@ -31,26 +30,6 @@ class Assignment(sql.Base, assignment.Driver):
def db_sync(self, version=None):
migration.db_sync(version=version)
- def authorize_for_project(self, user_ref, tenant_id=None):
- user_id = user_ref['id']
- tenant_ref = None
- metadata_ref = {}
- if tenant_id is not None:
- # FIXME(gyee): this should really be
- # get_roles_for_user_and_project() after the dusts settle
- if tenant_id not in self.get_projects_for_user(user_id):
- raise AssertionError('Invalid project')
- try:
- tenant_ref = self.get_project(tenant_id)
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.ProjectNotFound:
- tenant_ref = None
- metadata_ref = {}
- except exception.MetadataNotFound:
- metadata_ref = {}
- user_ref = identity.filter_user(user_ref.to_dict())
- return (user_ref, tenant_ref, metadata_ref)
-
def _get_project(self, session, project_id):
project_ref = session.query(Project).get(project_id)
if project_ref is None:
@@ -91,8 +70,8 @@ class Assignment(sql.Base, assignment.Driver):
user_refs.append(user_ref)
return user_refs
- def get_metadata(self, user_id=None, tenant_id=None,
- domain_id=None, group_id=None):
+ def _get_metadata(self, user_id=None, tenant_id=None,
+ domain_id=None, group_id=None):
session = self.get_session()
if user_id:
@@ -130,8 +109,8 @@ class Assignment(sql.Base, assignment.Driver):
self._get_project(session, project_id)
try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
is_new = False
except exception.MetadataNotFound:
metadata_ref = {}
@@ -140,11 +119,11 @@ class Assignment(sql.Base, assignment.Driver):
roles.add(role_id)
metadata_ref['roles'] = list(roles)
if is_new:
- self.create_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
+ self._create_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
else:
- self.update_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
+ self._update_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
def list_grants(self, user_id=None, group_id=None,
domain_id=None, project_id=None):
@@ -159,8 +138,8 @@ class Assignment(sql.Base, assignment.Driver):
self._get_project(session, project_id)
try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
except exception.MetadataNotFound:
metadata_ref = {}
return [self.get_role(x) for x in metadata_ref.get('roles', [])]
@@ -179,8 +158,8 @@ class Assignment(sql.Base, assignment.Driver):
self._get_project(session, project_id)
try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
except exception.MetadataNotFound:
metadata_ref = {}
role_ids = set(metadata_ref.get('roles', []))
@@ -202,8 +181,8 @@ class Assignment(sql.Base, assignment.Driver):
self._get_project(session, project_id)
try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
is_new = False
except exception.MetadataNotFound:
metadata_ref = {}
@@ -215,11 +194,11 @@ class Assignment(sql.Base, assignment.Driver):
raise exception.RoleNotFound(role_id=role_id)
metadata_ref['roles'] = list(roles)
if is_new:
- self.create_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
+ self._create_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
else:
- self.update_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
+ self._update_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
def list_projects(self):
session = self.get_session()
@@ -234,39 +213,13 @@ class Assignment(sql.Base, assignment.Driver):
membership_refs = query.all()
return [x.project_id for x in membership_refs]
- def _get_user_group_project_roles(self, metadata_ref, user_id, project_id):
- group_refs = self.identity_api.list_groups_for_user(user_id=user_id)
- for x in group_refs:
- try:
- metadata_ref.update(
- self.get_metadata(group_id=x['id'],
- tenant_id=project_id))
- except exception.MetadataNotFound:
- # no group grant, skip
- pass
-
- def _get_user_project_roles(self, metadata_ref, user_id, project_id):
- try:
- metadata_ref.update(self.get_metadata(user_id, project_id))
- except exception.MetadataNotFound:
- pass
-
- def get_roles_for_user_and_project(self, user_id, tenant_id):
- session = self.get_session()
- self.identity_api._get_user(session, user_id)
- self._get_project(session, tenant_id)
- metadata_ref = {}
- self._get_user_project_roles(metadata_ref, user_id, tenant_id)
- self._get_user_group_project_roles(metadata_ref, user_id, tenant_id)
- return list(set(metadata_ref.get('roles', [])))
-
def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
session = self.get_session()
self.identity_api._get_user(session, user_id)
self._get_project(session, tenant_id)
self._get_role(session, role_id)
try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
+ metadata_ref = self._get_metadata(user_id, tenant_id)
is_new = False
except exception.MetadataNotFound:
metadata_ref = {}
@@ -279,13 +232,13 @@ class Assignment(sql.Base, assignment.Driver):
roles.add(role_id)
metadata_ref['roles'] = list(roles)
if is_new:
- self.create_metadata(user_id, tenant_id, metadata_ref)
+ self._create_metadata(user_id, tenant_id, metadata_ref)
else:
- self.update_metadata(user_id, tenant_id, metadata_ref)
+ self._update_metadata(user_id, tenant_id, metadata_ref)
def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
+ metadata_ref = self._get_metadata(user_id, tenant_id)
roles = set(metadata_ref.get('roles', []))
if role_id not in roles:
raise exception.RoleNotFound(message=_(
@@ -294,7 +247,7 @@ class Assignment(sql.Base, assignment.Driver):
roles.remove(role_id)
metadata_ref['roles'] = list(roles)
if len(roles):
- self.update_metadata(user_id, tenant_id, metadata_ref)
+ self._update_metadata(user_id, tenant_id, metadata_ref)
else:
session = self.get_session()
q = session.query(UserProjectGrant)
@@ -396,8 +349,8 @@ class Assignment(sql.Base, assignment.Driver):
session.flush()
@sql.handle_conflicts(type='metadata')
- def create_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
+ def _create_metadata(self, user_id, tenant_id, metadata,
+ domain_id=None, group_id=None):
session = self.get_session()
with session.begin():
if user_id:
@@ -426,8 +379,8 @@ class Assignment(sql.Base, assignment.Driver):
return metadata
@sql.handle_conflicts(type='metadata')
- def update_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
+ def _update_metadata(self, user_id, tenant_id, metadata,
+ domain_id=None, group_id=None):
session = self.get_session()
with session.begin():
if user_id:
diff --git a/keystone/assignment/core.py b/keystone/assignment/core.py
index 251a3bc6..879fee0b 100644
--- a/keystone/assignment/core.py
+++ b/keystone/assignment/core.py
@@ -58,8 +58,8 @@ class Manager(manager.Manager):
(user_id=user_id))
for x in group_refs:
try:
- metadata_ref = self.get_metadata(group_id=x['id'],
- tenant_id=tenant_id)
+ metadata_ref = self._get_metadata(group_id=x['id'],
+ tenant_id=tenant_id)
role_list += metadata_ref.get('roles', [])
except exception.MetadataNotFound:
# no group grant, skip
@@ -69,8 +69,8 @@ class Manager(manager.Manager):
def _get_user_project_roles(user_id, tenant_id):
metadata_ref = {}
try:
- metadata_ref = self.get_metadata(user_id=user_id,
- tenant_id=tenant_id)
+ metadata_ref = self._get_metadata(user_id=user_id,
+ tenant_id=tenant_id)
except exception.MetadataNotFound:
pass
return metadata_ref.get('roles', [])
@@ -97,8 +97,8 @@ class Manager(manager.Manager):
list_groups_for_user(user_id=user_id))
for x in group_refs:
try:
- metadata_ref = self.get_metadata(group_id=x['id'],
- domain_id=domain_id)
+ metadata_ref = self._get_metadata(group_id=x['id'],
+ domain_id=domain_id)
role_list += metadata_ref.get('roles', [])
except (exception.MetadataNotFound, exception.NotImplemented):
# MetadataNotFound implies no group grant, so skip.
@@ -110,8 +110,8 @@ class Manager(manager.Manager):
def _get_user_domain_roles(user_id, domain_id):
metadata_ref = {}
try:
- metadata_ref = self.get_metadata(user_id=user_id,
- domain_id=domain_id)
+ metadata_ref = self._get_metadata(user_id=user_id,
+ domain_id=domain_id)
except (exception.MetadataNotFound, exception.NotImplemented):
# MetadataNotFound implies no user grants.
# Ignore NotImplemented since not all backends support
@@ -152,12 +152,6 @@ class Manager(manager.Manager):
class Driver(object):
- def authorize_for_project(self, tenant_id, user_ref):
- """Authenticate a given user for a tenant.
- :returns: (user_ref, tenant_ref, metadata_ref)
- :raises: AssertionError
- """
- raise exception.NotImplemented()
def get_project_by_name(self, tenant_name, domain_id):
"""Get a tenant by name.
@@ -205,39 +199,68 @@ class Driver(object):
"""
raise exception.NotImplemented()
- def list_role_assignments(self):
+ # assignment/grant crud
+
+ def create_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None):
+ """Creates a new assignment/grant.
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.GroupNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.DomainNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.RoleNotFound
+
+ """
raise exception.NotImplemented()
- # metadata crud
- def get_metadata(self, user_id=None, tenant_id=None,
- domain_id=None, group_id=None):
- """Gets the metadata for the specified user/group on project/domain.
+ def list_grants(self, user_id=None, group_id=None,
+ domain_id=None, project_id=None):
+ """Lists assignments/grants.
- :raises: keystone.exception.MetadataNotFound
- :returns: metadata
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.GroupNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.DomainNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.RoleNotFound
"""
raise exception.NotImplemented()
- def create_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
- """Creates the metadata for the specified user/group on project/domain.
+ def get_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None):
+ """Lists assignments/grants.
- :returns: metadata created
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.GroupNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.DomainNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.RoleNotFound
"""
raise exception.NotImplemented()
- def update_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
- """Updates the metadata for the specified user/group on project/domain.
+ def delete_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None):
+ """Lists assignments/grants.
- :returns: metadata updated
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.GroupNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.DomainNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.RoleNotFound
"""
raise exception.NotImplemented()
+ def list_role_assignments(self):
+
+ raise exception.NotImplemented()
+
# domain crud
def create_domain(self, domain_id, domain):
"""Creates a new domain.