Ejemplo n.º 1
0
    def sync_group_to_role_maps(self, group_to_role_map_apis):
        LOG.info("Synchronizing group to role maps...")

        # Retrieve all the mappings currently in the db
        group_to_role_map_dbs = rbac_service.get_all_group_to_role_maps()

        # 1. Delete all the existing mappings in the db
        group_to_role_map_to_delete = []
        for group_to_role_map_db in group_to_role_map_dbs:
            group_to_role_map_to_delete.append(group_to_role_map_db.id)

        GroupToRoleMapping.query(id__in=group_to_role_map_to_delete).delete()

        # 2. Insert all mappings read from disk
        for group_to_role_map_api in group_to_role_map_apis:
            source = getattr(group_to_role_map_api, "file_path", None)
            rbac_service.create_group_to_role_map(
                group=group_to_role_map_api.group,
                roles=group_to_role_map_api.roles,
                description=group_to_role_map_api.description,
                enabled=group_to_role_map_api.enabled,
                source=source,
            )

        LOG.info("Group to role map definitions synchronized.")
Ejemplo n.º 2
0
    def sync_group_to_role_maps(self, group_to_role_map_apis):
        LOG.info('Synchronizing group to role maps...')

        # Retrieve all the mappings currently in the db
        group_to_role_map_dbs = rbac_services.get_all_group_to_role_maps()

        # 1. Delete all the existing mappings in the db
        group_to_role_map_to_delete = []
        for group_to_role_map_db in group_to_role_map_dbs:
            group_to_role_map_to_delete.append(group_to_role_map_db.id)

        GroupToRoleMapping.query(id__in=group_to_role_map_to_delete).delete()

        # 2. Insert all mappings read from disk
        for group_to_role_map_api in group_to_role_map_apis:
            source = getattr(group_to_role_map_api, 'file_path', None)
            rbac_services.create_group_to_role_map(group=group_to_role_map_api.group,
                                                   roles=group_to_role_map_api.roles,
                                                   description=group_to_role_map_api.description,
                                                   enabled=group_to_role_map_api.enabled,
                                                   source=source)

        LOG.info('Group to role map definitions synchronized.')
Ejemplo n.º 3
0
    def sync(self, user_db, groups):
        """
        :param user_db: User to sync the assignments for.
        :type user: :class:`UserDB`

        :param groups: A list of remote groups user is a member of.
        :type groups: ``list`` of ``str``

        :return: A list of mappings which have been created.
        :rtype: ``list`` of :class:`UserRoleAssignmentDB`
        """
        groups = list(set(groups))

        extra = {'user_db': user_db, 'groups': groups}
        LOG.info('Synchronizing remote role assignments for user "%s"' %
                 (str(user_db)),
                 extra=extra)

        # 1. Retrieve group to role mappings for the provided groups
        all_mapping_dbs = GroupToRoleMapping.query(group__in=groups)
        enabled_mapping_dbs = [
            mapping_db for mapping_db in all_mapping_dbs if mapping_db.enabled
        ]
        disabled_mapping_dbs = [
            mapping_db for mapping_db in all_mapping_dbs
            if not mapping_db.enabled
        ]

        if not all_mapping_dbs:
            LOG.debug('No group to role mappings found for user "%s"' %
                      (str(user_db)),
                      extra=extra)

        # 2. Remove all the existing remote role assignments
        remote_assignment_dbs = UserRoleAssignment.query(user=user_db.name,
                                                         is_remote=True)

        existing_role_names = [
            assignment_db.role for assignment_db in remote_assignment_dbs
        ]
        existing_role_names = set(existing_role_names)
        current_role_names = set([])

        for mapping_db in all_mapping_dbs:
            for role in mapping_db.roles:
                current_role_names.add(role)

        # A list of new role assignments which should be added to the database
        new_role_names = current_role_names.difference(existing_role_names)

        # A list of role assignments which need to be updated in the database
        updated_role_names = existing_role_names.intersection(
            current_role_names)

        # A list of role assignments which should be removed from the database
        removed_role_names = (existing_role_names - new_role_names)

        # Also remove any assignments for mappings which are disabled in the database
        for mapping_db in disabled_mapping_dbs:
            for role in mapping_db.roles:
                removed_role_names.add(role)

        LOG.debug('New role assignments: %r' % (new_role_names))
        LOG.debug('Updated role assignments: %r' % (updated_role_names))
        LOG.debug('Removed role assignments: %r' % (removed_role_names))

        # Build a list of role assignments to delete
        role_names_to_delete = updated_role_names.union(removed_role_names)
        role_assignment_dbs_to_delete = [
            role_assignment_db for role_assignment_db in remote_assignment_dbs
            if role_assignment_db.role in role_names_to_delete
        ]

        UserRoleAssignment.query(user=user_db.name,
                                 role__in=role_names_to_delete,
                                 is_remote=True).delete()

        # 3. Create role assignments for all the current groups
        created_assignments_dbs = []
        for mapping_db in enabled_mapping_dbs:
            extra['mapping_db'] = mapping_db

            for role_name in mapping_db.roles:
                role_db = rbac_services.get_role_by_name(name=role_name)

                if not role_db:
                    # Gracefully skip assignment for role which doesn't exist in the db
                    LOG.info(
                        'Role with name "%s" for mapping "%s" not found, skipping assignment.'
                        % (role_name, str(mapping_db)),
                        extra=extra)
                    continue

                description = (
                    'Automatic role assignment based on the remote user membership in '
                    'group "%s"' % (mapping_db.group))
                assignment_db = rbac_services.assign_role_to_user(
                    role_db=role_db,
                    user_db=user_db,
                    description=description,
                    is_remote=True,
                    source=mapping_db.source,
                    ignore_already_exists_error=True)
                assert assignment_db.is_remote is True
                created_assignments_dbs.append(assignment_db)

        LOG.debug('Created %s new remote role assignments for user "%s"' %
                  (len(created_assignments_dbs), str(user_db)),
                  extra=extra)

        return (created_assignments_dbs, role_assignment_dbs_to_delete)
Ejemplo n.º 4
0
    def test_no_mappings_in_db_old_mappings_are_deleted(self):
        # Test case which verifies that existing / old mappings are deleted from db if no mappings
        # exist on disk for a particular set of groups.
        syncer = RBACRemoteGroupToRoleSyncer()
        user_db = self.users['user_1']

        # Create mock mapping which maps CN=stormers,OU=groups,DC=stackstorm,DC=net
        # to "mock_remote_role_3" and CN=testers,OU=groups,DC=stackstorm,DC=net to
        # "mock_remote_role_4"
        create_group_to_role_map(
            group='CN=stormers,OU=groups,DC=stackstorm,DC=net',
            roles=['mock_remote_role_3'],
            source='mappings/stormers.yaml',
            enabled=True)

        create_group_to_role_map(
            group='CN=testers,OU=groups,DC=stackstorm,DC=net',
            roles=['mock_remote_role_4'],
            source='mappings/testers.yaml',
            enabled=True)

        # Verify initial state
        role_dbs = get_roles_for_user(user_db=user_db, include_remote=True)
        self.assertEqual(len(role_dbs), 2)
        self.assertEqual(role_dbs[0], self.roles['mock_local_role_1'])
        self.assertEqual(role_dbs[1], self.roles['mock_local_role_2'])

        groups = [
            'CN=stormers,OU=groups,DC=stackstorm,DC=net',
            'CN=testers,OU=groups,DC=stackstorm,DC=net'
        ]

        # Two new remote assignments should have been created
        # No mappings exist for the groups user is a member of so no new assignments should be
        # created
        result = syncer.sync(user_db=self.users['user_1'], groups=groups)
        created_role_assignment_dbs = result[0]
        removed_role_assignment_dbs = result[1]
        self.assertEqual(len(created_role_assignment_dbs), 2)
        self.assertEqual(created_role_assignment_dbs[0].role,
                         'mock_remote_role_3')
        self.assertEqual(created_role_assignment_dbs[1].role,
                         'mock_remote_role_4')
        self.assertEqual(removed_role_assignment_dbs, [])

        # Verify post sync run state - two new assignments should have been created
        role_dbs = get_roles_for_user(user_db=user_db, include_remote=True)
        self.assertEqual(len(role_dbs), 4)
        self.assertEqual(role_dbs[0], self.roles['mock_local_role_1'])
        self.assertEqual(role_dbs[1], self.roles['mock_local_role_2'])
        self.assertEqual(role_dbs[2], self.roles['mock_remote_role_3'])
        self.assertEqual(role_dbs[3], self.roles['mock_remote_role_4'])

        # Delete all existing mappings, make sure all old assignments are deleted on sync
        GroupToRoleMapping.query(group__in=groups).delete()
        self.assertEqual(len(GroupToRoleMapping.query(group__in=groups)), 0)

        result = syncer.sync(user_db=self.users['user_1'], groups=groups)
        created_role_assignment_dbs = result[0]
        removed_role_assignment_dbs = result[1]

        self.assertEqual(created_role_assignment_dbs, [])
        self.assertEqual(len(removed_role_assignment_dbs), 2)
        self.assertEqual(removed_role_assignment_dbs[0].role,
                         'mock_remote_role_3')
        self.assertEqual(removed_role_assignment_dbs[1].role,
                         'mock_remote_role_4')

        # Verify post sync run state - two old remote assignments should have been deleted, but
        # local assignments shouldn't have been touched
        role_dbs = get_roles_for_user(user_db=user_db, include_remote=True)
        self.assertEqual(len(role_dbs), 2)
        self.assertEqual(role_dbs[0], self.roles['mock_local_role_1'])
        self.assertEqual(role_dbs[1], self.roles['mock_local_role_2'])
Ejemplo n.º 5
0
    def test_no_mappings_in_db_old_mappings_are_deleted(self):
        # Test case which verifies that existing / old mappings are deleted from db if no mappings
        # exist on disk for a particular set of groups.
        syncer = RBACRemoteGroupToRoleSyncer()
        user_db = self.users['user_1']

        # Create mock mapping which maps CN=stormers,OU=groups,DC=stackstorm,DC=net
        # to "mock_remote_role_3" and CN=testers,OU=groups,DC=stackstorm,DC=net to
        # "mock_remote_role_4"
        create_group_to_role_map(group='CN=stormers,OU=groups,DC=stackstorm,DC=net',
                                 roles=['mock_remote_role_3'],
                                 source='mappings/stormers.yaml',
                                 enabled=True)

        create_group_to_role_map(group='CN=testers,OU=groups,DC=stackstorm,DC=net',
                                 roles=['mock_remote_role_4'],
                                 source='mappings/testers.yaml',
                                 enabled=True)

        # Verify initial state
        role_dbs = get_roles_for_user(user_db=user_db, include_remote=True)
        self.assertEqual(len(role_dbs), 2)
        self.assertEqual(role_dbs[0], self.roles['mock_local_role_1'])
        self.assertEqual(role_dbs[1], self.roles['mock_local_role_2'])

        groups = [
            'CN=stormers,OU=groups,DC=stackstorm,DC=net',
            'CN=testers,OU=groups,DC=stackstorm,DC=net'
        ]

        # Two new remote assignments should have been created
        # No mappings exist for the groups user is a member of so no new assignments should be
        # created
        result = syncer.sync(user_db=self.users['user_1'], groups=groups)
        created_role_assignment_dbs = result[0]
        removed_role_assignment_dbs = result[1]
        self.assertEqual(len(created_role_assignment_dbs), 2)
        self.assertEqual(created_role_assignment_dbs[0].role, 'mock_remote_role_3')
        self.assertEqual(created_role_assignment_dbs[1].role, 'mock_remote_role_4')
        self.assertEqual(removed_role_assignment_dbs, [])

        # Verify post sync run state - two new assignments should have been created
        role_dbs = get_roles_for_user(user_db=user_db, include_remote=True)
        self.assertEqual(len(role_dbs), 4)
        self.assertEqual(role_dbs[0], self.roles['mock_local_role_1'])
        self.assertEqual(role_dbs[1], self.roles['mock_local_role_2'])
        self.assertEqual(role_dbs[2], self.roles['mock_remote_role_3'])
        self.assertEqual(role_dbs[3], self.roles['mock_remote_role_4'])

        # Delete all existing mappings, make sure all old assignments are deleted on sync
        GroupToRoleMapping.query(group__in=groups).delete()
        self.assertEqual(len(GroupToRoleMapping.query(group__in=groups)), 0)

        result = syncer.sync(user_db=self.users['user_1'], groups=groups)
        created_role_assignment_dbs = result[0]
        removed_role_assignment_dbs = result[1]

        self.assertEqual(created_role_assignment_dbs, [])
        self.assertEqual(len(removed_role_assignment_dbs), 2)
        self.assertEqual(removed_role_assignment_dbs[0].role, 'mock_remote_role_3')
        self.assertEqual(removed_role_assignment_dbs[1].role, 'mock_remote_role_4')

        # Verify post sync run state - two old remote assignments should have been deleted, but
        # local assignments shouldn't have been touched
        role_dbs = get_roles_for_user(user_db=user_db, include_remote=True)
        self.assertEqual(len(role_dbs), 2)
        self.assertEqual(role_dbs[0], self.roles['mock_local_role_1'])
        self.assertEqual(role_dbs[1], self.roles['mock_local_role_2'])
Ejemplo n.º 6
0
    def sync(self, user_db, groups):
        """
        :param user_db: User to sync the assignments for.
        :type user: :class:`UserDB`

        :param groups: A list of remote groups user is a member of.
        :type groups: ``list`` of ``str``

        :return: A list of mappings which have been created.
        :rtype: ``list`` of :class:`UserRoleAssignmentDB`
        """
        groups = list(set(groups))

        extra = {'user_db': user_db, 'groups': groups}
        LOG.info('Synchronizing remote role assignments for user "%s"' % (str(user_db)),
                 extra=extra)

        # 1. Retrieve group to role mappings for the provided groups
        all_mapping_dbs = GroupToRoleMapping.query(group__in=groups)
        enabled_mapping_dbs = [mapping_db for mapping_db in all_mapping_dbs if
                               mapping_db.enabled]
        disabled_mapping_dbs = [mapping_db for mapping_db in all_mapping_dbs if
                                not mapping_db.enabled]

        if not all_mapping_dbs:
            LOG.debug('No group to role mappings found for user "%s"' % (str(user_db)), extra=extra)

        # 2. Remove all the existing remote role assignments
        remote_assignment_dbs = UserRoleAssignment.query(user=user_db.name, is_remote=True)

        existing_role_names = [assignment_db.role for assignment_db in remote_assignment_dbs]
        existing_role_names = set(existing_role_names)
        current_role_names = set([])

        for mapping_db in all_mapping_dbs:
            for role in mapping_db.roles:
                current_role_names.add(role)

        # A list of new role assignments which should be added to the database
        new_role_names = current_role_names.difference(existing_role_names)

        # A list of role assignments which need to be updated in the database
        updated_role_names = existing_role_names.intersection(current_role_names)

        # A list of role assignments which should be removed from the database
        removed_role_names = (existing_role_names - new_role_names)

        # Also remove any assignments for mappings which are disabled in the database
        for mapping_db in disabled_mapping_dbs:
            for role in mapping_db.roles:
                removed_role_names.add(role)

        LOG.debug('New role assignments: %r' % (new_role_names))
        LOG.debug('Updated role assignments: %r' % (updated_role_names))
        LOG.debug('Removed role assignments: %r' % (removed_role_names))

        # Build a list of role assignments to delete
        role_names_to_delete = updated_role_names.union(removed_role_names)
        role_assignment_dbs_to_delete = [role_assignment_db for role_assignment_db
                                         in remote_assignment_dbs
                                         if role_assignment_db.role in role_names_to_delete]

        UserRoleAssignment.query(user=user_db.name, role__in=role_names_to_delete,
                                 is_remote=True).delete()

        # 3. Create role assignments for all the current groups
        created_assignments_dbs = []
        for mapping_db in enabled_mapping_dbs:
            extra['mapping_db'] = mapping_db

            for role_name in mapping_db.roles:
                role_db = rbac_services.get_role_by_name(name=role_name)

                if not role_db:
                    # Gracefully skip assignment for role which doesn't exist in the db
                    LOG.info('Role with name "%s" for mapping "%s" not found, skipping assignment.'
                             % (role_name, str(mapping_db)), extra=extra)
                    continue

                description = ('Automatic role assignment based on the remote user membership in '
                               'group "%s"' % (mapping_db.group))
                assignment_db = rbac_services.assign_role_to_user(role_db=role_db, user_db=user_db,
                                                                  description=description,
                                                                  is_remote=True,
                                                                  source=mapping_db.source,
                                                                  ignore_already_exists_error=True)
                assert assignment_db.is_remote is True
                created_assignments_dbs.append(assignment_db)

        LOG.debug('Created %s new remote role assignments for user "%s"' %
                  (len(created_assignments_dbs), str(user_db)), extra=extra)

        return (created_assignments_dbs, role_assignment_dbs_to_delete)