def test_sync_user_same_role_granted_locally_and_remote_via_mapping(self): syncer = RBACRemoteGroupToRoleSyncer() user_db = self.users['user_6'] # Insert 2 local assignments for mock_role_7 role_db = create_role(name='mock_role_7') source = 'assignments/user_6_one.yaml' assign_role_to_user(role_db=role_db, user_db=user_db, source=source, is_remote=False) source = 'assignments/user_6_two.yaml' assign_role_to_user(role_db=role_db, user_db=user_db, source=source, is_remote=False) # Create mock mapping which maps CN=stormers,OU=groups,DC=stackstorm,DC=net # to "mock_role_7" create_group_to_role_map(group='CN=stormers,OU=groups,DC=stackstorm,DC=net', roles=['mock_role_7'], source='mappings/stormers.yaml') # Create mock mapping which maps CN=testers,OU=groups,DC=stackstorm,DC=net # to "mock_role_7" create_group_to_role_map(group='CN=testers,OU=groups,DC=stackstorm,DC=net', roles=['mock_role_7'], source='mappings/testers.yaml') groups = [ 'CN=stormers,OU=groups,DC=stackstorm,DC=net', 'CN=testers,OU=groups,DC=stackstorm,DC=net' ] result = syncer.sync(user_db=self.users['user_6'], 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_role_7') self.assertEqual(created_role_assignment_dbs[1].role, 'mock_role_7') self.assertEqual(removed_role_assignment_dbs, []) # There should be one role and 4 assignments for the same role role_dbs = get_roles_for_user(user_db=user_db, include_remote=True) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0].name, 'mock_role_7') role_assignment_dbs = get_role_assignments_for_user(user_db=self.users['user_6']) self.assertEqual(len(role_assignment_dbs), 4) self.assertEqual(role_assignment_dbs[0].source, 'assignments/user_6_one.yaml') self.assertEqual(role_assignment_dbs[1].source, 'assignments/user_6_two.yaml') self.assertEqual(role_assignment_dbs[2].source, 'mappings/stormers.yaml') self.assertEqual(role_assignment_dbs[3].source, 'mappings/testers.yaml') # Remove one remote group - should be 3 left groups = [ 'CN=stormers,OU=groups,DC=stackstorm,DC=net' ] result = syncer.sync(user_db=self.users['user_6'], groups=groups) role_dbs = get_roles_for_user(user_db=user_db, include_remote=True) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0].name, 'mock_role_7') role_assignment_dbs = get_role_assignments_for_user(user_db=self.users['user_6']) self.assertEqual(len(role_assignment_dbs), 3)
def test_grant_and_revoke_role(self): user_db = UserDB(name='test-user-1') user_db = User.add_or_update(user_db) # Initial state, no roles role_dbs = rbac_services.get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) role_dbs = user_db.get_roles() self.assertItemsEqual(role_dbs, []) # Assign a role, should have one role assigned rbac_services.assign_role_to_user(role_db=self.roles['custom_role_1'], user_db=user_db) role_dbs = rbac_services.get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, [self.roles['custom_role_1']]) role_dbs = user_db.get_roles() self.assertItemsEqual(role_dbs, [self.roles['custom_role_1']]) # Revoke previously assigned role, should have no roles again rbac_services.revoke_role_from_user(role_db=self.roles['custom_role_1'], user_db=user_db) role_dbs = rbac_services.get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) role_dbs = user_db.get_roles() self.assertItemsEqual(role_dbs, [])
def test_group_to_role_sync_is_performed_on_successful_auth_single_group_no_mappings(self): # Enable group sync cfg.CONF.set_override(group='rbac', name='sync_remote_groups', override=True) cfg.CONF.set_override(group='rbac', name='sync_remote_groups', override=True) user_db = self.users['user_1'] h = handlers.StandaloneAuthHandler() request = {} # 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']) # Single group configured but no group mapping in the database h._auth_backend.groups = [ 'CN=stormers,OU=groups,DC=stackstorm,DC=net' ] token = h.handle_auth(request, headers={}, remote_addr=None, remote_user=None, authorization=('basic', DUMMY_CREDS)) self.assertEqual(token.user, 'auser') # Verify nothing has changed 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'])
def test_get_roles_for_user(self): # User with no roles user_db = self.users['no_roles'] role_dbs = rbac_services.get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) role_dbs = user_db.get_roles() self.assertItemsEqual(role_dbs, []) # User with one custom role user_db = self.users['1_custom_role'] role_dbs = rbac_services.get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, [self.roles['custom_role_1']]) role_dbs = user_db.get_roles() self.assertItemsEqual(role_dbs, [self.roles['custom_role_1']]) # User with remote roles user_db = self.users['user_5'] role_dbs = user_db.get_roles() self.assertEqual(len(role_dbs), 4) user_db = self.users['user_5'] role_dbs = user_db.get_roles(include_remote=True) self.assertEqual(len(role_dbs), 4) user_db = self.users['user_5'] role_dbs = user_db.get_roles(include_remote=False) self.assertEqual(len(role_dbs), 3)
def test_sync_user_assignments_locally_removed_assignments_are_removed_from_db(self): syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertItemsEqual(role_dbs, []) # Do the sync with two roles defined api = UserRoleAssignmentFileFormatAPI(username='******', roles=['role_1', 'role_2']) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertTrue(len(role_dbs), 2) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) # Do the sync with one role defined (one should be removed from the db) api = UserRoleAssignmentFileFormatAPI(username='******', roles=['role_2']) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertTrue(len(role_dbs), 1) self.assertEqual(role_dbs[0], self.roles['role_2'])
def test_sync_user_assignments_locally_removed_assignments_are_removed_from_db( self): syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertItemsEqual(role_dbs, []) # Do the sync with two roles defined api = UserRoleAssignmentFileFormatAPI( username='******', roles=['role_1', 'role_2'], file_path='assignments/user2.yaml') syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertEqual(len(role_dbs), 2) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) # Do the sync with one role defined (one should be removed from the db) api = UserRoleAssignmentFileFormatAPI( username='******', roles=['role_2'], file_path='assignments/user2.yaml') syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0], self.roles['role_2'])
def test_grant_and_revoke_role(self): user_db = UserDB(name='test-user-1') user_db = User.add_or_update(user_db) # Initial state, no roles role_dbs = rbac_services.get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) role_dbs = user_db.get_roles() self.assertItemsEqual(role_dbs, []) # Assign a role, should have one role assigned rbac_services.assign_role_to_user(role_db=self.roles['custom_role_1'], user_db=user_db, source='assignments/%s.yaml' % user_db.name) role_dbs = rbac_services.get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, [self.roles['custom_role_1']]) role_dbs = user_db.get_roles() self.assertItemsEqual(role_dbs, [self.roles['custom_role_1']]) # Revoke previously assigned role, should have no roles again rbac_services.revoke_role_from_user( role_db=self.roles['custom_role_1'], user_db=user_db) role_dbs = rbac_services.get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) role_dbs = user_db.get_roles() self.assertItemsEqual(role_dbs, [])
def test_sync_success_no_existing_remote_assignments(self): syncer = RBACRemoteGroupToRoleSyncer() user_db = self.users['user_1'] # Create mock mapping which maps CN=stormers,OU=groups,DC=stackstorm,DC=net # to "mock_role_3" and "mock_role_4" create_group_to_role_map(group='CN=stormers,OU=groups,DC=stackstorm,DC=net', roles=['mock_role_3', 'mock_role_4']) # 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']) groups = [ 'CN=stormers,OU=groups,DC=stackstorm,DC=net', 'CN=testers,OU=groups,DC=stackstorm,DC=net', # We repeat the same group to validate that repated groups are correctly de-duplicated 'CN=stormers,OU=groups,DC=stackstorm,DC=net', ] 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_role_3') self.assertEqual(created_role_assignment_dbs[1].role, 'mock_role_4') self.assertEqual(removed_role_assignment_dbs, []) # User should have two new roles assigned now 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_role_3']) self.assertEqual(role_dbs[3], self.roles['mock_role_4'])
def test_sync_assignments_user_doesnt_exist_in_db(self): # Make sure that the assignments for the users which don't exist in the db are still saved syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() username = '******' # Initial state, no roles user_db = UserDB(name=username) self.assertEqual(len(User.query(name=username)), 0) role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) # Do the sync with two roles defined api = UserRoleAssignmentFileFormatAPI( username=user_db.name, roles=['role_1', 'role_2'], file_path='assignments/foobar.yaml') syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 2) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2'])
def test_group_to_role_sync_is_performed_on_successful_auth_no_groups_returned(self): # Enable group sync cfg.CONF.set_override(group='rbac', name='sync_remote_groups', override=True) cfg.CONF.set_override(group='rbac', name='sync_remote_groups', override=True) user_db = self.users['user_1'] h = handlers.StandaloneAuthHandler() request = {} # 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']) # No groups configured should return early h._auth_backend.groups = [] token = h.handle_auth(request, headers={}, remote_addr=None, remote_user=None, authorization=('basic', DUMMY_CREDS)) self.assertEqual(token.user, 'auser') # Verify nothing has changed 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'])
def test_sync_user_assignments_multiple_custom_roles_assignments(self): syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertItemsEqual(role_dbs, []) # Do the sync with two roles defined api = UserRoleAssignmentFileFormatAPI( username='******', roles=['role_1', 'role_2'], file_path='assignments/user2.yaml') syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertEqual(len(role_dbs), 2) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) role_assignment_dbs = get_role_assignments_for_user( user_db=self.users['user_2']) self.assertEqual(len(role_assignment_dbs), 2) self.assertEqual(role_assignment_dbs[0].source, 'assignments/user2.yaml') self.assertEqual(role_assignment_dbs[1].source, 'assignments/user2.yaml')
def test_sync_no_groups_and_on_disk_definitions(self): syncer = RBACRemoteGroupToRoleSyncer() user_db = self.users['user_1'] # 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']) # No groups - should result in no new remote assignments but existing local assignments # shouldn't be manipulated result = syncer.sync(user_db=self.users['user_1'], groups=[]) created_role_assignment_dbs = result[0] removed_role_assignment_dbs = result[1] self.assertEqual(created_role_assignment_dbs, []) self.assertEqual(removed_role_assignment_dbs, []) 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 but no mapping to role definitions, should result in no new remote assignments groups = ['CN=stormers,OU=groups,DC=stackstorm,DC=net'] 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(removed_role_assignment_dbs, []) 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'])
def test_sync_role_assignments_no_assignment_file_on_disk(self): syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles user_db = self.users['user_3'] role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) # Do the sync with two roles defined api = UserRoleAssignmentFileFormatAPI( username=user_db.name, roles=['role_1', 'role_2'], file_path='assignments/%s.yaml' % user_db.name) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 2) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) # Do the sync with no roles - existing assignments should be removed from the databse syncer.sync_users_role_assignments(role_assignment_apis=[]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 0)
def test_sync_role_assignments_no_assignment_file_on_disk(self): syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles user_db = self.users['user_3'] role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) # Do the sync with two roles defined api = UserRoleAssignmentFileFormatAPI(username=user_db.name, roles=['role_1', 'role_2'], file_path='assignments/%s.yaml' % user_db.name) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 2) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) # Do the sync with no roles - existing assignments should be removed from the databse syncer.sync_users_role_assignments(role_assignment_apis=[]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 0)
def test_sync_remote_assignments_are_not_manipulated(self): # Verify remote assignments are not manipulated. syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles user_db = UserDB(name='doesntexistwhaha') role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) # Create mock remote role assignment role_db = self.roles['role_3'] source = 'assignments/%s.yaml' % user_db.name role_assignment_db = assign_role_to_user(role_db=role_db, user_db=user_db, source=source, is_remote=True) self.assertTrue(role_assignment_db.is_remote) # Verify assignment has been created role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, [self.roles['role_3']]) # Do the sync with two roles defined - verify remote role assignment hasn't been # manipulated with. api = UserRoleAssignmentFileFormatAPI(username=user_db.name, roles=['role_1', 'role_2'], file_path='assignments/%s.yaml' % user_db.name) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 3) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) self.assertEqual(role_dbs[2], self.roles['role_3']) # Do sync with no roles - verify all roles except remote one are removed. api = UserRoleAssignmentFileFormatAPI(username=user_db.name, roles=[], file_path='assignments/%s.yaml' % user_db.name) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0], self.roles['role_3'])
def test_sync_success_one_existing_remote_assignment(self): 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 "mock_remote_role_4" create_group_to_role_map( group='CN=stormers,OU=groups,DC=stackstorm,DC=net', roles=['mock_remote_role_3', 'mock_remote_role_4'], source='mappings/stormers.yaml') # Assign existing remote mock_role_5 to the user role_db = self.roles['mock_role_5'] source = 'mappings/stormers.yaml' assign_role_to_user(role_db=role_db, user_db=user_db, source=source, is_remote=True) # Verify initial state role_dbs = get_roles_for_user(user_db=user_db, include_remote=True) self.assertEqual(len(role_dbs), 3) 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_role_5']) groups = [ 'CN=stormers,OU=groups,DC=stackstorm,DC=net', 'CN=testers,OU=groups,DC=stackstorm,DC=net' ] 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(len(removed_role_assignment_dbs), 1) self.assertEqual(removed_role_assignment_dbs[0].role, 'mock_role_5') # User should have two new roles assigned now, but the existing "mock_role_5" remote role # removed since it wasn't specified in any mapping 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'])
def test_sync_user_assignments_multiple_sources_same_role_assignment(self): syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertItemsEqual(role_dbs, []) # Do the sync with role defined in separate files assignment1 = UserRoleAssignmentFileFormatAPI( username='******', roles=['role_1'], file_path='assignments/user2a.yaml') assignment2 = UserRoleAssignmentFileFormatAPI( username='******', roles=['role_1'], file_path='assignments/user2b.yaml') syncer.sync_users_role_assignments( role_assignment_apis=[assignment1, assignment2]) role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0], self.roles['role_1']) role_assignment_dbs = get_role_assignments_for_user( user_db=self.users['user_2']) self.assertEqual(len(role_assignment_dbs), 2) sources = [r.source for r in role_assignment_dbs] self.assertIn('assignments/user2a.yaml', sources) self.assertIn('assignments/user2b.yaml', sources) # Do another sync with one assignment file removed - only one assignment should be left syncer.sync_users_role_assignments(role_assignment_apis=[assignment2]) role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0], self.roles['role_1']) role_assignment_dbs = get_role_assignments_for_user( user_db=self.users['user_2']) self.assertEqual(len(role_assignment_dbs), 1) sources = [r.source for r in role_assignment_dbs] self.assertIn('assignments/user2b.yaml', sources)
def get(self, requester_user, auth_info): """ Meta API endpoint wich returns information about the currently authenticated user. Handle: GET /v1/user """ data = {} if cfg.CONF.rbac.enable and requester_user: role_dbs = get_roles_for_user(user_db=requester_user) roles = [role_db.name for role_db in role_dbs] else: roles = [] data = { 'username': requester_user.name, 'authentication': { 'method': auth_info['method'], 'location': auth_info['location'] }, 'rbac': { 'enabled': cfg.CONF.rbac.enable, 'roles': roles, 'is_admin': rbac_utils.user_is_admin(user_db=requester_user) } } if auth_info.get('token_expire', None): token_expire = auth_info['token_expire'].strftime('%Y-%m-%dT%H:%M:%SZ') data['authentication']['token_expire'] = token_expire return data
def get(self, requester_user, auth_info): """ Meta API endpoint wich returns information about the currently authenticated user. Handle: GET /v1/user """ data = {} if cfg.CONF.rbac.enable and requester_user: role_dbs = get_roles_for_user(user_db=requester_user) roles = [role_db.name for role_db in role_dbs] else: roles = [] data = { 'username': requester_user.name, 'authentication': { 'method': auth_info['method'], 'location': auth_info['location'] }, 'rbac': { 'enabled': cfg.CONF.rbac.enable, 'roles': roles, 'is_admin': rbac_utils.user_is_admin(user_db=requester_user) } } if auth_info.get('token_expire', None): token_expire = auth_info['token_expire'].strftime( '%Y-%m-%dT%H:%M:%SZ') data['authentication']['token_expire'] = token_expire return data
def test_sync_user_assignments_single_role_assignment(self): syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles role_dbs = get_roles_for_user(user_db=self.users['user_1']) self.assertItemsEqual(role_dbs, []) # Do the sync with a single role defined api = UserRoleAssignmentFileFormatAPI(username='******', roles=['role_1']) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=self.users['user_1']) self.assertItemsEqual(role_dbs, [self.roles['role_1']])
def test_get_roles_for_user(self): # User with no roles user_db = self.users['no_roles'] role_dbs = rbac_services.get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) role_dbs = user_db.get_roles() self.assertItemsEqual(role_dbs, []) # User with one custom role user_db = self.users['1_custom_role'] role_dbs = rbac_services.get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, [self.roles['custom_role_1']]) role_dbs = user_db.get_roles() self.assertItemsEqual(role_dbs, [self.roles['custom_role_1']])
def test_sync_no_mappings_exist_for_the_provided_groups(self): 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 "mock_remote_role_4" create_group_to_role_map( group='CN=stormers,OU=groups,DC=stackstorm,DC=net', roles=['mock_remote_role_3', 'mock_remote_role_4'], source='mappings/stormers.yaml') # 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=testers1,OU=groups,DC=stackstorm,DC=net', 'CN=testers2,OU=groups,DC=stackstorm,DC=net' ] # 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(created_role_assignment_dbs, []) self.assertEqual(removed_role_assignment_dbs, [])
def test_sync_no_mappings_exist_for_the_provided_groups(self): 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 "mock_remote_role_4" create_group_to_role_map(group='CN=stormers,OU=groups,DC=stackstorm,DC=net', roles=['mock_remote_role_3', 'mock_remote_role_4'], source='mappings/stormers.yaml') # 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=testers1,OU=groups,DC=stackstorm,DC=net', 'CN=testers2,OU=groups,DC=stackstorm,DC=net' ] # 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(created_role_assignment_dbs, []) self.assertEqual(removed_role_assignment_dbs, [])
def get_roles(self): """ Retrieve roles assigned to that user. :rtype: ``list`` of :class:`RoleDB` """ result = get_roles_for_user(user_db=self) return result
def test_sync_remote_assignments_are_not_manipulated(self): # Verify remote assignments are not manipulated. syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles user_db = UserDB(name='doesntexistwhaha') role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) # Create mock remote role assignment role_db = self.roles['role_3'] source = 'assignments/%s.yaml' % user_db.name role_assignment_db = assign_role_to_user( role_db=role_db, user_db=user_db, source=source, is_remote=True) self.assertTrue(role_assignment_db.is_remote) # Verify assignment has been created role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, [self.roles['role_3']]) # Do the sync with two roles defined - verify remote role assignment hasn't been # manipulated with. api = UserRoleAssignmentFileFormatAPI( username=user_db.name, roles=['role_1', 'role_2'], file_path='assignments/%s.yaml' % user_db.name) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 3) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) self.assertEqual(role_dbs[2], self.roles['role_3']) # Do sync with no roles - verify all roles except remote one are removed. api = UserRoleAssignmentFileFormatAPI( username=user_db.name, roles=[], file_path='assignments/%s.yaml' % user_db.name) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0], self.roles['role_3'])
def test_sync_user_assignments_multiple_custom_roles_assignments(self): syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertItemsEqual(role_dbs, []) # Do the sync with two roles defined api = UserRoleAssignmentFileFormatAPI(username='******', roles=['role_1', 'role_2']) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertTrue(len(role_dbs), 2) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2'])
def test_group_to_role_sync_is_performed_on_successful_auth_with_groups_and_mappings( self): # Enable group sync cfg.CONF.set_override(group='rbac', name='sync_remote_groups', override=True) cfg.CONF.set_override(group='rbac', name='sync_remote_groups', override=True) user_db = self.users['user_1'] h = handlers.StandaloneAuthHandler() request = {} # Single mapping, new remote assignment should be created create_group_to_role_map( group='CN=stormers,OU=groups,DC=stackstorm,DC=net', roles=['mock_role_3', 'mock_role_4'], source='mappings/stormers.yaml') # 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']) h._auth_backend.groups = ['CN=stormers,OU=groups,DC=stackstorm,DC=net'] token = h.handle_auth(request, headers={}, remote_addr=None, remote_user=None, authorization=('basic', DUMMY_CREDS)) self.assertEqual(token.user, 'auser') # Verify a new role assignments based on the group mapping has 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_role_3']) self.assertEqual(role_dbs[3], self.roles['mock_role_4'])
def test_sync_success_one_existing_remote_assignment(self): 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 "mock_remote_role_4" create_group_to_role_map(group='CN=stormers,OU=groups,DC=stackstorm,DC=net', roles=['mock_remote_role_3', 'mock_remote_role_4'], source='mappings/stormers.yaml') # Assign existing remote mock_role_5 to the user role_db = self.roles['mock_role_5'] source = 'mappings/stormers.yaml' assign_role_to_user(role_db=role_db, user_db=user_db, source=source, is_remote=True) # Verify initial state role_dbs = get_roles_for_user(user_db=user_db, include_remote=True) self.assertEqual(len(role_dbs), 3) 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_role_5']) groups = [ 'CN=stormers,OU=groups,DC=stackstorm,DC=net', 'CN=testers,OU=groups,DC=stackstorm,DC=net' ] 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(len(removed_role_assignment_dbs), 1) self.assertEqual(removed_role_assignment_dbs[0].role, 'mock_role_5') # User should have two new roles assigned now, but the existing "mock_role_5" remote role # removed since it wasn't specified in any mapping 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'])
def test_sync_success_no_existing_remote_assignments(self): 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 "mock_remote_role_4" create_group_to_role_map(group='CN=stormers,OU=groups,DC=stackstorm,DC=net', roles=['mock_remote_role_3', 'mock_remote_role_4'], source='mappings/stormers.yaml') # 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']) role_assignment_dbs = get_role_assignments_for_user(user_db=self.users['user_1']) groups = [ 'CN=stormers,OU=groups,DC=stackstorm,DC=net', 'CN=testers,OU=groups,DC=stackstorm,DC=net', # We repeat the same group to validate that repated groups are correctly de-duplicated 'CN=stormers,OU=groups,DC=stackstorm,DC=net', ] 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, []) # User should have two new roles assigned now 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']) role_assignment_dbs = get_role_assignments_for_user(user_db=self.users['user_1']) self.assertEqual(len(role_assignment_dbs), 4) self.assertEqual(role_assignment_dbs[2].source, 'mappings/stormers.yaml') self.assertEqual(role_assignment_dbs[3].source, 'mappings/stormers.yaml')
def test_sync_assignments_user_doesnt_exist_in_db(self): # Make sure that the assignments for the users which don't exist in the db are still saved syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles user_db = UserDB(name='doesntexistwhaha') role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) # Do the sync with two roles defined api = UserRoleAssignmentFileFormatAPI(username=user_db.name, roles=['role_1', 'role_2']) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertTrue(len(role_dbs), 2) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2'])
def get_roles(self, include_remote=True): """ Retrieve roles assigned to that user. :param include_remote: True to also include remote role assignments. :type include_remote: ``bool`` :rtype: ``list`` of :class:`RoleDB` """ result = get_roles_for_user(user_db=self, include_remote=include_remote) return result
def test_sync_user_assignments_multiple_sources_same_role_assignment(self): syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertItemsEqual(role_dbs, []) # Do the sync with role defined in separate files assignment1 = UserRoleAssignmentFileFormatAPI( username='******', roles=['role_1'], file_path='assignments/user2a.yaml') assignment2 = UserRoleAssignmentFileFormatAPI( username='******', roles=['role_1'], file_path='assignments/user2b.yaml') syncer.sync_users_role_assignments(role_assignment_apis=[assignment1, assignment2]) role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0], self.roles['role_1']) role_assignment_dbs = get_role_assignments_for_user(user_db=self.users['user_2']) self.assertEqual(len(role_assignment_dbs), 2) sources = [r.source for r in role_assignment_dbs] self.assertIn('assignments/user2a.yaml', sources) self.assertIn('assignments/user2b.yaml', sources) # Do another sync with one assignment file removed - only one assignment should be left syncer.sync_users_role_assignments(role_assignment_apis=[assignment2]) role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0], self.roles['role_1']) role_assignment_dbs = get_role_assignments_for_user(user_db=self.users['user_2']) self.assertEqual(len(role_assignment_dbs), 1) sources = [r.source for r in role_assignment_dbs] self.assertIn('assignments/user2b.yaml', sources)
def test_sync_assignments_are_removed_user_doesnt_exist_in_db(self): # Make sure that the assignments for the users which don't exist in the db are correctly # removed syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() username = '******' # Initial state, no roles user_db = UserDB(name=username) self.assertEqual(len(User.query(name=username)), 0) role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) # Do the sync with two roles defined api = UserRoleAssignmentFileFormatAPI(username=user_db.name, roles=['role_1', 'role_2']) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 2) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) # Sync with no roles on disk - existing roles should be removed syncer.sync_users_role_assignments(role_assignment_apis=[]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 0) username = '******' # Initial state, no roles user_db = UserDB(name=username) self.assertEqual(len(User.query(name=username)), 0) role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) # Do the sync with three roles defined api = UserRoleAssignmentFileFormatAPI(username=user_db.name, roles=['role_1', 'role_2', 'role_3']) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 3) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) self.assertEqual(role_dbs[2], self.roles['role_3']) # Sync with one role on disk - two roles should be removed api = UserRoleAssignmentFileFormatAPI(username=user_db.name, roles=['role_3']) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0], self.roles['role_3'])
def test_group_to_role_sync_is_performed_on_successful_auth_with_groups_and_mappings(self): # Enable group sync cfg.CONF.set_override(group='rbac', name='sync_remote_groups', override=True) cfg.CONF.set_override(group='rbac', name='sync_remote_groups', override=True) user_db = self.users['user_1'] h = handlers.StandaloneAuthHandler() request = {} # Single mapping, new remote assignment should be created create_group_to_role_map(group='CN=stormers,OU=groups,DC=stackstorm,DC=net', roles=['mock_role_3', 'mock_role_4'], source='mappings/stormers.yaml') # 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']) h._auth_backend.groups = [ 'CN=stormers,OU=groups,DC=stackstorm,DC=net' ] token = h.handle_auth(request, headers={}, remote_addr=None, remote_user=None, authorization=('basic', DUMMY_CREDS)) self.assertEqual(token.user, 'auser') # Verify a new role assignments based on the group mapping has 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_role_3']) self.assertEqual(role_dbs[3], self.roles['mock_role_4'])
def test_sync_user_assignments_role_doesnt_exist_in_db(self): syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() # Initial state, no roles role_dbs = get_roles_for_user(user_db=self.users['user_2']) self.assertItemsEqual(role_dbs, []) # Do the sync with role defined in separate files assignment1 = UserRoleAssignmentFileFormatAPI( username='******', roles=['doesnt_exist'], file_path='assignments/user2.yaml') expected_msg = ('Role "doesnt_exist" referenced in assignment file ' '"assignments/user2.yaml" doesn\'t exist') self.assertRaisesRegexp(ValueError, expected_msg, syncer.sync_users_role_assignments, role_assignment_apis=[assignment1])
def user_has_role(user_db, role): """ :param user: User object to check for. :type user: :class:`UserDB` :param role: Role name to check for. :type role: ``str`` :rtype: ``bool`` """ assert isinstance(role, six.string_types) if not cfg.CONF.rbac.enable: return True user_role_dbs = rbac_services.get_roles_for_user(user_db=user_db) user_role_names = [role_db.name for role_db in user_role_dbs] return role in user_role_names
def _user_has_system_role_permission(self, user_db, permission_type): """ Check the user system roles and return True if user has the required permission. :rtype: ``bool`` """ permission_name = PermissionType.get_permission_name(permission_type) user_role_dbs = get_roles_for_user(user_db=user_db) user_role_names = [role_db.name for role_db in user_role_dbs] if SystemRole.SYSTEM_ADMIN in user_role_names: # System admin has all the permissions return True elif SystemRole.ADMIN in user_role_names: # Admin has all the permissions return True elif SystemRole.OBSERVER in user_role_names and permission_name == 'view': # Observer role has "view" permission on all the resources return True return False
def _user_has_system_role_permission(self, user_db, permission_type): """ Check the user system roles and return True if user has the required permission. :rtype: ``bool`` """ permission_name = PermissionType.get_permission_name(permission_type) user_role_dbs = get_roles_for_user(user_db=user_db) user_role_names = [role_db.name for role_db in user_role_dbs] if SystemRole.SYSTEM_ADMIN in user_role_names: # System admin has all the permissions return True elif SystemRole.ADMIN in user_role_names: # Admin has all the permissions return True elif SystemRole.OBSERVER in user_role_names and permission_name in READ_PERMISSION_NAMES: # Observer role has "view" permission on all the resources return True return False
def _schedule_execution(self, liveaction, requester_user, user=None, context_string=None, show_secrets=False, pack=None): # Initialize execution context if it does not exist. if not hasattr(liveaction, 'context'): liveaction.context = dict() liveaction.context['user'] = user liveaction.context['pack'] = pack LOG.debug('User is: %s' % liveaction.context['user']) # Retrieve other st2 context from request header. if context_string: context = try_loads(context_string) if not isinstance(context, dict): raise ValueError( 'Unable to convert st2-context from the headers into JSON.' ) liveaction.context.update(context) # Include RBAC context (if RBAC is available and enabled) if cfg.CONF.rbac.enable: user_db = UserDB(name=user) role_dbs = rbac_service.get_roles_for_user(user_db=user_db, include_remote=True) roles = [role_db.name for role_db in role_dbs] liveaction.context['rbac'] = {'user': user, 'roles': roles} # Schedule the action execution. liveaction_db = LiveActionAPI.to_model(liveaction) action_db = action_utils.get_action_by_ref(liveaction_db.action) runnertype_db = action_utils.get_runnertype_by_name( action_db.runner_type['name']) try: liveaction_db.parameters = param_utils.render_live_params( runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters, liveaction_db.context) except param_exc.ParamException: # We still need to create a request, so liveaction_db is assigned an ID liveaction_db, actionexecution_db = action_service.create_request( liveaction_db) # By this point the execution is already in the DB therefore need to mark it failed. _, e, tb = sys.exc_info() action_service.update_status( liveaction=liveaction_db, new_status=action_constants.LIVEACTION_STATUS_FAILED, result={ 'error': str(e), 'traceback': ''.join(traceback.format_tb(tb, 20)) }) # Might be a good idea to return the actual ActionExecution rather than bubble up # the exception. raise validation_exc.ValueValidationException(str(e)) # The request should be created after the above call to render_live_params # so any templates in live parameters have a chance to render. liveaction_db, actionexecution_db = action_service.create_request( liveaction_db) liveaction_db = LiveAction.add_or_update(liveaction_db, publish=False) _, actionexecution_db = action_service.publish_request( liveaction_db, actionexecution_db) mask_secrets = self._get_mask_secrets(requester_user, show_secrets=show_secrets) execution_api = ActionExecutionAPI.from_model( actionexecution_db, mask_secrets=mask_secrets) return Response(json=execution_api, status=http_client.CREATED)
def _schedule_execution(self, liveaction, requester_user, action_db, user=None, context_string=None, show_secrets=False): # Initialize execution context if it does not exist. if not hasattr(liveaction, 'context'): liveaction.context = dict() liveaction.context['user'] = user liveaction.context['pack'] = action_db.pack LOG.debug('User is: %s' % liveaction.context['user']) # Retrieve other st2 context from request header. if context_string: context = try_loads(context_string) if not isinstance(context, dict): raise ValueError('Unable to convert st2-context from the headers into JSON.') liveaction.context.update(context) # Include RBAC context (if RBAC is available and enabled) if cfg.CONF.rbac.enable: user_db = UserDB(name=user) role_dbs = rbac_service.get_roles_for_user(user_db=user_db, include_remote=True) roles = [role_db.name for role_db in role_dbs] liveaction.context['rbac'] = { 'user': user, 'roles': roles } # Schedule the action execution. liveaction_db = LiveActionAPI.to_model(liveaction) runnertype_db = action_utils.get_runnertype_by_name(action_db.runner_type['name']) try: liveaction_db.parameters = param_utils.render_live_params( runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters, liveaction_db.context) except param_exc.ParamException: # We still need to create a request, so liveaction_db is assigned an ID liveaction_db, actionexecution_db = action_service.create_request( liveaction=liveaction_db, action_db=action_db, runnertype_db=runnertype_db) # By this point the execution is already in the DB therefore need to mark it failed. _, e, tb = sys.exc_info() action_service.update_status( liveaction=liveaction_db, new_status=action_constants.LIVEACTION_STATUS_FAILED, result={'error': six.text_type(e), 'traceback': ''.join(traceback.format_tb(tb, 20))}) # Might be a good idea to return the actual ActionExecution rather than bubble up # the exception. raise validation_exc.ValueValidationException(six.text_type(e)) # The request should be created after the above call to render_live_params # so any templates in live parameters have a chance to render. liveaction_db, actionexecution_db = action_service.create_request(liveaction=liveaction_db, action_db=action_db, runnertype_db=runnertype_db) _, actionexecution_db = action_service.publish_request(liveaction_db, actionexecution_db) mask_secrets = self._get_mask_secrets(requester_user, show_secrets=show_secrets) execution_api = ActionExecutionAPI.from_model(actionexecution_db, mask_secrets=mask_secrets) return Response(json=execution_api, status=http_client.CREATED)
def test_sync_success_one_mapping_is_disabled_on_second_sync_run(self): 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']) # Disable second mapping - one assignment should be removed mapping_db = GroupToRoleMapping.get( group='CN=testers,OU=groups,DC=stackstorm,DC=net') mapping_db.enabled = False GroupToRoleMapping.add_or_update(mapping_db) 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), 1) self.assertEqual(len(removed_role_assignment_dbs), 2) self.assertEqual(created_role_assignment_dbs[0].role, 'mock_remote_role_3') 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 - mock_remote_role_4 assignment should be removed role_dbs = get_roles_for_user(user_db=user_db, include_remote=True) self.assertEqual(len(role_dbs), 3) 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'])
def test_sync_assignments_are_removed_user_doesnt_exist_in_db(self): # Make sure that the assignments for the users which don't exist in the db are correctly # removed syncer = RBACDefinitionsDBSyncer() self._insert_mock_roles() username = '******' # Initial state, no roles user_db = UserDB(name=username) self.assertEqual(len(User.query(name=username)), 0) role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) # Do the sync with two roles defined api = UserRoleAssignmentFileFormatAPI( username=user_db.name, roles=['role_1', 'role_2'], file_path='assignments/%s.yaml' % user_db.name) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 2) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) # Sync with no roles on disk - existing roles should be removed syncer.sync_users_role_assignments(role_assignment_apis=[]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 0) username = '******' # Initial state, no roles user_db = UserDB(name=username) self.assertEqual(len(User.query(name=username)), 0) role_dbs = get_roles_for_user(user_db=user_db) self.assertItemsEqual(role_dbs, []) # Do the sync with three roles defined api = UserRoleAssignmentFileFormatAPI( username=user_db.name, roles=['role_1', 'role_2', 'role_3'], file_path='assignments/%s.yaml' % user_db.name) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 3) self.assertEqual(role_dbs[0], self.roles['role_1']) self.assertEqual(role_dbs[1], self.roles['role_2']) self.assertEqual(role_dbs[2], self.roles['role_3']) role_assignment_dbs = get_role_assignments_for_user(user_db=user_db) self.assertEqual(len(role_assignment_dbs), 3) self.assertEqual(role_assignment_dbs[0].source, 'assignments/%s.yaml' % user_db.name) # Sync with one role on disk - two roles should be removed api = UserRoleAssignmentFileFormatAPI( username=user_db.name, roles=['role_3'], file_path='assignments/%s.yaml' % user_db.name) syncer.sync_users_role_assignments(role_assignment_apis=[api]) role_dbs = get_roles_for_user(user_db=user_db) self.assertEqual(len(role_dbs), 1) self.assertEqual(role_dbs[0], self.roles['role_3'])
def test_sync_success_one_mapping_is_disabled_on_second_sync_run(self): 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']) # Disable second mapping - one assignment should be removed mapping_db = GroupToRoleMapping.get(group='CN=testers,OU=groups,DC=stackstorm,DC=net') mapping_db.enabled = False GroupToRoleMapping.add_or_update(mapping_db) 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), 1) self.assertEqual(len(removed_role_assignment_dbs), 2) self.assertEqual(created_role_assignment_dbs[0].role, 'mock_remote_role_3') 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 - mock_remote_role_4 assignment should be removed role_dbs = get_roles_for_user(user_db=user_db, include_remote=True) self.assertEqual(len(role_dbs), 3) 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'])
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'])
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'])