/*******************************************************************************
* Cloud Foundry
* Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
* You may not use this product except in compliance with the License.
*
* This product includes a number of subcomponents with
* separate copyright notices and license terms. Your use of these
* subcomponents is subject to the terms and conditions of the
* subcomponent's license, as noted in the LICENSE file.
*******************************************************************************/
package org.cloudfoundry.identity.uaa.mock.ldap;
import com.fasterxml.jackson.core.type.TypeReference;
import org.cloudfoundry.identity.uaa.authentication.UaaAuthentication;
import org.cloudfoundry.identity.uaa.authentication.manager.DynamicZoneAwareAuthenticationManager;
import org.cloudfoundry.identity.uaa.constants.OriginKeys;
import org.cloudfoundry.identity.uaa.mock.DefaultConfigurationTestSuite;
import org.cloudfoundry.identity.uaa.mock.util.ApacheDSHelper;
import org.cloudfoundry.identity.uaa.mock.util.MockMvcUtils;
import org.cloudfoundry.identity.uaa.mock.util.MockMvcUtils.ZoneScimInviteData;
import org.cloudfoundry.identity.uaa.oauth.UaaTokenServices;
import org.cloudfoundry.identity.uaa.provider.IdentityProvider;
import org.cloudfoundry.identity.uaa.provider.IdentityProviderValidationRequest;
import org.cloudfoundry.identity.uaa.provider.IdentityProviderValidationRequest.UsernamePasswordAuthentication;
import org.cloudfoundry.identity.uaa.provider.LdapIdentityProviderDefinition;
import org.cloudfoundry.identity.uaa.scim.ScimUser;
import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning;
import org.cloudfoundry.identity.uaa.user.UaaUser;
import org.cloudfoundry.identity.uaa.user.UaaUserDatabase;
import org.cloudfoundry.identity.uaa.util.JsonUtils;
import org.cloudfoundry.identity.uaa.util.UaaStringUtils;
import org.cloudfoundry.identity.uaa.zone.IdentityZone;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneSwitchingFilter;
import org.hamcrest.core.StringContains;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.ldap.server.ApacheDsSSLContainer;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.util.Collections.EMPTY_LIST;
import static org.cloudfoundry.identity.uaa.constants.OriginKeys.LDAP;
import static org.cloudfoundry.identity.uaa.mock.util.MockMvcUtils.CookieCsrfPostProcessor.cookieCsrf;
import static org.cloudfoundry.identity.uaa.mock.util.MockMvcUtils.utils;
import static org.cloudfoundry.identity.uaa.provider.ldap.ProcessLdapProperties.NONE;
import static org.cloudfoundry.identity.uaa.provider.ldap.ProcessLdapProperties.SIMPLE;
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
import static org.springframework.http.HttpHeaders.HOST;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.TEXT_HTML_VALUE;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
import static org.springframework.security.web.context.HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
@RunWith(Parameterized.class)
public class LdapMockMvcTests {
private static int ldapPortRotation = 0;
private String host;
private static WebApplicationContext webApplicationContext;
private static MockMvc mockMvc;
public WebApplicationContext getWebApplicationContext() {
return webApplicationContext;
}
public MockMvc getMockMvc() {
return mockMvc;
}
@Parameters(name = "{index}: auth[{0}]; group[{1}]; url[{2}]; tls[{3}]")
public static List<Object[]> data() {
return Arrays.asList(new Object[][]{
{"ldap-simple-bind.xml", "ldap-groups-null.xml", "ldap://localhost:33389", NONE},
//{"ldap-simple-bind.xml", "ldap-groups-as-scopes.xml", "ldap://localhost:33389", SIMPLE},
//{"ldap-simple-bind.xml", "ldap-groups-map-to-scopes.xml", "ldap://localhost:33389", SIMPLE},
//{"ldap-simple-bind.xml", "ldap-groups-map-to-scopes.xml", "ldaps://localhost:33636", NONE},
//{"ldap-search-and-bind.xml", "ldap-groups-null.xml", "ldap://localhost:33389", SIMPLE},
//{"ldap-search-and-bind.xml", "ldap-groups-as-scopes.xml", "ldap://localhost:33389", SIMPLE},
{"ldap-search-and-bind.xml", "ldap-groups-map-to-scopes.xml", "ldap://localhost:33389", SIMPLE},
//{"ldap-search-and-bind.xml", "ldap-groups-map-to-scopes.xml", "ldaps://localhost:33636", NONE},
//{"ldap-search-and-compare.xml", "ldap-groups-null.xml", "ldap://localhost:33389", NONE},
//{"ldap-search-and-compare.xml", "ldap-groups-as-scopes.xml", "ldap://localhost:33389", NONE},
//{"ldap-search-and-compare.xml", "ldap-groups-map-to-scopes.xml", "ldap://localhost:33389", SIMPLE},
{"ldap-search-and-compare.xml", "ldap-groups-as-scopes.xml", "ldaps://localhost:33636", NONE},
//{"ldap-search-and-compare.xml", "ldap-groups-map-to-scopes.xml", "ldaps://localhost:33636", NONE}
});
}
private static ApacheDsSSLContainer apacheDS;
private static ApacheDsSSLContainer apacheDS2;
private static File tmpDir;
@AfterClass
public static void afterClass() throws Exception {
DefaultConfigurationTestSuite.destroyMyContext();
apacheDS.stop();
}
public static boolean checkOpenPorts(int port) throws Exception {
//need to configure gradle to not swallow the output, but log it to a file
System.out.println("Checking for processes using port:"+port);
ProcessBuilder builder = new ProcessBuilder(Arrays.asList("sudo", "lsof", "-i", ":"+port));
builder.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(builder.start().getInputStream()))) {
long count = reader.lines().count();
reader.lines().forEach(line -> System.err.println("LDAP Port["+port+"] lsof:"+line));
return count > 0;
}
}
@BeforeClass
public static void startApacheDS() throws Exception {
checkOpenPorts(33389);
checkOpenPorts(33636);
apacheDS = ApacheDSHelper.start();
webApplicationContext = DefaultConfigurationTestSuite.setUpContext();
FilterChainProxy springSecurityFilterChain = webApplicationContext.getBean("springSecurityFilterChain", FilterChainProxy.class);
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilter(springSecurityFilterChain)
.build();
}
private String ldapProfile;
private String ldapGroup;
private String ldapBaseUrl;
private String tlsConfig;
private String REDIRECT_URI = "http://invitation.redirect.test";
private ZoneScimInviteData zone;
private IdentityProvider<LdapIdentityProviderDefinition> provider;
public LdapMockMvcTests(String ldapProfile, String ldapGroup, String baseUrl, String tlsConfig) {
this.ldapGroup = ldapGroup;
this.ldapProfile = ldapProfile;
this.ldapBaseUrl = baseUrl;
this.tlsConfig = tlsConfig;
}
@Before
public void createTestZone() throws Exception {
String clientId = new RandomValueStringGenerator().generate().toLowerCase();
zone = utils().createZoneForInvites(getMockMvc(), getWebApplicationContext(), clientId, REDIRECT_URI);
LdapIdentityProviderDefinition definition = new LdapIdentityProviderDefinition();
definition.setLdapProfileFile("ldap/" + ldapProfile);
definition.setLdapGroupFile("ldap/" + ldapGroup);
definition.setMaxGroupSearchDepth(10);
definition.setBaseUrl(ldapBaseUrl);
definition.setBindUserDn("cn=admin,ou=Users,dc=test,dc=com");
definition.setBindPassword("adminsecret");
definition.setSkipSSLVerification(true);
definition.setTlsConfiguration(tlsConfig);
definition.setMailAttributeName("mail");
definition.setReferral("ignore");
provider = MockMvcUtils.createIdentityProvider(getMockMvc(),
zone.getZone(),
LDAP,
definition);
host = zone.getZone().getIdentityZone().getSubdomain() + ".localhost";
IdentityZoneHolder.clear();
}
@After
public void tearDown() throws Exception {
getMockMvc().perform(
delete("/identity-zones/{id}", zone.getZone().getIdentityZone().getId())
.header("Authorization", "Bearer " + zone.getDefaultZoneAdminToken())
.accept(APPLICATION_JSON))
.andExpect(status().isOk());
}
@Test
public void acceptInvitation_for_ldap_user_whose_username_is_not_email() throws Exception {
getWebApplicationContext().getBean(JdbcTemplate.class).update("delete from expiring_code_store");
String email = "marissa2@test.com";
getWebApplicationContext().getBean(JdbcTemplate.class).update("DELETE FROM users WHERE email=?", email);
LdapIdentityProviderDefinition definition = provider.getConfig();
definition.setEmailDomain(Arrays.asList("test.com"));
updateLdapProvider();
URL url = utils().inviteUser(
getWebApplicationContext(),
getMockMvc(),
email,
zone.getAdminToken(),
zone.getZone().getIdentityZone().getSubdomain(),
zone.getScimInviteClient().getClientId(),
LDAP,
REDIRECT_URI
);
String code = utils().extractInvitationCode(url.toString());
String userInfoOrigin = getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select origin from users where email=? and identity_zone_id=?", String.class, email, zone.getZone().getIdentityZone().getId());
String userInfoId = getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select id from users where email=? and identity_zone_id=?", String.class, email, zone.getZone().getIdentityZone().getId());
assertEquals(LDAP, userInfoOrigin);
ResultActions actions = getMockMvc().perform(get("/invitations/accept")
.param("code", code)
.accept(MediaType.TEXT_HTML)
.header(HOST, host)
);
MvcResult result = actions.andExpect(status().isOk())
.andExpect(content().string(containsString("Link your account")))
.andExpect(content().string(containsString("Email: " + email)))
.andExpect(content().string(containsString("Sign in with enterprise credentials:")))
.andExpect(content().string(containsString("username")))
.andExpect(content().string(containsString("<input type=\"submit\" value=\"Sign in\" class=\"island-button\"/>")))
.andReturn();
code = getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select code from expiring_code_store", String.class);
MockHttpSession session = (MockHttpSession) result.getRequest().getSession(false);
getMockMvc().perform(post("/invitations/accept_enterprise.do")
.session(session)
.param("enterprise_username", "marissa2")
.param("enterprise_password", LDAP)
.param("enterprise_email", "email")
.param("code", code)
.header(HOST, host)
.with(csrf()))
.andExpect(status().isFound())
.andExpect(redirectedUrl(REDIRECT_URI))
.andReturn();
String newUserInfoId = getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select id from users where email=? and identity_zone_id=?", String.class, email, zone.getZone().getIdentityZone().getId());
String newUserInfoOrigin = getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select origin from users where email=? and identity_zone_id=?", String.class, email, zone.getZone().getIdentityZone().getId());
String newUserInfoUsername = getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select username from users where email=? and identity_zone_id=?", String.class, email, zone.getZone().getIdentityZone().getId());
assertEquals(LDAP, newUserInfoOrigin);
assertEquals("marissa2", newUserInfoUsername);
//ensure that a new user wasn't created
assertEquals(userInfoId, newUserInfoId);
//email mismatch
getWebApplicationContext().getBean(JdbcTemplate.class).update("delete from expiring_code_store");
email = "different@test.com";
url = utils().inviteUser(getWebApplicationContext(), getMockMvc(), email, zone.getAdminToken(), zone.getZone().getIdentityZone().getSubdomain(), zone.getScimInviteClient().getClientId(), LDAP, REDIRECT_URI);
code = utils().extractInvitationCode(url.toString());
actions = getMockMvc().perform(get("/invitations/accept")
.param("code", code)
.accept(MediaType.TEXT_HTML)
.header(HOST, host)
);
result = actions.andExpect(status().isOk())
.andExpect(content().string(containsString("Email: " + email)))
.andExpect(content().string(containsString("Sign in with enterprise credentials:")))
.andExpect(content().string(containsString("username")))
.andReturn();
code = getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select code from expiring_code_store", String.class);
session = (MockHttpSession) result.getRequest().getSession(false);
getMockMvc().perform(post("/invitations/accept_enterprise.do")
.session(session)
.param("enterprise_username", "marissa2")
.param("enterprise_password", LDAP)
.param("enterprise_email", "email")
.param("code", code)
.header(HOST, host)
.with(csrf()))
.andExpect(status().isUnprocessableEntity())
.andExpect(content().string(containsString("The authenticated email does not match the invited email. Please log in using a different account.")))
.andReturn();
boolean userVerified = Boolean.parseBoolean(getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select verified from users where email=? and identity_zone_id=?", String.class, email, zone.getZone().getIdentityZone().getId()));
assertFalse(userVerified);
}
@Test
public void test_external_groups_whitelist() throws Exception {
Assume.assumeThat("ldap-groups-map-to-scopes.xml, ldap-groups-as-scopes.xml", StringContains.containsString(ldapGroup));
AuthenticationManager manager = getWebApplicationContext().getBean(DynamicZoneAwareAuthenticationManager.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa3", "ldap3");
LdapIdentityProviderDefinition def = provider.getConfig();
def.addWhiteListedGroup("admins");
def.addWhiteListedGroup("thirdmarissa");
provider.setConfig(def);
updateLdapProvider();
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
Authentication auth = manager.authenticate(token);
assertNotNull(auth);
assertTrue(auth instanceof UaaAuthentication);
UaaAuthentication uaaAuth = (UaaAuthentication) auth;
Set<String> externalGroups = uaaAuth.getExternalGroups();
assertNotNull(externalGroups);
assertEquals(2, externalGroups.size());
assertThat(externalGroups, containsInAnyOrder("admins", "thirdmarissa"));
//default whitelist
def = provider.getConfig();
def.setExternalGroupsWhitelist(EMPTY_LIST);
provider.setConfig(def);
updateLdapProvider();
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
auth = manager.authenticate(token);
assertNotNull(auth);
assertTrue(auth instanceof UaaAuthentication);
uaaAuth = (UaaAuthentication) auth;
externalGroups = uaaAuth.getExternalGroups();
assertNotNull(externalGroups);
assertEquals(0, externalGroups.size());
IdentityZoneHolder.clear();
}
@Test
public void testCustomUserAttributes() throws Exception {
Assume.assumeThat("ldap-groups-map-to-scopes.xml, ldap-groups-as-scopes.xml", StringContains.containsString(ldapGroup));
final String MANAGER = "uaaManager";
final String MANAGERS = "managers";
final String DENVER_CO = "Denver,CO";
final String COST_CENTER = "costCenter";
final String COST_CENTERS = COST_CENTER + "s";
final String JOHN_THE_SLOTH = "John the Sloth";
final String KARI_THE_ANT_EATER = "Kari the Ant Eater";
final String FIRST_NAME = "first_name";
final String FAMILY_NAME = "family_name";
final String PHONE_NUMBER = "phone_number";
final String EMAIL = "email";
Map<String, Object> attributeMappings = new HashMap<>();
LdapIdentityProviderDefinition definition = provider.getConfig();
attributeMappings.put("user.attribute." + MANAGERS, MANAGER);
attributeMappings.put("user.attribute." + COST_CENTERS, COST_CENTER);
//test to remap the user/person properties
attributeMappings.put(FIRST_NAME, "sn");
attributeMappings.put(PHONE_NUMBER, "givenname");
attributeMappings.put(FAMILY_NAME, "telephonenumber");
definition.setAttributeMappings(attributeMappings);
provider.setConfig(definition);
updateLdapProvider();
String username = "marissa9";
String password = "ldap9";
MvcResult result = performUiAuthentication(username, password, HttpStatus.FOUND, true);
UaaAuthentication authentication = (UaaAuthentication) ((SecurityContext) result.getRequest().getSession().getAttribute(SPRING_SECURITY_CONTEXT_KEY)).getAuthentication();
assertEquals("Expected two user attributes", 2, authentication.getUserAttributes().size());
assertNotNull("Expected cost center attribute", authentication.getUserAttributes().get(COST_CENTERS));
assertEquals(DENVER_CO, authentication.getUserAttributes().getFirst(COST_CENTERS));
assertNotNull("Expected manager attribute", authentication.getUserAttributes().get(MANAGERS));
assertEquals("Expected 2 manager attribute values", 2, authentication.getUserAttributes().get(MANAGERS).size());
assertThat(authentication.getUserAttributes().get(MANAGERS), containsInAnyOrder(JOHN_THE_SLOTH, KARI_THE_ANT_EATER));
assertEquals("8885550986", getFamilyName(username));
assertEquals("Marissa", getPhoneNumber(username));
assertEquals("Marissa9", getGivenName(username));
}
@Test
public void testLdapConfigurationBeforeSave() throws Exception {
//we only need to test this once
Assume.assumeThat("ldap-search-and-bind.xml", StringContains.containsString(ldapProfile));
Assume.assumeThat("ldap-groups-map-to-scopes.xml", StringContains.containsString(ldapGroup));
String identityAccessToken = utils().getClientOAuthAccessToken(getMockMvc(), "identity", "identitysecret", "");
String adminAccessToken = utils().getClientOAuthAccessToken(getMockMvc(), "admin", "adminsecret", "");
IdentityZone zone = utils().createZoneUsingWebRequest(getMockMvc(), identityAccessToken);
String zoneAdminToken = utils().getZoneAdminToken(getMockMvc(), adminAccessToken, zone.getId());
LdapIdentityProviderDefinition definition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
"ldap://localhost:33389",
"cn=admin,ou=Users,dc=test,dc=com",
"adminsecret",
"dc=test,dc=com",
"cn={0}",
"ou=scopes,dc=test,dc=com",
"member={0}",
"mail",
null,
false,
true,
true,
10,
true
);
IdentityProvider provider = new IdentityProvider();
provider.setOriginKey(LDAP);
provider.setName("Test ldap provider");
provider.setType(LDAP);
provider.setConfig(definition);
provider.setActive(true);
provider.setIdentityZoneId(zone.getId());
UsernamePasswordAuthentication token = new UsernamePasswordAuthentication("marissa2", LDAP);
IdentityProviderValidationRequest request = new IdentityProviderValidationRequest(provider, token);
System.out.println("request = \n" + JsonUtils.writeValueAsString(request));
//Happy Day Scenario
MockHttpServletRequestBuilder post = post("/identity-providers/test")
.header("Accept", APPLICATION_JSON_VALUE)
.header("Content-Type", APPLICATION_JSON_VALUE)
.header("Authorization", "Bearer " + zoneAdminToken)
.contentType(APPLICATION_JSON)
.content(JsonUtils.writeValueAsString(request))
.header(IdentityZoneSwitchingFilter.HEADER, zone.getId());
MvcResult result = getMockMvc().perform(post)
.andExpect(status().isOk())
.andReturn();
assertEquals("\"ok\"", result.getResponse().getContentAsString());
//Correct configuration, invalid credentials
token = new UsernamePasswordAuthentication("marissa2", "koala");
request = new IdentityProviderValidationRequest(provider, token);
post = post("/identity-providers/test")
.header("Accept", APPLICATION_JSON_VALUE)
.header("Content-Type", APPLICATION_JSON_VALUE)
.header("Authorization", "Bearer " + zoneAdminToken)
.contentType(APPLICATION_JSON)
.content(JsonUtils.writeValueAsString(request))
.header(IdentityZoneSwitchingFilter.HEADER, zone.getId());
result = getMockMvc().perform(post)
.andExpect(status().isExpectationFailed())
.andReturn();
assertEquals("\"bad credentials\"", result.getResponse().getContentAsString());
//Insufficent scope
post = post("/identity-providers/test")
.header("Accept", APPLICATION_JSON_VALUE)
.header("Content-Type", APPLICATION_JSON_VALUE)
.header("Authorization", "Bearer " + identityAccessToken)
.contentType(APPLICATION_JSON)
.content(JsonUtils.writeValueAsString(request))
.header(IdentityZoneSwitchingFilter.HEADER, zone.getId());
result = getMockMvc().perform(post)
.andExpect(status().isForbidden())
.andReturn();
//Invalid LDAP configuration - change the password of search user
definition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
"ldap://localhost:33389",
"cn=admin,ou=Users,dc=test,dc=com",
"adminsecret23",
"dc=test,dc=com",
"cn={0}",
"ou=scopes,dc=test,dc=com",
"member={0}",
"mail",
null,
false,
true,
true,
10,
true
);
provider.setConfig(definition);
request = new IdentityProviderValidationRequest(provider, token);
post = post("/identity-providers/test")
.header("Accept", APPLICATION_JSON_VALUE)
.header("Content-Type", APPLICATION_JSON_VALUE)
.header("Authorization", "Bearer " + zoneAdminToken)
.contentType(APPLICATION_JSON)
.content(JsonUtils.writeValueAsString(request))
.header(IdentityZoneSwitchingFilter.HEADER, zone.getId());
result = getMockMvc().perform(post)
.andExpect(status().isBadRequest())
.andReturn();
assertThat(result.getResponse().getContentAsString(), containsString("Caused by:"));
//Invalid LDAP configuration - no ldap server
definition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
"ldap://localhost:33388",
"cn=admin,ou=Users,dc=test,dc=com",
"adminsecret",
"dc=test,dc=com",
"cn={0}",
"ou=scopes,dc=test,dc=com",
"member={0}",
"mail",
null,
false,
true,
true,
10,
true
);
provider.setConfig(definition);
request = new IdentityProviderValidationRequest(provider, token);
post = post("/identity-providers/test")
.header("Accept", APPLICATION_JSON_VALUE)
.header("Content-Type", APPLICATION_JSON_VALUE)
.header("Authorization", "Bearer " + zoneAdminToken)
.contentType(APPLICATION_JSON)
.content(JsonUtils.writeValueAsString(request))
.header(IdentityZoneSwitchingFilter.HEADER, zone.getId());
result = getMockMvc().perform(post)
.andExpect(status().isBadRequest())
.andReturn();
assertThat(result.getResponse().getContentAsString(), containsString("Caused by:"));
//Invalid LDAP configuration - invalid search base
definition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
"ldap://localhost:33389",
"cn=admin,ou=Users,dc=test,dc=com",
"adminsecret",
",,,,,dc=test,dc=com",
"cn={0}",
"ou=scopes,dc=test,dc=com",
"member={0}",
"mail",
null,
false,
true,
true,
10,
true
);
provider.setConfig(definition);
request = new IdentityProviderValidationRequest(provider, token);
post = post("/identity-providers/test")
.header("Accept", APPLICATION_JSON_VALUE)
.header("Content-Type", APPLICATION_JSON_VALUE)
.header("Authorization", "Bearer " + zoneAdminToken)
.contentType(APPLICATION_JSON)
.content(JsonUtils.writeValueAsString(request))
.header(IdentityZoneSwitchingFilter.HEADER, zone.getId());
result = getMockMvc().perform(post)
.andExpect(status().isBadRequest())
.andReturn();
assertThat(result.getResponse().getContentAsString(), containsString("Caused by:"));
token = new UsernamePasswordAuthentication("marissa2", LDAP);
//SSL self signed cert problems
definition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
"ldaps://localhost:33636",
"cn=admin,ou=Users,dc=test,dc=com",
"adminsecret",
"dc=test,dc=com",
"cn={0}",
"ou=scopes,dc=test,dc=com",
"member={0}",
"mail",
null,
false,
true,
true,
10,
false
);
provider.setConfig(definition);
request = new IdentityProviderValidationRequest(provider, token);
post = post("/identity-providers/test")
.header("Accept", APPLICATION_JSON_VALUE)
.header("Content-Type", APPLICATION_JSON_VALUE)
.header("Authorization", "Bearer " + zoneAdminToken)
.contentType(APPLICATION_JSON)
.content(JsonUtils.writeValueAsString(request))
.header(IdentityZoneSwitchingFilter.HEADER, zone.getId());
result = getMockMvc().perform(post)
.andExpect(status().isBadRequest())
.andReturn();
assertThat(result.getResponse().getContentAsString(), containsString("Caused by:"));
definition.setSkipSSLVerification(true);
provider.setConfig(definition);
request = new IdentityProviderValidationRequest(provider, token);
post = post("/identity-providers/test")
.header("Accept", APPLICATION_JSON_VALUE)
.header("Content-Type", APPLICATION_JSON_VALUE)
.header("Authorization", "Bearer " + zoneAdminToken)
.contentType(APPLICATION_JSON)
.content(JsonUtils.writeValueAsString(request))
.header(IdentityZoneSwitchingFilter.HEADER, zone.getId());
result = getMockMvc().perform(post)
.andExpect(status().isOk())
.andReturn();
assertThat(result.getResponse().getContentAsString(), containsString("\"ok\""));
}
@Test
public void testLoginInNonDefaultZone() throws Exception {
assumeFalse(!(ldapProfile.contains("ldap-search-and-bind.xml") &&
ldapGroup.contains("ldap-groups-map-to-scopes.xml")));
getMockMvc().perform(get("/login")
.header(HOST, host))
.andExpect(status().isOk())
.andExpect(view().name("login"))
.andExpect(model().attributeDoesNotExist("saml"));
getMockMvc().perform(post("/login.do").accept(TEXT_HTML_VALUE)
.with(cookieCsrf())
.header(HOST, host)
.param("username", "marissa2")
.param("password", LDAP))
.andExpect(status().isFound())
.andExpect(authenticated())
.andExpect(redirectedUrl("/"));
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
UaaUser user = getWebApplicationContext().getBean(UaaUserDatabase.class).retrieveUserByName("marissa2", LDAP);
IdentityZoneHolder.clear();
assertNotNull(user);
assertEquals(LDAP, user.getOrigin());
assertEquals(zone.getZone().getIdentityZone().getId(), user.getZoneId());
provider.setActive(false);
utils().createIdpUsingWebRequest(getMockMvc(), zone.getZone().getIdentityZone().getId(), zone.getZone().getZoneAdminToken(), provider, status().isOk(), true);
getMockMvc().perform(post("/login.do").accept(TEXT_HTML_VALUE)
.with(cookieCsrf())
.header(HOST, host)
.param("username", "marissa2")
.param("password", LDAP))
.andExpect(status().isFound())
.andExpect(unauthenticated())
.andExpect(redirectedUrl("/login?error=login_failure"));
provider.setActive(true);
utils().createIdpUsingWebRequest(getMockMvc(), zone.getZone().getIdentityZone().getId(), zone.getZone().getZoneAdminToken(), provider, status().isOk(), true);
getMockMvc().perform(post("/login.do").accept(TEXT_HTML_VALUE)
.with(cookieCsrf())
.header(HOST, host)
.param("username", "marissa2")
.param("password", LDAP))
.andExpect(status().isFound())
.andExpect(authenticated())
.andExpect(redirectedUrl("/"));
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
user = getWebApplicationContext().getBean(UaaUserDatabase.class).retrieveUserByName("marissa2", LDAP);
IdentityZoneHolder.clear();
assertNotNull(user);
assertEquals(LDAP, user.getOrigin());
assertEquals(zone.getZone().getIdentityZone().getId(), user.getZoneId());
assertEquals("marissa2@test.com", user.getEmail());
}
@Test
public void testLogin_partial_result_exception_on_group_search() throws Exception {
getMockMvc().perform(post("/login.do").accept(TEXT_HTML_VALUE)
.with(cookieCsrf())
.header(HOST, host)
.param("username", "marissa8")
.param("password", "ldap8"))
.andExpect(status().isFound())
.andExpect(authenticated())
.andExpect(redirectedUrl("/"));
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
UaaUser user = getWebApplicationContext().getBean(UaaUserDatabase.class).retrieveUserByName("marissa8", LDAP);
IdentityZoneHolder.clear();
assertNotNull(user);
assertEquals(LDAP, user.getOrigin());
assertEquals(zone.getZone().getIdentityZone().getId(), user.getZoneId());
}
public void test_memberOf_search() throws Exception {
provider.getConfig().setGroupSearchBase("memberOf");
updateLdapProvider();
Object securityContext = getMockMvc().perform(post("/login.do").accept(TEXT_HTML_VALUE)
.with(cookieCsrf())
.header(HOST, host)
.param("username", "marissa10")
.param("password", "ldap10"))
.andExpect(status().isFound())
.andExpect(redirectedUrl("/"))
.andReturn().getRequest().getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
assertNotNull(securityContext);
assertTrue(securityContext instanceof SecurityContext);
String[] list = new String[]{
"internal.read",
"internal.everything",
"internal.superuser"
};
Authentication authentication = ((SecurityContext) securityContext).getAuthentication();
validateUserAuthorities(list, authentication);
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
UaaUser user = getWebApplicationContext().getBean(UaaUserDatabase.class).retrieveUserByName("marissa10", LDAP);
IdentityZoneHolder.clear();
assertNotNull(user);
assertEquals(LDAP, user.getOrigin());
assertEquals(zone.getZone().getIdentityZone().getId(), user.getZoneId());
}
public ClassPathXmlApplicationContext getBeanContext() throws Exception {
DynamicZoneAwareAuthenticationManager zm = getWebApplicationContext().getBean(DynamicZoneAwareAuthenticationManager.class);
zm.getLdapAuthenticationManager(zone.getZone().getIdentityZone(), provider).getLdapAuthenticationManager();
return zm.getLdapAuthenticationManager(zone.getZone().getIdentityZone(), provider).getContext();
}
public Object getBean(String name) throws Exception {
ClassPathXmlApplicationContext beanContext = getBeanContext();
return beanContext.getBean(name);
}
public <T> T getBean(Class<T> clazz) throws Exception {
return getBeanContext().getBean(clazz);
}
@Test
public void printProfileType() throws Exception {
assertEquals(ldapProfile, getBean("testLdapProfile"));
assertEquals(ldapGroup, getBean("testLdapGroup"));
}
@Test
public void test_read_and_write_config_then_login() throws Exception {
String response = getMockMvc().perform(
get("/identity-providers/"+provider.getId())
.header(ACCEPT, APPLICATION_JSON)
.header(HOST, host)
.header(AUTHORIZATION, "Bearer " + zone.getAdminToken())
)
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();
assertThat(response, not(containsString("bindPassword")));
IdentityProvider<LdapIdentityProviderDefinition> provider = JsonUtils.readValue(response, new TypeReference<IdentityProvider<LdapIdentityProviderDefinition>>() {});
assertNull(provider.getConfig().getBindPassword());
getMockMvc().perform(
put("/identity-providers/"+provider.getId())
.content(JsonUtils.writeValueAsString(provider))
.header(CONTENT_TYPE, APPLICATION_JSON)
.header(ACCEPT, APPLICATION_JSON)
.header(HOST, host)
.header(AUTHORIZATION, "Bearer " + zone.getAdminToken())
)
.andExpect(status().isOk());
testSuccessfulLogin();
}
@Test
public void testLogin() throws Exception {
getMockMvc().perform(
get("/login")
.header(HOST, host))
.andExpect(status().isOk())
.andExpect(view().name("login"))
.andExpect(model().attributeDoesNotExist("saml"));
getMockMvc().perform(
post("/login.do").accept(TEXT_HTML_VALUE)
.header(HOST, host)
.with(cookieCsrf())
.param("username", "marissa")
.param("password", "koaladsada"))
.andExpect(status().isFound())
.andExpect(unauthenticated())
.andExpect(redirectedUrl("/login?error=login_failure"));
testSuccessfulLogin();
}
@Test
public void testTwoLdapServers() throws Exception {
int port = 33389 + 400 + (ldapPortRotation++);
int sslPort = 33636 + 400 + (ldapPortRotation++);
apacheDS2 = ApacheDSHelper.start(port,sslPort);
String originalUrl = ldapBaseUrl;
if (ldapBaseUrl.contains("ldap://")) {
ldapBaseUrl = ldapBaseUrl + " ldap://localhost:"+port;
} else {
ldapBaseUrl = ldapBaseUrl + " ldaps://localhost:"+sslPort;
}
provider.getConfig().setBaseUrl(ldapBaseUrl);
updateLdapProvider();
try {
testSuccessfulLogin();
apacheDS.stop();
testSuccessfulLogin();
apacheDS2.stop();
} finally {
ldapBaseUrl = originalUrl;
if (apacheDS.isRunning()) {
apacheDS.stop();
}
apacheDS = null;
if (apacheDS2.isRunning()) {
apacheDS2.stop();
}
apacheDS2 = null;
Thread.sleep(1500);
apacheDS = ApacheDSHelper.start();
}
}
@Test
public void test_username_with_space() throws Exception {
getMockMvc().perform(
post("/login.do").accept(TEXT_HTML_VALUE)
.header(HOST, host)
.with(cookieCsrf())
.param("username", "marissa 11")
.param("password", "ldap11"))
.andExpect(status().isFound())
.andExpect(redirectedUrl("/"));
}
protected void testSuccessfulLogin() throws Exception {
getMockMvc().perform(post("/login.do").accept(TEXT_HTML_VALUE)
.header(HOST, host)
.with(cookieCsrf())
.param("username", "marissa2")
.param("password", LDAP))
.andExpect(status().isFound())
.andExpect(authenticated())
.andExpect(redirectedUrl("/"));
}
@Test
public void testAuthenticateWithUTF8Characters() throws Exception {
String username = "\u7433\u8D3A";
HttpSession session =
getMockMvc().perform(
post("/login.do").accept(TEXT_HTML_VALUE)
.header(HOST, host)
.with(cookieCsrf())
.param("username", username)
.param("password", "koala"))
.andExpect(status().isFound())
.andExpect(redirectedUrl("/"))
.andExpect(authenticated())
.andReturn().getRequest().getSession(false);
assertNotNull(session);
assertNotNull(session.getAttribute(SPRING_SECURITY_CONTEXT_KEY));
Authentication authentication = ((SecurityContext)session.getAttribute(SPRING_SECURITY_CONTEXT_KEY)).getAuthentication();
assertNotNull(authentication);
assertTrue(authentication.isAuthenticated());
}
@Test
public void testAuthenticate() throws Exception {
String username = "marissa3";
String password = "ldap3";
MvcResult result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"marissa3@test.com\""));
}
@Test
public void testExtendedAttributes() throws Exception {
String username = "marissa3";
String password = "ldap3";
MvcResult result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"marissa3@test.com\""));
assertEquals("Marissa", getGivenName(username));
assertEquals("Lastnamerton", getFamilyName(username));
assertEquals("8885550986", getPhoneNumber(username));
}
@Test
public void testAuthenticateInactiveIdp() throws Exception {
provider.setActive(false);
updateLdapProvider();
String username = "marissa3";
String password = "ldap3";
performAuthentication(username, password, HttpStatus.UNAUTHORIZED);
}
@Test
public void testAuthenticateFailure() throws Exception {
String username = "marissa3";
String password = "ldapsadadasas";
MockHttpServletRequestBuilder post =
post("/authenticate")
.header(HOST, host)
.accept(MediaType.APPLICATION_JSON)
.param("username", username)
.param("password", password);
getMockMvc().perform(post)
.andExpect(status().isUnauthorized());
}
@Test
public void validateOriginForNonLdapUser() throws Exception {
String username = "marissa";
String password = "koala";
ScimUser user = new ScimUser(null, username, "Marissa","Koala");
user.setPrimaryEmail("marissa@test.org");
user.setPassword(password);
utils().createUserInZone(getMockMvc(), zone.getAdminToken(), user, zone.getZone().getIdentityZone().getSubdomain());
MvcResult result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"marissa@test.org\""));
assertEquals(OriginKeys.UAA, getOrigin(username));
}
@Test
public void validateOriginAndEmailForLdapUser() throws Exception {
String username = "marissa3";
String password = "ldap3";
MvcResult result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"marissa3@test.com\""));
assertEquals(LDAP, getOrigin(username));
assertEquals("marissa3@test.com",getEmail(username));
}
@Test
public void validateEmailMissingForLdapUser() throws Exception {
String username = "marissa7";
String password = "ldap7";
MvcResult result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"marissa7@user.from.ldap.cf\""));
assertEquals(LDAP, getOrigin(username));
assertEquals("marissa7@user.from.ldap.cf", getEmail(username));
}
@Test
@Ignore("This test was previously not run and does not pass")
public void validateLoginAsInvitedUserWithoutClickingInviteLink() throws Exception {
UaaUserDatabase userDatabase = getWebApplicationContext().getBean(UaaUserDatabase.class);
ScimUser createdUser;
try {
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
assertNull(userDatabase.retrieveUserByEmail("marissa7@user.from.ldap.cf", LDAP));
ScimUser user = new ScimUser(null, "marissa7@user.from.ldap.cf", "Marissa", "Seven");
user.setPrimaryEmail("marissa7@user.from.ldap.cf");
user.setOrigin(LDAP);
createdUser = getWebApplicationContext().getBean(ScimUserProvisioning.class).createUser(user, "");
} finally {
IdentityZoneHolder.clear();
}
performUiAuthentication("marissa7", "ldap7", HttpStatus.FOUND, true);
UaaUser authedUser = retrieveUserInZone(userDatabase, "marissa7@createdUser.from.ldap.cf", LDAP);
assertEquals(createdUser.getId(), authedUser.getId());
assertEquals("marissa7", authedUser.getUsername());
try {
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
List<ScimUser> scimUserList = getWebApplicationContext().getBean(ScimUserProvisioning.class).query(String.format("origin eq \"%s\"", LDAP));
assertEquals(1, scimUserList.size());
} finally {
IdentityZoneHolder.clear();
}
}
public UaaUser retrieveUserInZone(UaaUserDatabase userDatabase, String email, String origin) {
try {
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
return userDatabase.retrieveUserByEmail(email, origin);
} finally {
IdentityZoneHolder.clear();
}
}
@Test
public void validateCustomEmailForLdapUser() throws Exception {
provider.getConfig().setMailSubstitute("{0}@ldaptest.org");
updateLdapProvider();
String username = "marissa7";
String password = "ldap7";
MvcResult result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"marissa7@ldaptest.org\""));
assertEquals(LDAP, getOrigin(username));
assertEquals("marissa7@ldaptest.org",getEmail(username));
provider.getConfig().setMailSubstitute(null);
updateLdapProvider();
//null value should go back to default email
username = "marissa3";
password = "ldap3";
result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"marissa3@test.com\""));
assertEquals(LDAP, getOrigin(username));
assertEquals("marissa3@test.com",getEmail(username));
username = "marissa7";
password = "ldap7";
result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"marissa7@user.from.ldap.cf\""));
assertEquals(LDAP, getOrigin(username));
assertEquals("marissa7@user.from.ldap.cf",getEmail(username));
//non null value
provider.getConfig().setMailSubstitute("user-{0}@testldap.org");
updateLdapProvider();
result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"user-marissa7@testldap.org\""));
assertEquals(LDAP, getOrigin(username));
assertEquals("user-marissa7@testldap.org",getEmail(username));
//value not overridden
username = "marissa3";
password = "ldap3";
result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"marissa3@test.com\""));
assertEquals(LDAP, getOrigin(username));
assertEquals("marissa3@test.com",getEmail(username));
provider.getConfig().setMailSubstituteOverridesLdap(true);
updateLdapProvider();
username = "marissa3";
password = "ldap3";
result = performAuthentication(username, password);
assertThat(result.getResponse().getContentAsString(), containsString("\"username\":\"" + username + "\""));
assertThat(result.getResponse().getContentAsString(), containsString("\"email\":\"user-marissa3@testldap.org\""));
assertEquals(LDAP, getOrigin(username));
assertEquals("user-marissa3@testldap.org",getEmail(username));
}
private String getOrigin(String username) throws Exception {
return getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select origin from users where username=? and identity_zone_id=?", String.class, username, zone.getZone().getIdentityZone().getId());
}
private String getEmail(String username) throws Exception {
return getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select email from users where username=? and origin=? and identity_zone_id=?", String.class, username, LDAP, zone.getZone().getIdentityZone().getId());
}
private String getGivenName(String username) throws Exception {
return getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select givenname from users where username=? and origin=? and identity_zone_id=?", String.class, username, LDAP, zone.getZone().getIdentityZone().getId());
}
private String getFamilyName(String username) throws Exception {
return getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select familyname from users where username=? and origin=? and identity_zone_id=?", String.class, username, LDAP, zone.getZone().getIdentityZone().getId());
}
private String getPhoneNumber(String username) throws Exception {
return getWebApplicationContext().getBean(JdbcTemplate.class).queryForObject("select phonenumber from users where username=? and origin=? and identity_zone_id=?", String.class, username, LDAP, zone.getZone().getIdentityZone().getId());
}
private MvcResult performAuthentication(String username, String password) throws Exception {
return performAuthentication(username, password, HttpStatus.OK);
}
private MvcResult performAuthentication(String username, String password, HttpStatus status) throws Exception {
MockHttpServletRequestBuilder post =
post("/authenticate")
.header(HOST, host)
.accept(MediaType.APPLICATION_JSON)
.param("username", username)
.param("password", password);
return getMockMvc().perform(post)
.andExpect(status().is(status.value()))
.andReturn();
}
private MvcResult performUiAuthentication(String username, String password, HttpStatus status, boolean authenticated) throws Exception {
MockHttpServletRequestBuilder post =
post("/login.do")
.with(cookieCsrf())
.header(HOST, host)
.accept(MediaType.TEXT_HTML)
.param("username", username)
.param("password", password);
return getMockMvc().perform(post)
.andExpect(status().is(status.value()))
.andExpect(authenticated ? authenticated() : unauthenticated())
.andReturn();
}
@Test
public void testLdapScopes() throws Exception {
assumeTrue(ldapGroup.equals("ldap-groups-as-scopes.xml"));
AuthenticationManager manager = (AuthenticationManager)getBean("ldapAuthenticationManager");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa3","ldap3");
Authentication auth = manager.authenticate(token);
assertNotNull(auth);
String[] list = new String[]{
"uaa.admin",
"cloud_controller.read",
"thirdmarissa"
};
assertThat(list, arrayContainingInAnyOrder(getAuthorities(auth.getAuthorities())));
}
@Test
public void testLdapScopesFromChainedAuth() throws Exception {
assumeTrue(ldapGroup.equals("ldap-groups-as-scopes.xml"));
AuthenticationManager manager = (AuthenticationManager)getWebApplicationContext().getBean("zoneAwareAuthzAuthenticationManager");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa3","ldap3");
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
Authentication auth = manager.authenticate(token);
assertNotNull(auth);
String[] list = new String[]{
"uaa.admin",
"password.write",
"scim.userids",
"approvals.me",
"cloud_controller.write",
"scim.me",
"cloud_controller_service_permissions.read",
"openid",
"profile",
"roles",
"oauth.approvals",
"uaa.user",
"cloud_controller.read",
"user_attributes",
UaaTokenServices.UAA_REFRESH_TOKEN,
"thirdmarissa"
};
assertThat(list, arrayContainingInAnyOrder(getAuthorities(auth.getAuthorities())));
IdentityZoneHolder.clear();
}
@Test
public void testNestedLdapScopes() throws Exception {
if (!ldapGroup.equals("ldap-groups-as-scopes.xml")) {
return;
}
Set<String> defaultAuthorities = new HashSet((Set<String>)getWebApplicationContext().getBean("defaultUserAuthorities"));
AuthenticationManager manager = getWebApplicationContext().getBean(DynamicZoneAwareAuthenticationManager.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa4","ldap4");
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
Authentication auth = manager.authenticate(token);
assertNotNull(auth);
defaultAuthorities.addAll(Arrays.asList("test.read", "test.write", "test.everything"));
assertThat(UaaStringUtils.getStringsFromAuthorities(auth.getAuthorities()), containsInAnyOrder(defaultAuthorities.toArray()));
IdentityZoneHolder.clear();
}
public void doTestNestedLdapGroupsMappedToScopes(String username, String password, String[] expected) throws Exception {
assumeTrue(ldapGroup.equals("ldap-groups-map-to-scopes.xml"));
AuthenticationManager manager = getWebApplicationContext().getBean(DynamicZoneAwareAuthenticationManager.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username,password);
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
Authentication auth = manager.authenticate(token);
assertNotNull(auth);
validateUserAuthorities(expected, auth);
IdentityZoneHolder.clear();
}
protected void validateUserAuthorities(String[] expected, Authentication auth) throws Exception {
Set<String> defaultAuthorities = new HashSet((Set<String>) getWebApplicationContext().getBean("defaultUserAuthorities"));
for (String s : expected) {
defaultAuthorities.add(s);
}
assertThat(UaaStringUtils.getStringsFromAuthorities(auth.getAuthorities()), containsInAnyOrder(defaultAuthorities.toArray()));
}
@Test
public void testNestedLdapGroupsMappedToScopes() throws Exception {
String[] list = new String[] {
"internal.read",
"internal.write",
"internal.everything",
"internal.superuser"
};
doTestNestedLdapGroupsMappedToScopes("marissa4","ldap4",list);
}
@Test
public void testNestedLdapGroupsMappedToScopes2() throws Exception {
String[] list = new String[] {
"internal.read",
"internal.write",
};
doTestNestedLdapGroupsMappedToScopes("marissa5","ldap5",list);
}
@Test
public void testNestedLdapGroupsMappedToScopes3() throws Exception {
String[] list = new String[] {
"internal.read",
};
doTestNestedLdapGroupsMappedToScopes("marissa6","ldap6",list);
}
@Test
public void testNestedLdapGroupsMappedToScopesWithDefaultScopes() throws Exception {
String username = "marissa4";
String password = "ldap4";
String[] list = new String[] {
"internal.read",
"internal.write",
"internal.everything",
"internal.superuser"
};
doTestNestedLdapGroupsMappedToScopesWithDefaultScopes(username, password, list);
}
@Test
public void testNestedLdapGroupsMappedToScopesWithDefaultScopes2() throws Exception {
String username = "marissa5";
String password = "ldap5";
String[] list = new String[] {
"internal.read",
"internal.write",
};
doTestNestedLdapGroupsMappedToScopesWithDefaultScopes(username,password,list);
}
@Test
public void testNestedLdapGroupsMappedToScopesWithDefaultScopes3() throws Exception {
String username = "marissa6";
String password = "ldap6";
String[] list = new String[] {
"internal.read",
};
doTestNestedLdapGroupsMappedToScopesWithDefaultScopes(username,password,list);
}
@Test
public void testStopIfException() throws Exception {
if (ldapProfile.equals("ldap-simple-bind.xml") && ldapGroup.equals("ldap-groups-null.xml")) {
ScimUser user = new ScimUser();
String userName = "user"+new RandomValueStringGenerator().generate()+"@example.com";
user.setUserName(userName);
user.addEmail(userName);
user.setVerified(true);
user.setPassword("n1cel0ngp455w0rd");
user = utils().createUserInZone(getMockMvc(), zone.getAdminToken(), user, zone.getZone().getIdentityZone().getSubdomain());
assertNotNull(user.getId());
performAuthentication(userName, "n1cel0ngp455w0rd", HttpStatus.OK);
}
}
public void doTestNestedLdapGroupsMappedToScopesWithDefaultScopes(String username, String password, String[] expected) throws Exception {
assumeTrue(ldapGroup.equals("ldap-groups-map-to-scopes.xml"));
AuthenticationManager manager = getWebApplicationContext().getBean(DynamicZoneAwareAuthenticationManager.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username,password);
IdentityZoneHolder.set(zone.getZone().getIdentityZone());
Authentication auth = manager.authenticate(token);
assertNotNull(auth);
Set<String> defaultAuthorities = new HashSet((Set<String>)getWebApplicationContext().getBean("defaultUserAuthorities"));
defaultAuthorities.addAll(Arrays.asList(expected));
assertThat(UaaStringUtils.getStringsFromAuthorities(auth.getAuthorities()), containsInAnyOrder(defaultAuthorities.toArray()));
}
public String[] getAuthorities(Collection<? extends GrantedAuthority> authorities) {
String[] result = new String[authorities!=null?authorities.size():0];
if (result.length>0) {
int index=0;
for (GrantedAuthority a : authorities) {
result[index++] = a.getAuthority();
}
}
return result;
}
public void updateLdapProvider() throws Exception {
provider = utils().createIdpUsingWebRequest(
getMockMvc(),
zone.getZone().getIdentityZone().getId(),
zone.getZone().getZoneAdminToken(),
provider,
status().isOk(),
true
);
}
}