/*
* Copyright (c) 2011-2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.api.service;
import java.net.URI;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import javax.crypto.SecretKey;
import com.emc.storageos.services.util.EnvConfig;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.emc.storageos.db.client.model.AuthnProvider;
import com.emc.storageos.db.client.model.DiscoveredDataObject.Type;
import com.emc.storageos.db.client.model.StorageProtocol;
import com.emc.storageos.db.client.model.StorageProtocol.Block;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.model.DiscoveredSystemObjectRestRep;
import com.emc.storageos.model.NamedRelatedResourceRep;
import com.emc.storageos.model.RelatedResourceRep;
import com.emc.storageos.model.TagAssignment;
import com.emc.storageos.model.TaskList;
import com.emc.storageos.model.TaskResourceRep;
import com.emc.storageos.model.auth.ACLAssignmentChanges;
import com.emc.storageos.model.auth.ACLAssignments;
import com.emc.storageos.model.auth.ACLEntry;
import com.emc.storageos.model.auth.AuthnCreateParam;
import com.emc.storageos.model.auth.AuthnProviderList;
import com.emc.storageos.model.auth.AuthnProviderRestRep;
import com.emc.storageos.model.auth.AuthnUpdateParam;
import com.emc.storageos.model.auth.RoleAssignmentChanges;
import com.emc.storageos.model.auth.RoleAssignmentEntry;
import com.emc.storageos.model.auth.RoleAssignments;
import com.emc.storageos.model.block.BlockConsistencyGroupCreate;
import com.emc.storageos.model.block.VolumeCreate;
import com.emc.storageos.model.file.FileSystemParam;
import com.emc.storageos.model.file.FileSystemSnapshotParam;
import com.emc.storageos.model.ports.StoragePortList;
import com.emc.storageos.model.ports.StoragePortRestRep;
import com.emc.storageos.model.ports.StoragePortUpdate;
import com.emc.storageos.model.project.ProjectElement;
import com.emc.storageos.model.project.ProjectParam;
import com.emc.storageos.model.project.ProjectUpdateParam;
import com.emc.storageos.model.search.Tags;
import com.emc.storageos.model.smis.SMISProviderCreateParam;
import com.emc.storageos.model.smis.SMISProviderRestRep;
import com.emc.storageos.model.systems.StorageSystemList;
import com.emc.storageos.model.systems.StorageSystemRequestParam;
import com.emc.storageos.model.systems.StorageSystemRestRep;
import com.emc.storageos.model.tenant.TenantCreateParam;
import com.emc.storageos.model.tenant.TenantOrgList;
import com.emc.storageos.model.tenant.TenantOrgRestRep;
import com.emc.storageos.model.tenant.TenantResponse;
import com.emc.storageos.model.tenant.TenantUpdateParam;
import com.emc.storageos.model.tenant.UserMappingAttributeParam;
import com.emc.storageos.model.tenant.UserMappingChanges;
import com.emc.storageos.model.tenant.UserMappingParam;
import com.emc.storageos.model.user.UserInfo;
import com.emc.storageos.model.varray.BlockSettings;
import com.emc.storageos.model.varray.NetworkCreate;
import com.emc.storageos.model.varray.NetworkRestRep;
import com.emc.storageos.model.varray.VirtualArrayCreateParam;
import com.emc.storageos.model.varray.VirtualArrayList;
import com.emc.storageos.model.varray.VirtualArrayRestRep;
import com.emc.storageos.model.vdc.VirtualDataCenterAddParam;
import com.emc.storageos.model.vdc.VirtualDataCenterList;
import com.emc.storageos.model.vdc.VirtualDataCenterRestRep;
import com.emc.storageos.model.vdc.VirtualDataCenterSecretKeyRestRep;
import com.emc.storageos.model.vpool.BlockVirtualPoolParam;
import com.emc.storageos.model.vpool.BlockVirtualPoolRestRep;
import com.emc.storageos.model.vpool.FileVirtualPoolParam;
import com.emc.storageos.model.vpool.FileVirtualPoolRestRep;
import com.emc.storageos.model.vpool.NamedRelatedVirtualPoolRep;
import com.emc.storageos.model.vpool.StoragePoolAssignmentChanges;
import com.emc.storageos.model.vpool.StoragePoolAssignments;
import com.emc.storageos.model.vpool.VirtualPoolList;
import com.emc.storageos.model.vpool.VirtualPoolPoolUpdateParam;
import com.emc.storageos.security.SignatureHelper;
import com.emc.storageos.security.authorization.Role;
import com.emc.storageos.security.resource.UserInfoPage.UserTenant;
import com.emc.storageos.security.resource.UserInfoPage.UserTenantList;
import com.emc.storageos.svcs.errorhandling.resources.ServiceCode;
import com.emc.vipr.model.keystore.CertificateChain;
import com.emc.vipr.model.keystore.KeyAndCertificateChain;
import com.emc.vipr.model.keystore.RotateKeyAndCertParam;
import com.sun.jersey.api.client.ClientResponse;
/**
*
* ApiTest class to exercise the core api functionality (tenants, AD, role assignments, isilon, volumes...)
*/
public class ApiTest extends ApiTestBase {
@Before
public void setUp() throws Exception {
setupHttpsResources();
}
private static String STR144 = "abcdefghijklmnopqrstuvwxyz0123456789" +
"abcdefghijklmnopqrstuvwxyz0123456789" + "abcdefghijklmnopqrstuvwxyz0123456789" +
"abcdefghijklmnopqrstuvwxyz0123456789";
private final int _maxRoleAclEntries = 100;
private final static String RSA_KEY_2048 = "-----BEGIN RSA PRIVATE KEY-----\r\n"
+ "MIIEogIBAAKCAQEAt1uYybrxbA5ApP+ZWbxBLeZLn6tl0UWxB0M/uar7S38QWpk3\r\n"
+ "Qf+MuCJV9mRIP+LMeLJan2n7V+cmGn3nmNto22hQ9EqwSFnOCzhWf5GhOEuQ9J5v\r\n"
+ "tGyWLLg9434xF16DpjMvdGfC9P2ELPyWKhRTjJ1r7X2tDalH44SXKgNULIGLIT7m\r\n"
+ "q6QFRnxK3AXlX19g3D4kFdd5B1MmEXnSE9bJ35WA+9TBgy7/5+TrP6hoIYoo81YD\r\n"
+ "wxcyVsRy0jLE0ufDNU8D8VbHtnhJN5bO54uykCIY8ZHWYoxOCHFvDeZr/NqCpIP8\r\n"
+ "ONtJX/9Iqoc+VtHehZhED2BegbEKnq/19SvcewIDAQABAoIBAEPP/ovtNciO5N2h\r\n"
+ "ImgLtddx6tocm8VwDu7usizKzbG4RqYbMFKaXsLjAAPmRspJ6PFilR2MJsb12CPI\r\n"
+ "GNVxoDA1Pmt7DANWI1wG9AauJ4AYgn3V8t45orjbUxhF3YYVEH9xQsW8cmAFOtMg\r\n"
+ "f7EEX3oL5pSo/E2nI81DhlylaoYiqq7NdhXQSqdg6WBNcU72ieCSoRkxgIK2/GyO\r\n"
+ "+lGnUW/YNhDNwUxOXu4UdBUgqG740DeRhhKQ4jp/dNI5UbN/figBbQPGn0sxSYDR\r\n"
+ "bVUN9TpZpEdsGkrfQt8DbJADL+ULa8s9YRUMLmfFSDq/Pj40PI4e2QD61D5vYhRY\r\n"
+ "jnTeDcECgYEA3rRjeH9G2tSB6KLxHFMxLIrzz+MUUBa6d7c5HxVTYfp/g9+r89ad\r\n"
+ "HZI1xhbXYHk8paqlvlRsVWzWFjXowI3rXM2lpbnnymRhs0UV3KFV9eKoAYDHVG9B\r\n"
+ "RNrg8vcvA/uSbIcUOQZzedW9Looq4D+fOt63WYaGNlosjjAUsO5UnYsCgYEA0sVH\r\n"
+ "s62uIOv+eUcDqHL97W9twc/VPrzDh4K2Ez+5+nYFN6Irx+KxUxFlsh+T3CAFBjoI\r\n"
+ "BgR9JHzqCd8qb/NEKVHt97CVK5APOi8j9SRbGiW/OSoFqE0NltpP6eAXwM6nqbi0\r\n"
+ "pNvIy805YL4+/rN891HXGlGNO2KFOE97/3NpetECgYBxEfE26pgU3rQeYyw7j1l2\r\n"
+ "Hg5vzAEyMHf39ETCLVeqdT5svBFXue0HaIZ4znwHdUZ/bka8fayLKrj/idtkeCm5\r\n"
+ "cofZvquarKCWHktdO2SjdLKMINATZHEk/mQbt7hdM0tCYsq3sTjL8OMeT/Q46tRz\r\n"
+ "VUSN5akay2m3v12h/z9ixQKBgD/ZLWBb06z7cIoyngQQWaXspHYazIGF00GgsiFg\r\n"
+ "o6kgyXHR+atCm+8LDSCJelQrivoY6EdSYsqD4K3+4a8qJVLTE+B9qKKasFIy55Si\r\n"
+ "X8qq9qONfEtAlEZHef/iN6/bqmS6pFZwkgJS9/e7if/ERa3yJ9Q8Mil0LeEiCvEW\r\n"
+ "eDSRAoGAawKiSYC69vLi4yE7PVzT7aSbhv+qV2ZIHVBzbZ2Fka/0ZUw2ApXyOJ9X\r\n"
+ "NKnrSi/RNcA9OsZ1Tl6mhO2/LBw3piY6RIwBhG78f7c83At6SfYtR6rVYvrXJROg\r\n"
+ "VQ/xGSSBsagM/0k9ACZpM13eNazRAVzpn3FX1DaUByzIDFcfImk=\r\n"
+ "-----END RSA PRIVATE KEY-----";
private final static String CERTIFICATE_2048 = "-----BEGIN CERTIFICATE-----\r\n"
+ "MIIDRzCCAi+gAwIBAgIIbG1mWcur1ZEwDQYJKoZIhvcNAQELBQAwHzEdMBsGA1UE\r\n"
+ "AxMUbGdsdzMxNTMubHNzLmVtYy5jb20wHhcNMTQwNTI3MTgzMTU4WhcNMjQwNTI0\r\n"
+ "MTgzMTU4WjAfMR0wGwYDVQQDExRsZ2x3MzE1My5sc3MuZW1jLmNvbTCCASIwDQYJ\r\n"
+ "KoZIhvcNAQEBBQADggEPADCCAQoCggEBALdbmMm68WwOQKT/mVm8QS3mS5+rZdFF\r\n"
+ "sQdDP7mq+0t/EFqZN0H/jLgiVfZkSD/izHiyWp9p+1fnJhp955jbaNtoUPRKsEhZ\r\n"
+ "zgs4Vn+RoThLkPSeb7Rsliy4PeN+MRdeg6YzL3RnwvT9hCz8lioUU4yda+19rQ2p\r\n"
+ "R+OElyoDVCyBiyE+5qukBUZ8StwF5V9fYNw+JBXXeQdTJhF50hPWyd+VgPvUwYMu\r\n"
+ "/+fk6z+oaCGKKPNWA8MXMlbEctIyxNLnwzVPA/FWx7Z4STeWzueLspAiGPGR1mKM\r\n"
+ "Tghxbw3ma/zagqSD/DjbSV//SKqHPlbR3oWYRA9gXoGxCp6v9fUr3HsCAwEAAaOB\r\n"
+ "hjCBgzAfBgNVHSMEGDAWgBSUgojM0wSrCa9lwGqW/x+9LHfPOjBBBgNVHREEOjA4\r\n"
+ "ghRsZ2x3MzE1My5sc3MuZW1jLmNvbYcECvdnmYIUbGdsdzMxNTIubHNzLmVtYy5j\r\n"
+ "b22HBAr3Z5gwHQYDVR0OBBYEFJSCiMzTBKsJr2XAapb/H70sd886MA0GCSqGSIb3\r\n"
+ "DQEBCwUAA4IBAQCo6XtB1kMXUt9WjoUmkrOZJfgfnps3jaB0N14wnO6EhdOXqHnm\r\n"
+ "CXFiTVAFcju/y4k2HqSlnkrgbcp3mjzY5CKUBBYTsi8MNgjL43+AkOvAOeDu3hen\r\n"
+ "+t5koeZ8dvpO39kR2u2eXsUBeaCo3ZKtOfDyrstiAtalrRDBWQl2IDO6AZ0ZjBy6\r\n"
+ "x9zn0sj9ahtPCSF6scG5UPyVKQzXREmDGLxXSxuKXlewljyMZwPDKH6GrhoO1yqo\r\n"
+ "6OOuAXPNzN5vuAUVj3Qjvs5lRWMrBMDH0XkjoEX2AAqs1pFfuAO17rgEnFO9iBgh\r\n"
+ "aSHrpqdkEwwx/9p/lDJ4wJDgDD/GrpLvl7s0\r\n" + "-----END CERTIFICATE-----";
private static final String RSA_KEY_1024 = "-----BEGIN RSA PRIVATE KEY-----\r\n"
+ "MIICXAIBAAKBgQDJYd1wxB87o/tq+1MZdIzveINYXjPDUmgjT5ZCZlZjjV2HdG1w\r\n"
+ "h9Pp6Y6cav45c7BcvQq4fsmT5pZVzOG5U5cJTEdjPJ9nOJrh11gQJVenOXqGRI73\r\n"
+ "pZzhiG4uWNFV84skxU4ObPTsernN8kTrNQoygR8wTsZziwAaY2zhvyuuXQIDAQAB\r\n"
+ "AoGAa/s65s1yxeMO2/V5QIv7Sii/nPGeJdyZFF4HfwEqz2SswwYN7KoYWjOvEXZZ\r\n"
+ "bOr4pTGEfxsU8WZSNB2Q53PH5vMQ1B1/72QZUnLoKLOGR/EOX5RA1PhM6Ea5u18P\r\n"
+ "wzJ9TcvHsH1QIxEH0pep2qhWIl8D6JjdYaIliPynCGOONeECQQD2+fwAIUPZa5Wg\r\n"
+ "s3t/z6azFOlKdnITdkqm1B0erwl9ZgN5ZiS9P5BS30PNXxJ0EiZdXJzPcBIZFuY2\r\n"
+ "NJZAsvylAkEA0L1uAkdGroFYDp1xu3HJcO0JGkrO3Rs6W6G697damYgYB4pfTTng\r\n"
+ "pUd9FgLu4HLb6Y0muGpB8sXirb2aB1YlWQJBAMxUDZTd8JBUXbpSQ35+gV/vkQK1\r\n"
+ "87L+Tsyu+FiGX8eLOpyZURPxHqoxZJroaQ/2ZB8hm+pSweZX96Yo45YrfrECQFaE\r\n"
+ "HQNuvVn4nCG6mfgB6mcWp64xEVpNPbva5Z5kbXWzFZqSfHuKoJSAc9TatF1s3b8I\r\n"
+ "VOMcj2brI8+1BRFDYEkCQFbKUFyfFOjVZczK2NdbXSrO3iSTIZFOGETa9dxrchRP\r\n"
+ "/TXoqhkTuzu9y/E8QVQXBdCEXD72v5sn1kl1hd8Pgro=\r\n"
+ "-----END RSA PRIVATE KEY-----";
private final static String CERTIFICATE_1024 = "-----BEGIN CERTIFICATE-----\r\n"
+ "MIICZDCCAc2gAwIBAgIJAKeFkwH41qufMA0GCSqGSIb3DQEBBQUAMB8xHTAbBgNV\r\n"
+ "BAMTFGxnbHc4MDk1Lmxzcy5lbWMuY29tMCAXDTcwMDEwMTAwMDAwMFoYDzIwNzAw\r\n"
+ "MTAxMDAwMDAwWjAfMR0wGwYDVQQDExRsZ2x3ODA5NS5sc3MuZW1jLmNvbTCBnzAN\r\n"
+ "BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyWHdcMQfO6P7avtTGXSM73iDWF4zw1Jo\r\n"
+ "I0+WQmZWY41dh3RtcIfT6emOnGr+OXOwXL0KuH7Jk+aWVczhuVOXCUxHYzyfZzia\r\n"
+ "4ddYECVXpzl6hkSO96Wc4YhuLljRVfOLJMVODmz07Hq5zfJE6zUKMoEfME7Gc4sA\r\n"
+ "GmNs4b8rrl0CAwEAAaOBpTCBojAdBgNVHQ4EFgQUnFPfhlGJixUjlDnxDPguQr5a\r\n"
+ "Ux0wTwYDVR0jBEgwRoAUnFPfhlGJixUjlDnxDPguQr5aUx2hI6QhMB8xHTAbBgNV\r\n"
+ "BAMTFGxnbHc4MDk1Lmxzcy5lbWMuY29tggkAp4WTAfjWq58wCQYDVR0SBAIwADAl\r\n"
+ "BgNVHREEHjAcghRsZ2x3ODA5NS5sc3MuZW1jLmNvbYcECvdiXzANBgkqhkiG9w0B\r\n"
+ "AQUFAAOBgQAxd5VQA31X01gXTNSUhXTQ6y7VWox7OCGAhINhtdpLBp54CL30W8oK\r\n"
+ "qQnIlpEP+GB4CJYfdSa8ltNUx4yRJjzG8QiPVkJV1b88Uba+gn4/xlHLLH3PqPDX\r\n"
+ "TzLGkt6+Prz+1w/ZAMKAXr6KAi4I0pnduqVRJ++GPmYBhPZre5auvw==\r\n"
+ "-----END CERTIFICATE-----";
// right now, this only test one particular bad parameter (search filter).
// We can enhance this to test out all the precheckConditions present in the AuthnConfigurationService
private void addBadADConfig() throws NoSuchAlgorithmException {
// Test that a config without a proper filter (key=%u) results in 400
AuthnCreateParam param = new AuthnCreateParam();
param.setLabel("ad apitest config bad");
param.setDescription("ad configuration created by ApiTest.java");
param.setDisable(false);
param.getDomains().add("sanity2.local");
param.setGroupAttribute("CN");
param.setGroupWhitelistValues(new HashSet<String>());
param.getGroupWhitelistValues().add("*Admins*");
param.getGroupWhitelistValues().add("*Test*");
param.getGroupWhitelistValues().add("*Users*");
param.setManagerDn("CN=Administrator,CN=Users,DC=sanity,DC=local");
param.setManagerPassword(AD_PASS_WORD);
param.setSearchBase("CN=Users,DC=sanity,DC=local");
// %u is there but not on the right side of the "=". Adding this config should fail
param.setSearchFilter("%u=userPrincipalName");
param.setServerUrls(new HashSet<String>());
param.getServerUrls().add("ldap:\\" + AD_SERVER1_IP);
param.setMode("ad");
ClientResponse resp = rSys.path("/vdc/admin/authnproviders").post(ClientResponse.class, param);
Assert.assertEquals(400, resp.getStatus());
// Test that adding two profiles with the same domain name results in 400
String label = "ad apitest config duplicate 1";
AuthnCreateParam duplicateConfig1 = new AuthnCreateParam();
duplicateConfig1.setLabel(label);
duplicateConfig1.setDescription("ad configuration created by ApiTest.java");
duplicateConfig1.setDisable(false);
duplicateConfig1.getDomains().add("mydomain.com");
duplicateConfig1.setGroupAttribute("CN");
duplicateConfig1.setGroupWhitelistValues(new HashSet<String>());
duplicateConfig1.getGroupWhitelistValues().add("*Admins*");
duplicateConfig1.setManagerDn("CN=Administrator,CN=Users,DC=sanity,DC=local");
duplicateConfig1.setManagerPassword(AD_PASS_WORD);
duplicateConfig1.setSearchBase("CN=Users,DC=sanity,DC=local");
duplicateConfig1.setSearchFilter("userPrincipalName=%u");
duplicateConfig1.setServerUrls(new HashSet<String>());
duplicateConfig1.getServerUrls().add("ldap:\\" + AD_SERVER1_IP);
duplicateConfig1.setMode("ad");
AuthnProviderRestRep authnResp = rSys.path("/vdc/admin/authnproviders").post(AuthnProviderRestRep.class, duplicateConfig1);
Assert.assertNotNull(authnResp);
URI firstCreatedConfig = authnResp.getId();
AuthnCreateParam duplicateConfig2 = new AuthnCreateParam();
duplicateConfig2.setLabel("ad apitest config duplicate 2");
duplicateConfig2.setDescription("ad configuration created by ApiTest.java");
duplicateConfig2.setDisable(false);
duplicateConfig2.getDomains().add("mydomain.com");
duplicateConfig2.setGroupAttribute("CN");
duplicateConfig2.setGroupWhitelistValues(new HashSet<String>());
duplicateConfig2.getGroupWhitelistValues().add("*Admins*");
duplicateConfig2.setManagerDn("CN=Administrator,CN=Users,DC=sanity,DC=local");
duplicateConfig2.setManagerPassword(AD_PASS_WORD);
duplicateConfig2.setSearchBase("CN=Users,DC=sanity,DC=local");
duplicateConfig2.setSearchFilter("userPrincipalName=%u");
duplicateConfig2.setServerUrls(new HashSet<String>());
duplicateConfig2.getServerUrls().add("ldap:\\" + AD_SERVER1_IP);
duplicateConfig2.setMode("ad");
resp = rSys.path("/vdc/admin/authnproviders").post(ClientResponse.class, duplicateConfig2);
Assert.assertEquals(400, resp.getStatus());
// Test for duplicate name check (post)
duplicateConfig2.setLabel(label);
duplicateConfig2.getDomains().add("mydomain2.com");
resp = rSys.path("/vdc/admin/authnproviders").post(ClientResponse.class, duplicateConfig2);
Assert.assertEquals(400, resp.getStatus());
// Test that you cannot update an existing with a domain name that exists somewhere else
AuthnUpdateParam updateParam = new AuthnUpdateParam();
updateParam.getDomainChanges().getAdd().add("sanity.local");
String myDomainComauthnProvidersUrlFormat = String.format("/vdc/admin/authnproviders/%s",
firstCreatedConfig.toString());
resp = rSys.path(myDomainComauthnProvidersUrlFormat).put(ClientResponse.class, updateParam);
Assert.assertEquals(400, resp.getStatus());
// test that updating the config with the same name as itself is fine (no op)
AuthnUpdateParam updateParamSameName = new AuthnUpdateParam();
updateParamSameName.getDomainChanges().getAdd().add("mydomain.com");
resp = rSys.path(myDomainComauthnProvidersUrlFormat).put(ClientResponse.class, updateParamSameName);
Assert.assertEquals(200, resp.getStatus());
// test that trying to update a config with a name too short causes 400
AuthnUpdateParam updateParamNameTooShort = new AuthnUpdateParam();
updateParamNameTooShort.setLabel("a");
resp = rSys.path(myDomainComauthnProvidersUrlFormat).put(ClientResponse.class, updateParamNameTooShort);
Assert.assertEquals(400, resp.getStatus());
// test that trying to update a config with a name too long causes 400
AuthnUpdateParam updateParamNameTooLong = new AuthnUpdateParam();
updateParamNameTooLong.setLabel("authn" + STR144);
resp = rSys.path(myDomainComauthnProvidersUrlFormat).put(ClientResponse.class, updateParamNameTooLong);
Assert.assertEquals(400, resp.getStatus());
// test that trying to update a config with the same name doesn't cause an error
AuthnUpdateParam updateParam2 = new AuthnUpdateParam();
updateParam2.setLabel(label);
resp = rSys.path(myDomainComauthnProvidersUrlFormat).put(ClientResponse.class, updateParam2);
Assert.assertEquals(200, resp.getStatus());
// test that the String payload will be trimmed
updateParam2 = new AuthnUpdateParam();
updateParam2.setLabel(" " + label + " ");
authnResp = rSys.path(myDomainComauthnProvidersUrlFormat).put(AuthnProviderRestRep.class, updateParam2);
Assert.assertTrue(authnResp.getName().equals(label));
// Mark the mydomain.com provider as disabled. Try to add a conflicting domain provider.
// Should still fail. Because even though disabled the provider can eventually be renabled.
AuthnUpdateParam updateParam3 = new AuthnUpdateParam();
updateParam3.setDisable(true);
resp = rSys.path(myDomainComauthnProvidersUrlFormat).put(ClientResponse.class, updateParam3);
Assert.assertEquals(200, resp.getStatus());
resp = rSys.path(myDomainComauthnProvidersUrlFormat).put(ClientResponse.class, updateParam);
Assert.assertEquals(400, resp.getStatus());
// Now delete that mydomain.com provider and re-add it, see that
// it is now allowed because the conflicting provider has been deleted
resp = rSys.path(myDomainComauthnProvidersUrlFormat).delete(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
authnResp = rSys.path("/vdc/admin/authnproviders").post(AuthnProviderRestRep.class, duplicateConfig1);
Assert.assertNotNull(authnResp);
// Test that updating a config with a MaxPageSize=0 fails
AuthnUpdateParam pageSizeUpdateParam = new AuthnUpdateParam();
pageSizeUpdateParam.setMaxPageSize(0);
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", authnResp.getId().toString())).put(ClientResponse.class,
pageSizeUpdateParam);
Assert.assertEquals(400, resp.getStatus());
// Set the page size and verify that it is successful.
pageSizeUpdateParam.setMaxPageSize(500);
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", authnResp.getId().toString())).put(ClientResponse.class,
pageSizeUpdateParam);
Assert.assertEquals(200, resp.getStatus());
// Get the provider and verify that it has the new page size
authnResp = rSys.path(String.format("/vdc/admin/authnproviders/%s", authnResp.getId().toString())).get(AuthnProviderRestRep.class);
Assert.assertEquals(pageSizeUpdateParam.getMaxPageSize().intValue(), authnResp.getMaxPageSize().intValue());
// Test that a bad search scope gets rejected.
// Missing scope is tested by all the other tests above which do not
// supply scope.
AuthnCreateParam badScopeParam = new AuthnCreateParam();
badScopeParam.setLabel("ad apitest config with bad scope");
badScopeParam.setDescription("ad configuration created by ApiTest.java");
badScopeParam.setDisable(false);
badScopeParam.getDomains().add("mydomain4.com");
badScopeParam.setGroupAttribute("CN");
badScopeParam.setGroupWhitelistValues(new HashSet<String>());
badScopeParam.getGroupWhitelistValues().add("*Admins*");
badScopeParam.setManagerDn("CN=Administrator,CN=Users,DC=sanity,DC=local");
badScopeParam.setManagerPassword(AD_PASS_WORD);
badScopeParam.setSearchBase("CN=Users,DC=sanity,DC=local");
badScopeParam.setSearchFilter("userPrincipalName=%u");
badScopeParam.setServerUrls(new HashSet<String>());
badScopeParam.getServerUrls().add("ldap:\\" + AD_SERVER1_IP);
badScopeParam.setSearchScope("bad scope"); // BAD SCOPE
badScopeParam.setMode("ad");
resp = rSys.path("/vdc/admin/authnproviders").post(ClientResponse.class, badScopeParam);
Assert.assertEquals(400, resp.getStatus());
// Test that a good search scope works
AuthnCreateParam goodScopeParam = new AuthnCreateParam();
String goodScopeName = "ad apitest config with good scope";
goodScopeParam.setLabel(goodScopeName);
goodScopeParam.setDescription("ad configuration created by ApiTest.java");
goodScopeParam.setDisable(false);
goodScopeParam.getDomains().add("mydomain5.com");
goodScopeParam.setGroupAttribute("CN");
goodScopeParam.setGroupWhitelistValues(new HashSet<String>());
goodScopeParam.getGroupWhitelistValues().add("*Admins*");
goodScopeParam.setManagerDn("CN=Administrator,CN=Users,DC=sanity,DC=local");
goodScopeParam.setManagerPassword(AD_PASS_WORD);
goodScopeParam.setSearchBase("CN=Users,DC=sanity,DC=local");
goodScopeParam.setSearchFilter("userPrincipalName=%u");
goodScopeParam.setServerUrls(new HashSet<String>());
goodScopeParam.getServerUrls().add("ldap:\\" + AD_SERVER1_IP);
goodScopeParam.setSearchScope(AuthnProvider.SearchScope.SUBTREE.toString());
goodScopeParam.setMode("ad");
resp = rSys.path("/vdc/admin/authnproviders").post(ClientResponse.class, goodScopeParam);
Assert.assertEquals(200, resp.getStatus());
// create a config, then try to modify its name to one that exists.
AuthnCreateParam randomConfig = new AuthnCreateParam();
randomConfig.setLabel("random");
randomConfig.setDescription("random provider");
randomConfig.setDisable(false);
randomConfig.getDomains().add("mydomain6.com");
randomConfig.setGroupAttribute("CN");
randomConfig.setGroupWhitelistValues(new HashSet<String>());
randomConfig.getGroupWhitelistValues().add("*Admins*");
randomConfig.setManagerDn("CN=Administrator,CN=Users,DC=sanity,DC=local");
randomConfig.setManagerPassword(AD_PASS_WORD);
randomConfig.setSearchBase("CN=Users,DC=sanity,DC=local");
randomConfig.setSearchFilter("userPrincipalName=%u");
randomConfig.setServerUrls(new HashSet<String>());
randomConfig.getServerUrls().add("ldap:\\" + AD_SERVER1_IP);
randomConfig.setSearchScope(AuthnProvider.SearchScope.SUBTREE.toString());
randomConfig.setMode("ad");
AuthnProviderRestRep authnResp2 = rSys.path("/vdc/admin/authnproviders").post(AuthnProviderRestRep.class, randomConfig);
Assert.assertNotNull(authnResp2);
AuthnUpdateParam updateParam4 = new AuthnUpdateParam();
updateParam4.setLabel(goodScopeName);
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", authnResp2.getId().toString()))
.put(ClientResponse.class, updateParam4);
Assert.assertEquals(400, resp.getStatus());
// attempt to delete the only url in the config. should fail with 400
AuthnUpdateParam lastUrl = new AuthnUpdateParam();
lastUrl.getServerUrlChanges().setRemove(new HashSet<String>());
lastUrl.getServerUrlChanges().getRemove().add("ldap:\\" + AD_SERVER1_IP);
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", _goodADConfig)).put(ClientResponse.class, lastUrl);
Assert.assertEquals(400, resp.getStatus());
// modify the main config with a bad group CN. Verify you get 400
AuthnUpdateParam badCN = new AuthnUpdateParam();
badCN.setGroupAttribute("garbage");
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", _goodADConfig)).
queryParam("allow_group_attr_change", "true").put(ClientResponse.class, badCN);
String errorMessage = String
.format("The authentication provider could not be added or modified because of the following error: The group attribute %s could not be found in AD schema at server [%s].",
badCN.getGroupAttribute(), "ldap:\\" + AD_SERVER1_IP);
assertExpectedError(resp, 400, ServiceCode.API_PARAMETER_INVALID, errorMessage);
_savedTokens.remove(ROOTTENANTADMIN);
// put the config back.
AuthnUpdateParam goodCN = new AuthnUpdateParam();
goodCN.setGroupAttribute("CN");
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", _goodADConfig)).queryParam("allow_group_attr_change", "true")
.put(ClientResponse.class, goodCN);
Assert.assertEquals(200, resp.getStatus());
// modify the group attribute. Should fail.
AuthnUpdateParam changeCN = new AuthnUpdateParam();
changeCN.setGroupAttribute("objectSid");
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", _goodADConfig)).put(ClientResponse.class, changeCN);
Assert.assertEquals(400, resp.getStatus());
// modify the group attribute with force flag. Should succeed.
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", _goodADConfig)).queryParam("allow_group_attr_change", "true")
.put(ClientResponse.class, changeCN);
Assert.assertEquals(200, resp.getStatus());
// put the original group attribute back for the rest of the tests.
changeCN.setGroupAttribute("CN");
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", _goodADConfig)).queryParam("allow_group_attr_change", "true")
.put(ClientResponse.class, changeCN);
Assert.assertEquals(200, resp.getStatus());
}
private void authProvidersConnectivityTests() {
// Test that a config invalid server url results in 400
AuthnCreateParam param = new AuthnCreateParam();
param.setLabel("ad apitest config bad url");
param.setDescription("ad apitest config bad url");
param.setDisable(false);
param.getDomains().add("domain1.com");
param.setGroupAttribute("CN");
param.setGroupWhitelistValues(new HashSet<String>());
param.getGroupWhitelistValues().add("*Admins*");
param.getGroupWhitelistValues().add("*Test*");
param.getGroupWhitelistValues().add("*Users*");
param.setManagerDn("CN=Administrator,CN=Users,DC=sanity,DC=local");
param.setManagerPassword(AD_PASS_WORD);
param.setSearchBase("CN=Users,DC=sanity,DC=local");
param.setSearchFilter("userPrincipalName=%u");
param.setServerUrls(new HashSet<String>());
param.getServerUrls().add("ldap://" + EnvConfig.get("sanity", "ad.bogus.ip"));
param.setMode("ad");
ClientResponse resp = rSys.path("/vdc/admin/authnproviders").post(ClientResponse.class, param);
Assert.assertEquals(400, resp.getStatus());
// Test that a config invalid manager DN results in 400
param.setManagerDn("xxxxxministrator,CN=Users,DC=sanity,DC=local");
param.setServerUrls(new HashSet<String>());
param.getServerUrls().add("ldap:\\" + AD_SERVER1_IP);
resp = rSys.path("/vdc/admin/authnproviders").post(ClientResponse.class, param);
Assert.assertEquals(400, resp.getStatus());
// Test that a config invalid manager password results in 400
param.setManagerDn("CN=Administrator,CN=Users,DC=sanity,DC=local");
param.setManagerPassword("bad");
resp = rSys.path("/vdc/admin/authnproviders").post(ClientResponse.class, param);
Assert.assertEquals(400, resp.getStatus());
// test that the same invalid config as above succeeds if disable is set to true
// (validation skipped)
param.setDisable(true);
AuthnProviderRestRep authnResp = rSys.path("/vdc/admin/authnproviders").post(AuthnProviderRestRep.class, param);
Assert.assertNotNull(authnResp);
// test that trying to enable that bad disabled config fails with 400
AuthnUpdateParam updateParam = new AuthnUpdateParam();
updateParam.setDisable(false);
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", authnResp.getId().toString()))
.put(ClientResponse.class, updateParam);
Assert.assertEquals(400, resp.getStatus());
// fix what was wrong (password), and disable = false from above, validation should rerun and be ok
updateParam.setManagerPassword(AD_PASS_WORD);
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", authnResp.getId().toString()))
.put(ClientResponse.class, updateParam);
Assert.assertEquals(200, resp.getStatus());
// test basic ldap mode connectivity
AuthnCreateParam ldapParam = new AuthnCreateParam();
ldapParam.setLabel("ldap connectivity test");
ldapParam.setDescription("ldap connectivity test");
ldapParam.setDisable(false);
ldapParam.getDomains().add("domain22.com");
ldapParam.setManagerDn("CN=Administrator,CN=Users,DC=sanity,DC=local");
ldapParam.setManagerPassword(AD_PASS_WORD);
ldapParam.setSearchBase("CN=Users,DC=sanity,DC=local");
ldapParam.setSearchFilter("userPrincipalName=%u");
ldapParam.setServerUrls(new HashSet<String>());
ldapParam.getServerUrls().add("ldap:\\" + AD_SERVER1_IP);
ldapParam.setGroupAttribute("CN");
ldapParam.setMode("ldap");
AuthnProviderRestRep goodAuthnResp = rSys.path("/vdc/admin/authnproviders").post(AuthnProviderRestRep.class, ldapParam);
Assert.assertNotNull(goodAuthnResp);
// test that modifying the good config by adding one bad url still works. The good url that
// is left in the set makes the url set valid.
AuthnUpdateParam updateParamBadUrl = new AuthnUpdateParam();
updateParamBadUrl.getServerUrlChanges().setAdd(new HashSet<String>());
updateParamBadUrl.getServerUrlChanges().getAdd().add("ldap://garbage");
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", goodAuthnResp.getId().toString())).put(ClientResponse.class,
updateParamBadUrl);
Assert.assertEquals(200, resp.getStatus());
// update the good config above with a bad search base which won't be found. Should fail.
AuthnUpdateParam updateParamBadSearchBase = new AuthnUpdateParam();
updateParamBadSearchBase.setSearchBase("CN=garbage");
resp = rSys.path(String.format("/vdc/admin/authnproviders/%s", goodAuthnResp.getId().toString())).put(ClientResponse.class,
updateParamBadSearchBase);
Assert.assertEquals(400, resp.getStatus());
}
private void adConfigListTests() {
AuthnProviderList resp = rSys.path("/vdc/admin/authnproviders").get(AuthnProviderList.class);
int sz = resp.getProviders().size();
// Add one more, then one with no name field. The new total should be sz + 2.
AuthnCreateParam param = new AuthnCreateParam();
param.setLabel("ad apitest config one");
param.setDescription("ad configuration created by ApiTest.java");
param.setDisable(false);
param.getDomains().add("sanity3.local");
param.setGroupAttribute("CN");
param.setGroupWhitelistValues(new HashSet<String>());
param.getGroupWhitelistValues().add("*Admins*");
param.getGroupWhitelistValues().add("*Test*");
param.getGroupWhitelistValues().add("*Users*");
param.setManagerDn("CN=Administrator,CN=Users,DC=sanity,DC=local");
param.setManagerPassword(AD_PASS_WORD);
param.setSearchBase("CN=Users,DC=sanity,DC=local");
param.setSearchFilter("userPrincipalName=%u");
param.setServerUrls(new HashSet<String>());
param.getServerUrls().add("ldap:\\" + AD_SERVER1_IP);
param.getServerUrls().add("ldap:\\" + AD_SERVER1_HOST);
param.setMode("ad");
ClientResponse resp2 = rSys.path("/vdc/admin/authnproviders").post(ClientResponse.class, param);
Assert.assertEquals(200, resp2.getStatus());
param.setLabel("ad apitest config two");
param.getDomains().remove("sanity3.local");
param.getDomains().add("another.com");
AuthnProviderRestRep authnResp = rSys.path("/vdc/admin/authnproviders").post(AuthnProviderRestRep.class, param);
Assert.assertNotNull(authnResp);
resp = rSys.path("/vdc/admin/authnproviders").get(AuthnProviderList.class);
int sz2 = resp.getProviders().size();
Assert.assertEquals(sz2, sz + 2);
// update test
AuthnUpdateParam updateParam = new AuthnUpdateParam();
updateParam.setLabel("ad apitest config two");
updateParam.getDomainChanges().setRemove(new HashSet<String>());
updateParam.getDomainChanges().getRemove().add("another.com");
updateParam.getGroupWhitelistValueChanges().setRemove(new HashSet<String>());
updateParam.getGroupWhitelistValueChanges().getRemove().add("*Admins*");
updateParam.getGroupWhitelistValueChanges().getRemove().add("*Test*");
updateParam.getGroupWhitelistValueChanges().getRemove().add("*Users*");
updateParam.getServerUrlChanges().setRemove(new HashSet<String>());
updateParam.getServerUrlChanges().getRemove().add("ldap:\\" + AD_SERVER1_HOST);
AuthnProviderRestRep authnResp2 = rSys.path("/vdc/admin/authnproviders/" + authnResp.getId().toString() + "/")
.put(AuthnProviderRestRep.class, updateParam);
Assert.assertNotNull(authnResp2);
Assert.assertEquals(0, authnResp2.getDomains().size());
Assert.assertEquals(0, authnResp2.getGroupWhitelistValues().size());
Assert.assertEquals(1, authnResp2.getServerUrls().size());
}
@Test
public void HttpsTest() throws Exception {
testAll();
}
private void proxyTokenTests() {
// Login as root
TenantResponse tenantResp = rSys.path("/tenant").get(TenantResponse.class);
rootTenantId = tenantResp.getTenant();
// Get a proxy token for root
ClientResponse resp = rSys.path("/proxytoken").get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
String proxyToken = (String) _savedProxyTokens.get("root");
Assert.assertNotNull(proxyToken);
// try to access tenant/id as proxy user. Does not work because proxy token was not passed in.
// Proxy user by itself doesn't have TENANT_ADMIN.
resp = rProxyUser.path("/tenants/" + rootTenantId.toString()).get(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
// try to access tenant/id as proxy user with proxy token this time.
resp = rProxyUser.path("/tenants/" + rootTenantId.toString()).header(ApiTestBase.AUTH_PROXY_TOKEN_HEADER, proxyToken)
.get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
// negative tests
// proxy token, but a user without PROXY_USER role
resp = rZAdmin.path("/tenants/" + rootTenantId.toString()).header(ApiTestBase.AUTH_PROXY_TOKEN_HEADER, proxyToken)
.get(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
// check that the root when proxied does not have SECURITY_ADMIN in it.
UserInfo info = rProxyUser.path("/user/whoami")
.header(ApiTestBase.AUTH_PROXY_TOKEN_HEADER, proxyToken)
.get(UserInfo.class);
Assert.assertEquals("root", info.getCommonName());
Assert.assertTrue(!info.getVdcRoles().contains(Role.SECURITY_ADMIN.toString()));
// zone admin, when proxied, can not do role assignments
resp = rZAdmin.path("/proxytoken").get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
String zAdminProxyToken = (String) _savedProxyTokens.get(ZONEADMIN);
Assert.assertNotNull(zAdminProxyToken);
resp = rProxyUser.path("/vdc/role-assignments")
.header(ApiTestBase.AUTH_PROXY_TOKEN_HEADER, zAdminProxyToken)
.put(ClientResponse.class, new RoleAssignmentChanges());
Assert.assertEquals(403, resp.getStatus());
// logout issuer of the proxy token with the force option. This should wipe out
// all tokens including proxy tokens. Consequently, proxyuser should no longer be able
// to access the tenants/id call with that proxy token anymore.
// ( added .xml and used mixed cases to test that the logout filter forwards the request
// appropriately)
// resp = rSys.path("/loGout.XmL").queryParam("force", "true").get(ClientResponse.class);
resp = rSys.path("/logout.xml").queryParam("force", "true").queryParam("proxytokens", "true").get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
resp = rProxyUser.path("/tenants/" + rootTenantId.toString()).header(ApiTestBase.AUTH_PROXY_TOKEN_HEADER, proxyToken)
.get(ClientResponse.class);
Assert.assertEquals(401, resp.getStatus());
}
private void logoutTests() throws Exception {
BalancedWebResource rootUser = createHttpsClient(SYSADMIN, SYSADMIN_PASS_WORD, baseUrls);
ClientResponse resp = rootUser.path("/login").get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
Assert.assertNotNull(_savedTokens.get("root"));
resp = rootUser.path("/tenant").get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
// logout normally
resp = rootUser.path("/logout").get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
// logout again with an aleady logged out token
resp = rootUser.path("/logout").get(ClientResponse.class);
Assert.assertEquals(401, resp.getStatus());
// logout again with a bad token
_savedTokens.put("root", "invalid");
resp = rootUser.path("/logout").get(ClientResponse.class);
Assert.assertEquals(401, resp.getStatus());
// login again, logout with .xml and mixed case
_savedTokens.remove("root");
resp = rootUser.path("/login").get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
Assert.assertNotNull(_savedTokens.get("root"));
resp = rootUser.path("/logOut.xMl").get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
// login again, logout with .json and mixed case
_savedTokens.remove("root");
resp = rootUser.path("/login").get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
Assert.assertNotNull(_savedTokens.get("root"));
resp = rootUser.path("/logOut.json").get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
resp = rootUser.path("/logout.junk").get(ClientResponse.class);
Assert.assertEquals(404, resp.getStatus());
}
private void testAll() throws Exception {
adConfigTests();
proxyTokenTests();
userInfoTests();
// uncomment the following line when CQ606655 has been fixed
// logoutTests();
tenantTests();
testOtherBadParameterErrors();
testOtherEntityNotFoundErrors();
projectTests();
usageAclTests();
// commenting this out, since its becoming hard to keep up with the changes in controller area
// we can revive these once we have stabilized the api changes in this area
// projectResourceTests();
testKeystore();
testVDCSecretKey();
prepareVdcTest();
groupSuffixTest();
disabledAuthnProviderTest();
loneAuthnProviderDeleteTest();
authnProviderAddDomainTest();
}
/**
*
*/
private void testKeystore() {
/*
* GET THE CERTIFICATE CHAIN
*/
// test with a security admin -should succeed
ClientResponse response = rZAdmin.path("/vdc/keystore").get(ClientResponse.class);
Assert.assertEquals(200, response.getStatus());
CertificateChain previousChain =
rZAdmin.path("/vdc/keystore").get(CertificateChain.class);
// test with a non-privileged user user -should succeed
response = rRootUser2.path("/vdc/keystore").get(ClientResponse.class);
Assert.assertEquals(200, response.getStatus());
/*
* REGENERATE THE KEY AND CERTIFICATE
*/
// test with a non-privileged user -should fail
RotateKeyAndCertParam rotateKeyAndCertParam = new RotateKeyAndCertParam();
rotateKeyAndCertParam.setSystemSelfSigned(true);
response = rRootUser2.path("/vdc/keystore").put(ClientResponse.class, rotateKeyAndCertParam);
Assert.assertEquals(403, response.getStatus());
// test with a security admin -should succeed
CertificateChain currChain =
rZAdmin.path("/vdc/keystore").put(CertificateChain.class, rotateKeyAndCertParam);
Assert.assertNotSame(removeNewLines(previousChain.getChain()),
removeNewLines(currChain.getChain()));
waitForClusterToBeStable();
previousChain = currChain;
/*
* SET THE KEY AND CERTIFICATE
*/
// test with a non-privileged user -should fail
rotateKeyAndCertParam.setSystemSelfSigned(false);
KeyAndCertificateChain keyAndCertificateChain = new KeyAndCertificateChain();
keyAndCertificateChain.setCertificateChain(CERTIFICATE_2048);
keyAndCertificateChain.setPrivateKey(RSA_KEY_2048);
rotateKeyAndCertParam.setKeyCertChain(keyAndCertificateChain);
response =
rRootUser2.path("/vdc/keystore").put(ClientResponse.class,
rotateKeyAndCertParam);
Assert.assertEquals(403, response.getStatus());
// test with a security admin -should succeed
currChain =
rZAdmin.path("/vdc/keystore").put(CertificateChain.class,
rotateKeyAndCertParam);
Assert.assertNotSame(removeNewLines(previousChain.getChain()),
removeNewLines(currChain.getChain()));
waitForClusterToBeStable();
// test with the same key and certificate - should fail
String expectedError =
"The specified certificate is already being used. Please specify a new key and certificate pair.";
response =
rZAdmin.path("/vdc/keystore").put(ClientResponse.class,
rotateKeyAndCertParam);
assertExpectedError(response, 400, ServiceCode.API_BAD_REQUEST,
expectedError);
// test with a mismatched key and certificate
keyAndCertificateChain.setPrivateKey(RSA_KEY_2048);
keyAndCertificateChain.setCertificateChain(CERTIFICATE_1024);
rotateKeyAndCertParam.setKeyCertChain(keyAndCertificateChain);
response =
rZAdmin.path("/vdc/keystore").put(ClientResponse.class,
rotateKeyAndCertParam);
expectedError = "The provided key and certificate do not match";
assertExpectedError(response, 400, ServiceCode.API_PARAMETER_INVALID,
expectedError);
// test with bad key
keyAndCertificateChain = new KeyAndCertificateChain();
keyAndCertificateChain.setCertificateChain(CERTIFICATE_1024);
keyAndCertificateChain.setPrivateKey("this is a bad key");
rotateKeyAndCertParam.setKeyCertChain(keyAndCertificateChain);
response =
rZAdmin.path("/vdc/keystore").put(ClientResponse.class,
rotateKeyAndCertParam);
expectedError = "Failed to load the private key.";
assertExpectedError(response, 400, ServiceCode.API_PARAMETER_INVALID,
expectedError);
// test with bad certificate
keyAndCertificateChain = new KeyAndCertificateChain();
String badCert = "this is a bad certificate";
keyAndCertificateChain.setCertificateChain(badCert);
keyAndCertificateChain.setPrivateKey(RSA_KEY_1024);
rotateKeyAndCertParam.setKeyCertChain(keyAndCertificateChain);
response =
rZAdmin.path("/vdc/keystore").put(ClientResponse.class,
rotateKeyAndCertParam);
expectedError = "Failed to load the following certificate(s): " + badCert;
assertExpectedError(response, 400, ServiceCode.API_PARAMETER_INVALID,
expectedError);
// test with a key that's less than 2048 bits long
keyAndCertificateChain = new KeyAndCertificateChain();
keyAndCertificateChain.setCertificateChain(CERTIFICATE_1024);
keyAndCertificateChain.setPrivateKey(RSA_KEY_1024);
rotateKeyAndCertParam.setKeyCertChain(keyAndCertificateChain);
response =
rZAdmin.path("/vdc/keystore").put(ClientResponse.class,
rotateKeyAndCertParam);
expectedError =
"Invalid parameter private_key was 1,024bits but minimum is 2,048bits";
assertExpectedError(response, 400, ServiceCode.API_PARAMETER_INVALID_RANGE,
expectedError);
}
/**
* @param chain
* @return
*/
private String removeNewLines(String chain) {
return chain.replaceAll("\n", "").replaceAll("\r", "");
}
/**
* UserInfo
*
* @throws Exception
*/
private void userInfoTests() throws Exception {
UserInfo info = rSys.path("/user/whoami").get(UserInfo.class);
Assert.assertEquals(SYSADMIN, info.getCommonName());
Assert.assertEquals(4, info.getVdcRoles().size()); // no tenant role since 2.0
// check the root user's default vdc roles.
userInfoCheckRoles(rSys, new ArrayList<String>(Arrays.asList("SECURITY_ADMIN", "SYSTEM_ADMIN",
"SYSTEM_MONITOR", "SYSTEM_AUDITOR")));
info = rZAdmin.path("/user/whoami").get(UserInfo.class);
Assert.assertEquals(ZONEADMIN, info.getCommonName());
Assert.assertEquals(0, info.getVdcRoles().size());
}
/**
* Checks if the user passed in has all the roles in the provided roles list using the whoami api.
*
* @throws Exception
*/
private void userInfoCheckRoles(BalancedWebResource user, List<String> roles) throws Exception {
UserInfo info = user.path("/user/whoami").get(UserInfo.class);
// since 2.0, tenant role in home tenant roles.
List<String> allRoles = new ArrayList<>();
allRoles.addAll(info.getHomeTenantRoles());
allRoles.addAll(info.getVdcRoles());
Assert.assertTrue(allRoles.containsAll(roles));
}
private void adConfigTests() throws Exception {
addBadADConfig();
adConfigListTests();
authProvidersConnectivityTests();
}
/**
* 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");
values1.add("two"); // Duplicate one, so should be removed in the expected list.
values1.add("three"); // Duplicate one, so should be removed in the expected list.
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");
values2.add("two"); // Duplicate one, so should be removed in the expected list.
values2.add("three"); // Duplicate one, so should be removed in the expected list.
values2.add("five"); // One additional value that is not there in value1. So, not a duplicate.
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);
UserMappingAttributeParam userMappingAttributeParam2 = new UserMappingAttributeParam(key1, values1); // Duplicate Attribute.
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);
attributeList.add(userMappingAttributeParam2); // Duplicate one, so should be removed in the expected list.
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);
additionalAttributeList.add(userMappingAttributeParam2); // Duplicate one, so should be removed in the expected list.
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);
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); // Duplicate one, so should be removed in the expected list.
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);
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); // Duplicate one, so should be removed in the expected list.
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);
dupUserMappings.add(dupTenantMapping2); // Adding the same userMapping here, just make sure the duplicate will be removed..
// 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());
// Since, both the UserMapping in the list is same, doing the validation in the loop with
// 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());
}
/**
* test for API /vdc/prepare-vdc, which will remove all root's tenant roles and project ownerships
*
* before calling the API, prepare root to be:
* 1. Provider Tenant's tenant admin
* 2. owner of a project of Provider Tenant
* 3. Tenant Admin of a subtenant
* 4. owner of a project from subtenant
*/
public void prepareVdcTest() throws Exception {
ClientResponse resp = null;
BalancedWebResource rootUser = createHttpsClient(SYSADMIN, SYSADMIN_PASS_WORD, baseUrls);
UserInfo info = rootUser.path("/user/whoami").get(UserInfo.class);
String rootTenantId = info.getTenant();
String rootToken = (String) _savedTokens.get(SYSADMIN);
BalancedWebResource superSanity = createHttpsClient(SUPERUSER, AD_PASS_WORD, baseUrls);
superSanity.path("/tenant").get(TenantResponse.class);
String superSanityToken = (String) _savedTokens.get(SUPERUSER);
// prepare tenant roles and project ownership
// also assign TenantAdmin to superuser, so it can be used to verify afterwards
boolean bRootHasProviderTenantAdmin = true;
if (info.getHomeTenantRoles().isEmpty()) {
bRootHasProviderTenantAdmin = false;
resp = assignTenantRole(rootTenantId, SYSADMIN, "TENANT_ADMIN");
Assert.assertEquals(200, resp.getStatus());
resp = assignTenantRole(rootTenantId, SUPERUSER, "TENANT_ADMIN");
Assert.assertEquals(200, resp.getStatus());
}
// create a project of Provider Tenant by root, root will be its owner.
ProjectParam paramProj = new ProjectParam("project_" + new Random().nextInt());
ProjectEntry rootProject1 = rootUser.path(String.format(_projectsUrlFormat, rootTenantId.toString()))
.header(AUTH_TOKEN_HEADER, rootToken)
.post(ProjectEntry.class, paramProj);
Assert.assertTrue(rootProject1.name.equals(paramProj.getName()));
Assert.assertTrue(rootProject1.id != null);
// create a subtenant by root, root will be its TenantAdmin
String tenantLabel = "tenant_" + new Random().nextInt();
TenantOrgRestRep subtenant = createTenant(tenantLabel, "sanity.local", "key", tenantLabel);
resp = assignTenantRole(subtenant.getId().toString(), SUPERUSER, "TENANT_ADMIN");
Assert.assertEquals(200, resp.getStatus());
// create a project under the subtenant created above, root will be its owner
paramProj = new ProjectParam("project_" + new Random().nextInt());
ProjectEntry rootProject2 = rootUser.path(String.format(_projectsUrlFormat, subtenant.getId().toString()))
.header(AUTH_TOKEN_HEADER, rootToken)
.post(ProjectEntry.class, paramProj);
Assert.assertTrue(rootProject2.name.equals(paramProj.getName()));
Assert.assertTrue(rootProject2.id != null);
// call /vdc/prepare-vdc
ClientResponse response = rootUser.path("/vdc/prepare-vdc")
.header(AUTH_TOKEN_HEADER, rootToken)
.post(ClientResponse.class);
Assert.assertEquals(200, response.getStatus());
// verify root's tenant roles and project ownership be removed
resp = rootUser.path("/user/whoami").get(ClientResponse.class);
String output = resp.getEntity(String.class);
Assert.assertFalse(output.contains("TENANT_ADMIN"));
resp = superSanity.path(String.format(_projectUrl, rootProject1.id.toString())).get(ClientResponse.class);
output = resp.getEntity(String.class);
Assert.assertFalse(output.contains(SYSADMIN));
resp = superSanity.path(String.format(_projectUrl, rootProject2.id.toString())).get(ClientResponse.class);
output = resp.getEntity(String.class);
Assert.assertFalse(output.contains(SYSADMIN));
// test done, restore root's tenant role and remove the project
if (bRootHasProviderTenantAdmin) {
assignTenantRole(rootTenantId, SYSADMIN, "TENANT_ADMIN");
}
if (rootProject1 != null) {
superSanity.path(String.format(_projectUrl + "/deactivate", rootProject1.id.toString()))
.header(AUTH_TOKEN_HEADER, superSanityToken)
.post(ClientResponse.class);
}
if (rootProject2 != null) {
superSanity.path(String.format(_projectUrl + "/deactivate", rootProject2.id.toString()))
.header(AUTH_TOKEN_HEADER, superSanityToken)
.post(ClientResponse.class);
}
if (subtenant != null) {
superSanity.path("/tenants/" + subtenant.getId() + "/deactivate")
.header(AUTH_TOKEN_HEADER, superSanityToken)
.post();
}
}
private TenantOrgRestRep createTenant(String label, String domain, String attrKey, String attrValue) throws Exception {
BalancedWebResource rootUser = createHttpsClient(SYSADMIN, SYSADMIN_PASS_WORD, baseUrls);
UserInfo info = rootUser.path("/user/whoami").get(UserInfo.class);
String rootTenantId = info.getTenant();
String rootToken = (String) _savedTokens.get(SYSADMIN);
TenantCreateParam tenantParam = new TenantCreateParam();
tenantParam.setLabel(label);
tenantParam.setDescription("description for " + label);
tenantParam.setUserMappings(new ArrayList<UserMappingParam>());
UserMappingParam tenant2UserMapping = new UserMappingParam();
tenant2UserMapping.setDomain(domain);
UserMappingAttributeParam tenant2Attr = new UserMappingAttributeParam();
tenant2Attr.setKey(attrKey);
tenant2Attr.setValues(Collections.singletonList(attrValue));
tenant2UserMapping.setAttributes(Collections.singletonList(tenant2Attr));
tenantParam.getUserMappings().add(tenant2UserMapping);
String subtenant_url = "/tenants/" + rootTenantId + "/subtenants";
TenantOrgRestRep tenantOrg = rootUser.path(subtenant_url)
.header(AUTH_TOKEN_HEADER, rootToken)
.post(TenantOrgRestRep.class, tenantParam);
return tenantOrg;
}
private ClientResponse assignTenantRole(String tenantId, String subjectId, String role) throws Exception {
return changeTenantRoles(tenantId, subjectId, Arrays.asList(role), new ArrayList<String>());
}
private ClientResponse removeTenantRole(String tenantId, String subjectId, String role) throws Exception {
return changeTenantRoles(tenantId, subjectId, new ArrayList<String>(), Arrays.asList(role));
}
private ClientResponse changeTenantRoles(String tenantId, String subjectId, List<String> addRoles, List<String> removeRoles)
throws Exception {
BalancedWebResource rootUser = createHttpsClient(SYSADMIN, SYSADMIN_PASS_WORD, baseUrls);
rootUser.path("/user/whoami").get(UserInfo.class);
String rootToken = (String) _savedTokens.get(SYSADMIN);
RoleAssignmentEntry roleAssignmentEntry;
RoleAssignmentChanges roleAssignmentChanges = new RoleAssignmentChanges();
if (!addRoles.isEmpty()) {
List<RoleAssignmentEntry> add = new ArrayList<>();
roleAssignmentEntry = new RoleAssignmentEntry();
roleAssignmentEntry.setSubjectId(subjectId);
roleAssignmentEntry.setRoles(addRoles);
add.add(roleAssignmentEntry);
roleAssignmentChanges.setAdd(add);
}
if (!removeRoles.isEmpty()) {
List<RoleAssignmentEntry> remove = new ArrayList<>();
roleAssignmentEntry = new RoleAssignmentEntry();
roleAssignmentEntry.setSubjectId(subjectId);
roleAssignmentEntry.setRoles(removeRoles);
remove.add(roleAssignmentEntry);
roleAssignmentChanges.setRemove(remove);
}
return rootUser.path("/tenants/" + tenantId + "/role-assignments")
.header(AUTH_TOKEN_HEADER, rootToken)
.put(ClientResponse.class, roleAssignmentChanges);
}
/**
* test when creating Tenant, group's correct domain name can be trimmed automatically.
*/
public void groupSuffixTest() throws Exception {
String groupName = "fredTestGroup";
String domain = "sanity.local";
String groupNameWithDomain = groupName + "@sanity.local";
ClientResponse response = createTenant("subTenantForGroupSuffixTest_"
+ new Random().nextInt(), domain, groupName);
Assert.assertEquals(200, response.getStatus());
response = createTenant("subTenantForGroupSuffixTest_"
+ new Random().nextInt(), domain, groupNameWithDomain);
Assert.assertEquals(400, response.getStatus());
String output = response.getEntity(String.class);
Assert.assertTrue(output.contains("duplicated"));
}
private ClientResponse createTenant(String label, String domain, String groupName) throws Exception {
BalancedWebResource rootUser = createHttpsClient(SYSADMIN, SYSADMIN_PASS_WORD, baseUrls);
UserInfo info = rootUser.path("/user/whoami").get(UserInfo.class);
String rootTenantId = info.getTenant();
String rootToken = (String) _savedTokens.get(SYSADMIN);
TenantCreateParam tenantParam = new TenantCreateParam();
tenantParam.setLabel(label);
tenantParam.setDescription("description for " + label);
tenantParam.setUserMappings(new ArrayList<UserMappingParam>());
UserMappingParam tenant2UserMapping = new UserMappingParam();
tenant2UserMapping.setDomain(domain);
tenant2UserMapping.setGroups(new ArrayList<String>(Arrays.asList(groupName)));
tenantParam.getUserMappings().add(tenant2UserMapping);
String subtenant_url = "/tenants/" + rootTenantId + "/subtenants";
ClientResponse response = rootUser.path(subtenant_url)
.header(AUTH_TOKEN_HEADER, rootToken)
.post(ClientResponse.class, tenantParam);
return response;
}
/**
* test tenantCreation will fail, if the authn provider is disabled
*
* @throws Exception
*/
public void disabledAuthnProviderTest() throws Exception {
// create a disabled authn provider
String domain = "secqe.com";
AuthnCreateParam param = new AuthnCreateParam();
param.setLabel("secqe.com");
param.setDescription("ad apitest disabled auth provider");
param.setDisable(true);
param.getDomains().add(domain);
param.setGroupAttribute("CN");
param.setManagerDn("CN=Administrator,CN=Users,DC=secqe,DC=com");
param.setManagerPassword(AD_PASS_WORD);
param.setSearchBase("CN=Users,DC=secqe,DC=com");
param.setSearchFilter("userPrincipalName=%u");
param.setServerUrls(new HashSet<String>());
param.getServerUrls().add("ldap:\\" + AD_SERVER2_IP);
param.setMode("ad");
AuthnProviderRestRep resp = rSys.path("/vdc/admin/authnproviders").post(AuthnProviderRestRep.class, param);
Assert.assertNotNull(resp.getId());
// create tenant against the disabled authn provider, should fail
String groupName = "e2egroup";
ClientResponse response = createTenant("disabled_tenant" + new Random().nextInt(), domain, groupName);
Assert.assertEquals(400, response.getStatus());
// enable the authn provider
AuthnUpdateParam updateParam = new AuthnUpdateParam();
updateParam.setDisable(false);
response = rSys.path("/vdc/admin/authnproviders/" + resp.getId()).put(ClientResponse.class, updateParam);
Assert.assertEquals(200, response.getStatus());
// create the tenant again, should success
response = createTenant("disabled_tenant" + new Random().nextInt(), domain, groupName);
Assert.assertEquals(200, response.getStatus());
}
// quick test to see that one can create and delete
// a provider with no errors if there are no tenants associated
public void loneAuthnProviderDeleteTest() throws Exception {
AuthnCreateParam param = new AuthnCreateParam();
param.setLabel("ldaps apitest config");
param.setDescription("ldaps configuration created by ApiTest.java");
param.setDisable(false);
param.getDomains().add("secureldap.com");
param.getDomains().add("someotherdomain2.com");
param.setManagerDn("CN=Manager,DC=root,DC=com");
param.setManagerPassword("secret");
param.setSearchBase("OU=People,DC=root,DC=com");
param.setSearchFilter("mail=%u");
param.setServerUrls(new HashSet<String>());
param.getServerUrls().add("ldaps:\\" + LDAP_SERVER1_IP);
param.setMode("ldap");
AuthnProviderRestRep resp = rSys.path("/vdc/admin/authnproviders").post(AuthnProviderRestRep.class,
param);
Assert.assertNotNull(resp);
// update by removing a domain should work because neither are used by any tenants
AuthnUpdateParam updateParam = new AuthnUpdateParam();
updateParam.getDomainChanges().getRemove().add("someotherdomain2.com");
ClientResponse response = rSys.path("/vdc/admin/authnproviders/" + resp.getId()).put(ClientResponse.class, updateParam);
Assert.assertEquals(200, response.getStatus());
// disable, delete, should work, because there are no tenants associated
// with it.
// disable it
updateParam = new AuthnUpdateParam();
updateParam.setDisable(true);
response = rSys.path("/vdc/admin/authnproviders/" + resp.getId()).put(ClientResponse.class, updateParam);
Assert.assertEquals(200, response.getStatus());
// delete it
response = rSys.path("/vdc/admin/authnproviders/" + resp.getId()).delete(ClientResponse.class);
Assert.assertEquals(200, response.getStatus());
}
// quick test to see if the added domain of AP server is converted to all lowercase
public void authnProviderAddDomainTest() throws Exception {
AuthnCreateParam param = new AuthnCreateParam();
param.setLabel("domain test AP server");
param.setDescription("AP server configuration created by ApiTest.java");
param.setDisable(false);
param.getDomains().add("asd.locl");
param.setManagerDn("CN=Manager,DC=root,DC=com");
param.setManagerPassword("secret");
param.setSearchBase("OU=People,DC=root,DC=com");
param.setSearchFilter("mail=%u");
param.setServerUrls(new HashSet<String>());
param.getServerUrls().add("ldaps:\\" + LDAP_SERVER1_IP);
param.setMode("ldap");
AuthnProviderRestRep resp = rSys.path("/vdc/admin/authnproviders").post(AuthnProviderRestRep.class,
param);
Assert.assertNotNull(resp);
// update the AP server by adding a domain name with mixed case
AuthnUpdateParam updateParam = new AuthnUpdateParam();
Set<String> toAddSet = new HashSet<String>();
toAddSet.add("sAnItY2.local");
updateParam.getDomainChanges().setAdd(toAddSet);
ClientResponse response = rSys.path("/vdc/admin/authnproviders/" + resp.getId()).put(ClientResponse.class, updateParam);
Assert.assertEquals(200, response.getStatus());
// verify the added domain name is converted to lower case
response = rSys.path("/vdc/admin/authnproviders/" + resp.getId()).get(ClientResponse.class);
AuthnProviderRestRep responseRestRep = response.getEntity(AuthnProviderRestRep.class);
Assert.assertFalse(responseRestRep.getDomains().contains("sAnItY2.local"));
Assert.assertTrue(responseRestRep.getDomains().contains("sanity2.local"));
// use the added domain to create a subtenant, verify it's successful
TenantCreateParam tenantParam = new TenantCreateParam();
tenantParam.setLabel("sub2");
tenantParam.setDescription("My sub tenant 2");
UserMappingParam tenantMapping1 = new UserMappingParam();
tenantMapping1.setDomain("sAnItY2.local");
UserMappingAttributeParam attriParam = new UserMappingAttributeParam("department", Collections.singletonList("ASD"));
tenantMapping1.getAttributes().add(attriParam);
tenantParam.getUserMappings().add(tenantMapping1);
response = rSys.path("/tenants/" + rootTenantId + "/subtenants").post(ClientResponse.class, tenantParam);
Assert.assertEquals(200, response.getStatus());
}
/**
* projects api tests
*/
public void projectTests() {
ProjectParam paramProj = new ProjectParam("aclstestproject1");
ProjectEntry project1 = rSTAdminGr1.path(String.format(_projectsUrlFormat, subtenant1Id.toString()))
.post(ProjectEntry.class, paramProj);
Assert.assertTrue(project1.name.equals(paramProj.getName()));
Assert.assertTrue(project1.id != null);
expectedProjListResults.get("st1").add(new ProjectEntry(project1));
paramProj.setName("aclstestproject2");
ProjectEntry project2 = rSTAdmin1.path(String.format(_projectsUrlFormat, subtenant1Id.toString()))
.post(ProjectEntry.class, paramProj);
Assert.assertTrue(project2.name.equals(paramProj.getName()));
Assert.assertTrue(project2.id != null);
expectedProjListResults.get("st1").add(new ProjectEntry(project2));
ACLAssignments read_assignments = rSTAdminGr1
.path(String.format(_projectAclUrl, project1.id.toString())).get(ACLAssignments.class);
Assert.assertTrue(read_assignments.getAssignments().isEmpty());
ClientResponse resp = rSTAdmin2
.path(String.format(_projectAclUrl, project1.id.toString())).get(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
// name duplicate tests for PUTs.
// add temp project 1
ProjectParam tempProject = new ProjectParam("temproject");
ProjectEntry projectTemp = rSTAdminGr1.path(String.format(_projectsUrlFormat, subtenant1Id.toString()))
.post(ProjectEntry.class, tempProject);
Assert.assertTrue(projectTemp.id != null);
expectedProjListResults.get("st1").add(new ProjectEntry(projectTemp));
// add temp project 2
ProjectParam tempProject2 = new ProjectParam("temproject2");
ProjectEntry projectTemp2 = rSTAdminGr1.path(String.format(_projectsUrlFormat, subtenant1Id.toString()))
.post(ProjectEntry.class, tempProject2);
Assert.assertTrue(projectTemp2.id != null);
expectedProjListResults.get("st1").add(new ProjectEntry(projectTemp2));
// attempt to modify the first project with the same name as itself. should be fine.
ProjectUpdateParam projectUpdate1 = new ProjectUpdateParam(tempProject.getName());
resp = rSTAdminGr1.path(String.format(_projectUrl, projectTemp.id.toString()))
.put(ClientResponse.class, projectUpdate1);
Assert.assertEquals(200, resp.getStatus());
// attempt to modify the first project with the same name as itself. upper case. should be fine.
ProjectUpdateParam projectUpdate1b = new ProjectUpdateParam(tempProject.getName().toUpperCase());
resp = rSTAdminGr1.path(String.format(_projectUrl, projectTemp.id.toString()))
.put(ClientResponse.class, projectUpdate1b);
Assert.assertEquals(200, resp.getStatus());
// put it back how it was
ProjectUpdateParam projectUpdate1c = new ProjectUpdateParam(tempProject.getName());
resp = rSTAdminGr1.path(String.format(_projectUrl, projectTemp.id.toString()))
.put(ClientResponse.class, projectUpdate1c);
Assert.assertEquals(200, resp.getStatus());
// attempt to modify the first project with the name of the second one. Should fail.
ProjectUpdateParam projectUpdate2 = new ProjectUpdateParam(tempProject2.getName());
resp = rSTAdminGr1.path(String.format(_projectUrl, projectTemp.id.toString()))
.put(ClientResponse.class, projectUpdate2);
Assert.assertEquals(400, resp.getStatus());
// attempt to modify the first project with the name of the second one, but upper case.
// This should fail also, as the names are case insensitive. ( proj1 == pRoJ1 )
ProjectUpdateParam projectUpdate3 = new ProjectUpdateParam(tempProject2.getName().toUpperCase());
resp = rSTAdminGr1.path(String.format(_projectUrl, projectTemp.id.toString()))
.put(ClientResponse.class, projectUpdate3);
Assert.assertEquals(400, resp.getStatus());
ACLAssignmentChanges changes = new ACLAssignmentChanges();
ACLEntry entry1 = new ACLEntry();
entry1.setSubjectId(SUBTENANT1_READER);
entry1.setAces(new ArrayList<String>());
entry1.getAces().add("backup");
entry1.getAces().add("all");
ACLEntry entry2 = new ACLEntry();
entry2.setSubjectId(SUBTENANT1_USER);
entry2.setAces(new ArrayList<String>());
entry2.getAces().add("all");
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry1);
changes.getAdd().add(entry2);
resp = rSTAdminGr1
.path(String.format(_projectAclUrl, project1.id.toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
resp = rProjRead
.path(String.format(_projectAclUrl, project1.id.toString())).get(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
resp = rProjRead
.path(String.format(_projectUrl, project1.id.toString())).get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
read_assignments = rSTAdminGr1
.path(String.format(_projectAclUrl, project1.id.toString())).get(ACLAssignments.class);
Assert.assertTrue(checkEqualsAcls(changes.getAdd(), read_assignments.getAssignments()));
// try to add more than 100 acls - this should fail (quickly, because
// it's not validating)
ACLAssignments assignements = rSTAdminGr1.path(
String.format(_projectAclUrl, project1.id.toString())).get(
ACLAssignments.class);
ACLAssignmentChanges tooMuchChanges = new ACLAssignmentChanges();
tooMuchChanges.setAdd(new ArrayList<ACLEntry>());
for (int i = 0; i < _maxRoleAclEntries + 1 - assignements.getAssignments().size() - 1; i++) {
ACLEntry invalidEntry = new ACLEntry();
invalidEntry.setAces(new ArrayList<String>());
invalidEntry.getAces().add("backup");
invalidEntry.setSubjectId("invalidUser" + i + "@invalidDomain.com");
tooMuchChanges.getAdd().add(invalidEntry);
}
resp = rSTAdminGr1.path(String.format(_projectAclUrl, project1.id.toString()))
.put(ClientResponse.class, tooMuchChanges);
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);
// full update
entry1.getAces().remove("backup");
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry1);
changes.setRemove(new ArrayList<ACLEntry>());
changes.getRemove().addAll(read_assignments.getAssignments());
resp = rSTAdminGr1
.path(String.format(_projectAclUrl, project1.id.toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
read_assignments = rSTAdmin1
.path(String.format(_projectAclUrl, project1.id.toString())).get(ACLAssignments.class);
Assert.assertTrue(checkEqualsAcls(changes.getAdd(), read_assignments.getAssignments()));
resp = rProjRead
.path(String.format(_projectUrl, project1.id.toString())).get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
// partial update
entry1 = new ACLEntry();
entry1.setSubjectId(SUBTENANT1_READER);
entry1.setAces(new ArrayList<String>());
entry1.getAces().add("all");
entry2 = new ACLEntry();
entry2.setSubjectId(SUBTENANT1_READER);
entry2.setAces(new ArrayList<String>());
entry2.getAces().add("backup");
ACLEntry entry3 = new ACLEntry();
entry3.setGroup(SUBTENANT1_USERS_GROUP);
entry3.setAces(new ArrayList<String>());
entry3.getAces().add("all");
changes = new ACLAssignmentChanges();
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry2);
changes.getAdd().add(entry3);
changes.setRemove(new ArrayList<ACLEntry>());
changes.getRemove().add(entry1);
resp = rSTAdmin1
.path(String.format(_projectAclUrl, project1.id.toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
read_assignments = rSTAdminGr1
.path(String.format(_projectAclUrl, project1.id.toString())).get(ACLAssignments.class);
ACLAssignments assignments = new ACLAssignments();
assignments.getAssignments().add(entry2);
entry3.setGroup(SUBTENANT1_USERS_GROUP);
assignments.getAssignments().add(entry3);
Assert.assertTrue(checkEqualsAcls(assignments.getAssignments(), read_assignments.getAssignments()));
resp = rProjRead
.path(String.format(_projectUrl, project1.id.toString())).get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
resp = rProjUserGr
.path(String.format(_projectUrl, project1.id.toString())).get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
// Check that a subtenant2 user who happens to be in the
// subtenant1 users group does not have access to the project
// in subtenant1
resp = rSTAdminGr2
.path(String.format(_projectUrl, project1.id.toString())).get(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
changes = new ACLAssignmentChanges();
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry3);
changes.setRemove(new ArrayList<ACLEntry>());
changes.getRemove().addAll(read_assignments.getAssignments());
resp = rSTAdmin1
.path(String.format(_projectAclUrl, project2.id.toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
read_assignments = rSys
.path(String.format(_projectAclUrl, project2.id.toString())).get(ACLAssignments.class);
Assert.assertTrue(checkEqualsAcls(changes.getAdd(), read_assignments.getAssignments()));
// negatives - assign invalid acl
ACLEntry entryBad = new ACLEntry();
entryBad.setSubjectId("bad");
entryBad.setAces(new ArrayList<String>());
entryBad.getAces().add("bad");
changes = new ACLAssignmentChanges();
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entryBad);
entry1 = new ACLEntry();
entry1.setSubjectId(SUBTENANT1_READER);
entry1.setAces(new ArrayList<String>());
entry1.getAces().add("backup");
entry1.getAces().add("all");
changes.getAdd().add(entry1);
resp = rSTAdminGr1
.path(String.format(_projectAclUrl, project1.id.toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(400, resp.getStatus());
entryBad.getAces().clear();
entryBad.getAces().add("own");
resp = rSTAdminGr1
.path(String.format(_projectAclUrl, project1.id.toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(400, resp.getStatus());
entryBad.getAces().clear();
entryBad.getAces().add("any");
resp = rSTAdminGr1
.path(String.format(_projectAclUrl, project1.id.toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(400, resp.getStatus());
// batch acl assignment test - 2 users and 2 groups added at the same time
ACLAssignments assignmentsToHaveWhenImDone =
rSTAdmin1.path(String.format(_projectAclUrl, project1.id.toString()))
.get(ACLAssignments.class);
changes = new ACLAssignmentChanges();
changes.setRemove(assignmentsToHaveWhenImDone.getAssignments());
entry2 = new ACLEntry();
entry2.setSubjectId(SUBTENANT1_USER);
entry2.setAces(new ArrayList<String>());
entry2.getAces().add("all");
entry3 = new ACLEntry();
entry3.setGroup(SUBTENANT1_USERS_GROUP);
entry3.setAces(new ArrayList<String>());
entry3.getAces().add("backup");
ACLEntry entry4 = new ACLEntry();
entry4.setGroup(SUBTENANT1_ADMINS_GROUP);
entry4.setAces(new ArrayList<String>());
entry4.getAces().add("all");
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry1);
changes.getAdd().add(entry2);
changes.getAdd().add(entry3);
changes.getAdd().add(entry4);
resp =
rSTAdmin1.path(String.format(_projectAclUrl, project1.id.toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
read_assignments =
rSTAdminGr1.path(String.format(_projectAclUrl, project1.id.toString()))
.get(ACLAssignments.class);
Assert.assertTrue(checkEqualsAcls(changes.getAdd(),
read_assignments.getAssignments()));
// reverting all the batch acl assignment changes back to how it was
changes =
new ACLAssignmentChanges(assignmentsToHaveWhenImDone.getAssignments(),
read_assignments.getAssignments());
resp =
rSTAdmin1.path(String.format(_projectAclUrl, project1.id.toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
// test lists
ProjectList projList = rSTAdmin1.path(String.format(_projectsUrlFormat, subtenant1Id.toString()))
.get(ProjectList.class);
Assert.assertTrue(checkEqualsList(projList._projects, expectedProjListResults.get("st1")));
// read - only one project
//
projList = rProjRead.path(String.format(_projectsUrlFormat, subtenant1Id.toString()))
.get(ProjectList.class);
Assert.assertEquals(1, projList._projects.size());
Assert.assertEquals(project1.id, projList._projects.get(0).id);
Assert.assertEquals(project1.name, projList._projects.get(0).name);
// use set on both, so we should see both
projList = rProjUserGr.path(String.format(_projectsUrlFormat, subtenant1Id.toString()))
.get(ProjectList.class);
ArrayList<ProjectEntry> expected = new ArrayList<ProjectEntry>();
expected.add(new ProjectEntry(project1));
expected.add(new ProjectEntry(project2));
Assert.assertTrue(checkEqualsList(projList._projects, expected));
resp = rProjUserGr.path(String.format(_projectUrl + "/deactivate", project2.id.toString())).post(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
resp = rProjRead.path(String.format(_projectUrl + "/deactivate", project1.id.toString())).post(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
// project update - change owner
ProjectUpdateParam project1Updated = new ProjectUpdateParam();
project1Updated.setOwner(SUBTENANT1_USER);
resp = rSTAdmin1.path(String.format(_projectUrl, project1.id.toString()))
.put(ClientResponse.class, project1Updated);
Assert.assertEquals(200, resp.getStatus());
// project update - change owner to a user that is not part of the project's tenant. Should fail with 400.
ProjectUpdateParam project1UpdatedBadOwner = new ProjectUpdateParam();
project1UpdatedBadOwner.setOwner(SUBTENANT2_ADMIN);
resp = rSTAdmin1.path(String.format(_projectUrl, project1.id.toString()))
.put(ClientResponse.class, project1UpdatedBadOwner);
Assert.assertEquals(403, resp.getStatus());
resp = rProjUserGr.path(String.format(_projectUrl + "/deactivate", project1.id.toString())).post(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
// Test bad parameter is returned if the name in the project is not specified
paramProj = new ProjectParam(null);
resp = rTAdmin.path(String.format(_projectsUrlFormat, rootTenantId.toString()))
.post(ClientResponse.class, paramProj);
Assert.assertEquals(400, resp.getStatus());
// URL with bad project id
resp = rSTAdmin1.path("/projects/null.xml").get(ClientResponse.class);
Assert.assertEquals(404, resp.getStatus());
// Test entity not found is returned if we try to retrieve a project that does not exist
String getProjectUrl = "/tenants/%s/projects/%s";
resp = rTAdmin.path(
String.format(getProjectUrl, rootTenantId.toString(), "urn:storageos:Project:815b507c-26eb-4124-bc96-9d0400a16596:"))
.get(ClientResponse.class);
Assert.assertEquals(404, resp.getStatus());
// Tests for duplicate name checks for projects
paramProj = new ProjectParam("root project1");
resp = rTAdmin.path(String.format(_projectsUrlFormat, rootTenantId.toString()))
.post(ClientResponse.class, paramProj);
Assert.assertEquals(400, resp.getStatus());
paramProj = new ProjectParam("subtenant project for name check");
resp = rSTAdmin1.path(String.format(_projectsUrlFormat, subtenant1Id.toString()))
.post(ClientResponse.class, paramProj);
Assert.assertEquals(200, resp.getStatus());
resp = rSTAdmin1.path(String.format(_projectsUrlFormat, subtenant1Id.toString()))
.post(ClientResponse.class, paramProj);
Assert.assertEquals(400, resp.getStatus());
resp = rSTAdmin2.path(String.format(_projectsUrlFormat, subtenant2Id.toString()))
.post(ClientResponse.class, paramProj);
Assert.assertEquals(200, resp.getStatus());
resp = rSTAdmin2.path(String.format(_projectsUrlFormat, subtenant2Id.toString()))
.post(ClientResponse.class, paramProj);
Assert.assertEquals(400, resp.getStatus());
}
/**
* Cos and VirtualArray acls tests
*/
public void usageAclTests() {
TenantResponse tenantResp = rSys.path("/tenant").get(TenantResponse.class);
rootTenantId = tenantResp.getTenant();
String subtenant_url = "/tenants/" + rootTenantId.toString() + "/subtenants";
TenantOrgList list = rSys.path(subtenant_url).get(TenantOrgList.class);
Assert.assertEquals(4, list.getSubtenants().size());
NamedRelatedResourceRep st1 = list.getSubtenants().get(0);
NamedRelatedResourceRep st2 = list.getSubtenants().get(1);
// create neighborhoods for test
VirtualArrayCreateParam neighborhoodParam = new VirtualArrayCreateParam();
neighborhoodParam.setLabel("n1");
VirtualArrayRestRep n1 = rSys.path("/vdc/varrays").post(VirtualArrayRestRep.class, neighborhoodParam);
Assert.assertNotNull(n1.getId());
neighborhoodParam.setLabel("n2");
VirtualArrayRestRep n2 = rSys.path("/vdc/varrays").post(VirtualArrayRestRep.class, neighborhoodParam);
Assert.assertNotNull(n2.getId());
// test open to all by default
ClientResponse resp = rSTAdmin1.path("/vdc/varrays/" + n1.getId().toString()).get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
resp = rSTAdmin2.path("/vdc/varrays/" + n1.getId().toString()).get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
// set usage acl for st1 on n1
String neighborAclUrl = "/vdc/varrays/%s/acl";
ACLAssignmentChanges changes = new ACLAssignmentChanges();
ACLEntry entry1 = new ACLEntry();
entry1.setTenant(st1.getId().toString());
entry1.setAces(new ArrayList<String>());
entry1.getAces().add("USE");
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry1);
resp = rSys.path(String.format(neighborAclUrl, n1.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
VirtualArrayRestRep nRead = rSTAdmin1.path("/vdc/varrays/" + n1.getId().toString()).get(VirtualArrayRestRep.class);
Assert.assertEquals(nRead.getId(), n1.getId());
Assert.assertEquals(nRead.getName(), n1.getName());
resp = rSTAdmin2.path("/vdc/varrays/" + n1.getId().toString()).get(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
// set usage acl for st2 on n2
changes = new ACLAssignmentChanges();
ACLEntry entry2 = new ACLEntry();
entry2.setTenant(st2.getId().toString());
entry2.setAces(new ArrayList<String>());
entry2.getAces().add("USE");
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry2);
resp = rSys.path(String.format(neighborAclUrl, n2.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
nRead = rSTAdmin2.path("/vdc/varrays/" + n2.getId().toString()).get(VirtualArrayRestRep.class);
Assert.assertEquals(nRead.getId(), n2.getId());
Assert.assertEquals(nRead.getName(), n2.getName());
resp = rSTAdmin1.path("/vdc/varrays/" + n2.getId().toString()).get(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
// negative test - invalid tenant id
changes = new ACLAssignmentChanges();
entry2 = new ACLEntry();
entry2.setTenant("invalid");
entry2.setAces(new ArrayList<String>());
entry2.getAces().add("USE");
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry2);
resp = rSys.path(String.format(neighborAclUrl, n2.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(400, resp.getStatus());
// negative test - missing ace
changes = new ACLAssignmentChanges();
entry2 = new ACLEntry();
entry2.setTenant(st2.getId().toString());
entry2.setAces(new ArrayList<String>());
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry2);
resp = rSys.path(String.format(neighborAclUrl, n2.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(400, resp.getStatus());
// negative test - choice of tenant/group/subject_id (multiple present)
changes = new ACLAssignmentChanges();
entry2 = new ACLEntry();
entry2.setTenant(st2.getId().toString());
entry2.setGroup("TEST");
entry2.setAces(new ArrayList<String>());
entry2.getAces().add("USE");
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry2);
resp = rSys.path(String.format(neighborAclUrl, n2.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(400, resp.getStatus());
changes = new ACLAssignmentChanges();
entry2 = new ACLEntry();
entry2.setTenant(st2.getId().toString());
entry2.setSubjectId("TEST");
entry2.setAces(new ArrayList<String>());
entry2.getAces().add("USE");
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry2);
resp = rSys.path(String.format(neighborAclUrl, n2.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(400, resp.getStatus());
changes = new ACLAssignmentChanges();
entry2 = new ACLEntry();
entry2.setTenant(st2.getId().toString());
entry2.setGroup("TEST");
entry2.setSubjectId("TEST");
entry2.setAces(new ArrayList<String>());
entry2.getAces().add("USE");
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry2);
resp = rSys.path(String.format(neighborAclUrl, n2.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(400, resp.getStatus());
// list neighborhoods
VirtualArrayList nList = rSTAdminGr1.path("/vdc/varrays/")
.get(VirtualArrayList.class);
Assert.assertEquals(1, nList.getVirtualArrays().size());
Assert.assertEquals(n1.getId(), nList.getVirtualArrays().get(0).getId());
// newly created varray, accessible for all
neighborhoodParam = new VirtualArrayCreateParam();
neighborhoodParam.setLabel("n3");
VirtualArrayRestRep n3 = rSys.path("/vdc/varrays").post(VirtualArrayRestRep.class, neighborhoodParam);
Assert.assertNotNull(n3.getId());
nList = rSTAdminGr1.path("/vdc/varrays/")
.get(VirtualArrayList.class);
Assert.assertEquals(2, nList.getVirtualArrays().size());
Assert.assertTrue(nList.getVirtualArrays().get(0).getId().equals(n1.getId()) ||
nList.getVirtualArrays().get(1).getId().equals(n1.getId()));
Assert.assertTrue(nList.getVirtualArrays().get(0).getId().equals(n3.getId()) ||
nList.getVirtualArrays().get(1).getId().equals(n3.getId()));
// delete nh3
rSys.path("/vdc/varrays/" + n3.getId().toString() + "/deactivate").post();
// create vpool
BlockVirtualPoolParam paramCosBlock = new BlockVirtualPoolParam();
paramCosBlock.setName("foobar-block");
paramCosBlock.setDescription("foobar-block description");
paramCosBlock.setProtocols(new HashSet<String>());
paramCosBlock.getProtocols().add(StorageProtocol.Block.FC.name());
paramCosBlock.setMaxPaths(2);
paramCosBlock.setProvisionType("Thick");
BlockVirtualPoolRestRep cos1 = rZAdmin.path("/block/vpools").post(BlockVirtualPoolRestRep.class, paramCosBlock);
Assert.assertNotNull(cos1.getId());
resp = rZAdmin.path("/block/vpools").post(ClientResponse.class, paramCosBlock);
Assert.assertEquals(400, resp.getStatus());
resp = rSTAdmin1.path("/block/vpools/" + cos1.getId().toString()).get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
resp = rSTAdmin2.path("/block/vpools/" + cos1.getId().toString()).get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
// negative test: assign an empty storage pool
VirtualPoolPoolUpdateParam paramPoolUpdate = new VirtualPoolPoolUpdateParam();
paramPoolUpdate.setStoragePoolAssignmentChanges(new StoragePoolAssignmentChanges());
paramPoolUpdate.getStoragePoolAssignmentChanges().setAdd(new StoragePoolAssignments());
paramPoolUpdate.getStoragePoolAssignmentChanges().getAdd().setStoragePools(new HashSet<String>());
paramPoolUpdate.getStoragePoolAssignmentChanges().getAdd().getStoragePools().add("");
resp = rZAdmin.path("/block/vpools/" + cos1.getId().toString() + "/assign-matched-pools/")
.put(ClientResponse.class, paramPoolUpdate);
Assert.assertEquals(400, resp.getStatus());
// Set Cos acl
changes = new ACLAssignmentChanges();
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry1);
resp = rSys.path(String.format(_blockCosAclUrl, cos1.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
resp = rSys.path(String.format(_fileCosAclUrl, cos1.getId().toString()))
.get(ClientResponse.class);
Assert.assertEquals(400, resp.getStatus());
BlockVirtualPoolRestRep cRead = rSTAdmin1.path("/block/vpools/" + cos1.getId().toString()).get(BlockVirtualPoolRestRep.class);
Assert.assertEquals(cRead.getId(), cos1.getId());
Assert.assertEquals(cRead.getName(), cos1.getName());
resp = rSTAdmin2.path("/block/vpools/" + cos1.getId().toString()).get(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
// create second CoS
paramCosBlock = new BlockVirtualPoolParam();
paramCosBlock.setName("foobar-block2");
paramCosBlock.setDescription("foobar-block2 description");
paramCosBlock.setProtocols(new HashSet<String>());
paramCosBlock.getProtocols().add(StorageProtocol.Block.FC.name());
paramCosBlock.setProvisionType("Thick");
BlockVirtualPoolRestRep cos2 = rZAdminGr.path("/block/vpools").post(BlockVirtualPoolRestRep.class, paramCosBlock);
Assert.assertNotNull(cos2.getId());
// list vpool
VirtualPoolList cList = rSTAdminGr1.path("/block/vpools/")
.get(VirtualPoolList.class);
Assert.assertEquals(2, cList.getVirtualPool().size());
Assert.assertTrue(cList.getVirtualPool().get(0).getId().equals(cos1.getId()) ||
cList.getVirtualPool().get(1).getId().equals(cos1.getId()));
Assert.assertTrue(cList.getVirtualPool().get(0).getId().equals(cos2.getId()) ||
cList.getVirtualPool().get(1).getId().equals(cos2.getId()));
cList = rSTAdmin2.path("/block/vpools/")
.get(VirtualPoolList.class);
Assert.assertEquals(1, cList.getVirtualPool().size());
Assert.assertEquals(cos2.getId(), cList.getVirtualPool().get(0).getId());
// test limits
for (int i = 0; i < 100; i++) {
changes = new ACLAssignmentChanges();
entry1.setTenant(st2.getId().toString());
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry1);
resp = rSys.path(String.format(_blockCosAclUrl, cos2.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
}
changes = new ACLAssignmentChanges();
entry1.setTenant("tenant_invalid");
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry1);
resp = rSys.path(String.format(_blockCosAclUrl, cos2.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(400, resp.getStatus());
// testing tags
String cosTagUrl = "/block/vpools/%s/tags";
TagAssignment tags = new TagAssignment();
tags.setAdd(new StringSet());
tags.getAdd().add("testtag1");
resp = rSTAdmin2.path(String.format(cosTagUrl, cos1.getId())).put(ClientResponse.class, tags);
Assert.assertEquals(403, resp.getStatus());
Tags tagsResp = rSys.path(String.format(cosTagUrl, cos1.getId())).put(Tags.class, tags);
Assert.assertTrue(tagsResp.getTag().equals(tags.getAdd()));
tags.setRemove(new StringSet());
tags.getRemove().addAll(new HashSet(tags.getAdd()));
tags.getAdd().add("t"); // invalid tag, too short
resp = rSys.path(String.format(cosTagUrl, cos1.getId())).put(ClientResponse.class, tags);
Assert.assertEquals(400, resp.getStatus());
tags.getAdd().clear();
tags.getAdd().add("tag" + STR144); // invalid tag, too long
resp = rSys.path(String.format(cosTagUrl, cos1.getId())).put(ClientResponse.class, tags);
Assert.assertEquals(400, resp.getStatus());
tags.getAdd().clear();
tags.getAdd().add(" testtag "); // tags should be trimmed
tagsResp = rSys.path(String.format(cosTagUrl, cos1.getId())).put(Tags.class, tags);
Assert.assertTrue(tagsResp.getTag().equals(new StringSet() {
{
add("testtag");
}
}));
resp = rSTAdmin2.path(String.format(cosTagUrl, cos1.getId())).get(ClientResponse.class);
Assert.assertEquals(403, resp.getStatus());
resp = rSTAdmin1.path(String.format(cosTagUrl, cos1.getId())).get(ClientResponse.class);
Assert.assertEquals(200, resp.getStatus());
// Test bad parameter is returned if we add an invalid varray while creating the VirtualPool
FileVirtualPoolParam paramFileCos = new FileVirtualPoolParam();
paramFileCos.setName("Generic File VirtualPool");
paramFileCos.setProtocols(new HashSet<String>());
paramFileCos.getProtocols().add(StorageProtocol.File.NFS.name());
paramFileCos.getProtocols().add(StorageProtocol.File.CIFS.name());
paramFileCos.setVarrays(new HashSet<String>());
paramFileCos.getVarrays().add("IDontExist");
resp = rZAdmin.path("/file/vpools").post(ClientResponse.class, paramFileCos);
Assert.assertEquals(400, resp.getStatus());
// below is vpool restricted to tenant test
/*
* test setup:
* create a varray and vpool and associate the vpool with the varray
* restrict the vpool to the tenant
*/
String vaLabel = "va-testTenantRestrictAccess-" + Calendar.getInstance().getTime().getTime();
String vpLabel = "vp-testTenantRestrictAccess-" + Calendar.getInstance().getTime().getTime();
// create a varray
VirtualArrayCreateParam vaParam = new VirtualArrayCreateParam();
vaParam.setLabel(vaLabel);
BlockSettings bs = new BlockSettings();
bs.setAutoSanZoning(true);
vaParam.setBlockSettings(bs);
VirtualArrayRestRep va1 = rSys.path("/vdc/varrays").post(VirtualArrayRestRep.class, vaParam);
// create a vpool associated with the varray
BlockVirtualPoolParam vpParam = new BlockVirtualPoolParam();
vpParam.setName(vpLabel);
vpParam.setDescription(vpLabel);
Set<String> vas = new HashSet<String>();
vas.add(va1.getId().toString());
vpParam.setVarrays(vas);
vpParam.setProvisionType("Thin");
Set<String> protos = new HashSet();
protos.add("FC");
vpParam.setProtocols(protos);
BlockVirtualPoolRestRep vp1 = rSys.path("/block/vpools").post(BlockVirtualPoolRestRep.class, vpParam);
// restrict the vpool to a tenant
ACLAssignmentChanges aclChange = new ACLAssignmentChanges();
List<ACLEntry> acls = new ArrayList<>();
ACLEntry acl = new ACLEntry();
acl.setTenant(subtenant2Id.toString());
acl.setAces(new ArrayList<String>(Arrays.asList("USE")));
acls.add(acl);
aclChange.setAdd(acls);
String uri = String.format("/block/vpools/%s/acl", vp1.getId());
ACLAssignments aclAssignments = rSys.path(uri).put(ACLAssignments.class, aclChange);
// test1: sysadmin can see vpool
// test2: sysmonitor can see vpool
String vpUri = String.format("/vdc/varrays/%s/vpools", va1.getId().toString());
VirtualPoolList vpoolList = rSys.path(vpUri).get(VirtualPoolList.class);
List<NamedRelatedVirtualPoolRep> vpools = vpoolList.getVirtualPool();
boolean foundVpool = false;
for (NamedRelatedVirtualPoolRep vpool : vpools) {
if (vpool.getId().equals(vp1.getId())) {
foundVpool = true;
_log.info("user root can see the vpool {}", vp1.getName());
}
}
Assert.assertTrue(foundVpool);
// test3: tenant user can see vpool
VirtualPoolList vpoolList2 = rST2User.path(vpUri).get(VirtualPoolList.class);
List<NamedRelatedVirtualPoolRep> vpools2 = vpoolList2.getVirtualPool();
foundVpool = false;
for (NamedRelatedVirtualPoolRep vpool : vpools2) {
if (vpool.getId().equals(vp1.getId())) {
foundVpool = true;
_log.info("user st2user can see the vpool {}", vp1.getName());
}
}
Assert.assertTrue(foundVpool);
}
private void zoneCosSetup() {
VirtualArrayList nList = rSTAdmin1.path("/vdc/varrays/")
.get(VirtualArrayList.class);
Assert.assertEquals(1, nList.getVirtualArrays().size());
_nh = nList.getVirtualArrays().get(0).getId();
_log.info("varray: " + _nh.toString());
NetworkCreate param = new NetworkCreate();
param.setTransportType("IP");
param.setLabel("iptz");
_iptzone = rZAdmin
.path(String.format("/vdc/varrays/%s/networks", _nh).toString())
.post(NetworkRestRep.class, param);
NetworkCreate fctzone = new NetworkCreate();
fctzone.setTransportType("FC");
fctzone.setLabel("fctz");
_fctzone = rZAdmin
.path(String.format("/vdc/varrays/%s/networks", _nh).toString())
.post(NetworkRestRep.class, fctzone);
FileVirtualPoolParam paramCosFile = new FileVirtualPoolParam();
paramCosFile.setName("isilon-file");
paramCosFile.setProtocols(new HashSet<String>());
paramCosFile.getProtocols().add(StorageProtocol.File.NFS.name());
_cosFile = rZAdmin.path("/file/vpools").post(FileVirtualPoolRestRep.class, paramCosFile);
BlockVirtualPoolParam paramCosBlock = new BlockVirtualPoolParam();
paramCosBlock.setName("vnx-block");
paramCosBlock.setProtocols(new HashSet<String>());
paramCosBlock.getProtocols().add(StorageProtocol.Block.FC.name());
paramCosBlock.setProvisionType("Thick");
paramCosBlock.setMaxPaths(2);
_cosBlock = rZAdminGr.path("/block/vpools").post(BlockVirtualPoolRestRep.class, paramCosBlock);
ACLAssignmentChanges changes = new ACLAssignmentChanges();
changes.setAdd(new ArrayList<ACLEntry>());
ACLEntry entry1 = new ACLEntry();
entry1.setTenant(subtenant1Id.toString());
entry1.setAces(new ArrayList<String>());
entry1.getAces().add("USE");
changes.getAdd().add(entry1);
ClientResponse resp = rSys.path(String.format(_blockCosAclUrl, _cosBlock.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
resp = rSys.path(String.format(_fileCosAclUrl, _cosFile.getId().toString()))
.put(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
}
private void projectSetup() {
ProjectParam paramProj = new ProjectParam("resourcetestproject");
ProjectElement project1 = rSTAdminGr1.path(String.format(_projectsUrlFormat, subtenant1Id.toString()))
.post(ProjectElement.class, paramProj);
_testProject = project1.getId();
ACLEntry entry = new ACLEntry();
entry.setSubjectId(SUBTENANT1_READER);
entry.setAces(new ArrayList<String>());
entry.getAces().add("backup");
ACLEntry entry2 = new ACLEntry();
entry2.setGroup(SUBTENANT1_USERS_GROUP);
entry2.setAces(new ArrayList<String>());
entry2.getAces().add("all");
ACLAssignmentChanges changes = new ACLAssignmentChanges();
changes.setAdd(new ArrayList<ACLEntry>());
changes.getAdd().add(entry2);
changes.getAdd().add(entry);
ClientResponse resp = rSTAdmin1
.path(String.format(_projectAclUrl, _testProject.toString()))
.post(ClientResponse.class, changes);
Assert.assertEquals(200, resp.getStatus());
}
private void deviceSetup() throws InterruptedException {
// Create a isilon device - file
StorageSystemRestRep isilonDevice = createIsilonDevice();
// Update the discovered Isilon storage ports to set the transport zone.
updateAllIsilonPorts(isilonDevice);
// Create a VNXBlock SMISProvider
SMISProviderRestRep provider = createSMISProvider();
// Update the discovered VNX/VMAX storage ports to set the transport zone.
updateAllVnxAndVmaxPorts(provider);
}
/**
* Update the discovered VNX/VMAX storage ports to set the transport zone.
*
* @param provider : Provider.
*/
private void updateAllVnxAndVmaxPorts(SMISProviderRestRep provider) {
StorageSystemList systemList = rZAdmin
.path("/vdc/storage-systems")
.get(StorageSystemList.class);
for (RelatedResourceRep resRep : systemList.getStorageSystems()) {
StorageSystemRestRep system = rZAdmin
.path(String.format("/vdc/storage-systems/%s",
resRep.getId()).toString()).get(StorageSystemRestRep.class);
if (system.getSystemType().equals(Type.vnxblock.toString()) ||
system.getSystemType().equals(Type.vmax.toString())) {
// Register all the discovered storage ports .
StoragePortList vnxBlockPortList = rZAdmin
.path(String.format("/vdc/storage-systems/%s/storage-ports",
system.getId()).toString())
.get(StoragePortList.class);
List<NamedRelatedResourceRep> vnxBlockPortURIList = vnxBlockPortList.getPorts();
for (RelatedResourceRep portURI : vnxBlockPortURIList) {
updateStoragePortTZ(resRep.getId(), portURI);
}
}
}
}
/**
* Create a VNXBlock SMISProvider.
*
* @return SMISProviderRestRep : provider.
* @throws InterruptedException
*/
private SMISProviderRestRep createSMISProvider() throws InterruptedException {
// vnxblock
SMISProviderCreateParam providerParam = new SMISProviderCreateParam();
providerParam.setName("VNXBlock_Provider");
providerParam.setIpAddress(EnvConfig.get("sanity", "smis.ip"));
providerParam.setPortNumber(5988);
providerParam.setUserName("admin");
providerParam.setPassword("#1Password");
providerParam.setUseSSL(false);
TaskResourceRep task = rZAdmin.path("/vdc/smis-providers")
.post(TaskResourceRep.class, providerParam);
String opId = task.getOpId();
Assert.assertNotNull(opId);
NamedRelatedResourceRep providerLink = task.getResource();
Assert.assertNotNull(providerLink);
// wait upto ~3 minute for SMIS provider scan
int checkCount = 18;
String status;
do {
Thread.sleep(10000);
TaskResourceRep taskResp = rZAdmin.path(String.format("/vdc/smis-providers/%s/tasks/%s", providerLink.getId(), opId))
.get(TaskResourceRep.class);
status = taskResp.getState();
} while (status.equals("pending") && checkCount-- > 0);
if (!status.equals("ready")) {
Assert.assertTrue("Failed to create SMIS provider: time out", false);
}
SMISProviderRestRep provider = rZAdmin.path(String.format("/vdc/smis-providers/%s", providerLink.getId()))
.get(SMISProviderRestRep.class);
Assert.assertNotNull(provider);
_log.info("Scanned SMI-S Provider : " + providerLink.getId());
// Discover SMIS Provider:
TaskList tasks = rZAdmin.path("/vdc/storage-systems/discover")
.post(TaskList.class, providerParam);
// wait upto ~10 minute for discover
checkCount = 60;
for (TaskResourceRep taskRep : tasks.getTaskList()) {
opId = taskRep.getOpId();
Assert.assertNotNull(opId);
providerLink = taskRep.getResource();
Assert.assertNotNull(providerLink);
boolean success = monitorDiscoveredObjectTask(StorageSystemRestRep.class, taskRep);
if (!success) {
Assert.assertTrue("Failed to discover system : " + providerLink.getId().toString(), false);
}
}
_log.info(" Discover for all devices is completed");
return provider;
}
private <T extends DiscoveredSystemObjectRestRep>
boolean monitorDiscoveredObjectTask(Class<T> clazz, TaskResourceRep taskRep)
throws InterruptedException {
int checkCount = 60;
boolean ready = false;
boolean success = true;
for (; checkCount > 0;) {
TaskResourceRep curTask = rZAdmin.path(taskRep.getLink().getLinkRef().toString())
.get(TaskResourceRep.class);
String status = curTask.getState();
if (status.equals("pending")) {
Thread.sleep(10000);
checkCount--;
}
else if (status.equals("error")) {
// first check if the discovery already ran for this object
do {
T resource = rZAdmin.path(taskRep.getResource().getLink().getLinkRef().toString()).
get(clazz);
String resourceStatus = resource.getDiscoveryJobStatus();
if (resourceStatus.equalsIgnoreCase("IN_PROGRESS")) {
Thread.sleep(10000);
checkCount--;
}
else if (resourceStatus.equalsIgnoreCase("COMPLETE")) {
ready = true;
break;
}
else {
ready = true;
success = false;
break;
}
} while (checkCount > 0);
}
else {
ready = true;
}
if (ready) {
break;
}
}
return success;
}
/**
* Update the discovered Isilon storage ports to set the transport zone.
*
* @param isilonDevice : Isilon Device.
*/
private void updateAllIsilonPorts(StorageSystemRestRep isilonDevice) {
// Register all the discovered storage ports .
StoragePortList portList = rZAdmin
.path(String.format("/vdc/storage-systems/%s/storage-ports",
isilonDevice.getId()).toString())
.get(StoragePortList.class);
List<NamedRelatedResourceRep> portURIList = portList.getPorts();
for (RelatedResourceRep portURI : portURIList) {
updateStoragePortTZ(isilonDevice.getId(), portURI);
}
}
/**
* create a Isilon device.
*
* @return
* @throws InterruptedException
*/
private StorageSystemRestRep createIsilonDevice() throws InterruptedException {
StorageSystemRequestParam param = new StorageSystemRequestParam();
param.setSystemType("isilon");
param.setIpAddress(EnvConfig.get("sanity", "isilon.ip"));
param.setPortNumber(8080);
param.setUserName("root");
param.setPassword("a");
param.setSerialNumber("6805ca00ad441c3ca650a5087c0bd1674ce2");
TaskResourceRep task = rZAdmin.path("/vdc/storage-systems")
.post(TaskResourceRep.class, param);
String opId = task.getOpId();
Assert.assertNotNull(opId);
NamedRelatedResourceRep deviceLink = task.getResource();
Assert.assertNotNull(deviceLink);
// wait upto ~3 minute for SMIS provider scan
int checkCount = 18;
String status;
do {
Thread.sleep(10000);
TaskResourceRep taskResp = rZAdmin.path(String.format("/vdc/storage-systems/%s/tasks/%s", deviceLink.getId(), opId))
.get(TaskResourceRep.class);
status = taskResp.getState();
} while (status.equals("pending") && checkCount-- > 0);
if (!status.equals("ready")) {
Assert.assertTrue("Failed to create isilon device: time out", false);
}
StorageSystemRestRep dev1 = rZAdmin.path(String.format("/vdc/storage-systems/%s", deviceLink.getId()))
.get(StorageSystemRestRep.class);
Assert.assertNotNull(dev1);
_log.info("Discover for device is complete : " + deviceLink.getId());
return dev1;
}
/**
* Updates the storage port to set the transport zone.
*
* @param systemURI The storage system URI
* @param portURI The storage port URI
*/
private void updateStoragePortTZ(URI systemURI, RelatedResourceRep portURI) {
StoragePortRestRep portRep = rZAdmin.path(
String.format("/vdc/storage-systems/%s/storage-ports/%s", systemURI,
portURI.getId()).toString()).get(StoragePortRestRep.class);
StoragePortUpdate updateParam = new StoragePortUpdate();
if (portRep.getTransportType().equals(Block.FC.toString())) {
updateParam.setNetwork(_fctzone.getId());
} else if (portRep.getTransportType().equals("IP")) {
updateParam.setNetwork(_iptzone.getId());
}
ClientResponse resp = rZAdmin.path(
String.format("/vdc/storage-ports/%s", portRep.getId()).toString()).put(
ClientResponse.class, updateParam);
Assert.assertEquals(200, resp.getStatus());
}
private void checkFSCreate(BalancedWebResource user, boolean good, boolean dup)
throws Exception {
FileSystemParam fsparam = new FileSystemParam();
fsparam.setVpool(_cosFile.getId());
fsparam.setLabel("test-fs-" + System.currentTimeMillis());
fsparam.setVarray(_nh);
fsparam.setSize("10240000");
if (good) {
TaskResourceRep resp = user.path("/file/filesystems/")
.queryParam("project", _testProject.toString())
.post(TaskResourceRep.class, fsparam);
Assert.assertNotNull(resp.getOpId());
Assert.assertNotNull(resp.getResource());
_fs = resp.getResource().getId();
String fsId = _fs.toString();
String opId = resp.getOpId();
int checkCount = 1200;
String status;
do {
// wait upto ~2 minute for fs creation
Thread.sleep(100);
resp = user.path(String.format("/file/filesystems/%s/tasks/%s", fsId, opId))
.get(TaskResourceRep.class);
status = resp.getState();
} while (status.equals("pending") && checkCount-- > 0);
if (!status.equals("ready")) {
Assert.assertTrue("Fileshare create timed out", false);
}
if (dup) {
ClientResponse response = user.path("/file/filesystems")
.queryParam("project", _testProject.toString())
.post(ClientResponse.class, fsparam);
Assert.assertEquals(400, response.getStatus());
}
} else {
ClientResponse resp = user.path("/file/filesystems")
.queryParam("project", _testProject.toString())
.post(ClientResponse.class, fsparam);
Assert.assertEquals(403, resp.getStatus());
}
}
private void checkFSCreate(BalancedWebResource user, boolean good) throws Exception {
checkFSCreate(user, good, false);
}
private void checkSnapCreate(BalancedWebResource user, boolean good) {
FileSystemSnapshotParam param = new FileSystemSnapshotParam();
param.setLabel("test-fs-snap-" + System.currentTimeMillis());
String snapCreateURL = String.format("/file/filesystems/%s/snapshots", _fs);
if (good) {
TaskResourceRep resp = user.path(snapCreateURL)
.post(TaskResourceRep.class, param);
Assert.assertNotNull(resp.getOpId());
Assert.assertNotNull(resp.getResource());
} else {
ClientResponse resp = user.path(snapCreateURL)
.post(ClientResponse.class, param);
Assert.assertEquals(403, resp.getStatus());
}
}
private void fileTests() throws Exception {
// tenant admin, project owner and project user can create fs
checkFSCreate(rSTAdmin1, true);
checkFSCreate(rSTAdmin1, true, true);
checkFSCreate(rSTAdminGr1, true);
checkFSCreate(rProjUserGr, true);
// root tenant admin, secadmin, unauth can not create fs or snap
checkFSCreate(rProjRead, false);
checkFSCreate(rZAdmin, false);
checkFSCreate(rSys, false);
checkFSCreate(rUnAuth, false);
// tenant admin, project owner and project user/backup can create snapshot
checkSnapCreate(rSTAdmin1, true);
checkSnapCreate(rSTAdminGr1, true);
checkSnapCreate(rProjUserGr, true);
checkSnapCreate(rProjRead, true);
checkSnapCreate(rZAdmin, false);
checkSnapCreate(rSys, false);
checkSnapCreate(rUnAuth, false);
}
private void checkVolumeCreate(BalancedWebResource user, boolean good, boolean dup) throws Exception {
VolumeCreate param = new VolumeCreate();
param.setVpool(_cosBlock.getId());
param.setName("test_volume_" + System.currentTimeMillis());
param.setVarray(_nh);
param.setSize("307200000");
param.setProject(_testProject);
if (_group != null) {
param.setConsistencyGroup(_group);
}
if (good) {
TaskList resp = user.path("/block/volumes")
.post(TaskList.class, param);
Assert.assertTrue(resp.getTaskList().size() == 1);
Assert.assertNotNull(resp.getTaskList().get(0).getOpId());
Assert.assertNotNull(resp.getTaskList().get(0).getResource().getId());
_volume = resp.getTaskList().get(0).getResource().getId();
String volumeId = _volume.toString();
String opId = resp.getTaskList().get(0).getOpId();
int checkCount = 1200;
String status;
do {
// wait upto ~2 minute for volume creation
Thread.sleep(100);
TaskResourceRep taskResp = user.path(String.format("/block/volumes/%s/tasks/%s", volumeId, opId))
.get(TaskResourceRep.class);
status = taskResp.getState();
} while (status.equals("pending") && checkCount-- > 0);
if (!status.equals("ready")) {
Assert.assertTrue("Volume create timed out", false);
}
if (dup) {
// create the volume with same name again.
ClientResponse response = user.path("/block/volumes")
.post(ClientResponse.class, param);
Assert.assertEquals(400, response.getStatus());
}
} else {
ClientResponse resp = user.path("/block/volumes")
.post(ClientResponse.class, param);
Assert.assertEquals(403, resp.getStatus());
}
}
private void checkVolumeCreate(BalancedWebResource user, boolean good) throws Exception {
checkVolumeCreate(user, good, false);
}
private void checkCreateConsistencyGroup(BalancedWebResource user, boolean good)
throws InterruptedException {
final BlockConsistencyGroupCreate param = new BlockConsistencyGroupCreate();
param.setName("test_group_" + System.currentTimeMillis());
param.setProject(_testProject);
if (good) {
TaskList resp = user.path("/block/consistency-groups").post(TaskList.class, param);
Assert.assertTrue(resp.getTaskList().size() == 1);
Assert.assertNotNull(resp.getTaskList().get(0).getOpId());
Assert.assertNotNull(resp.getTaskList().get(0).getResource().getId());
_group = resp.getTaskList().get(0).getResource().getId();
String groupId = _group.toString();
String opId = resp.getTaskList().get(0).getOpId();
int checkCount = 1200;
String status;
do {
// wait upto ~2 minute for group creation
Thread.sleep(100);
TaskResourceRep taskResp = user.path(
String.format("/block/consistency-groups/%s/tasks/%s", groupId, opId))
.get(TaskResourceRep.class);
status = taskResp.getState();
} while (status.equals("pending") && checkCount-- > 0);
if (!status.equals("ready")) {
Assert.assertTrue("ConsistencyGroup create timed out", false);
}
} else {
ClientResponse resp = user.path("/block/consistency-groups")
.post(ClientResponse.class, param);
Assert.assertEquals(403, resp.getStatus());
}
}
private void blockTests() throws Exception {
// try creating the consistency group first, then create and add volume
// to the group
// tenant admin, project owner and project user can create fs
checkCreateConsistencyGroup(rSTAdmin1, true);
checkVolumeCreate(rSTAdmin1, true);
checkVolumeCreate(rSTAdmin1, true, true);
checkCreateConsistencyGroup(rSTAdminGr1, true);
checkVolumeCreate(rSTAdminGr1, true);
checkCreateConsistencyGroup(rProjUserGr, true);
checkVolumeCreate(rProjUserGr, true);
// root tenant admin, secadmin, unauth can not create fs or snap
checkCreateConsistencyGroup(rProjRead, false);
checkVolumeCreate(rProjRead, false);
checkCreateConsistencyGroup(rZAdmin, false);
checkVolumeCreate(rZAdmin, false);
checkCreateConsistencyGroup(rSys, false);
checkVolumeCreate(rSys, false);
checkCreateConsistencyGroup(rUnAuth, false);
checkVolumeCreate(rUnAuth, false);
}
/**
* Project resource tests
*/
public void projectResourceTests() throws Exception {
zoneCosSetup();
projectSetup();
deviceSetup();
// The storage pools and devices are not set yet to create files/volumes.
// Still needs to be fixed.
// fileTests();
// blockTests();
}
/*
* the secret key service is no longer at this address
* commenting out for now
* private void testSecretKeysTest() throws Exception {
* BalancedWebResource keyUser = rSys;
* String keyServicePath = "/secret-keys/stadmin@subtenant1.com";
* // first clear old keys (if there are such keys
*
* ClientResponse resp = keyUser.path(keyServicePath + "/all")
* .delete(ClientResponse.class);
* Assert.assertEquals(200, resp.getStatus());
*
* // Verify that the user "stadmin" does not have a key
* resp = keyUser.path(keyServicePath)
* .get(ClientResponse.class);
* Assert.assertEquals(400, resp.getStatus());
*
* //create the first key for the user stadmin
* SecretKeyInfoRep keyInfo1 = keyUser.path(keyServicePath)
* .post(SecretKeyInfoRep.class);
* Assert.assertFalse(keyInfo1._secreteKey.equals(""));
* SecretKeyRestRep userKeys = keyUser.path(keyServicePath)
* .get(SecretKeyRestRep.class);
* Assert.assertEquals(keyInfo1._secreteKey,userKeys._secreteKey1);
* Assert.assertEquals(keyInfo1._secreteKeyTimestamp,userKeys._secreteKeyTimestamp1);
* Assert.assertEquals(userKeys._secreteKey2,"");
*
* //create additional key
* SecretKeyInfoRep keyInfo2 = keyUser.path(keyServicePath)
* .post(SecretKeyInfoRep.class);
* Assert.assertFalse(keyInfo1._secreteKey.equals(""));
* userKeys = keyUser.path(keyServicePath)
* .get(SecretKeyRestRep.class);
* Assert.assertEquals(keyInfo2._secreteKey,userKeys._secreteKey2);
* Assert.assertEquals(keyInfo2._secreteKeyTimestamp,userKeys._secreteKeyTimestamp2);
*
* // No more keys can be create for the user
* resp = keyUser.path(keyServicePath)
* .post(ClientResponse.class);
* Assert.assertEquals(400, resp.getStatus());
*
* // Delete the first key and check that only 1 left in the DB
* SecretKeyService.KeyDeleteParam deleteParam = new SecretKeyService.KeyDeleteParam();
* deleteParam.key_timestamp = keyInfo1._secreteKeyTimestamp;
* resp = keyUser.path(keyServicePath)
* .delete(ClientResponse.class,deleteParam);
* Assert.assertEquals(200, resp.getStatus());
*
* userKeys = keyUser.path(keyServicePath)
* .get(SecretKeyRestRep.class);
* Assert.assertEquals(userKeys._secreteKeyTimestamp1,keyInfo2._secreteKeyTimestamp);
* Assert.assertEquals(userKeys._secreteKey2,"");
*
* //delete all key again
* resp = keyUser.path(keyServicePath + "/all")
* .delete(ClientResponse.class);
* Assert.assertEquals(200, resp.getStatus());
* }
*/
private void testOtherBadParameterErrors() {
ClientResponse resp = null;
// Test bad parameter is returned if we attempt to create a StorageSystem of an unsupported type
StorageSystemRequestParam storageSystemParam = new StorageSystemRequestParam();
storageSystemParam.setSystemType("AMadeUpOne");
storageSystemParam.setIpAddress("10.64.213.226");
storageSystemParam.setPortNumber(8080);
storageSystemParam.setUserName("MyUser");
storageSystemParam.setPassword("MyPassword");
storageSystemParam.setSerialNumber("1");
resp = rZAdmin.path("/vdc/storage-systems").post(ClientResponse.class, storageSystemParam);
Assert.assertEquals(400, resp.getStatus());
}
private void testOtherEntityNotFoundErrors() {
ClientResponse resp = null;
// Test entity not found is returned if we try to deactivate a snapshot that does not exist
String deactivateSnapshotUrl = "/block/snapshots/%s/deactivate";
resp = rTAdmin.path(String.format(deactivateSnapshotUrl, "urn:storageos:Snapshot:815b507c-26eb-4124-bc96-9d0400a16596:")).post(
ClientResponse.class);
Assert.assertEquals(404, resp.getStatus());
// Test entity not found is returned if we request the list of storage pools for a vpool that does not exist
String getStoragePoolsUrl = "/block/vpools/%s/storage-pools";
resp = rZAdmin.path(String.format(getStoragePoolsUrl, "urn:storageos:VirtualPool:815b507c-26eb-4124-bc96-9d0400a16596:")).get(
ClientResponse.class);
Assert.assertEquals(404, resp.getStatus());
}
// TODO: to be moved in another test suite
public void testVDCs() {
// This disables vdc test altogether on devkit
// TODO: once devkit gets switched to 1+0 appliance, we should enable it again.
if (System.getenv("APP_HOST_NAMES").equals("localhost")) {
return;
}
VirtualDataCenterAddParam addParam = new VirtualDataCenterAddParam();
addParam.setApiEndpoint("http://apitest");
addParam.setSecretKey("apitestSecret");
addParam.setCertificateChain("apitestCertchain");
addParam.setName("apitestName" + System.currentTimeMillis());
// TODO: enhance to track task progress
// root should NOT do this.
ClientResponse rsp = rSys.path("/vdc").post(ClientResponse.class, addParam);
Assert.assertEquals(403, rsp.getStatus());
// use super admin with geo securityAdmin role to do post vdc
// assign geo securityadmin to superuser.
RoleAssignmentChanges changes = new RoleAssignmentChanges();
changes.setAdd(new ArrayList<RoleAssignmentEntry>());
RoleAssignmentEntry entry1 = new RoleAssignmentEntry();
entry1.setSubjectId(SUPERUSER);
entry1.getRoles().add("SECURITY_ADMIN");
changes.getAdd().add(entry1);
ClientResponse rsp1 = rSys.path("/vdc/role-assignments").put(ClientResponse.class, changes);
Assert.assertEquals(200, rsp1.getStatus());
// then do post VDC using superuser. should pass.
TaskResourceRep taskRep = rZAdminGr.path("/vdc").post(TaskResourceRep.class, addParam);
Assert.assertNotNull("vdc create task should not be null", taskRep);
VirtualDataCenterList vdcList = rSys.path("/vdc").get(VirtualDataCenterList.class);
Assert.assertNotNull("vdcList should not be null", vdcList);
Assert.assertNotNull("vdcList.getVirtualDataCenters should not be null", vdcList.getVirtualDataCenters());
// boolean found = false;
// for (NamedRelatedResourceRep vdcResource : vdcList.getVirtualDataCenters()) {
// if (vdcResource.getName().equals(addParam.getName())) {
// found = true;
// }
// }
// Assert.assertTrue("newly created vdc could not be found in vdc list", found);
VirtualDataCenterRestRep vdc = rZAdminGr.path("/vdc/" + taskRep.getResource().getId()).get(VirtualDataCenterRestRep.class);
Assert.assertNotNull("created vdc object can't be retrieved", vdc);
Assert.assertTrue("vdc name does not match", vdc.getName().equals(addParam.getName()));
// TODO: enhance to track task progress
ClientResponse response = rZAdminGr.path("/vdc/" + vdc.getId() + "/disconnect").post(ClientResponse.class);
Assert.assertEquals(405, response.getStatus());
// TODO: enhance to track task progress
response = rZAdminGr.path("/vdc/" + vdc.getId() + "/reconnect").post(ClientResponse.class);
Assert.assertEquals(405, response.getStatus());
// TODO: enhance to track task progress
taskRep = rZAdminGr.path("/vdc/" + vdc.getId()).delete(TaskResourceRep.class);
Assert.assertNotNull("vdc delete task should not be null", taskRep);
}
/**
* Basic test for vdc secret key api
*/
public void testVDCSecretKey() {
VirtualDataCenterSecretKeyRestRep resp = rSys.path("/vdc/secret-key").get(VirtualDataCenterSecretKeyRestRep.class);
Assert.assertNotNull(resp);
String encodedKey = resp.getSecretKey();
SecretKey decodedKey = SignatureHelper.createKey(encodedKey, "HmacSHA256");
Assert.assertNotNull(decodedKey);
Assert.assertTrue(decodedKey.getAlgorithm().equals("HmacSHA256"));
String data = "some data";
String signature = SignatureHelper.sign2(data, decodedKey, decodedKey.getAlgorithm());
// do it again. Make sure this is the same key.
resp = rSys.path("/vdc/secret-key").get(VirtualDataCenterSecretKeyRestRep.class);
Assert.assertNotNull(resp);
String encodedKey2 = resp.getSecretKey();
Assert.assertTrue(encodedKey.equals(encodedKey2));
SecretKey decodedKey2 = SignatureHelper.createKey(encodedKey2, "HmacSHA256");
Assert.assertNotNull(encodedKey2);
String signature2 = SignatureHelper.sign2(data, decodedKey2, decodedKey2.getAlgorithm());
Assert.assertTrue(signature.equals(signature2));
}
}