aboutsummaryrefslogtreecommitdiffstats
path: root/keystone-moon/keystone/assignment/backends/sql.py
diff options
context:
space:
mode:
Diffstat (limited to 'keystone-moon/keystone/assignment/backends/sql.py')
-rw-r--r--keystone-moon/keystone/assignment/backends/sql.py252
1 files changed, 36 insertions, 216 deletions
diff --git a/keystone-moon/keystone/assignment/backends/sql.py b/keystone-moon/keystone/assignment/backends/sql.py
index e249ba34..e089726a 100644
--- a/keystone-moon/keystone/assignment/backends/sql.py
+++ b/keystone-moon/keystone/assignment/backends/sql.py
@@ -12,21 +12,12 @@
# License for the specific language governing permissions and limitations
# under the License.
-from oslo_config import cfg
-from oslo_log import log
-import sqlalchemy
-from sqlalchemy.sql.expression import false
-
from keystone import assignment as keystone_assignment
from keystone.common import sql
from keystone import exception
from keystone.i18n import _
-CONF = cfg.CONF
-LOG = log.getLogger(__name__)
-
-
class AssignmentType(object):
USER_PROJECT = 'UserProject'
GROUP_PROJECT = 'GroupProject'
@@ -49,7 +40,7 @@ class AssignmentType(object):
raise exception.AssignmentTypeCalculationError(**locals())
-class Assignment(keystone_assignment.AssignmentDriverV8):
+class Assignment(keystone_assignment.AssignmentDriverV9):
def default_role_driver(self):
return 'sql'
@@ -57,60 +48,6 @@ class Assignment(keystone_assignment.AssignmentDriverV8):
def default_resource_driver(self):
return 'sql'
- def list_user_ids_for_project(self, tenant_id):
- with sql.transaction() as session:
- query = session.query(RoleAssignment.actor_id)
- query = query.filter_by(type=AssignmentType.USER_PROJECT)
- query = query.filter_by(target_id=tenant_id)
- query = query.distinct('actor_id')
- assignments = query.all()
- return [assignment.actor_id for assignment in assignments]
-
- def _get_metadata(self, user_id=None, tenant_id=None,
- domain_id=None, group_id=None, session=None):
- # TODO(henry-nash): This method represents the last vestiges of the old
- # metadata concept in this driver. Although we no longer need it here,
- # since the Manager layer uses the metadata concept across all
- # assignment drivers, we need to remove it from all of them in order to
- # finally remove this method.
-
- # We aren't given a session when called by the manager directly.
- if session is None:
- session = sql.get_session()
-
- q = session.query(RoleAssignment)
-
- def _calc_assignment_type():
- # Figure out the assignment type we're checking for from the args.
- if user_id:
- if tenant_id:
- return AssignmentType.USER_PROJECT
- else:
- return AssignmentType.USER_DOMAIN
- else:
- if tenant_id:
- return AssignmentType.GROUP_PROJECT
- else:
- return AssignmentType.GROUP_DOMAIN
-
- q = q.filter_by(type=_calc_assignment_type())
- q = q.filter_by(actor_id=user_id or group_id)
- q = q.filter_by(target_id=tenant_id or domain_id)
- refs = q.all()
- if not refs:
- raise exception.MetadataNotFound()
-
- metadata_ref = {}
- metadata_ref['roles'] = []
- for assignment in refs:
- role_ref = {}
- role_ref['id'] = assignment.role_id
- if assignment.inherited:
- role_ref['inherited_to'] = 'projects'
- metadata_ref['roles'].append(role_ref)
-
- return metadata_ref
-
def create_grant(self, role_id, user_id=None, group_id=None,
domain_id=None, project_id=None,
inherited_to_projects=False):
@@ -118,21 +55,21 @@ class Assignment(keystone_assignment.AssignmentDriverV8):
assignment_type = AssignmentType.calculate_type(
user_id, group_id, project_id, domain_id)
try:
- with sql.transaction() as session:
+ with sql.session_for_write() as session:
session.add(RoleAssignment(
type=assignment_type,
actor_id=user_id or group_id,
target_id=project_id or domain_id,
role_id=role_id,
inherited=inherited_to_projects))
- except sql.DBDuplicateEntry:
- # The v3 grant APIs are silent if the assignment already exists
+ except sql.DBDuplicateEntry: # nosec : The v3 grant APIs are silent if
+ # the assignment already exists
pass
def list_grant_role_ids(self, user_id=None, group_id=None,
domain_id=None, project_id=None,
inherited_to_projects=False):
- with sql.transaction() as session:
+ with sql.session_for_read() as session:
q = session.query(RoleAssignment.role_id)
q = q.filter(RoleAssignment.actor_id == (user_id or group_id))
q = q.filter(RoleAssignment.target_id == (project_id or domain_id))
@@ -151,7 +88,7 @@ class Assignment(keystone_assignment.AssignmentDriverV8):
def check_grant_role_id(self, role_id, user_id=None, group_id=None,
domain_id=None, project_id=None,
inherited_to_projects=False):
- with sql.transaction() as session:
+ with sql.session_for_read() as session:
try:
q = self._build_grant_filter(
session, role_id, user_id, group_id, domain_id, project_id,
@@ -167,7 +104,7 @@ class Assignment(keystone_assignment.AssignmentDriverV8):
def delete_grant(self, role_id, user_id=None, group_id=None,
domain_id=None, project_id=None,
inherited_to_projects=False):
- with sql.transaction() as session:
+ with sql.session_for_write() as session:
q = self._build_grant_filter(
session, role_id, user_id, group_id, domain_id, project_id,
inherited_to_projects)
@@ -178,143 +115,9 @@ class Assignment(keystone_assignment.AssignmentDriverV8):
actor_id=actor_id,
target_id=target_id)
- def _list_project_ids_for_actor(self, actors, hints, inherited,
- group_only=False):
- # TODO(henry-nash): Now that we have a single assignment table, we
- # should be able to honor the hints list that is provided.
-
- assignment_type = [AssignmentType.GROUP_PROJECT]
- if not group_only:
- assignment_type.append(AssignmentType.USER_PROJECT)
-
- sql_constraints = sqlalchemy.and_(
- RoleAssignment.type.in_(assignment_type),
- RoleAssignment.inherited == inherited,
- RoleAssignment.actor_id.in_(actors))
-
- with sql.transaction() as session:
- query = session.query(RoleAssignment.target_id).filter(
- sql_constraints).distinct()
-
- return [x.target_id for x in query.all()]
-
- def list_project_ids_for_user(self, user_id, group_ids, hints,
- inherited=False):
- actor_list = [user_id]
- if group_ids:
- actor_list = actor_list + group_ids
-
- return self._list_project_ids_for_actor(actor_list, hints, inherited)
-
- def list_domain_ids_for_user(self, user_id, group_ids, hints,
- inherited=False):
- with sql.transaction() as session:
- query = session.query(RoleAssignment.target_id)
- filters = []
-
- if user_id:
- sql_constraints = sqlalchemy.and_(
- RoleAssignment.actor_id == user_id,
- RoleAssignment.inherited == inherited,
- RoleAssignment.type == AssignmentType.USER_DOMAIN)
- filters.append(sql_constraints)
-
- if group_ids:
- sql_constraints = sqlalchemy.and_(
- RoleAssignment.actor_id.in_(group_ids),
- RoleAssignment.inherited == inherited,
- RoleAssignment.type == AssignmentType.GROUP_DOMAIN)
- filters.append(sql_constraints)
-
- if not filters:
- return []
-
- query = query.filter(sqlalchemy.or_(*filters)).distinct()
-
- return [assignment.target_id for assignment in query.all()]
-
- def list_role_ids_for_groups_on_domain(self, group_ids, domain_id):
- if not group_ids:
- # If there's no groups then there will be no domain roles.
- return []
-
- sql_constraints = sqlalchemy.and_(
- RoleAssignment.type == AssignmentType.GROUP_DOMAIN,
- RoleAssignment.target_id == domain_id,
- RoleAssignment.inherited == false(),
- RoleAssignment.actor_id.in_(group_ids))
-
- with sql.transaction() as session:
- query = session.query(RoleAssignment.role_id).filter(
- sql_constraints).distinct()
- return [role.role_id for role in query.all()]
-
- def list_role_ids_for_groups_on_project(
- self, group_ids, project_id, project_domain_id, project_parents):
-
- if not group_ids:
- # If there's no groups then there will be no project roles.
- return []
-
- # NOTE(rodrigods): First, we always include projects with
- # non-inherited assignments
- sql_constraints = sqlalchemy.and_(
- RoleAssignment.type == AssignmentType.GROUP_PROJECT,
- RoleAssignment.inherited == false(),
- RoleAssignment.target_id == project_id)
-
- if CONF.os_inherit.enabled:
- # Inherited roles from domains
- sql_constraints = sqlalchemy.or_(
- sql_constraints,
- sqlalchemy.and_(
- RoleAssignment.type == AssignmentType.GROUP_DOMAIN,
- RoleAssignment.inherited,
- RoleAssignment.target_id == project_domain_id))
-
- # Inherited roles from projects
- if project_parents:
- sql_constraints = sqlalchemy.or_(
- sql_constraints,
- sqlalchemy.and_(
- RoleAssignment.type == AssignmentType.GROUP_PROJECT,
- RoleAssignment.inherited,
- RoleAssignment.target_id.in_(project_parents)))
-
- sql_constraints = sqlalchemy.and_(
- sql_constraints, RoleAssignment.actor_id.in_(group_ids))
-
- with sql.transaction() as session:
- # NOTE(morganfainberg): Only select the columns we actually care
- # about here, in this case role_id.
- query = session.query(RoleAssignment.role_id).filter(
- sql_constraints).distinct()
-
- return [result.role_id for result in query.all()]
-
- def list_project_ids_for_groups(self, group_ids, hints,
- inherited=False):
- return self._list_project_ids_for_actor(
- group_ids, hints, inherited, group_only=True)
-
- def list_domain_ids_for_groups(self, group_ids, inherited=False):
- if not group_ids:
- # If there's no groups then there will be no domains.
- return []
-
- group_sql_conditions = sqlalchemy.and_(
- RoleAssignment.type == AssignmentType.GROUP_DOMAIN,
- RoleAssignment.inherited == inherited,
- RoleAssignment.actor_id.in_(group_ids))
-
- with sql.transaction() as session:
- query = session.query(RoleAssignment.target_id).filter(
- group_sql_conditions).distinct()
- return [x.target_id for x in query.all()]
-
def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
try:
- with sql.transaction() as session:
+ with sql.session_for_write() as session:
session.add(RoleAssignment(
type=AssignmentType.USER_PROJECT,
actor_id=user_id, target_id=tenant_id,
@@ -325,7 +128,7 @@ class Assignment(keystone_assignment.AssignmentDriverV8):
raise exception.Conflict(type='role grant', details=msg)
def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
- with sql.transaction() as session:
+ with sql.session_for_write() as session:
q = session.query(RoleAssignment)
q = q.filter_by(actor_id=user_id)
q = q.filter_by(target_id=tenant_id)
@@ -415,7 +218,7 @@ class Assignment(keystone_assignment.AssignmentDriverV8):
assignment['inherited_to_projects'] = 'projects'
return assignment
- with sql.transaction() as session:
+ with sql.session_for_read() as session:
assignment_types = self._get_assignment_types(
user_id, group_ids, project_ids, domain_id)
@@ -447,34 +250,51 @@ class Assignment(keystone_assignment.AssignmentDriverV8):
return [denormalize_role(ref) for ref in query.all()]
def delete_project_assignments(self, project_id):
- with sql.transaction() as session:
+ with sql.session_for_write() as session:
q = session.query(RoleAssignment)
- q = q.filter_by(target_id=project_id)
+ q = q.filter_by(target_id=project_id).filter(
+ RoleAssignment.type.in_((AssignmentType.USER_PROJECT,
+ AssignmentType.GROUP_PROJECT))
+ )
q.delete(False)
def delete_role_assignments(self, role_id):
- with sql.transaction() as session:
+ with sql.session_for_write() as session:
q = session.query(RoleAssignment)
q = q.filter_by(role_id=role_id)
q.delete(False)
+ def delete_domain_assignments(self, domain_id):
+ with sql.session_for_write() as session:
+ q = session.query(RoleAssignment)
+ q = q.filter(RoleAssignment.target_id == domain_id).filter(
+ (RoleAssignment.type == AssignmentType.USER_DOMAIN) |
+ (RoleAssignment.type == AssignmentType.GROUP_DOMAIN))
+ q.delete(False)
+
def delete_user_assignments(self, user_id):
- with sql.transaction() as session:
+ with sql.session_for_write() as session:
q = session.query(RoleAssignment)
- q = q.filter_by(actor_id=user_id)
+ q = q.filter_by(actor_id=user_id).filter(
+ RoleAssignment.type.in_((AssignmentType.USER_PROJECT,
+ AssignmentType.USER_DOMAIN))
+ )
q.delete(False)
def delete_group_assignments(self, group_id):
- with sql.transaction() as session:
+ with sql.session_for_write() as session:
q = session.query(RoleAssignment)
- q = q.filter_by(actor_id=group_id)
+ q = q.filter_by(actor_id=group_id).filter(
+ RoleAssignment.type.in_((AssignmentType.GROUP_PROJECT,
+ AssignmentType.GROUP_DOMAIN))
+ )
q.delete(False)
class RoleAssignment(sql.ModelBase, sql.DictBase):
__tablename__ = 'assignment'
attributes = ['type', 'actor_id', 'target_id', 'role_id', 'inherited']
- # NOTE(henry-nash); Postgres requires a name to be defined for an Enum
+ # NOTE(henry-nash): Postgres requires a name to be defined for an Enum
type = sql.Column(
sql.Enum(AssignmentType.USER_PROJECT, AssignmentType.GROUP_PROJECT,
AssignmentType.USER_DOMAIN, AssignmentType.GROUP_DOMAIN,
@@ -491,7 +311,7 @@ class RoleAssignment(sql.ModelBase, sql.DictBase):
)
def to_dict(self):
- """Override parent to_dict() method with a simpler implementation.
+ """Override parent method with a simpler implementation.
RoleAssignment doesn't have non-indexed 'extra' attributes, so the
parent implementation is not applicable.