def test_domain_specific_separation(self): domain1 = unit.new_domain_ref() role1 = unit.new_role_ref(domain_id=domain1['id']) role_ref1 = self.role_api.create_role(role1['id'], role1) self.assertDictEqual(role1, role_ref1) # Check we can have the same named role in a different domain domain2 = unit.new_domain_ref() role2 = unit.new_role_ref(name=role1['name'], domain_id=domain2['id']) role_ref2 = self.role_api.create_role(role2['id'], role2) self.assertDictEqual(role2, role_ref2) # ...and in fact that you can have the same named role as a global role role3 = unit.new_role_ref(name=role1['name']) role_ref3 = self.role_api.create_role(role3['id'], role3) self.assertDictEqual(role3, role_ref3) # Check that updating one doesn't change the others role1['name'] = uuid.uuid4().hex self.role_api.update_role(role1['id'], role1) role_ref1 = self.role_api.get_role(role1['id']) self.assertDictEqual(role1, role_ref1) role_ref2 = self.role_api.get_role(role2['id']) self.assertDictEqual(role2, role_ref2) role_ref3 = self.role_api.get_role(role3['id']) self.assertDictEqual(role3, role_ref3) # Check that deleting one of these, doesn't affect the others self.role_api.delete_role(role1['id']) self.assertRaises(exception.RoleNotFound, self.role_api.get_role, role1['id']) self.role_api.get_role(role2['id']) self.role_api.get_role(role3['id'])
def test_update_domain_id_of_role_fails(self): # Create a global role role1 = unit.new_role_ref() role1 = self.role_api.create_role(role1['id'], role1) # Try and update it to be domain specific domainA = unit.new_domain_ref() role1['domain_id'] = domainA['id'] self.assertRaises(exception.ValidationError, self.role_api.update_role, role1['id'], role1) # Create a domain specific role from scratch role2 = unit.new_role_ref(domain_id=domainA['id']) self.role_api.create_role(role2['id'], role2) # Try to "move" it to another domain domainB = unit.new_domain_ref() role2['domain_id'] = domainB['id'] self.assertRaises(exception.ValidationError, self.role_api.update_role, role2['id'], role2) # Now try to make it global role2['domain_id'] = None self.assertRaises(exception.ValidationError, self.role_api.update_role, role2['id'], role2)
def test_list_domains_for_user(self): domain = unit.new_domain_ref() PROVIDERS.resource_api.create_domain(domain['id'], domain) user = unit.new_user_ref(domain_id=domain['id']) test_domain1 = unit.new_domain_ref() PROVIDERS.resource_api.create_domain(test_domain1['id'], test_domain1) test_domain2 = unit.new_domain_ref() PROVIDERS.resource_api.create_domain(test_domain2['id'], test_domain2) user = PROVIDERS.identity_api.create_user(user) user_domains = PROVIDERS.assignment_api.list_domains_for_user( user['id'] ) self.assertEqual(0, len(user_domains)) PROVIDERS.assignment_api.create_grant( user_id=user['id'], domain_id=test_domain1['id'], role_id=self.role_member['id'] ) PROVIDERS.assignment_api.create_grant( user_id=user['id'], domain_id=test_domain2['id'], role_id=self.role_member['id'] ) user_domains = PROVIDERS.assignment_api.list_domains_for_user( user['id'] ) self.assertThat(user_domains, matchers.HasLength(2))
def test_list_domains_for_user_with_grants(self): # Create two groups each with a role on a different domain, and # make user1 a member of both groups. Both these new domains # should now be included, along with any direct user grants. domain = unit.new_domain_ref() self.resource_api.create_domain(domain['id'], domain) user = unit.new_user_ref(domain_id=domain['id']) user = self.identity_api.create_user(user) group1 = unit.new_group_ref(domain_id=domain['id']) group1 = self.identity_api.create_group(group1) group2 = unit.new_group_ref(domain_id=domain['id']) group2 = self.identity_api.create_group(group2) test_domain1 = unit.new_domain_ref() self.resource_api.create_domain(test_domain1['id'], test_domain1) test_domain2 = unit.new_domain_ref() self.resource_api.create_domain(test_domain2['id'], test_domain2) test_domain3 = unit.new_domain_ref() self.resource_api.create_domain(test_domain3['id'], test_domain3) self.identity_api.add_user_to_group(user['id'], group1['id']) self.identity_api.add_user_to_group(user['id'], group2['id']) # Create 3 grants, one user grant, the other two as group grants self.assignment_api.create_grant(user_id=user['id'], domain_id=test_domain1['id'], role_id=self.role_member['id']) self.assignment_api.create_grant(group_id=group1['id'], domain_id=test_domain2['id'], role_id=self.role_admin['id']) self.assignment_api.create_grant(group_id=group2['id'], domain_id=test_domain3['id'], role_id=self.role_admin['id']) user_domains = self.assignment_api.list_domains_for_user(user['id']) self.assertThat(user_domains, matchers.HasLength(3))
def test_user_management_normalized_keys(self): """Illustrate the inconsistent handling of hyphens in keys. To quote Morgan in bug 1526244: the reason this is converted from "domain-id" to "domain_id" is because of how we process/normalize data. The way we have to handle specific data types for known columns requires avoiding "-" in the actual python code since "-" is not valid for attributes in python w/o significant use of "getattr" etc. In short, historically we handle some things in conversions. The use of "extras" has long been a poor design choice that leads to odd/strange inconsistent behaviors because of other choices made in handling data from within the body. (In many cases we convert from "-" to "_" throughout openstack) Source: https://bugs.launchpad.net/keystone/+bug/1526244/comments/9 """ # Create two domains to work with. domain1 = unit.new_domain_ref() self.resource_api.create_domain(domain1["id"], domain1) domain2 = unit.new_domain_ref() self.resource_api.create_domain(domain2["id"], domain2) # We can successfully create a normal user without any surprises. user = unit.new_user_ref(domain_id=domain1["id"]) r = self.post("/users", body={"user": user}) self.assertValidUserResponse(r, user) user["id"] = r.json["user"]["id"] # Query strings are not normalized: so we get all users back (like # self.user), not just the ones in the specified domain. r = self.get("/users?domain-id=%s" % domain1["id"]) self.assertValidUserListResponse(r, ref=self.user) self.assertNotEqual(domain1["id"], self.user["domain_id"]) # When creating a new user, if we move the 'domain_id' into the # 'domain-id' attribute, the server will normalize the request # attribute, and effectively "move it back" for us. user = unit.new_user_ref(domain_id=domain1["id"]) user["domain-id"] = user.pop("domain_id") r = self.post("/users", body={"user": user}) self.assertNotIn("domain-id", r.json["user"]) self.assertEqual(domain1["id"], r.json["user"]["domain_id"]) # (move this attribute back so we can use assertValidUserResponse) user["domain_id"] = user.pop("domain-id") self.assertValidUserResponse(r, user) user["id"] = r.json["user"]["id"] # If we try updating the user's 'domain_id' by specifying a # 'domain-id', then it'll be stored into extras rather than normalized, # and the user's actual 'domain_id' is not affected. r = self.patch("/users/%s" % user["id"], body={"user": {"domain-id": domain2["id"]}}) self.assertEqual(domain2["id"], r.json["user"]["domain-id"]) self.assertEqual(user["domain_id"], r.json["user"]["domain_id"]) self.assertNotEqual(domain2["id"], user["domain_id"]) self.assertValidUserResponse(r, user)
def load_sample_data(self): self.addCleanup(self.clean_sample_data) domainA = unit.new_domain_ref() self.domainA = PROVIDERS.resource_api.create_domain( domainA['id'], domainA ) domainB = unit.new_domain_ref() self.domainB = PROVIDERS.resource_api.create_domain( domainB['id'], domainB )
def test_create_domain_unsafe(self): """Call ``POST /domains with unsafe names``.""" unsafe_name = "i am not / safe" self.config_fixture.config(group="resource", domain_name_url_safe="off") ref = unit.new_domain_ref(name=unsafe_name) self.post("/domains", body={"domain": ref}) self.config_fixture.config(group="resource", domain_name_url_safe="new") ref = unit.new_domain_ref(name=unsafe_name) self.post("/domains", body={"domain": ref}, expected_status=http_client.BAD_REQUEST)
def load_sample_data(self): """Create sample data for these tests. As well as the usual housekeeping, create a set of domains, users, roles and projects for the subsequent tests: - Three domains: A,B & C. C is disabled. - DomainA has user1, DomainB has user2 and user3 - DomainA has group1 and group2, DomainB has group3 - User1 has a role on DomainA Remember that there will also be a fourth domain in existence, the default domain. """ # Start by creating a few domains self._populate_default_domain() self.domainA = unit.new_domain_ref() self.resource_api.create_domain(self.domainA['id'], self.domainA) self.domainB = unit.new_domain_ref() self.resource_api.create_domain(self.domainB['id'], self.domainB) self.domainC = unit.new_domain_ref() self.domainC['enabled'] = False self.resource_api.create_domain(self.domainC['id'], self.domainC) # Now create some users, one in domainA and two of them in domainB self.user1 = self.new_user_ref(domain_id=self.domainA['id']) password = uuid.uuid4().hex self.user1['password'] = password self.user1 = self.identity_api.create_user(self.user1) self.user1['password'] = password self.user2 = self.new_user_ref(domain_id=self.domainB['id']) self.user2['password'] = password self.user2 = self.identity_api.create_user(self.user2) self.user2['password'] = password self.user3 = self.new_user_ref(domain_id=self.domainB['id']) self.user3['password'] = password self.user3 = self.identity_api.create_user(self.user3) self.user3['password'] = password self.role = unit.new_role_ref() self.role_api.create_role(self.role['id'], self.role) self.assignment_api.create_grant(self.role['id'], user_id=self.user1['id'], domain_id=self.domainA['id']) # A default auth request we can use - un-scoped user token self.auth = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'])
def test_user_cannot_filter_domains_by_name(self): domain_name = uuid.uuid4().hex domain = unit.new_domain_ref(name=domain_name) domain = PROVIDERS.resource_api.create_domain(domain['id'], domain) PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) with self.test_client() as c: c.get( '/v3/domains?name=%s' % domain_name, headers=self.headers, expected_status_code=http_client.FORBIDDEN )
def test_validate_v3_token_simple(self): # Check the fields in the token result when use validate_v3_token # with a simple token. domain_ref = unit.new_domain_ref() domain_ref = PROVIDERS.resource_api.create_domain( domain_ref['id'], domain_ref ) user_ref = unit.new_user_ref(domain_ref['id']) user_ref = PROVIDERS.identity_api.create_user(user_ref) method_names = ['password'] token = PROVIDERS.token_provider_api.issue_token( user_ref['id'], method_names) token = PROVIDERS.token_provider_api.validate_token(token.id) self.assertIsInstance(token.audit_ids, list) self.assertIsInstance(token.expires_at, str) self.assertIsInstance(token.issued_at, str) self.assertEqual(method_names, token.methods) self.assertEqual(user_ref['id'], token.user_id) self.assertEqual(user_ref['name'], token.user['name']) self.assertDictEqual(domain_ref, token.user_domain) self.assertEqual( user_ref['password_expires_at'], token.user['password_expires_at'] )
def test_validate_v3_receipt_simple(self): # Check the fields in the receipt result when use validate_v3_receipt # with a simple receipt. domain_ref = unit.new_domain_ref() domain_ref = PROVIDERS.resource_api.create_domain( domain_ref['id'], domain_ref ) rule_list = [ ['password', 'totp'], ['password', 'totp', 'token'], ] user_ref = unit.new_user_ref(domain_ref['id']) user_ref = PROVIDERS.identity_api.create_user(user_ref) user_ref['options'][ro.MFA_RULES_OPT.option_name] = rule_list user_ref['options'][ro.MFA_ENABLED_OPT.option_name] = True PROVIDERS.identity_api.update_user(user_ref['id'], user_ref) method_names = ['password'] receipt = PROVIDERS.receipt_provider_api.\ issue_receipt(user_ref['id'], method_names) receipt = PROVIDERS.receipt_provider_api.validate_receipt( receipt.id) self.assertIsInstance(receipt.expires_at, str) self.assertIsInstance(receipt.issued_at, str) self.assertEqual(set(method_names), set(receipt.methods)) self.assertEqual( set(frozenset(r) for r in rule_list), set(frozenset(r) for r in receipt.required_methods)) self.assertEqual(user_ref['id'], receipt.user_id)
def test_token_revoked_once_domain_disabled(self): """Test token from a disabled domain has been invalidated. Test that a token that was valid for an enabled domain becomes invalid once that domain is disabled. """ domain = unit.new_domain_ref() self.resource_api.create_domain(domain["id"], domain) user2 = unit.create_user(self.identity_api, domain_id=domain["id"]) # build a request body auth_body = self.build_authentication_request(user_id=user2["id"], password=user2["password"]) # sends a request for the user's token token_resp = self.post("/auth/tokens", body=auth_body) subject_token = token_resp.headers.get("x-subject-token") # validates the returned token and it should be valid. self.head("/auth/tokens", headers={"x-subject-token": subject_token}, expected_status=http_client.OK) # now disable the domain domain["enabled"] = False url = "/domains/%(domain_id)s" % {"domain_id": domain["id"]} self.patch(url, body={"domain": {"enabled": False}}) # validates the same token again and it should be 'not found' # as the domain has already been disabled. self.head("/auth/tokens", headers={"x-subject-token": subject_token}, expected_status=http_client.NOT_FOUND)
def setUp(self): super(ProjectAdminTests, self).setUp() self.loadapp() self.policy_file = self.useFixture(temporaryfile.SecureTempFile()) self.policy_file_name = self.policy_file.file_name self.useFixture( ksfixtures.Policy( self.config_fixture, policy_file=self.policy_file_name ) ) self._override_policy() self.config_fixture.config(group='oslo_policy', enforce_scope=True) domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) self.domain_id = domain['id'] self.user_id = self.bootstrapper.admin_user_id auth = self.build_authentication_request( user_id=self.user_id, password=self.bootstrapper.admin_password, project_id=self.bootstrapper.project_id ) # Grab a token using the persona we're testing and prepare headers # for requests we'll be making in the tests. with self.test_client() as c: r = c.post('/v3/auth/tokens', json=auth) self.token_id = r.headers['X-Subject-Token'] self.headers = {'X-Auth-Token': self.token_id}
def test_validate_v3_token_simple(self): # Check the fields in the token result when use validate_v3_token # with a simple token. domain_ref = unit.new_domain_ref() domain_ref = self.resource_api.create_domain(domain_ref['id'], domain_ref) user_ref = unit.new_user_ref(domain_ref['id']) user_ref = self.identity_api.create_user(user_ref) method_names = ['password'] token_id, token_data_ = self.token_provider_api.issue_v3_token( user_ref['id'], method_names) token_data = self.token_provider_api.validate_v3_token(token_id) token = token_data['token'] self.assertIsInstance(token['audit_ids'], list) self.assertIsInstance(token['expires_at'], str) self.assertEqual({}, token['extras']) self.assertIsInstance(token['issued_at'], str) self.assertEqual(method_names, token['methods']) exp_user_info = { 'id': user_ref['id'], 'name': user_ref['name'], 'domain': { 'id': domain_ref['id'], 'name': domain_ref['name'], }, } self.assertEqual(exp_user_info, token['user'])
def test_create_domain(self): """Call ``POST /domains``.""" ref = unit.new_domain_ref() r = self.post( '/domains', body={'domain': ref}) return self.assertValidDomainResponse(r, ref)
def test_disable_of_disabled_domain_does_not_notify(self): domain_ref = unit.new_domain_ref(enabled=False) self.resource_api.create_domain(domain_ref["id"], domain_ref) # The domain_ref above is not changed during the create process. We # can use the same ref to perform the update. self.resource_api.update_domain(domain_ref["id"], domain_ref) self._assert_notify_not_sent(domain_ref["id"], "disabled", "domain", public=False)
def test_delete_domain_hierarchy(self): """Call ``DELETE /domains/{domain_id}``.""" domain = unit.new_domain_ref() self.resource_api.create_domain(domain['id'], domain) root_project = unit.new_project_ref(domain_id=domain['id']) self.resource_api.create_project(root_project['id'], root_project) leaf_project = unit.new_project_ref( domain_id=domain['id'], parent_id=root_project['id']) self.resource_api.create_project(leaf_project['id'], leaf_project) # Need to disable it first. self.patch('/domains/%(domain_id)s' % { 'domain_id': domain['id']}, body={'domain': {'enabled': False}}) self.delete( '/domains/%(domain_id)s' % { 'domain_id': domain['id']}) self.assertRaises(exception.DomainNotFound, self.resource_api.get_domain, domain['id']) self.assertRaises(exception.ProjectNotFound, self.resource_api.get_project, root_project['id']) self.assertRaises(exception.ProjectNotFound, self.resource_api.get_project, leaf_project['id'])
def test_update_domain(self): domain_ref = unit.new_domain_ref() self.resource_api.create_domain(domain_ref["id"], domain_ref) domain_ref["description"] = uuid.uuid4().hex self.resource_api.update_domain(domain_ref["id"], domain_ref) self._assert_last_note(domain_ref["id"], UPDATED_OPERATION, "domain") self._assert_last_audit(domain_ref["id"], UPDATED_OPERATION, "domain", cadftaxonomy.SECURITY_DOMAIN)
def test_list_entities_filtered_by_domain(self): # NOTE(henry-nash): This method is here rather than in # unit.identity.test_backends since any domain filtering with LDAP is # handled by the manager layer (and is already tested elsewhere) not at # the driver level. self.addCleanup(self.clean_up_entities) self.domain1 = unit.new_domain_ref() self.resource_api.create_domain(self.domain1['id'], self.domain1) self.entity_list = {} self.domain1_entity_list = {} for entity in ['user', 'group', 'project']: # Create 5 entities, 3 of which are in domain1 DOMAIN1_ENTITIES = 3 self.entity_list[entity] = self._create_test_data(entity, 2) self.domain1_entity_list[entity] = self._create_test_data( entity, DOMAIN1_ENTITIES, self.domain1['id']) # Should get back the DOMAIN1_ENTITIES in domain1 hints = driver_hints.Hints() hints.add_filter('domain_id', self.domain1['id']) entities = self._list_entities(entity)(hints=hints) self.assertEqual(DOMAIN1_ENTITIES, len(entities)) self._match_with_list(entities, self.domain1_entity_list[entity]) # Check the driver has removed the filter from the list hints self.assertFalse(hints.get_exact_filter_by_name('domain_id'))
def test_delete_domain_deletes_configs(self): """Test domain deletion clears the domain configs.""" domain = unit.new_domain_ref() self.resource_api.create_domain(domain['id'], domain) config = {'ldap': {'url': uuid.uuid4().hex, 'user_tree_dn': uuid.uuid4().hex, 'password': uuid.uuid4().hex}} self.domain_config_api.create_config(domain['id'], config) # Now delete the domain domain['enabled'] = False self.resource_api.update_domain(domain['id'], domain) self.resource_api.delete_domain(domain['id']) # Check domain configs have also been deleted self.assertRaises( exception.DomainConfigNotFound, self.domain_config_api.get_config, domain['id']) # The get_config_with_sensitive_info does not throw an exception if # the config is empty, it just returns an empty dict self.assertDictEqual( {}, self.domain_config_api.get_config_with_sensitive_info( domain['id']))
def test_get_catalog_always_returns_service_name(self): user_id = uuid.uuid4().hex # create a project since the project should exist if we want to # filter the catalog by the project or replace the url with a # valid project id. domain = unit.new_domain_ref() PROVIDERS.resource_api.create_domain(domain['id'], domain) project = unit.new_project_ref(domain_id=domain['id']) PROVIDERS.resource_api.create_project(project['id'], project) # create a service, with a name named_svc = unit.new_service_ref() PROVIDERS.catalog_api.create_service(named_svc['id'], named_svc) self.create_endpoint(service_id=named_svc['id']) # create a service, with no name unnamed_svc = unit.new_service_ref(name=None) del unnamed_svc['name'] PROVIDERS.catalog_api.create_service(unnamed_svc['id'], unnamed_svc) self.create_endpoint(service_id=unnamed_svc['id']) catalog = PROVIDERS.catalog_api.get_v3_catalog(user_id, project['id']) named_endpoint = [ep for ep in catalog if ep['type'] == named_svc['type']][0] self.assertEqual(named_svc['name'], named_endpoint['name']) unnamed_endpoint = [ep for ep in catalog if ep['type'] == unnamed_svc['type']][0] self.assertEqual('', unnamed_endpoint['name'])
def test_create_domain_unsafe_default(self): """Check default for unsafe names for``POST /domains ``.""" unsafe_name = "i am not / safe" # By default, we should be able to create unsafe names ref = unit.new_domain_ref(name=unsafe_name) self.post("/domains", body={"domain": ref})
def test_validate_v3_token_simple(self): # Check the fields in the token result when use validate_v3_token # with a simple token. domain_ref = unit.new_domain_ref() domain_ref = self.resource_api.create_domain(domain_ref["id"], domain_ref) user_ref = unit.new_user_ref(domain_ref["id"]) user_ref = self.identity_api.create_user(user_ref) method_names = ["password"] token_id, token_data_ = self.token_provider_api.issue_v3_token(user_ref["id"], method_names) token_data = self.token_provider_api.validate_v3_token(token_id) token = token_data["token"] self.assertIsInstance(token["audit_ids"], list) self.assertIsInstance(token["expires_at"], str) self.assertIsInstance(token["issued_at"], str) self.assertEqual(method_names, token["methods"]) exp_user_info = { "id": user_ref["id"], "name": user_ref["name"], "domain": {"id": domain_ref["id"], "name": domain_ref["name"]}, } self.assertEqual(exp_user_info, token["user"])
def test_user_can_filter_domains_by_name(self): domain_name = uuid.uuid4().hex domain = unit.new_domain_ref(name=domain_name) domain = PROVIDERS.resource_api.create_domain(domain['id'], domain) PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) with self.test_client() as c: r = c.get( '/v3/domains?name=%s' % domain_name, headers=self.headers ) self.assertEqual(1, len(r.json['domains'])) self.assertEqual(domain['id'], r.json['domains'][0]['id'])
def test_delete_domain_deletes_configs(self): """Test domain deletion clears the domain configs.""" domain = unit.new_domain_ref() self.resource_api.create_domain(domain["id"], domain) config1 = {"group": uuid.uuid4().hex, "option": uuid.uuid4().hex, "value": uuid.uuid4().hex} # Put config2 in the same group as config1 config2 = {"group": config1["group"], "option": uuid.uuid4().hex, "value": uuid.uuid4().hex} self.domain_config_api.create_config_option(domain["id"], config1["group"], config1["option"], config1["value"]) self.domain_config_api.create_config_option( domain["id"], config2["group"], config2["option"], config2["value"], sensitive=True ) res = self.domain_config_api.list_config_options(domain["id"]) self.assertThat(res, matchers.HasLength(1)) res = self.domain_config_api.list_config_options(domain["id"], sensitive=True) self.assertThat(res, matchers.HasLength(1)) # Now delete the domain domain["enabled"] = False self.resource_api.update_domain(domain["id"], domain) self.resource_api.delete_domain(domain["id"]) # Check domain configs have also been deleted res = self.domain_config_api.list_config_options(domain["id"]) self.assertThat(res, matchers.HasLength(0)) res = self.domain_config_api.list_config_options(domain["id"], sensitive=True) self.assertThat(res, matchers.HasLength(0))
def setUp(self): super(DomainUserTests, self).setUp() self.loadapp() self.useFixture(ksfixtures.Policy(self.config_fixture)) self.config_fixture.config(group='oslo_policy', enforce_scope=True) domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) self.domain_id = domain['id'] domain_admin = unit.new_user_ref(domain_id=self.domain_id) self.user_id = PROVIDERS.identity_api.create_user(domain_admin)['id'] PROVIDERS.assignment_api.create_grant( self.bootstrapper.admin_role_id, user_id=self.user_id, domain_id=self.domain_id ) auth = self.build_authentication_request( user_id=self.user_id, password=domain_admin['password'], domain_id=self.domain_id ) # Grab a token using the persona we're testing and prepare headers # for requests we'll be making in the tests. with self.test_client() as c: r = c.post('/v3/auth/tokens', json=auth) self.token_id = r.headers['X-Subject-Token'] self.headers = {'X-Auth-Token': self.token_id}
def test_list_projects_default_domain(self): """Test that list projects only returns those in the default domain.""" domain = unit.new_domain_ref() self.resource_api.create_domain(domain['id'], domain) project1 = unit.new_project_ref(domain_id=domain['id']) self.resource_api.create_project(project1['id'], project1) # Check the real total number of projects, we should have the: # - tenants in the default fixtures # - the project representing the default domain # - the project representing the domain we created above # - the project we created above refs = self.resource_api.list_projects() self.assertThat( refs, matchers.HasLength(len(default_fixtures.TENANTS) + 3)) # Now list all projects using the v2 API - we should only get # back those in the default features, since only those are in the # default domain. refs = self.tenant_controller.get_all_projects(_ADMIN_CONTEXT) self.assertEqual(len(default_fixtures.TENANTS), len(refs['tenants'])) for tenant in default_fixtures.TENANTS: tenant_copy = tenant.copy() tenant_copy.pop('domain_id') tenant_copy.pop('parent_id') tenant_copy.pop('is_domain') self.assertIn(tenant_copy, refs['tenants'])
def test_user_can_get_a_domain(self): domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) with self.test_client() as c: r = c.get('/v3/domains/%s' % domain['id'], headers=self.headers) self.assertEqual(domain['id'], r.json['domain']['id'])
def setUp(self): super(DomainConfigTestCase, self).setUp() self.domain = unit.new_domain_ref() self.resource_api.create_domain(self.domain['id'], self.domain) self.config = {'ldap': {'url': uuid.uuid4().hex, 'user_tree_dn': uuid.uuid4().hex}, 'identity': {'driver': uuid.uuid4().hex}}
def test_update_domain(self): """Call ``PATCH /domains/{domain_id}``.""" ref = unit.new_domain_ref() del ref['id'] r = self.patch('/domains/%(domain_id)s' % { 'domain_id': self.domain_id}, body={'domain': ref}) self.assertValidDomainResponse(r, ref)
def test_user_cannot_list_groups_in_other_domain(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) PROVIDERS.identity_api.create_group( unit.new_group_ref(domain_id=domain['id'])) with self.test_client() as c: r = c.get('/v3/groups?domain_id=%s' % domain['id'], headers=self.headers) self.assertEqual(0, len(r.json['groups']))
def test_user_can_get_a_group(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) group = PROVIDERS.identity_api.create_group( unit.new_group_ref(domain_id=domain['id'])) with self.test_client() as c: r = c.get('/v3/groups/%s' % group['id'], headers=self.headers) self.assertEqual(group['id'], r.json['group']['id'])
def test_validate_v3_token_federated_info(self): # Check the user fields in the token result when use validate_v3_token # when the token has federated info. domain_ref = unit.new_domain_ref() domain_ref = PROVIDERS.resource_api.create_domain( domain_ref['id'], domain_ref) user_ref = unit.new_user_ref(domain_ref['id']) user_ref = PROVIDERS.identity_api.create_user(user_ref) method_names = ['mapped'] group_ids = [ uuid.uuid4().hex, ] idp_id = uuid.uuid4().hex idp_ref = { 'id': idp_id, 'description': uuid.uuid4().hex, 'enabled': True } self.federation_api.create_idp(idp_id, idp_ref) protocol = uuid.uuid4().hex auth_context_params = { 'user_id': user_ref['id'], 'user_name': user_ref['name'], 'group_ids': group_ids, federation_constants.IDENTITY_PROVIDER: idp_id, federation_constants.PROTOCOL: protocol, } auth_context = auth.core.AuthContext(**auth_context_params) token_id, token_data_ = PROVIDERS.token_provider_api.issue_token( user_ref['id'], method_names, auth_context=auth_context) token_data = PROVIDERS.token_provider_api.validate_token(token_id) token = token_data['token'] exp_user_info = { 'id': user_ref['id'], 'name': user_ref['name'], 'domain': { 'id': CONF.federation.federated_domain_name, 'name': CONF.federation.federated_domain_name, }, federation_constants.FEDERATION: { 'groups': [{ 'id': group_id } for group_id in group_ids], 'identity_provider': { 'id': idp_id, }, 'protocol': { 'id': protocol, }, }, } self.assertDictEqual(exp_user_info, token['user'])
def test_user_cannot_delete_group_in_other_domain(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) group = PROVIDERS.identity_api.create_group( unit.new_group_ref(domain_id=domain['id'])) with self.test_client() as c: c.delete('/v3/groups/%s' % group['id'], headers=self.headers, expected_status_code=http_client.FORBIDDEN)
def test_get_security_compliance_config_with_user_from_other_domain(self): """Make sure users from other domains can access password requirements. Even though a user is in a separate domain, they should be able to see the security requirements for the deployment. This is because security compliance is not yet implemented on a per domain basis. Once that happens, then this should no longer be possible since a user should only care about the security compliance requirements for the domain that they are in. """ # Make a new domain domain = unit.new_domain_ref() self.resource_api.create_domain(domain['id'], domain) # Create a user in the new domain user = unit.create_user(self.identity_api, domain['id']) # Create a project in the new domain project = unit.new_project_ref(domain_id=domain['id']) self.resource_api.create_project(project['id'], project) # Give the new user a non-admin role on the project self.assignment_api.add_role_to_user_and_project( user['id'], project['id'], self.non_admin_role['id']) # Set our security compliance config values, we do this after we've # created our test user otherwise password validation will fail with a # uuid type regex. password_regex = uuid.uuid4().hex password_regex_description = uuid.uuid4().hex group = 'security_compliance' self.config_fixture.config(group=group, password_regex=password_regex) self.config_fixture.config( group=group, password_regex_description=password_regex_description) # Get a token for the newly created user scoped to the project in the # non-default domain and use it to get the password security # requirements. user_token = self.build_authentication_request( user_id=user['id'], password=user['password'], project_id=project['id']) user_token = self.get_requested_token(user_token) url = ('/domains/%(domain_id)s/config/%(group)s' % { 'domain_id': CONF.identity.default_domain_id, 'group': group, }) response = self.get(url, token=user_token) self.assertEqual(response.result['config'][group]['password_regex'], password_regex) self.assertEqual( response.result['config'][group]['password_regex_description'], password_regex_description) # Ensure HEAD requests behave the same way self.head(url, token=user_token, expected_status=http_client.OK)
def test_user_can_get_non_existent_config_option(self): domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) config = {'ldap': {'url': uuid.uuid4().hex}} PROVIDERS.domain_config_api.create_config(domain['id'], config) with self.test_client() as c: c.get('/v3/domains/%s/config/ldap/user_tree_dn' % domain['id'], headers=self.headers, expected_status_code=http_client.NOT_FOUND)
def test_user_can_get_config_by_group_invalid_domain(self): domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) PROVIDERS.domain_config_api.create_config(domain['id'], unit.new_domain_config_ref()) invalid_domain_id = uuid.uuid4().hex with self.test_client() as c: c.get('/v3/domains/%s/config/ldap' % invalid_domain_id, headers=self.headers, expected_status_code=http_client.NOT_FOUND)
def test_user_cannot_list_groups(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) PROVIDERS.identity_api.create_group( unit.new_group_ref(domain_id=domain['id'])) with self.test_client() as c: c.get('/v3/groups', headers=self.headers, expected_status_code=http.client.FORBIDDEN)
def test_user_can_list_domains(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) with self.test_client() as c: r = c.get('/v3/domains', headers=self.headers) domain_ids = [] for domain in r.json['domains']: domain_ids.append(domain['id']) self.assertIn(domain['id'], domain_ids)
def test_user_cannot_get_users_in_other_domains(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) user = PROVIDERS.identity_api.create_user( unit.new_user_ref(domain_id=domain['id'])) with self.test_client() as c: c.get('/v3/users/%s' % user['id'], headers=self.headers, expected_status_code=http.client.FORBIDDEN)
def test_user_can_create_domain_config(self): domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) with self.test_client() as c: c.put('/v3/domains/%s/config' % domain['id'], json={'config': unit.new_domain_config_ref()}, headers=self.headers, expected_status_code=http_client.CREATED)
def test_user_can_delete_a_domain(self): domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) with self.test_client() as c: update = {'domain': {'enabled': False}} path = '/v3/domains/%s' % domain['id'] c.patch(path, json=update, headers=self.headers) c.delete(path, headers=self.headers)
def test_domain_duplicate_conflict_gives_name(self): domain = unit.new_domain_ref() self.resource_api.create_domain(domain['id'], domain) domain['id'] = uuid.uuid4().hex try: self.resource_api.create_domain(domain['id'], domain) except exception.Conflict as e: self.assertIn("%s" % domain['name'], repr(e)) else: self.fail("Creating duplicate domain did not raise a conflict")
def test_user_cannot_get_domain_config_option(self): domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) PROVIDERS.domain_config_api.create_config( domain['id'], unit.new_domain_config_ref()) with self.test_client() as c: c.get('/v3/domains/%s/config/ldap/url' % domain['id'], headers=self.headers, expected_status_code=http_client.FORBIDDEN)
def test_user_cannot_update_a_domain(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) update = {'domain': {'description': uuid.uuid4().hex}} with self.test_client() as c: c.patch('/v3/domains/%s' % domain['id'], json=update, headers=self.headers, expected_status_code=http_client.FORBIDDEN)
def test_user_cannot_get_a_domain_they_are_not_authorized_to_access(self): domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) with self.test_client() as c: c.get( '/v3/domains/%s' % domain['id'], headers=self.headers, expected_status_code=http_client.FORBIDDEN )
def test_user_cannot_delete_a_domain(self): domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) with self.test_client() as c: c.delete( '/v3/domains/%s' % domain['id'], headers=self.headers, expected_status_code=http_client.FORBIDDEN )
def load_sample_data(self): """Create sample data for these tests. As well as the usual housekeeping, create a set of domains, users, roles and projects for the subsequent tests: - Three domains: A,B & C. C is disabled. - DomainA has user1, DomainB has user2 and user3 - DomainA has group1 and group2, DomainB has group3 - User1 has a role on DomainA Remember that there will also be a fourth domain in existence, the default domain. """ # Start by creating a few domains self._populate_default_domain() self.domainA = unit.new_domain_ref() self.resource_api.create_domain(self.domainA['id'], self.domainA) self.domainB = unit.new_domain_ref() self.resource_api.create_domain(self.domainB['id'], self.domainB) self.domainC = unit.new_domain_ref() self.domainC['enabled'] = False self.resource_api.create_domain(self.domainC['id'], self.domainC) # Now create some users, one in domainA and two of them in domainB self.user1 = unit.create_user(self.identity_api, domain_id=self.domainA['id']) self.user2 = unit.create_user(self.identity_api, domain_id=self.domainB['id']) self.user3 = unit.create_user(self.identity_api, domain_id=self.domainB['id']) self.role = unit.new_role_ref() self.role_api.create_role(self.role['id'], self.role) self.assignment_api.create_grant(self.role['id'], user_id=self.user1['id'], domain_id=self.domainA['id']) # A default auth request we can use - un-scoped user token self.auth = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'])
def test_validate_v3_token_trust(self): # Check the trust fields in the token result when use validate_v3_token # when the token has trust info. domain_ref = unit.new_domain_ref() domain_ref = PROVIDERS.resource_api.create_domain( domain_ref['id'], domain_ref ) user_ref = unit.new_user_ref(domain_ref['id']) user_ref = PROVIDERS.identity_api.create_user(user_ref) trustor_user_ref = unit.new_user_ref(domain_ref['id']) trustor_user_ref = PROVIDERS.identity_api.create_user(trustor_user_ref) project_ref = unit.new_project_ref(domain_id=domain_ref['id']) project_ref = PROVIDERS.resource_api.create_project( project_ref['id'], project_ref ) role_ref = unit.new_role_ref() role_ref = PROVIDERS.role_api.create_role(role_ref['id'], role_ref) PROVIDERS.assignment_api.create_grant( role_ref['id'], user_id=user_ref['id'], project_id=project_ref['id']) PROVIDERS.assignment_api.create_grant( role_ref['id'], user_id=trustor_user_ref['id'], project_id=project_ref['id']) trustor_user_id = trustor_user_ref['id'] trustee_user_id = user_ref['id'] trust_ref = unit.new_trust_ref( trustor_user_id, trustee_user_id, project_id=project_ref['id'], role_ids=[role_ref['id'], ]) trust_ref = PROVIDERS.trust_api.create_trust( trust_ref['id'], trust_ref, trust_ref['roles'] ) method_names = ['password'] token_id, token_data_ = PROVIDERS.token_provider_api.issue_token( user_ref['id'], method_names, project_id=project_ref['id'], trust=trust_ref) token_data = PROVIDERS.token_provider_api.validate_token(token_id) token = token_data['token'] exp_trust_info = { 'id': trust_ref['id'], 'impersonation': False, 'trustee_user': {'id': user_ref['id'], }, 'trustor_user': {'id': trustor_user_ref['id'], }, } self.assertEqual(exp_trust_info, token['OS-TRUST:trust'])
def test_list_users_with_multiple_backends(self): """Call ``GET /users`` when multiple backends is enabled. In this scenario, the controller requires a domain to be specified either as a filter or by using a domain scoped token. """ self.config_fixture.config(group='identity', domain_specific_drivers_enabled=True) # Create a new domain with a new project and user domain = unit.new_domain_ref() self.resource_api.create_domain(domain['id'], domain) project = unit.new_project_ref(domain_id=domain['id']) self.resource_api.create_project(project['id'], project) user = unit.create_user(self.identity_api, domain_id=domain['id']) # Create both project and domain role grants for the user so we # can get both project and domain scoped tokens self.assignment_api.create_grant( role_id=self.role_id, user_id=user['id'], domain_id=domain['id']) self.assignment_api.create_grant( role_id=self.role_id, user_id=user['id'], project_id=project['id']) dom_auth = self.build_authentication_request( user_id=user['id'], password=user['password'], domain_id=domain['id']) project_auth = self.build_authentication_request( user_id=user['id'], password=user['password'], project_id=project['id']) # First try using a domain scoped token resource_url = '/users' r = self.get(resource_url, auth=dom_auth) self.assertValidUserListResponse(r, ref=user, resource_url=resource_url) # Now try using a project scoped token resource_url = '/users' r = self.get(resource_url, auth=project_auth) self.assertValidUserListResponse(r, ref=user, resource_url=resource_url) # Now try with an explicit filter resource_url = ('/users?domain_id=%(domain_id)s' % {'domain_id': domain['id']}) r = self.get(resource_url) self.assertValidUserListResponse(r, ref=user, resource_url=resource_url)
def test_user_cannot_update_domain_group_config(self): domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) PROVIDERS.domain_config_api.create_config(domain['id'], unit.new_domain_config_ref()) new_config = {'ldap': {'url': uuid.uuid4().hex, 'user_filter': uuid.uuid4().hex}} with self.test_client() as c: c.patch('/v3/domains/%s/config/ldap' % domain['id'], json={'config': new_config}, headers=self.headers, expected_status_code=http_client.FORBIDDEN)
def test_user_can_update_domain_config_option(self): domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref() ) new_config = {'url': uuid.uuid4().hex} PROVIDERS.domain_config_api.create_config( domain['id'], unit.new_domain_config_ref()) with self.test_client() as c: c.patch('/v3/domains/%s/config/ldap/url' % domain['id'], json={'config': new_config}, headers=self.headers)
def test_user_can_create_grant_for_user_on_domain(self): user = PROVIDERS.identity_api.create_user( unit.new_user_ref(domain_id=CONF.identity.default_domain_id)) domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) with self.test_client() as c: c.put('/v3/domains/%s/users/%s/roles/%s' % (domain['id'], user['id'], self.bootstrapper.reader_role_id), headers=self.headers)
def test_user_can_filter_domains_by_enabled(self): enabled_domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref()) disabled_domain = PROVIDERS.resource_api.create_domain( uuid.uuid4().hex, unit.new_domain_ref(enabled=False)) with self.test_client() as c: r = c.get('/v3/domains?enabled=true', headers=self.headers) enabled_domain_ids = [] for domain in r.json['domains']: enabled_domain_ids.append(domain['id']) self.assertIn(enabled_domain['id'], enabled_domain_ids) self.assertNotIn(disabled_domain['id'], enabled_domain_ids) r = c.get('/v3/domains?enabled=false', headers=self.headers) disabled_domain_ids = [] for domain in r.json['domains']: disabled_domain_ids.append(domain['id']) self.assertIn(disabled_domain['id'], disabled_domain_ids) self.assertNotIn(enabled_domain['id'], disabled_domain_ids)
def test_user_can_add_users_to_group(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) group = PROVIDERS.identity_api.create_group( unit.new_group_ref(domain_id=domain['id'])) user = PROVIDERS.identity_api.create_user( unit.new_user_ref(domain_id=domain['id'])) with self.test_client() as c: c.put('/v3/groups/%s/users/%s' % (group['id'], user['id']), headers=self.headers)
def test_user_cannot_update_users_in_other_domain(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) user = PROVIDERS.identity_api.create_user( unit.new_user_ref(domain_id=domain['id'])) update = {'user': {'email': uuid.uuid4().hex}} with self.test_client() as c: c.patch('/v3/users/%s' % user['id'], json=update, headers=self.headers, expected_status_code=http.client.FORBIDDEN)
def test_delete_group_without_role_does_not_revoke_users(self): revocation_backend = sql.Revoke() domain = unit.new_domain_ref() PROVIDERS.resource_api.create_domain(domain['id'], domain) # Create two groups. Group1 will be used to test deleting a group, # without role assignments and users in the group, doesn't create # revoked events. Group2 will show that deleting a group with role # assignment and users in the group does create revoked events group1 = unit.new_group_ref(domain_id=domain['id']) group1 = PROVIDERS.identity_api.create_group(group1) group2 = unit.new_group_ref(domain_id=domain['id']) group2 = PROVIDERS.identity_api.create_group(group2) role = unit.new_role_ref() PROVIDERS.role_api.create_role(role['id'], role) user1 = unit.new_user_ref(domain_id=domain['id']) user1 = PROVIDERS.identity_api.create_user(user1) user2 = unit.new_user_ref(domain_id=domain['id']) user2 = PROVIDERS.identity_api.create_user(user2) # Add two users to the group, verify they are added, delete group, and # check that the revocaiton events have not been created PROVIDERS.identity_api.add_user_to_group( user_id=user1['id'], group_id=group1['id'] ) PROVIDERS.identity_api.add_user_to_group( user_id=user2['id'], group_id=group1['id'] ) self.assertEqual( 2, len(PROVIDERS.identity_api.list_users_in_group(group1['id']))) PROVIDERS.identity_api.delete_group(group1['id']) self.assertEqual(0, len(revocation_backend.list_events())) # Assign a role to the group, add two users to the group, verify that # the role has been assigned to the group, verify the users have been # added to the group, delete the group, check that the revocation # events have been created PROVIDERS.assignment_api.create_grant( group_id=group2['id'], domain_id=domain['id'], role_id=role['id'] ) grants = PROVIDERS.assignment_api.list_role_assignments( role_id=role['id'] ) self.assertThat(grants, matchers.HasLength(1)) PROVIDERS.identity_api.add_user_to_group( user_id=user1['id'], group_id=group2['id'] ) PROVIDERS.identity_api.add_user_to_group( user_id=user2['id'], group_id=group2['id'] ) self.assertEqual( 2, len(PROVIDERS.identity_api.list_users_in_group(group2['id']))) PROVIDERS.identity_api.delete_group(group2['id']) self.assertEqual(2, len(revocation_backend.list_events()))
def test_user_cannot_list_users_in_own_domain_group_in_other_domain(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) user = PROVIDERS.identity_api.create_user( unit.new_user_ref(domain_id=self.domain_id)) group = PROVIDERS.identity_api.create_group( unit.new_group_ref(domain_id=domain['id'])) PROVIDERS.identity_api.add_user_to_group(user['id'], group['id']) with self.test_client() as c: c.get('/v3/groups/%s/users' % group['id'], headers=self.headers, expected_status_code=http.client.FORBIDDEN)
def test_user_cannot_update_group_in_other_domain(self): domain = PROVIDERS.resource_api.create_domain(uuid.uuid4().hex, unit.new_domain_ref()) group = PROVIDERS.identity_api.create_group( unit.new_group_ref(domain_id=domain['id'])) update = {'group': {'description': uuid.uuid4().hex}} with self.test_client() as c: c.patch('/v3/groups/%s' % group['id'], json=update, headers=self.headers, expected_status_code=http.client.FORBIDDEN)
def test_list_domains_for_user(self): domain = unit.new_domain_ref() self.resource_api.create_domain(domain['id'], domain) user = unit.new_user_ref(domain_id=domain['id']) test_domain1 = unit.new_domain_ref() self.resource_api.create_domain(test_domain1['id'], test_domain1) test_domain2 = unit.new_domain_ref() self.resource_api.create_domain(test_domain2['id'], test_domain2) user = self.identity_api.create_user(user) user_domains = self.assignment_api.list_domains_for_user(user['id']) self.assertEqual(0, len(user_domains)) self.assignment_api.create_grant(user_id=user['id'], domain_id=test_domain1['id'], role_id=self.role_member['id']) self.assignment_api.create_grant(user_id=user['id'], domain_id=test_domain2['id'], role_id=self.role_member['id']) user_domains = self.assignment_api.list_domains_for_user(user['id']) self.assertThat(user_domains, matchers.HasLength(2))