Search in sources :

Example 1 with TenantUpdateParam

use of com.emc.storageos.model.tenant.TenantUpdateParam in project coprhd-controller by CoprHD.

the class ApiTestBase method updateRootTenantAttrs.

/**
 * Update tenant attributes for the root tenant
 */
protected void updateRootTenantAttrs() {
    TenantResponse tenantResp = rSys.path("/tenant").get(TenantResponse.class);
    rootTenantId = tenantResp.getTenant();
    /*
         * PUT the ou=sanity attribute mapping into the root tenant attributes
         */
    TenantUpdateParam tenantUpdate = new TenantUpdateParam();
    tenantUpdate.setUserMappingChanges(new UserMappingChanges());
    tenantUpdate.getUserMappingChanges().setAdd(new ArrayList<UserMappingParam>());
    UserMappingParam rootMapping = new UserMappingParam();
    rootMapping.setDomain("SANITY.local");
    UserMappingAttributeParam rootAttr = new UserMappingAttributeParam();
    rootAttr.setKey("ou");
    rootAttr.setValues(Collections.singletonList(ROOTTENANT_ATTR));
    rootMapping.setAttributes(Collections.singletonList(rootAttr));
    tenantUpdate.getUserMappingChanges().getAdd().add(rootMapping);
    // TODO: FIX: not sure why name is required for update
    tenantUpdate.setLabel(ROOTTENANT_NAME);
    ClientResponse resp = rSys.path("/tenants/" + rootTenantId.toString()).put(ClientResponse.class, tenantUpdate);
    Assert.assertEquals(200, resp.getStatus());
}
Also used : ClientResponse(com.sun.jersey.api.client.ClientResponse) UserMappingAttributeParam(com.emc.storageos.model.tenant.UserMappingAttributeParam) UserMappingChanges(com.emc.storageos.model.tenant.UserMappingChanges) UserMappingParam(com.emc.storageos.model.tenant.UserMappingParam) TenantResponse(com.emc.storageos.model.tenant.TenantResponse) TenantUpdateParam(com.emc.storageos.model.tenant.TenantUpdateParam)

Example 2 with TenantUpdateParam

use of com.emc.storageos.model.tenant.TenantUpdateParam in project coprhd-controller by CoprHD.

the class TenantModificationTest method tenantAdminModifyUserMapping.

@Test
public void tenantAdminModifyUserMapping() throws Exception {
    TenantUpdateParam tenantUpdateParam = new TenantUpdateParam();
    UserMappingChanges changes = new UserMappingChanges();
    List<UserMappingParam> listAdd = new ArrayList<UserMappingParam>();
    UserMappingParam param = new UserMappingParam();
    param.setDomain("Not Exist");
    listAdd.add(param);
    changes.setAdd(listAdd);
    tenantUpdateParam.setUserMappingChanges(changes);
    try {
        tenantAdminClient.tenants().update(rootTenantID, tenantUpdateParam);
        Assert.fail("Tenant admin should has no permission to modify tenant's user mapping");
    } catch (ServiceErrorException see) {
        Assert.assertEquals(see.getCode(), 3000);
        Assert.assertTrue(see.getMessage().contains("Only users with SECURITY_ADMIN role can"));
    }
}
Also used : UserMappingChanges(com.emc.storageos.model.tenant.UserMappingChanges) UserMappingParam(com.emc.storageos.model.tenant.UserMappingParam) ArrayList(java.util.ArrayList) ServiceErrorException(com.emc.vipr.client.exceptions.ServiceErrorException) TenantUpdateParam(com.emc.storageos.model.tenant.TenantUpdateParam) Test(org.junit.Test)

Example 3 with TenantUpdateParam

use of com.emc.storageos.model.tenant.TenantUpdateParam in project coprhd-controller by CoprHD.

the class TenantModificationTest method securityAdminModifyUserMapping.

@Test
public void securityAdminModifyUserMapping() throws Exception {
    TenantUpdateParam tenantUpdateParam = new TenantUpdateParam();
    UserMappingChanges changes = new UserMappingChanges();
    List<UserMappingParam> listAdd = new ArrayList<UserMappingParam>();
    UserMappingParam param = new UserMappingParam();
    param.setDomain("Not Exist");
    listAdd.add(param);
    changes.setAdd(listAdd);
    tenantUpdateParam.setUserMappingChanges(changes);
    try {
        secAdminClient.tenants().update(rootTenantID, tenantUpdateParam);
        Assert.fail("fail, as the input contains wrong domain");
    } catch (ServiceErrorException see) {
        // verify the exception is not insufficent permission.
        Assert.assertNotEquals(see.getCode(), 3000);
        Assert.assertTrue(see.getMessage().contains("Parameter was provided but invalid"));
    }
}
Also used : UserMappingChanges(com.emc.storageos.model.tenant.UserMappingChanges) UserMappingParam(com.emc.storageos.model.tenant.UserMappingParam) ArrayList(java.util.ArrayList) ServiceErrorException(com.emc.vipr.client.exceptions.ServiceErrorException) TenantUpdateParam(com.emc.storageos.model.tenant.TenantUpdateParam) Test(org.junit.Test)

Example 4 with TenantUpdateParam

use of com.emc.storageos.model.tenant.TenantUpdateParam in project coprhd-controller by CoprHD.

the class RoleChangeTest method accessTenantApis.

@Test
public void accessTenantApis() throws Exception {
    // list Tenants ok for root, as root has System Monitor role
    ClientResponse resp = rootUser.path("/tenants/" + rootTenantId + "/subtenants").get(ClientResponse.class);
    Assert.assertEquals(200, resp.getStatus());
    // root should no permisson to update tenant
    TenantUpdateParam tenantUpdateParam = new TenantUpdateParam();
    tenantUpdateParam.setLabel("updated_tenant_lable" + new Random().nextInt());
    resp = rootUser.path("/tenants/" + rootTenantId).put(ClientResponse.class, tenantUpdateParam);
    Assert.assertEquals(403, resp.getStatus());
    // root should no permission to get role-assignment
    resp = rootUser.path("/tenants/" + rootTenantId + "/role-assignments").get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
}
Also used : ClientResponse(com.sun.jersey.api.client.ClientResponse) TenantUpdateParam(com.emc.storageos.model.tenant.TenantUpdateParam) Test(org.junit.Test)

Example 5 with TenantUpdateParam

use of com.emc.storageos.model.tenant.TenantUpdateParam in project coprhd-controller by CoprHD.

the class ApiTest method tenantTests.

/**
 * tenant api tests
 *
 * @throws Exception
 */
private void tenantTests() throws Exception {
    /*
         * GET MY TENANT ID
         */
    TenantResponse tenantResp = rSys.path("/tenant").get(TenantResponse.class);
    rootTenantId = tenantResp.getTenant();
    /*
         * GET root tenant info
         */
    ClientResponse resp = rUnAuth.path("/tenants/" + rootTenantId.toString()).get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    TenantOrgRestRep tenant = rSys.path("/tenants/" + rootTenantId.toString()).get(TenantOrgRestRep.class);
    Assert.assertTrue(tenant != null);
    Assert.assertTrue(tenant.getId().equals(rootTenantId));
    Assert.assertFalse(tenant.getUserMappings().isEmpty());
    // ensure the tenent org name is the same name as the tenant and the tenant's link points to
    // the appropriate refs
    Assert.assertTrue(tenant.getName().equals(tenantResp.getName()));
    Assert.assertTrue(("/tenants/" + tenant.getId()).equals(tenantResp.getSelfLink().getLinkRef().toString()));
    // Remove the mapping and add a domain only mapping to make sure it works
    TenantUpdateParam tenantUpdate = new TenantUpdateParam();
    tenantUpdate.setUserMappingChanges(new UserMappingChanges());
    tenantUpdate.getUserMappingChanges().setRemove(tenant.getUserMappings());
    tenantUpdate.getUserMappingChanges().setAdd(new ArrayList<UserMappingParam>());
    UserMappingParam rootDomainMapping = new UserMappingParam();
    rootDomainMapping.setDomain("sanity.local");
    tenantUpdate.getUserMappingChanges().getAdd().add(rootDomainMapping);
    tenantUpdate.setLabel(ROOTTENANT_NAME);
    String rootTenantBaseUrl = "/tenants/" + rootTenantId.toString();
    resp = rSys.path(rootTenantBaseUrl).put(ClientResponse.class, tenantUpdate);
    Assert.assertEquals(200, resp.getStatus());
    tenant = rSys.path(rootTenantBaseUrl).get(TenantOrgRestRep.class);
    Assert.assertFalse(tenant.getUserMappings().isEmpty());
    // as sysmonitor, verify we can access tenant quota
    resp = rMon.path(rootTenantBaseUrl + "/quota").get(ClientResponse.class);
    Assert.assertEquals(200, resp.getStatus());
    // try to delete the auth provider that has the sanity.local domain.
    // should fail with 400.
    resp = rSys.path("/vdc/admin/authnproviders/" + _goodADConfig.toString()).delete(ClientResponse.class);
    Assert.assertEquals(400, resp.getStatus());
    // try to add another domain to that provider and remove the sanity.local domain which is used. Should fail.
    AuthnUpdateParam updateParam = new AuthnUpdateParam();
    updateParam.getDomainChanges().getAdd().add("someotherdomain2.com");
    updateParam.getDomainChanges().getRemove().add("sanity.local");
    resp = rSys.path("/vdc/admin/authnproviders/" + _goodADConfig.toString()).put(ClientResponse.class, updateParam);
    Assert.assertEquals(400, resp.getStatus());
    // Make sure that all mappings can be cleared from root
    tenantUpdate.setUserMappingChanges(new UserMappingChanges());
    tenantUpdate.getUserMappingChanges().setRemove(tenant.getUserMappings());
    resp = rSys.path(rootTenantBaseUrl).put(ClientResponse.class, tenantUpdate);
    Assert.assertEquals(200, resp.getStatus());
    tenant = rSys.path(rootTenantBaseUrl).get(TenantOrgRestRep.class);
    Assert.assertEquals(0, tenant.getUserMappings().size());
    // test that updating the tenant with its own name doesn't cause problems (no op)
    TenantUpdateParam tenantUpdateNameOnly = new TenantUpdateParam();
    tenantUpdateNameOnly.setLabel(tenant.getName());
    resp = rSys.path(rootTenantBaseUrl).put(ClientResponse.class, tenantUpdateNameOnly);
    Assert.assertEquals(200, resp.getStatus());
    // test adding attribute with a value, then modifying that value (add/remove in same call)
    // jira 4220 had a problem, this would return 400
    // start by adding an attribute
    tenantUpdate = new TenantUpdateParam();
    tenantUpdate.setUserMappingChanges(new UserMappingChanges());
    tenantUpdate.getUserMappingChanges().setAdd(new ArrayList<UserMappingParam>());
    rootDomainMapping = new UserMappingParam();
    rootDomainMapping.setDomain("sanity.local");
    UserMappingAttributeParam rootAttr = new UserMappingAttributeParam();
    rootAttr.setKey("ou");
    rootAttr.setValues(Collections.singletonList("attri1"));
    rootDomainMapping.setAttributes(Collections.singletonList(rootAttr));
    tenantUpdate.getUserMappingChanges().getAdd().add(rootDomainMapping);
    tenantUpdate.setLabel(ROOTTENANT_NAME);
    resp = rSys.path(rootTenantBaseUrl).put(ClientResponse.class, tenantUpdate);
    Assert.assertEquals(200, resp.getStatus());
    // now modify (add and remove) this attribute
    tenantUpdate = new TenantUpdateParam();
    tenantUpdate.setUserMappingChanges(new UserMappingChanges());
    tenantUpdate.getUserMappingChanges().setRemove(new ArrayList<UserMappingParam>());
    tenantUpdate.getUserMappingChanges().setAdd(new ArrayList<UserMappingParam>());
    rootDomainMapping = new UserMappingParam();
    rootDomainMapping.setDomain("sanity.local");
    rootAttr = new UserMappingAttributeParam();
    rootAttr.setKey("ou");
    rootAttr.setValues(Collections.singletonList("attri1"));
    rootDomainMapping.setAttributes(Collections.singletonList(rootAttr));
    tenantUpdate.getUserMappingChanges().getRemove().add(rootDomainMapping);
    UserMappingParam rootDomainMapping2 = new UserMappingParam();
    rootDomainMapping2.setDomain("sanity.local");
    rootAttr = new UserMappingAttributeParam();
    rootAttr.setKey("ou");
    rootAttr.setValues(Collections.singletonList("attri1b"));
    rootDomainMapping2.setAttributes(Collections.singletonList(rootAttr));
    tenantUpdate.getUserMappingChanges().getAdd().add(rootDomainMapping2);
    tenantUpdate.setLabel(ROOTTENANT_NAME);
    resp = rSys.path(rootTenantBaseUrl).put(ClientResponse.class, tenantUpdate);
    Assert.assertEquals(200, resp.getStatus());
    // remove what we did
    tenantUpdate = new TenantUpdateParam();
    tenantUpdate.setUserMappingChanges(new UserMappingChanges());
    tenantUpdate.getUserMappingChanges().setRemove(new ArrayList<UserMappingParam>());
    tenantUpdate.getUserMappingChanges().setAdd(new ArrayList<UserMappingParam>());
    rootDomainMapping = new UserMappingParam();
    rootDomainMapping.setDomain("sanity.local");
    rootAttr = new UserMappingAttributeParam();
    rootAttr.setKey("ou");
    rootAttr.setValues(Collections.singletonList("attri1b"));
    rootDomainMapping.setAttributes(Collections.singletonList(rootAttr));
    tenantUpdate.getUserMappingChanges().getRemove().add(rootDomainMapping);
    tenantUpdate.setLabel(ROOTTENANT_NAME);
    resp = rSys.path(rootTenantBaseUrl).put(ClientResponse.class, tenantUpdate);
    Assert.assertEquals(200, resp.getStatus());
    // put the mapping back
    updateRootTenantAttrs();
    /*
         * GET, PUT Zone Roles
         */
    RoleAssignments assignments = rSys.path("/vdc/role-assignments").get(RoleAssignments.class);
    Assert.assertTrue(assignments.getAssignments().isEmpty());
    // full update - bad role
    RoleAssignmentChanges changes = new RoleAssignmentChanges();
    RoleAssignmentEntry entry1 = new RoleAssignmentEntry();
    entry1.setSubjectId(ZONEADMIN);
    entry1.getRoles().add("SECURITY_ADMIN");
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.getAdd().add(entry1);
    RoleAssignmentEntry entry2 = new RoleAssignmentEntry();
    entry2.setSubjectId(ROOTUSER2);
    entry2.getRoles().add("SYSTEM_ADMIN");
    changes.getAdd().add(entry2);
    RoleAssignmentEntry entry_bad = new RoleAssignmentEntry();
    entry_bad.setSubjectId(ZONEADMIN);
    entry_bad.getRoles().add("INVALID_ROLE");
    changes.getAdd().add(entry_bad);
    resp = rSys.path("/vdc/role-assignments").put(ClientResponse.class, changes);
    Assert.assertEquals(400, resp.getStatus());
    changes.getAdd().remove(2);
    entry_bad.setSubjectId("bad");
    entry_bad.getRoles().add("SECURITY_ADMIN");
    changes.getAdd().add(entry_bad);
    resp = rSys.path("/vdc/role-assignments").put(ClientResponse.class, changes);
    Assert.assertEquals(400, resp.getStatus());
    changes.getAdd().remove(2);
    // all good
    assignments = rSys.path("/vdc/role-assignments").put(RoleAssignments.class, changes);
    Assert.assertEquals(assignments.getAssignments().size(), 2);
    RoleAssignments readAssignments = rSys.path("/vdc/role-assignments").get(RoleAssignments.class);
    Assert.assertTrue(checkEqualsRoles(changes.getAdd(), readAssignments.getAssignments()));
    // check with whoami, that zadmin at this point, has security_admin
    userInfoCheckRoles(rZAdmin, new ArrayList<String>(Collections.singletonList("SECURITY_ADMIN")));
    RoleAssignmentEntry entry3 = new RoleAssignmentEntry();
    entry3.setSubjectId(ZONEADMIN);
    entry3.getRoles().add("SYSTEM_ADMIN");
    RoleAssignmentEntry entry4 = new RoleAssignmentEntry();
    entry4.setGroup(ZONEADMINS_GROUP);
    entry4.getRoles().add("SYSTEM_ADMIN");
    entry4.getRoles().add("TENANT_ADMIN");
    // partial update
    changes = new RoleAssignmentChanges();
    changes.setRemove(new ArrayList<RoleAssignmentEntry>());
    changes.getRemove().add(entry2);
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.getAdd().add(entry3);
    changes.getAdd().add(entry4);
    resp = rZAdmin.path("/vdc/role-assignments").put(ClientResponse.class, changes);
    Assert.assertEquals(400, resp.getStatus());
    changes.getAdd().remove(entry4);
    entry4.getRoles().remove("TENANT_ADMIN");
    changes.getAdd().add(entry4);
    readAssignments = rZAdmin.path("/vdc/role-assignments").put(RoleAssignments.class, changes);
    assignments = new RoleAssignments();
    entry3.getRoles().add("SECURITY_ADMIN");
    assignments.getAssignments().add(entry3);
    assignments.getAssignments().add(entry4);
    Assert.assertTrue(checkEqualsRoles(assignments.getAssignments(), readAssignments.getAssignments()));
    // try an update with missing role in the entry
    RoleAssignmentEntry entry4b = new RoleAssignmentEntry();
    entry4b.setGroup(ZONEADMINS_GROUP);
    changes.getAdd().add(entry4b);
    resp = rZAdmin.path("/vdc/role-assignments").put(ClientResponse.class, changes);
    Assert.assertEquals(400, resp.getStatus());
    // try to modify zone roles for local users, make sure that fails with 400
    RoleAssignmentChanges changes2 = new RoleAssignmentChanges();
    RoleAssignmentEntry rootTenantAdminUserEntry = new RoleAssignmentEntry();
    rootTenantAdminUserEntry.setSubjectId(SYSADMIN);
    rootTenantAdminUserEntry.getRoles().add("SECURITY_ADMIN");
    changes2.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes2.getAdd().add(rootTenantAdminUserEntry);
    resp = rSys.path("/vdc/role-assignments").put(ClientResponse.class, changes2);
    Assert.assertEquals(400, resp.getStatus());
    changes2 = new RoleAssignmentChanges();
    changes2.setRemove(new ArrayList<RoleAssignmentEntry>());
    changes2.getRemove().add(rootTenantAdminUserEntry);
    resp = rSys.path("/vdc/role-assignments").put(ClientResponse.class, changes2);
    Assert.assertEquals(400, resp.getStatus());
    /*
         * GET/PUT/POST tenant roles
         */
    String roles_url_format = "/tenants/%s/role-assignments";
    assignments = rZAdmin.path(String.format(roles_url_format, rootTenantId.toString())).get(RoleAssignments.class);
    Assert.assertTrue(assignments.getAssignments().size() == 1);
    // - bad role
    entry1 = new RoleAssignmentEntry();
    entry1.setSubjectId(ROOTTENANTADMIN_FORASSIGNMENT);
    entry1.getRoles().add("TENANT_ADMIN");
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.getAdd().add(entry1);
    entry2 = new RoleAssignmentEntry();
    entry2.setSubjectId(ROOTUSER2);
    entry2.getRoles().add("TENANT_ADMIN");
    changes.getAdd().add(entry2);
    entry_bad = new RoleAssignmentEntry();
    entry_bad.setSubjectId("bad");
    entry_bad.getRoles().add("INVALID_ROLE");
    changes.getAdd().add(entry_bad);
    resp = rSys.path(String.format(roles_url_format, rootTenantId.toString())).put(ClientResponse.class, assignments);
    Assert.assertEquals(400, resp.getStatus());
    changes.getAdd().remove(2);
    // zone system admin can not do tenant admin stuff
    resp = rZAdminGr.path(String.format(roles_url_format, rootTenantId.toString())).put(ClientResponse.class, changes);
    Assert.assertEquals(403, resp.getStatus());
    // - all good
    // this will remove sysadmin's tenant_admin role on root
    rootTenantAdminUserEntry = new RoleAssignmentEntry();
    rootTenantAdminUserEntry.setSubjectId(SYSADMIN);
    rootTenantAdminUserEntry.getRoles().add("TENANT_ADMIN");
    changes.setRemove(new ArrayList<RoleAssignmentEntry>());
    changes.getRemove().add(rootTenantAdminUserEntry);
    readAssignments = rZAdmin.path(String.format(roles_url_format, rootTenantId.toString())).put(RoleAssignments.class, changes);
    Assert.assertTrue(checkEqualsRoles(changes.getAdd(), readAssignments.getAssignments()));
    // check with whoami, that root user2 at this point, has tenant_admin
    userInfoCheckRoles(rRootUser2, new ArrayList<String>(Collections.singletonList("TENANT_ADMIN")));
    // partial update
    resp = rTAdmin.path("/tenant").get(ClientResponse.class);
    Assert.assertEquals(200, resp.getStatus());
    RoleAssignmentEntry entry3t = new RoleAssignmentEntry();
    entry3t.setSubjectId(ROOTTENANTADMIN_FORASSIGNMENT);
    entry3t.getRoles().add("PROJECT_ADMIN");
    RoleAssignmentEntry entry4t = new RoleAssignmentEntry();
    entry4t.setGroup(TENANT_ADMINS_GROUP);
    entry4t.getRoles().add("TENANT_ADMIN");
    changes = new RoleAssignmentChanges();
    changes.setRemove(new ArrayList<RoleAssignmentEntry>());
    changes.getRemove().add(entry2);
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.getAdd().add(entry3t);
    changes.getAdd().add(entry4t);
    readAssignments = rTAdmin.path(String.format(roles_url_format, rootTenantId.toString())).put(RoleAssignments.class, changes);
    assignments = new RoleAssignments();
    entry3t.getRoles().add("TENANT_ADMIN");
    assignments.getAssignments().add(entry3t);
    assignments.getAssignments().add(entry4t);
    Assert.assertTrue(checkEqualsRoles(assignments.getAssignments(), readAssignments.getAssignments()));
    // verify Tenant Admin permission for admins on root tenant
    readAssignments = rTAdminGr.path(String.format(roles_url_format, rootTenantId.toString())).get(RoleAssignments.class);
    Assert.assertTrue(checkEqualsRoles(assignments.getAssignments(), readAssignments.getAssignments()));
    RoleAssignments vdcReadAssignments = rZAdmin.path("/vdc/role-assignments").get(RoleAssignments.class);
    // try to add more than 100 roles - this should fail (quickly, because
    // it's not validating)
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    // since 2.0, should exclude the vdc roles here since they are in NOT in tenant db.
    int currRolesCount = readAssignments.getAssignments().size();
    int rolesToAdd = _maxRoleAclEntries + 1 - currRolesCount;
    for (int i = 0; i < rolesToAdd; i++) {
        entry_bad = new RoleAssignmentEntry();
        entry_bad.setRoles(new ArrayList<String>());
        entry_bad.getRoles().add(Role.TENANT_ADMIN.toString());
        entry_bad.setSubjectId("invalidUser" + i + "@invalidDomain.com");
        changes.getAdd().add(entry_bad);
    }
    resp = rTAdminGr.path(String.format(roles_url_format, rootTenantId.toString())).put(ClientResponse.class, changes);
    final String message = String.format("Exceeding limit of %d role assignments with %d", _maxRoleAclEntries, _maxRoleAclEntries + 1);
    assertExpectedError(resp, 400, ServiceCode.API_EXCEEDING_ASSIGNMENT_LIMIT, message);
    // verify zone roles here, to test out role filtering code
    assignments = new RoleAssignments();
    assignments.getAssignments().add(entry3);
    assignments.getAssignments().add(entry4);
    readAssignments = rZAdmin.path("/vdc/role-assignments").get(RoleAssignments.class);
    Assert.assertTrue(checkEqualsRoles(assignments.getAssignments(), readAssignments.getAssignments()));
    /*
         * Before creating subtenant try to log in
         * as subtenant user and verify that it fails with
         * 403 because the user does not map to a tenant
         */
    resp = rSTAdmin1.path("/login").get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    /*
         * CREATE subtenants
         */
    String subtenant_url = rootTenantBaseUrl + "/subtenants";
    TenantCreateParam tenantParam = new TenantCreateParam();
    String subtenant1_label = "subtenant1";
    tenantParam.setLabel(subtenant1_label);
    tenantParam.setDescription("first subtenant");
    tenantParam.setUserMappings(new ArrayList<UserMappingParam>());
    UserMappingParam tenantMapping1 = new UserMappingParam();
    tenantMapping1.setDomain("bad_domain.com");
    // add user mapping with domain only. Should fail because it conflicts with an existing mapping
    resp = rTAdminGr.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(400, resp.getStatus());
    tenantMapping1.setDomain("sanity.LOCAL");
    // add user mapping with domain only. Should fail because it conflicts with an existing mapping
    resp = rTAdminGr.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(400, resp.getStatus());
    // Add an attribute scope to the mapping
    UserMappingAttributeParam tenantAttr = new UserMappingAttributeParam();
    tenantAttr.setKey("departMent");
    tenantAttr.setValues(Collections.singletonList(SUBTENANT1_ATTR));
    tenantMapping1.setAttributes(Collections.singletonList(tenantAttr));
    // create a second mapping with no domain
    // should fail to add it
    UserMappingAttributeParam tenantAttr2 = new UserMappingAttributeParam();
    tenantAttr2.setKey("Company");
    tenantAttr2.setValues(Collections.singletonList(SUBTENANT1_ATTR));
    UserMappingParam tenantMapping2 = new UserMappingParam();
    tenantMapping2.setAttributes(Collections.singletonList(tenantAttr2));
    tenantParam.getUserMappings().add(tenantMapping1);
    tenantParam.getUserMappings().add(tenantMapping2);
    resp = rTAdminGr.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(400, resp.getStatus());
    // Add the domain to the second mapping
    tenantMapping2.setDomain("Sanity.Local");
    // Should fail with 403
    resp = rSys.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(403, resp.getStatus());
    // Add the mappings
    TenantOrgRestRep subtenant1 = rTAdminGr.path(subtenant_url).post(TenantOrgRestRep.class, tenantParam);
    Assert.assertTrue(subtenant1.getName().equals(subtenant1_label));
    Assert.assertEquals(2, subtenant1.getUserMappings().size());
    for (UserMappingParam mapping : subtenant1.getUserMappings()) {
        Assert.assertEquals(1, mapping.getAttributes().size());
        UserMappingAttributeParam attribute = mapping.getAttributes().get(0);
        if (attribute.getKey().equalsIgnoreCase("department") || attribute.getKey().equalsIgnoreCase("company")) {
            Assert.assertEquals(1, attribute.getValues().size());
            Assert.assertEquals(SUBTENANT1_ATTR, attribute.getValues().get(0));
        } else {
            Assert.fail("Attribute key unexpected " + attribute.getKey());
        }
    }
    subtenant1Id = subtenant1.getId();
    // Try to remove all of the mappings
    // should fail for non-root tenant
    tenantUpdate = new TenantUpdateParam();
    tenantUpdate.setUserMappingChanges(new UserMappingChanges());
    tenantUpdate.getUserMappingChanges().setRemove(new ArrayList<UserMappingParam>());
    tenantUpdate.getUserMappingChanges().getRemove().add(tenantMapping1);
    tenantUpdate.getUserMappingChanges().getRemove().add(tenantMapping2);
    resp = rTAdminGr.path("/tenants/" + subtenant1Id.toString()).put(ClientResponse.class, tenantUpdate);
    Assert.assertEquals(400, resp.getStatus());
    subtenant1 = rTAdminGr.path("/tenants/" + subtenant1Id.toString()).get(TenantOrgRestRep.class);
    Assert.assertTrue(subtenant1.getId().equals(subtenant1Id));
    Assert.assertTrue(subtenant1.getName().equals(subtenant1_label));
    Assert.assertEquals(2, subtenant1.getUserMappings().size());
    for (UserMappingParam mapping : subtenant1.getUserMappings()) {
        Assert.assertEquals(1, mapping.getAttributes().size());
        UserMappingAttributeParam attribute = mapping.getAttributes().get(0);
        if (attribute.getKey().equalsIgnoreCase("department") || attribute.getKey().equalsIgnoreCase("company")) {
            Assert.assertEquals(1, attribute.getValues().size());
            Assert.assertEquals(SUBTENANT1_ATTR, attribute.getValues().get(0));
        } else {
            Assert.fail("Attribute key unexpected " + attribute.getKey());
        }
    }
    // Add a zone role for the subtenant1 admins group
    // verify that a subtenant user in that group does not get the zone role
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    RoleAssignmentEntry entry_subtenant = new RoleAssignmentEntry();
    entry_subtenant.setGroup(SUBTENANT1_ADMINS_GROUP);
    entry_subtenant.getRoles().add("SECURITY_ADMIN");
    changes.getAdd().add(entry_subtenant);
    assignments = rSys.path("/vdc/role-assignments").put(RoleAssignments.class, changes);
    Assert.assertEquals(3, assignments.getAssignments().size());
    resp = rSTAdminGr1.path("/vdc/role-assignments").get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    String subtenant2_label = "subtenant2";
    tenantParam.setLabel(subtenant2_label);
    tenantParam.setDescription("second subtenant");
    tenantParam.setUserMappings(new ArrayList<UserMappingParam>());
    UserMappingParam tenant2UserMapping = new UserMappingParam();
    tenant2UserMapping.setDomain("sanity.local");
    UserMappingAttributeParam tenant2Attr = new UserMappingAttributeParam();
    tenant2Attr.setKey("COMPANY");
    tenant2Attr.setValues(Collections.singletonList(SUBTENANT1_ATTR.toLowerCase()));
    tenant2UserMapping.setAttributes(Collections.singletonList(tenant2Attr));
    tenantParam.getUserMappings().add(tenant2UserMapping);
    // duplicate attribute - should fail
    resp = rTAdmin.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(400, resp.getStatus());
    // create second subtenant
    tenant2Attr.setValues(Collections.singletonList(SUBTENANT2_ATTR));
    UserMappingAttributeParam tenant2Attr2 = new UserMappingAttributeParam();
    tenant2Attr2.setKey("department");
    tenant2Attr2.setValues(Collections.singletonList(SUBTENANT2_ATTR.toLowerCase()));
    List<UserMappingAttributeParam> attributes = new ArrayList<UserMappingAttributeParam>();
    attributes.add(tenant2Attr);
    attributes.add(tenant2Attr2);
    tenant2UserMapping.setAttributes(attributes);
    // duplicate name check for tenants
    tenantParam.setLabel(subtenant1_label);
    resp = rTAdmin.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(400, resp.getStatus());
    tenantParam.setLabel(subtenant2_label);
    TenantOrgRestRep subtenant2 = rTAdmin.path(subtenant_url).post(TenantOrgRestRep.class, tenantParam);
    subtenant2Id = subtenant2.getId();
    // Add a mapping with less scope then remove the mapping
    // with more scope to verify that it works.
    UserMappingParam tenant2UserMapping2 = new UserMappingParam();
    tenant2UserMapping2.setDomain("sanity.local");
    UserMappingAttributeParam tenant2Attr3 = new UserMappingAttributeParam();
    tenant2Attr3.setKey("company");
    tenant2Attr3.setValues(Collections.singletonList(SUBTENANT2_ATTR));
    tenant2UserMapping2.setAttributes(Collections.singletonList(tenant2Attr3));
    tenantUpdate = new TenantUpdateParam();
    tenantUpdate.setUserMappingChanges(new UserMappingChanges());
    tenantUpdate.getUserMappingChanges().setAdd(new ArrayList<UserMappingParam>());
    // Create a third mapping equal to the first mapping
    // with differences in case and order of attributes
    UserMappingParam tenant2UserMapping3 = new UserMappingParam();
    tenantUpdate.setLabel(subtenant2_label);
    tenant2UserMapping3.setDomain("Sanity.Local");
    List<UserMappingAttributeParam> attributes2 = new ArrayList<UserMappingAttributeParam>();
    attributes2.add(tenant2Attr3);
    attributes2.add(tenant2Attr2);
    tenant2UserMapping3.setAttributes(attributes2);
    tenantUpdate.setLabel(subtenant2_label);
    tenantUpdate.getUserMappingChanges().getAdd().add(tenant2UserMapping2);
    resp = rTAdmin.path("/tenants/" + subtenant2Id.toString()).put(ClientResponse.class, tenantUpdate);
    Assert.assertEquals(200, resp.getStatus());
    tenantUpdate.getUserMappingChanges().setAdd(new ArrayList<UserMappingParam>());
    tenantUpdate.getUserMappingChanges().setRemove(new ArrayList<UserMappingParam>());
    tenantUpdate.getUserMappingChanges().getRemove().add(tenant2UserMapping3);
    resp = rTAdmin.path("/tenants/" + subtenant2Id.toString()).put(ClientResponse.class, tenantUpdate);
    Assert.assertEquals(200, resp.getStatus());
    subtenant2 = rTAdmin.path("/tenants/" + subtenant2Id.toString()).get(TenantOrgRestRep.class);
    Assert.assertTrue(subtenant2.getId().equals(subtenant2Id));
    Assert.assertTrue(subtenant2.getName().equals(subtenant2_label));
    Assert.assertEquals(1, subtenant2.getUserMappings().size());
    for (UserMappingParam mapping : subtenant2.getUserMappings()) {
        Assert.assertEquals(1, mapping.getAttributes().size());
        UserMappingAttributeParam attribute = mapping.getAttributes().get(0);
        if (attribute.getKey().equalsIgnoreCase("company")) {
            Assert.assertEquals(1, attribute.getValues().size());
            Assert.assertEquals(SUBTENANT2_ATTR, attribute.getValues().get(0));
        } else {
            Assert.fail("Attribute key unexpected " + attribute.getKey());
        }
    }
    // test that updating this tenant with the second tenant's name
    tenantUpdateNameOnly = new TenantUpdateParam();
    tenantUpdateNameOnly.setLabel(subtenant2_label);
    resp = rTAdminGr.path("/tenants/" + subtenant1Id.toString()).put(ClientResponse.class, tenantUpdateNameOnly);
    Assert.assertEquals(400, resp.getStatus());
    // as sysmonitor, verify we can access sub tenant quota
    resp = rMon.path("/tenants/" + subtenant2Id.toString() + "/quota").get(ClientResponse.class);
    Assert.assertEquals(200, resp.getStatus());
    // create second level tenant - should fail
    tenantParam.setLabel("bad");
    tenantParam.setDescription("bad subtenant");
    tenantParam.setUserMappings(new ArrayList<UserMappingParam>());
    UserMappingAttributeParam tenantAttrBad = new UserMappingAttributeParam();
    tenantAttrBad.setKey("company");
    tenantAttrBad.setValues(Collections.singletonList("subtenant_bad"));
    UserMappingParam tenantMappingBad = new UserMappingParam();
    tenantMappingBad.setAttributes(Collections.singletonList(tenantAttrBad));
    tenantParam.getUserMappings().add(tenantMappingBad);
    resp = rTAdminGr.path("/tenants/" + subtenant2Id.toString() + "/subtenants").post(ClientResponse.class, tenantParam);
    Assert.assertEquals(403, resp.getStatus());
    resp = rTAdmin.path("/tenants/" + subtenant2Id.toString() + "/subtenants").post(ClientResponse.class, tenantParam);
    Assert.assertEquals(400, resp.getStatus());
    // TODO - Refactor these tests to meet one of the good code property "one method is responsible for one work"
    // TODO - and make each tests as individual and simple unittests as possible that just runs in very few milliseconds.
    // But, still the process of understanding the whole test architecture, hence adding
    // my new test also here for now.
    // Create subtenants with duplicate groups. But API should
    // be able to find the duplicate groups and remove them
    // and create only the distinct groups to the userMappings.
    String dupGroupSubtenant_url = rootTenantBaseUrl + "/subtenants";
    String dupTenantParam_label = "DupGroupSubTenant";
    TenantCreateParam dupTenantParam = new TenantCreateParam();
    dupTenantParam.setLabel(dupTenantParam_label);
    dupTenantParam.setDescription("first subtenant with duplicate groups in the user mapping.");
    dupTenantParam.setUserMappings(new ArrayList<UserMappingParam>());
    String key1 = "Attr1";
    String key2 = "Attr2";
    String key3 = "Attr3";
    List<String> values1 = new ArrayList<String>();
    values1.add("one");
    values1.add("two");
    values1.add("three");
    values1.add("four");
    // Duplicate one, so should be removed in the expected list.
    values1.add("two");
    // Duplicate one, so should be removed in the expected list.
    values1.add("three");
    List<String> expectedValues1 = new ArrayList<String>();
    expectedValues1.add("one");
    expectedValues1.add("two");
    expectedValues1.add("three");
    expectedValues1.add("four");
    List<String> values2 = new ArrayList<String>();
    values2.add("one");
    values2.add("two");
    values2.add("three");
    values2.add("four");
    // Duplicate one, so should be removed in the expected list.
    values2.add("two");
    // Duplicate one, so should be removed in the expected list.
    values2.add("three");
    // One additional value that is not there in value1. So, not a duplicate.
    values2.add("five");
    List<String> expectedValues2 = new ArrayList<String>();
    expectedValues2.add("one");
    expectedValues2.add("two");
    expectedValues2.add("three");
    expectedValues2.add("four");
    expectedValues2.add("five");
    // Validating the duplicate removal code added in the UserMappingAttributeParam() constructor.
    UserMappingAttributeParam userMappingAttributeParam1 = new UserMappingAttributeParam(key1, values1);
    // Duplicate Attribute.
    UserMappingAttributeParam userMappingAttributeParam2 = new UserMappingAttributeParam(key1, values1);
    UserMappingAttributeParam userMappingAttributeParam3 = new UserMappingAttributeParam(key1, values2);
    UserMappingAttributeParam userMappingAttributeParam4 = new UserMappingAttributeParam(key2, values2);
    UserMappingAttributeParam userMappingAttributeParam5 = new UserMappingAttributeParam(key3, values2);
    Assert.assertArrayEquals(expectedValues1.toArray(), userMappingAttributeParam1.getValues().toArray());
    Assert.assertArrayEquals(expectedValues1.toArray(), userMappingAttributeParam2.getValues().toArray());
    Assert.assertArrayEquals(expectedValues2.toArray(), userMappingAttributeParam3.getValues().toArray());
    Assert.assertArrayEquals(expectedValues2.toArray(), userMappingAttributeParam4.getValues().toArray());
    Assert.assertArrayEquals(expectedValues2.toArray(), userMappingAttributeParam5.getValues().toArray());
    // Validating the duplicate removal code added in the UserMappingAttributeParam.setValues() method.
    userMappingAttributeParam1.setValues(values1);
    userMappingAttributeParam2.setValues(values1);
    userMappingAttributeParam3.setValues(values2);
    userMappingAttributeParam4.setValues(values2);
    userMappingAttributeParam5.setValues(values2);
    Assert.assertArrayEquals(expectedValues1.toArray(), userMappingAttributeParam1.getValues().toArray());
    Assert.assertArrayEquals(expectedValues1.toArray(), userMappingAttributeParam2.getValues().toArray());
    Assert.assertArrayEquals(expectedValues2.toArray(), userMappingAttributeParam3.getValues().toArray());
    Assert.assertArrayEquals(expectedValues2.toArray(), userMappingAttributeParam4.getValues().toArray());
    Assert.assertArrayEquals(expectedValues2.toArray(), userMappingAttributeParam5.getValues().toArray());
    List<UserMappingAttributeParam> attributeList = new ArrayList<UserMappingAttributeParam>();
    attributeList.add(userMappingAttributeParam1);
    // Duplicate one, so should be removed in the expected list.
    attributeList.add(userMappingAttributeParam2);
    attributeList.add(userMappingAttributeParam3);
    attributeList.add(userMappingAttributeParam4);
    List<UserMappingAttributeParam> expectedAttributeList = new ArrayList<UserMappingAttributeParam>();
    expectedAttributeList.add(userMappingAttributeParam1);
    expectedAttributeList.add(userMappingAttributeParam3);
    expectedAttributeList.add(userMappingAttributeParam4);
    List<UserMappingAttributeParam> additionalAttributeList = new ArrayList<UserMappingAttributeParam>();
    additionalAttributeList.add(userMappingAttributeParam1);
    // Duplicate one, so should be removed in the expected list.
    additionalAttributeList.add(userMappingAttributeParam2);
    additionalAttributeList.add(userMappingAttributeParam5);
    additionalAttributeList.add(userMappingAttributeParam3);
    additionalAttributeList.add(userMappingAttributeParam4);
    List<UserMappingAttributeParam> expectedAdditionalAttributeList = new ArrayList<UserMappingAttributeParam>();
    expectedAdditionalAttributeList.add(userMappingAttributeParam1);
    expectedAdditionalAttributeList.add(userMappingAttributeParam5);
    expectedAdditionalAttributeList.add(userMappingAttributeParam3);
    expectedAdditionalAttributeList.add(userMappingAttributeParam4);
    List<String> groups = new ArrayList<String>();
    groups.add(ZONEADMINS_GROUP);
    groups.add(TENANT_ADMINS_GROUP);
    groups.add(SUBTENANT1_ADMINS_GROUP);
    groups.add(SUBTENANT1_USERS_GROUP);
    // Duplicate one, so should be removed in the expected list.
    groups.add(ZONEADMINS_GROUP);
    // Duplicate one, so should be removed in the expected list.
    groups.add(TENANT_ADMINS_GROUP);
    // Duplicate one, so should be removed in the expected list.
    groups.add(SUBTENANT1_USERS_GROUP);
    List<String> expectedGroups = new ArrayList<String>();
    expectedGroups.add(ZONEADMINS_GROUP);
    expectedGroups.add(TENANT_ADMINS_GROUP);
    expectedGroups.add(SUBTENANT1_ADMINS_GROUP);
    expectedGroups.add(SUBTENANT1_USERS_GROUP);
    List<String> additionalGroups = new ArrayList<String>();
    additionalGroups.add(ZONEADMINS_GROUP);
    additionalGroups.add(TENANT_ADMINS_GROUP);
    additionalGroups.add(SUBTENANT2_ADMINS_GROUP);
    additionalGroups.add(ASUBSETOFUSERS_GROUP);
    additionalGroups.add(SUBTENANT1_ADMINS_GROUP);
    additionalGroups.add(SUBTENANT1_USERS_GROUP);
    // Duplicate one, so should be removed in the expected list.
    additionalGroups.add(ZONEADMINS_GROUP);
    // Duplicate one, so should be removed in the expected list.
    additionalGroups.add(TENANT_ADMINS_GROUP);
    // Duplicate one, so should be removed in the expected list.
    additionalGroups.add(SUBTENANT1_USERS_GROUP);
    List<String> expectedAdditionalGroups = new ArrayList<String>();
    expectedAdditionalGroups.add(ZONEADMINS_GROUP);
    expectedAdditionalGroups.add(TENANT_ADMINS_GROUP);
    expectedAdditionalGroups.add(SUBTENANT2_ADMINS_GROUP);
    expectedAdditionalGroups.add(ASUBSETOFUSERS_GROUP);
    expectedAdditionalGroups.add(SUBTENANT1_ADMINS_GROUP);
    expectedAdditionalGroups.add(SUBTENANT1_USERS_GROUP);
    UserMappingParam dupTenantMapping1 = new UserMappingParam("sanity.LOCAL", attributeList, groups);
    UserMappingParam dupTenantMapping2 = new UserMappingParam("sanity.LOCAL", attributeList, groups);
    // Validate against the expected list. This is to validate the new code added to remove the
    // duplicates in the UserMappingParam() constructor. For UserMappingParam1.
    List<UserMappingAttributeParam> retAttributeList = dupTenantMapping1.getAttributes();
    List<String> retGroups = dupTenantMapping1.getGroups();
    Assert.assertArrayEquals(expectedAttributeList.toArray(), retAttributeList.toArray());
    Assert.assertArrayEquals(expectedGroups.toArray(), retGroups.toArray());
    // For UserMappingParam2.
    retAttributeList = dupTenantMapping2.getAttributes();
    retGroups = dupTenantMapping2.getGroups();
    Assert.assertArrayEquals(expectedAttributeList.toArray(), retAttributeList.toArray());
    Assert.assertArrayEquals(expectedGroups.toArray(), retGroups.toArray());
    // Validate against the expected list. This is to validate the new code added to remove the
    // duplicates in the UserMappingParam.setAttributes() and UserMappingParam.setGroups().
    // For UserMappingParam1.
    dupTenantMapping1.setGroups(additionalGroups);
    dupTenantMapping1.setAttributes(additionalAttributeList);
    retAttributeList = dupTenantMapping1.getAttributes();
    retGroups = dupTenantMapping1.getGroups();
    Assert.assertArrayEquals(expectedAdditionalAttributeList.toArray(), retAttributeList.toArray());
    Assert.assertArrayEquals(expectedAdditionalGroups.toArray(), retGroups.toArray());
    // For UserMappingParam2.
    dupTenantMapping2.setGroups(additionalGroups);
    dupTenantMapping2.setAttributes(additionalAttributeList);
    retAttributeList = dupTenantMapping2.getAttributes();
    retGroups = dupTenantMapping2.getGroups();
    Assert.assertArrayEquals(expectedAdditionalAttributeList.toArray(), retAttributeList.toArray());
    Assert.assertArrayEquals(expectedAdditionalGroups.toArray(), retGroups.toArray());
    List<UserMappingParam> dupUserMappings = new ArrayList<UserMappingParam>();
    dupUserMappings.add(dupTenantMapping1);
    // Adding the same userMapping here, just make sure the duplicate will be removed..
    dupUserMappings.add(dupTenantMapping2);
    // Execute the API /tenants/{id}/subtenants with duplicate entries in the payload
    // and validate the response to make sure no duplicates are actually added to the resource.
    dupTenantParam.setUserMappings(dupUserMappings);
    TenantOrgRestRep dupTenantResp = rTAdminGr.path(dupGroupSubtenant_url).post(TenantOrgRestRep.class, dupTenantParam);
    Assert.assertTrue(dupTenantResp.getName().equals(dupTenantParam_label));
    Assert.assertEquals(1, dupTenantResp.getUserMappings().size());
    // same expected values.
    for (UserMappingParam retUserMapping : dupTenantResp.getUserMappings()) {
        // Unique groups are only ZONEADMINS_GROUP, TENANT_ADMINS_GROUP, SUBTENANT1_ADMINS_GROUP, SUBTENANT1_USERS_GROUP,
        // SUBTENANT2_ADMINS_GROUP, ASUBSETOFUSERS_GROUP. So, count is 6.
        List<String> actualGroupsWithoutDomainUserMapping = new ArrayList<>(retUserMapping.getGroups());
        List<String> actualGroupsWithDomainUserMapping = new ArrayList<>();
        for (String group : actualGroupsWithoutDomainUserMapping) {
            String groupWithDomain = group + "@sanity.local";
            actualGroupsWithDomainUserMapping.add(groupWithDomain);
        }
        Assert.assertEquals(6, retUserMapping.getGroups().size());
        Assert.assertArrayEquals(expectedAdditionalGroups.toArray(), actualGroupsWithDomainUserMapping.toArray());
        // Unique attributes are only userMappingAttributeParam1, userMappingAttributeParam3, userMappingAttributeParam4,
        // userMappingAttributeParam5. So, count is 4.
        Assert.assertEquals(4, retUserMapping.getAttributes().size());
        Assert.assertArrayEquals(expectedAdditionalAttributeList.toArray(), retUserMapping.getAttributes().toArray());
    }
    // Delete the create the subtenant to avoid the confusions in the further test cases that runs after this.
    ClientResponse dupTenantDeleteResp = rTAdminGr.path("/tenants/" + dupTenantResp.getId().toString() + "/deactivate").post(ClientResponse.class);
    Assert.assertEquals(200, dupTenantDeleteResp.getStatus());
    /*
         * create subtenant unauthorized
         */
    // no perms
    resp = rUnAuth.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(403, resp.getStatus());
    // sysadmin
    resp = rSys.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(403, resp.getStatus());
    subtenant2Id = subtenant2.getId();
    subtenant2 = rTAdmin.path("/tenants/" + subtenant2Id.toString()).get(TenantOrgRestRep.class);
    Assert.assertTrue(subtenant2.getId().equals(subtenant2Id));
    Assert.assertTrue(subtenant2.getName().equals(subtenant2_label));
    Assert.assertEquals(1, subtenant2.getUserMappings().size());
    for (UserMappingParam mapping : subtenant2.getUserMappings()) {
        Assert.assertEquals(1, mapping.getAttributes().size());
        UserMappingAttributeParam attribute = mapping.getAttributes().get(0);
        if (attribute.getKey().equalsIgnoreCase("company")) {
            Assert.assertEquals(1, attribute.getValues().size());
            Assert.assertEquals(SUBTENANT2_ATTR, attribute.getValues().get(0));
        } else {
            Assert.fail("Attribute key unexpected " + attribute.getKey());
        }
    }
    // create third subtenant
    String subtenant3_label = "subtenant3";
    tenantParam.setLabel(subtenant3_label);
    tenantParam.setDescription("third subtenant");
    tenantParam.setUserMappings(new ArrayList<UserMappingParam>());
    UserMappingParam tenant3Mapping = new UserMappingParam();
    // Try a group without the domain. Expect 400
    tenant3Mapping.setGroups(Collections.singletonList("Test Group"));
    resp = rTAdmin.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(400, resp.getStatus());
    tenant3Mapping.setDomain("SANITY.local");
    // Set the group to a user and expect 400
    tenant3Mapping.setGroups(Collections.singletonList(SUBTENANT3_ADMIN));
    tenantParam.getUserMappings().add(tenant3Mapping);
    resp = rTAdmin.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(400, resp.getStatus());
    // Try a non-whitelist group expect 400
    tenant3Mapping.setGroups(Collections.singletonList("NotOnWhitelist"));
    resp = rTAdmin.path(subtenant_url).post(ClientResponse.class, tenantParam);
    Assert.assertEquals(400, resp.getStatus());
    // Finally attempt the successful case
    tenant3Mapping.setGroups(Collections.singletonList("Test Group"));
    TenantOrgRestRep subtenant3 = rTAdmin.path(subtenant_url).post(TenantOrgRestRep.class, tenantParam);
    Assert.assertTrue(subtenant3.getName().equals(subtenant3_label));
    Assert.assertEquals(1, subtenant3.getUserMappings().size());
    Assert.assertEquals(1, subtenant3.getUserMappings().get(0).getGroups().size());
    Assert.assertEquals("test group", subtenant3.getUserMappings().get(0).getGroups().get(0).toLowerCase());
    subtenant3Id = subtenant3.getId();
    // login in with a user that should map to more than one tenant and expect a 403
    _savedTokens.remove(SUBTENANT13_USER);
    resp = rST13User.path("/login").get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    /*
         * list subtenants - sys monitor, tenant admin and group
         */
    TenantOrgList list = rSys.path(subtenant_url).get(TenantOrgList.class);
    Assert.assertEquals(3, list.getSubtenants().size());
    list = rTAdmin.path(subtenant_url).get(TenantOrgList.class);
    Assert.assertEquals(3, list.getSubtenants().size());
    list = rTAdminGr.path(subtenant_url).get(TenantOrgList.class);
    Assert.assertEquals(3, list.getSubtenants().size());
    // unauth
    resp = rUnAuth.path(subtenant_url).get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    // system admin only user, verify it doesn't have permision to list subtenants
    String SYSTEM_ADMIN_ONLY = "sysadminonly@sanity.local";
    RoleAssignmentEntry roleAssignmentEntry = new RoleAssignmentEntry();
    roleAssignmentEntry.setSubjectId(SYSTEM_ADMIN_ONLY);
    roleAssignmentEntry.setRoles(new ArrayList<String>(Arrays.asList("SYSTEM_ADMIN")));
    List<RoleAssignmentEntry> add = new ArrayList<RoleAssignmentEntry>();
    add.add(roleAssignmentEntry);
    RoleAssignmentChanges roleAssignmentChanges = new RoleAssignmentChanges();
    roleAssignmentChanges.setAdd(add);
    resp = rSys.path("/vdc/role-assignments").put(ClientResponse.class, changes);
    Assert.assertEquals(200, resp.getStatus());
    BalancedWebResource rSysadminOnly = createHttpsClient(SYSTEM_ADMIN_ONLY, AD_PASS_WORD, baseUrls);
    resp = rSysadminOnly.path(subtenant_url).get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    RoleAssignments previousAssignments = rZAdmin.path(String.format(roles_url_format, rootTenantId.toString())).get(RoleAssignments.class);
    // re-add the tenant admin role to root
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.getAdd().add(rootTenantAdminUserEntry);
    previousAssignments.getAssignments().add(rootTenantAdminUserEntry);
    readAssignments = rZAdmin.path(String.format(roles_url_format, rootTenantId.toString())).put(RoleAssignments.class, changes);
    Assert.assertTrue(checkEqualsRoles(previousAssignments.getAssignments(), readAssignments.getAssignments()));
    /*
         * ROLE ASSIGNMENT - subtenant
         */
    RoleAssignmentEntry entry5 = new RoleAssignmentEntry();
    entry5.setSubjectId(SUBTENANT1_ADMIN);
    entry5.getRoles().add("TENANT_ADMIN");
    entry5.getRoles().add("PROJECT_ADMIN");
    resp = rTAdmin.path(String.format(roles_url_format, subtenant1Id.toString())).get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    readAssignments = rTAdminGr.path(String.format(roles_url_format, subtenant1Id.toString())).get(RoleAssignments.class);
    Assert.assertTrue(readAssignments.getAssignments().size() == 1);
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.getAdd().add(entry5);
    changes.setRemove(new ArrayList<RoleAssignmentEntry>());
    changes.getRemove().addAll(readAssignments.getAssignments());
    resp = rTAdminGr.path(String.format(roles_url_format, subtenant1Id.toString())).put(ClientResponse.class, changes);
    Assert.assertEquals(200, resp.getStatus());
    readAssignments = rSTAdmin1.path(String.format(roles_url_format, subtenant1Id.toString())).get(RoleAssignments.class);
    Assert.assertTrue(checkEqualsRoles(changes.getAdd(), readAssignments.getAssignments()));
    // batch role assignment changes
    RoleAssignments assignmentToHaveWhenImDone = readAssignments;
    changes = new RoleAssignmentChanges(new ArrayList<RoleAssignmentEntry>(), readAssignments.getAssignments());
    entry1 = new RoleAssignmentEntry();
    entry1.setSubjectId(ROOTUSER);
    entry1.getRoles().add("TENANT_ADMIN");
    changes.getAdd().add(entry1);
    entry2 = new RoleAssignmentEntry();
    entry2.setSubjectId(SUBTENANT1_ADMIN);
    entry2.getRoles().add("TENANT_ADMIN");
    entry2.getRoles().add("PROJECT_ADMIN");
    changes.getAdd().add(entry2);
    entry3 = new RoleAssignmentEntry();
    entry3.setSubjectId(SUBTENANT1_USER);
    entry3.getRoles().add("PROJECT_ADMIN");
    changes.getAdd().add(entry3);
    entry4 = new RoleAssignmentEntry();
    entry4.setSubjectId(SUBTENANT1_READER);
    entry4.getRoles().add("TENANT_APPROVER");
    changes.getAdd().add(entry4);
    entry5 = new RoleAssignmentEntry();
    entry5.setGroup(SUBTENANT1_ADMINS_GROUP);
    entry5.getRoles().add("TENANT_ADMIN");
    entry5.getRoles().add("PROJECT_ADMIN");
    changes.getAdd().add(entry5);
    RoleAssignmentEntry entry6 = new RoleAssignmentEntry();
    entry6.setGroup(SUBTENANT1_USERS_GROUP);
    entry6.getRoles().add("TENANT_APPROVER");
    changes.getAdd().add(entry6);
    resp = rSTAdmin1.path(String.format(roles_url_format, subtenant1Id.toString())).put(ClientResponse.class, changes);
    Assert.assertEquals(200, resp.getStatus());
    readAssignments = rSTAdmin1.path(String.format(roles_url_format, subtenant1Id.toString())).get(RoleAssignments.class);
    Assert.assertTrue(checkEqualsRoles(changes.getAdd(), readAssignments.getAssignments()));
    // reverting back to the way it was before the batch role assignment changes
    changes = new RoleAssignmentChanges(assignmentToHaveWhenImDone.getAssignments(), readAssignments.getAssignments());
    resp = rSTAdmin1.path(String.format(roles_url_format, subtenant1Id.toString())).put(ClientResponse.class, changes);
    Assert.assertEquals(200, resp.getStatus());
    readAssignments = rSTAdmin1.path(String.format(roles_url_format, subtenant1Id.toString())).get(RoleAssignments.class);
    Assert.assertTrue(checkEqualsRoles(changes.getAdd(), readAssignments.getAssignments()));
    // check with whoami, that SUBTENANT1_ADMIN at this point, has tenant_admin and project admin
    ArrayList<String> lookFor = new ArrayList<String>();
    Collections.addAll(lookFor, "TENANT_ADMIN", "PROJECT_ADMIN");
    userInfoCheckRoles(rSTAdmin1, lookFor);
    entry6 = new RoleAssignmentEntry();
    entry6.setGroup(SUBTENANT2_ADMINS_GROUP);
    entry6.getRoles().add("TENANT_ADMIN");
    RoleAssignmentEntry entry7 = new RoleAssignmentEntry();
    entry7.setSubjectId(SUBTENANT2_ADMIN);
    entry7.getRoles().add("TENANT_ADMIN");
    readAssignments = rTAdmin.path(String.format(roles_url_format, subtenant2Id.toString())).get(RoleAssignments.class);
    Assert.assertTrue(readAssignments.getAssignments().size() == 1);
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.getAdd().add(entry6);
    changes.getAdd().add(entry7);
    changes.setRemove(new ArrayList<RoleAssignmentEntry>());
    changes.getRemove().add(entry5);
    changes.getRemove().addAll(readAssignments.getAssignments());
    resp = rTAdmin.path(String.format(roles_url_format, subtenant2Id.toString())).put(ClientResponse.class, changes);
    Assert.assertEquals(200, resp.getStatus());
    readAssignments = rSTAdminGr2.path(String.format(roles_url_format, subtenant2Id.toString())).get(RoleAssignments.class);
    Assert.assertTrue(checkEqualsRoles(changes.getAdd(), readAssignments.getAssignments()));
    readAssignments = rSTAdmin2.path(String.format(roles_url_format, subtenant2Id.toString())).get(RoleAssignments.class);
    Assert.assertTrue(checkEqualsRoles(changes.getAdd(), readAssignments.getAssignments()));
    /*
         * LIST subtenants
         */
    // tenant admins on root gets the full list
    list = rTAdmin.path(subtenant_url).get(TenantOrgList.class);
    Assert.assertEquals(3, list.getSubtenants().size());
    // tenant admin on the child get only the child
    list = rSTAdmin1.path(subtenant_url).get(TenantOrgList.class);
    Assert.assertEquals(1, list.getSubtenants().size());
    Assert.assertEquals(subtenant1Id, list.getSubtenants().get(0).getId());
    list = rSTAdminGr2.path(subtenant_url).get(TenantOrgList.class);
    Assert.assertEquals(1, list.getSubtenants().size());
    Assert.assertEquals(subtenant2Id, list.getSubtenants().get(0).getId());
    list = rSTAdmin2.path(subtenant_url).get(TenantOrgList.class);
    Assert.assertEquals(1, list.getSubtenants().size());
    Assert.assertEquals(subtenant2Id, list.getSubtenants().get(0).getId());
    /*
         * Changing subtenant roles
         */
    RoleAssignmentEntry entry8 = new RoleAssignmentEntry();
    entry8.setGroup(SUBTENANT2_ADMINS_GROUP);
    entry8.getRoles().add("PROJECT_ADMIN");
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.getAdd().add(entry8);
    changes.setRemove(new ArrayList<RoleAssignmentEntry>());
    changes.getRemove().add(entry6);
    resp = rSTAdmin2.path(String.format(roles_url_format, subtenant2Id.toString())).put(ClientResponse.class, changes);
    Assert.assertEquals(200, resp.getStatus());
    changes.getAdd().add(entry7);
    readAssignments = rSTAdmin2.path(String.format(roles_url_format, subtenant2Id.toString())).get(RoleAssignments.class);
    Assert.assertTrue(checkEqualsRoles(changes.getAdd(), readAssignments.getAssignments()));
    resp = rSTAdminGr2.path(String.format(roles_url_format, subtenant2Id.toString())).get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    RoleAssignmentEntry entry9 = new RoleAssignmentEntry();
    entry9.setGroup(SUBTENANT1_ADMINS_GROUP);
    entry9.getRoles().add("PROJECT_ADMIN");
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.getAdd().add(entry9);
    resp = rSTAdmin1.path(String.format(roles_url_format, subtenant1Id.toString())).put(ClientResponse.class, changes);
    Assert.assertEquals(200, resp.getStatus());
    resp = rSTAdminGr1.path(String.format(roles_url_format, subtenant1Id.toString())).get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    resp = rSTAdminGr2.path(String.format(roles_url_format, subtenant1Id.toString())).get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    // add a user from root tenant to be an TENANT_ADMIN in subtenant1
    entry_subtenant = new RoleAssignmentEntry();
    entry_subtenant.setSubjectId(ROOTUSER2);
    entry_subtenant.getRoles().add("TENANT_ADMIN");
    changes.getAdd().add(entry_subtenant);
    resp = rSTAdmin1.path(String.format(roles_url_format, subtenant1Id.toString())).put(ClientResponse.class, changes);
    Assert.assertEquals(200, resp.getStatus());
    // test out that rootuser2 is able to use his tenant admin in the subtenant even though that is not
    // his home tenant.
    resp = rRootUser2.path("/tenants/" + subtenant1Id.toString()).get(ClientResponse.class);
    Assert.assertEquals(200, resp.getStatus());
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.setRemove(new ArrayList<RoleAssignmentEntry>());
    // Assign a role to a recursive group
    RoleAssignmentEntry recursiveGroupEntry = new RoleAssignmentEntry();
    recursiveGroupEntry.setGroup("Domain Users@sanity.local");
    recursiveGroupEntry.getRoles().add("PROJECT_ADMIN");
    changes.getAdd().add(recursiveGroupEntry);
    // Try to assign a role to a group not on the whitelist
    RoleAssignmentEntry nonWhiteListGroupEntry = new RoleAssignmentEntry();
    nonWhiteListGroupEntry.setGroup("NotOnWhitelist@sanity.local");
    nonWhiteListGroupEntry.getRoles().add("PROJECT_ADMIN");
    changes.getAdd().add(nonWhiteListGroupEntry);
    // Assign a role to a user in this tenant
    RoleAssignmentEntry st3AdminEntry = new RoleAssignmentEntry();
    st3AdminEntry.setSubjectId(SUBTENANT3_ADMIN);
    st3AdminEntry.getRoles().add("TENANT_ADMIN");
    changes.getAdd().add(st3AdminEntry);
    resp = rTAdmin.path(String.format(roles_url_format, subtenant3Id.toString())).put(ClientResponse.class, changes);
    // Should fail with a 400 due to the non-whitelist group
    Assert.assertEquals(400, resp.getStatus());
    changes.getAdd().remove(nonWhiteListGroupEntry);
    // Adding this to the remove list should have no effect
    changes.getRemove().add(nonWhiteListGroupEntry);
    resp = rTAdmin.path(String.format(roles_url_format, subtenant3Id.toString())).put(ClientResponse.class, changes);
    // Should succeed now
    Assert.assertEquals(200, resp.getStatus());
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.setRemove(new ArrayList<RoleAssignmentEntry>());
    // STAdmin3 should be able to read roles now
    readAssignments = rSTAdmin3.path(String.format(roles_url_format, subtenant3Id.toString())).get(RoleAssignments.class);
    // Try to assign a role to a user in a different tenant
    RoleAssignmentEntry st2AdminEntry = new RoleAssignmentEntry();
    st2AdminEntry.setSubjectId(SUBTENANT2_ADMIN);
    st2AdminEntry.getRoles().add("TENANT_ADMIN");
    changes.getAdd().add(st2AdminEntry);
    resp = rSTAdmin3.path(String.format(roles_url_format, subtenant3Id.toString())).put(ClientResponse.class, changes);
    // Should fail with a 400 due to user in wrong tenant
    Assert.assertEquals(400, resp.getStatus());
    // Try to assign a role with the valid group as username
    RoleAssignmentEntry groupAsSidEntry = new RoleAssignmentEntry();
    groupAsSidEntry.setSubjectId("Domain Users");
    groupAsSidEntry.getRoles().add("TENANT_ADMIN");
    changes.getAdd().remove(0);
    changes.getAdd().add(groupAsSidEntry);
    resp = rSTAdmin3.path(String.format(roles_url_format, subtenant3Id.toString())).put(ClientResponse.class, changes);
    // Should fail with a 400 due to user with that name not existing
    Assert.assertEquals(400, resp.getStatus());
    // Try to assign a role with a valid username as the group
    RoleAssignmentEntry sidAsGroupEntry = new RoleAssignmentEntry();
    sidAsGroupEntry.setGroup(SUBTENANT3_ADMIN);
    sidAsGroupEntry.getRoles().add("TENANT_ADMIN");
    changes.getAdd().remove(0);
    changes.getAdd().add(sidAsGroupEntry);
    resp = rSTAdmin3.path(String.format(roles_url_format, subtenant3Id.toString())).put(ClientResponse.class, changes);
    // Should fail with a 400 due to group with that name not existing
    Assert.assertEquals(400, resp.getStatus());
    /*
         * Test the user tenant troubleshooting API
         */
    String userTenantURL = "/user/tenant";
    resp = rUnAuth.path(userTenantURL).queryParam("username", "sanity_user@sanity.local").get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    resp = rZAdmin.path(userTenantURL).queryParam("username", "sanity_user@baddomain.com").get(ClientResponse.class);
    Assert.assertEquals(400, resp.getStatus());
    resp = rZAdmin.path(userTenantURL).queryParam("username", "sanity_user").get(ClientResponse.class);
    Assert.assertEquals(400, resp.getStatus());
    resp = rZAdmin.path(userTenantURL).queryParam("username", "nouser@sanity.local").get(ClientResponse.class);
    Assert.assertEquals(400, resp.getStatus());
    resp = rZAdmin.path(userTenantURL).get(ClientResponse.class);
    Assert.assertEquals(400, resp.getStatus());
    UserTenantList userTenants = rZAdmin.path(userTenantURL).queryParam("username", "sanity_user@sanity.local").get(UserTenantList.class);
    Assert.assertEquals(userTenants._userTenantList.size(), 1);
    UserTenant userTenant = userTenants._userTenantList.get(0);
    Assert.assertEquals(rootTenantId, userTenant._id);
    Assert.assertEquals("sanity.local", userTenant._userMapping.getDomain());
    Assert.assertEquals(1, userTenant._userMapping.getAttributes().size());
    Assert.assertEquals("ou", userTenant._userMapping.getAttributes().get(0).getKey());
    Assert.assertArrayEquals(new String[] { ROOTTENANT_ATTR }, userTenant._userMapping.getAttributes().get(0).getValues().toArray(new String[0]));
    userTenants = rZAdmin.path(userTenantURL).queryParam("username", SUBTENANT13_USER).get(UserTenantList.class);
    Assert.assertEquals(userTenants._userTenantList.size(), 2);
    for (UserTenant userTenantEntry : userTenants._userTenantList) {
        if (userTenantEntry._id.equals(subtenant1Id)) {
            Assert.assertEquals(1, userTenantEntry._userMapping.getAttributes().size());
            Assert.assertEquals("company", userTenantEntry._userMapping.getAttributes().get(0).getKey().toLowerCase());
            Assert.assertArrayEquals(new String[] { SUBTENANT1_ATTR }, userTenantEntry._userMapping.getAttributes().get(0).getValues().toArray(new String[0]));
        } else if (userTenantEntry._id.equals(subtenant3Id)) {
            Assert.assertEquals(1, userTenantEntry._userMapping.getGroups().size());
            Assert.assertArrayEquals(new String[] { SUBTENANT3_ATTR }, userTenantEntry._userMapping.getGroups().toArray(new String[0]));
        } else {
            Assert.fail("Unexpected tenant ID: " + userTenantEntry._id);
        }
    }
    /*
         * CREATE, LIST projects
         */
    // as zone sysadmin
    expectedProjListResults.put("root", new ArrayList<ProjectEntry>());
    expectedProjListResults.put("st1", new ArrayList<ProjectEntry>());
    expectedProjListResults.put("st2", new ArrayList<ProjectEntry>());
    ProjectParam paramProj = new ProjectParam();
    resp = rZAdminGr.path(String.format(_projectsUrlFormat, rootTenantId.toString())).post(ClientResponse.class, paramProj);
    Assert.assertEquals(403, resp.getStatus());
    // as tenant admin of root
    paramProj = new ProjectParam("root project1");
    ProjectEntry createResp = rTAdmin.path(String.format(_projectsUrlFormat, rootTenantId.toString())).post(ProjectEntry.class, paramProj);
    Assert.assertTrue(createResp.name.equals(paramProj.getName()));
    Assert.assertTrue(createResp.id != null);
    ProjectEntry projEl = new ProjectEntry(createResp);
    expectedProjListResults.get("root").add(projEl);
    // as subtenant admins and project admins
    paramProj = new ProjectParam("subtenant1 project1");
    createResp = rSTAdmin1.path(String.format(_projectsUrlFormat, subtenant1Id.toString())).post(ProjectEntry.class, paramProj);
    Assert.assertTrue(createResp.name.equals(paramProj.getName()));
    Assert.assertTrue(createResp.id != null);
    expectedProjListResults.get("st1").add(new ProjectEntry(createResp));
    paramProj.setName("subtenant1 project2");
    createResp = rSTAdminGr1.path(String.format(_projectsUrlFormat, subtenant1Id.toString())).post(ProjectEntry.class, paramProj);
    Assert.assertTrue(createResp.name.equals(paramProj.getName()));
    Assert.assertTrue(createResp.id != null);
    expectedProjListResults.get("st1").add(new ProjectEntry(createResp));
    paramProj.setName("subtenant2 project1");
    createResp = rSTAdmin2.path(String.format(_projectsUrlFormat, subtenant2Id.toString())).post(ProjectEntry.class, paramProj);
    Assert.assertTrue(createResp.name.equals(paramProj.getName()));
    Assert.assertTrue(createResp.id != null);
    expectedProjListResults.get("st2").add(new ProjectEntry(createResp));
    paramProj.setName("subtenant2 project2");
    createResp = rSTAdminGr2.path(String.format(_projectsUrlFormat, subtenant2Id.toString())).post(ProjectEntry.class, paramProj);
    Assert.assertTrue(createResp.name.equals(paramProj.getName()));
    Assert.assertTrue(createResp.id != null);
    expectedProjListResults.get("st2").add(new ProjectEntry(createResp));
    // negative - create
    paramProj = new ProjectParam("bad");
    // tenant admin on root, can not create projects on subtenants
    resp = rTAdmin.path(String.format(_projectsUrlFormat, subtenant1Id.toString())).post(ClientResponse.class, paramProj);
    Assert.assertEquals(403, resp.getStatus());
    // tenant admin at subtenant level can not create project on root tenant
    resp = rSTAdmin1.path(String.format(_projectsUrlFormat, rootTenantId.toString())).post(ClientResponse.class, paramProj);
    Assert.assertEquals(403, resp.getStatus());
    // tenant admin at subtenant2 can not create project on subtenant1
    resp = rSTAdmin2.path(String.format(_projectsUrlFormat, subtenant1Id.toString())).post(ClientResponse.class, paramProj);
    Assert.assertEquals(403, resp.getStatus());
    // project admin at subtenant1 can not create project on subtenant2
    resp = rSTAdminGr1.path(String.format(_projectsUrlFormat, subtenant2Id.toString())).post(ClientResponse.class, paramProj);
    Assert.assertEquals(403, resp.getStatus());
    // create project on deleted tenant
    tenantParam.setLabel("toremove");
    tenantParam.setDescription("toremove subtenant");
    tenantParam.setUserMappings(new ArrayList<UserMappingParam>());
    UserMappingParam tenantMappingToRemove = new UserMappingParam();
    tenantMappingToRemove.setDomain("sanity.local");
    UserMappingAttributeParam tenantAttr3 = new UserMappingAttributeParam();
    tenantAttr3.setKey("company");
    tenantAttr3.setValues(Collections.singletonList("toremove"));
    tenantMappingToRemove.setAttributes(Collections.singletonList(tenantAttr3));
    tenantParam.getUserMappings().add(tenantMappingToRemove);
    TenantOrgRestRep stDeleted = rTAdminGr.path(subtenant_url).post(TenantOrgRestRep.class, tenantParam);
    rTAdminGr.path("/tenants/" + stDeleted.getId() + "/deactivate").post();
    resp = rTAdminGr.path(String.format(_projectsUrlFormat, stDeleted.getId())).post(ClientResponse.class, paramProj);
    Assert.assertEquals(404, resp.getStatus());
    // list and compare
    ProjectList projList = rSys.path(String.format(_projectsUrlFormat, rootTenantId.toString())).get(ProjectList.class);
    Assert.assertTrue(checkEqualsList(projList._projects, expectedProjListResults.get("root")));
    projList = rTAdmin.path(String.format(_projectsUrlFormat, rootTenantId.toString())).get(ProjectList.class);
    Assert.assertTrue(checkEqualsList(projList._projects, expectedProjListResults.get("root")));
    projList = rSys.path(String.format(_projectsUrlFormat, subtenant1Id.toString())).get(ProjectList.class);
    Assert.assertTrue(checkEqualsList(projList._projects, expectedProjListResults.get("st1")));
    projList = rSTAdmin1.path(String.format(_projectsUrlFormat, subtenant1Id.toString())).get(ProjectList.class);
    Assert.assertTrue(checkEqualsList(projList._projects, expectedProjListResults.get("st1")));
    projList = rSTAdmin2.path(String.format(_projectsUrlFormat, subtenant2Id.toString())).get(ProjectList.class);
    Assert.assertTrue(checkEqualsList(projList._projects, expectedProjListResults.get("st2")));
    projList = rSTAdminGr1.path(String.format(_projectsUrlFormat, subtenant1Id.toString())).get(ProjectList.class);
    Assert.assertEquals(1, projList._projects.size());
    Assert.assertTrue(projList._projects.get(0).name.equals("subtenant1 project2"));
    resp = rSTAdmin1.path(String.format(_projectsUrlFormat, rootTenantId.toString())).get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    resp = rSTAdmin1.path(String.format(_projectsUrlFormat, subtenant2Id.toString())).get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    // negative test:
    // 1. with TENANT_ADMIN user from root tenant, create subtenant
    // 2. with same user, create project in subtenant
    // 3. with same user, remove TENANT_ADMIN on himself in subtenant
    // 4. with same user, do get /projects/id/acl so show his project ownership
    // is still honored. (cq605248)
    String crossUserSubtenantUrl = rootTenantBaseUrl + "/subtenants";
    TenantCreateParam tenantParam2 = new TenantCreateParam();
    tenantParam2.setLabel("subtenantwithuserfromroottenant");
    tenantParam2.setDescription("subtenant where user from root tenant owns projects");
    tenantParam2.setUserMappings(new ArrayList<UserMappingParam>());
    UserMappingParam tenantMapping3 = new UserMappingParam();
    tenantMapping3.setDomain("sanity.local");
    UserMappingAttributeParam crossTenantAttr = new UserMappingAttributeParam();
    crossTenantAttr.setKey("COMPANY");
    crossTenantAttr.setValues(Collections.singletonList("crosstenant"));
    tenantMapping3.setAttributes(Collections.singletonList(crossTenantAttr));
    tenantParam2.getUserMappings().add(tenantMapping3);
    TenantOrgRestRep crossUserSubtenant = rTAdmin.path(crossUserSubtenantUrl).post(TenantOrgRestRep.class, tenantParam2);
    Assert.assertNotNull(crossUserSubtenant);
    paramProj = new ProjectParam();
    paramProj.setName("crosstenantuserproject");
    ProjectEntry project = rTAdmin.path(String.format(_projectsUrlFormat, crossUserSubtenant.getId().toString())).post(ProjectEntry.class, paramProj);
    Assert.assertNotNull(project);
    RoleAssignmentEntry rtTenantAdminUserEntry = new RoleAssignmentEntry();
    rtTenantAdminUserEntry.setSubjectId(ROOTTENANTADMIN);
    rtTenantAdminUserEntry.getRoles().add("TENANT_ADMIN");
    changes = new RoleAssignmentChanges();
    changes.setRemove(new ArrayList<RoleAssignmentEntry>());
    changes.getRemove().add(rtTenantAdminUserEntry);
    resp = rTAdmin.path(String.format(roles_url_format, crossUserSubtenant.getId().toString())).put(ClientResponse.class, changes);
    Assert.assertEquals(200, resp.getStatus());
    resp = rTAdmin.path(String.format(_projectAclUrl, project.id.toString())).get(ClientResponse.class);
    Assert.assertEquals(200, resp.getStatus());
    // negative test:
    // 1. assign TENANT_ADMIN to a group called ASubSetOfUsers in the root tenant
    // 2. Login with cross1@sanity.local. That user is part of the group above however is mapped
    // to the crosssubtenant by his attribute company=crosstenant. Therefore he should not be allowed
    // to perform a TENANT_ADMIN call in the root tenant.
    entry1 = new RoleAssignmentEntry();
    entry1.setGroup(ASUBSETOFUSERS_GROUP);
    entry1.getRoles().add("TENANT_ADMIN");
    changes = new RoleAssignmentChanges();
    changes.setAdd(new ArrayList<RoleAssignmentEntry>());
    changes.getAdd().add(entry1);
    resp = rSys.path(String.format(roles_url_format, rootTenantId.toString())).put(ClientResponse.class, changes);
    Assert.assertEquals(200, resp.getStatus());
    resp = rSTCross.path("/tenants/" + rootTenantId.toString()).get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    // list auth providers tests (CTRL-4314)
    // SECURITY_ADMIN can access auth providers
    resp = rZAdmin.path("/vdc/admin/authnproviders").get(ClientResponse.class);
    Assert.assertEquals(200, resp.getStatus());
    // root tenant TENANT_ADMIN can access auth providers
    resp = rTAdmin.path("/vdc/admin/authnproviders").get(ClientResponse.class);
    Assert.assertEquals(200, resp.getStatus());
    // subtenant TENANT_ADMIN can access auth providers
    resp = rSTAdmin2.path("/vdc/admin/authnproviders").get(ClientResponse.class);
    Assert.assertEquals(200, resp.getStatus());
    // regular user can't access auth providers
    resp = rUnAuth.path("/vdc/admin/authnproviders").get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
    // make the user the admin of a subtenant (not their home tenant)
    assignTenantRole(subtenant3Id.toString(), ROOTUSER, "TENANT_ADMIN");
    // subtenant TENANT_ADMIN can access auth providers, even if they aren't admin of their home tenant
    resp = rUnAuth.path("/vdc/admin/authnproviders").get(ClientResponse.class);
    Assert.assertEquals(200, resp.getStatus());
    // cleanup
    removeTenantRole(subtenant3Id.toString(), ROOTUSER, "TENANT_ADMIN");
    // verify the role was removed
    resp = rUnAuth.path("/vdc/admin/authnproviders").get(ClientResponse.class);
    Assert.assertEquals(403, resp.getStatus());
}
Also used : ClientResponse(com.sun.jersey.api.client.ClientResponse) AuthnUpdateParam(com.emc.storageos.model.auth.AuthnUpdateParam) UserMappingParam(com.emc.storageos.model.tenant.UserMappingParam) VirtualArrayList(com.emc.storageos.model.varray.VirtualArrayList) ArrayList(java.util.ArrayList) TenantCreateParam(com.emc.storageos.model.tenant.TenantCreateParam) TenantUpdateParam(com.emc.storageos.model.tenant.TenantUpdateParam) UserTenant(com.emc.storageos.security.resource.UserInfoPage.UserTenant) UserMappingAttributeParam(com.emc.storageos.model.tenant.UserMappingAttributeParam) RoleAssignmentChanges(com.emc.storageos.model.auth.RoleAssignmentChanges) ProjectParam(com.emc.storageos.model.project.ProjectParam) UserMappingChanges(com.emc.storageos.model.tenant.UserMappingChanges) RoleAssignmentEntry(com.emc.storageos.model.auth.RoleAssignmentEntry) RoleAssignments(com.emc.storageos.model.auth.RoleAssignments) UserTenantList(com.emc.storageos.security.resource.UserInfoPage.UserTenantList) TenantOrgList(com.emc.storageos.model.tenant.TenantOrgList) TenantOrgRestRep(com.emc.storageos.model.tenant.TenantOrgRestRep) TenantResponse(com.emc.storageos.model.tenant.TenantResponse)

Aggregations

TenantUpdateParam (com.emc.storageos.model.tenant.TenantUpdateParam)5 UserMappingChanges (com.emc.storageos.model.tenant.UserMappingChanges)4 UserMappingParam (com.emc.storageos.model.tenant.UserMappingParam)4 ClientResponse (com.sun.jersey.api.client.ClientResponse)3 ArrayList (java.util.ArrayList)3 Test (org.junit.Test)3 TenantResponse (com.emc.storageos.model.tenant.TenantResponse)2 UserMappingAttributeParam (com.emc.storageos.model.tenant.UserMappingAttributeParam)2 ServiceErrorException (com.emc.vipr.client.exceptions.ServiceErrorException)2 AuthnUpdateParam (com.emc.storageos.model.auth.AuthnUpdateParam)1 RoleAssignmentChanges (com.emc.storageos.model.auth.RoleAssignmentChanges)1 RoleAssignmentEntry (com.emc.storageos.model.auth.RoleAssignmentEntry)1 RoleAssignments (com.emc.storageos.model.auth.RoleAssignments)1 ProjectParam (com.emc.storageos.model.project.ProjectParam)1 TenantCreateParam (com.emc.storageos.model.tenant.TenantCreateParam)1 TenantOrgList (com.emc.storageos.model.tenant.TenantOrgList)1 TenantOrgRestRep (com.emc.storageos.model.tenant.TenantOrgRestRep)1 VirtualArrayList (com.emc.storageos.model.varray.VirtualArrayList)1 UserTenant (com.emc.storageos.security.resource.UserInfoPage.UserTenant)1 UserTenantList (com.emc.storageos.security.resource.UserInfoPage.UserTenantList)1