From 7dd538ff6ef75aeb8c7f63b7a96a3f800b3a5770 Mon Sep 17 00:00:00 2001 From: Danny Faught Date: Wed, 21 Feb 2024 16:07:12 -0800 Subject: [PATCH 1/2] delete: unused test * This test covers IdP features that are no longer supported. [#187065237] Co-authored-by: Hongchol Sinn --- .../saml/SamlAuthenticationMockMvcTests.java | 57 ------------------- 1 file changed, 57 deletions(-) diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/saml/SamlAuthenticationMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/saml/SamlAuthenticationMockMvcTests.java index db9765ec64a..b9f3c73ef7b 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/saml/SamlAuthenticationMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/saml/SamlAuthenticationMockMvcTests.java @@ -18,7 +18,6 @@ import org.cloudfoundry.identity.uaa.provider.saml.idp.SamlServiceProvider; import org.cloudfoundry.identity.uaa.scim.ScimUser; import org.cloudfoundry.identity.uaa.scim.jdbc.JdbcScimUserProvisioning; -import org.cloudfoundry.identity.uaa.user.UaaAuthority; import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.hamcrest.BaseMatcher; @@ -30,33 +29,23 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpSession; -import org.springframework.security.core.GrantedAuthority; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.client.BaseClientDetails; 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.RequestPostProcessor; import org.springframework.web.context.WebApplicationContext; -import org.xml.sax.InputSource; -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathFactory; -import java.io.StringReader; import java.util.*; import java.util.function.Consumer; -import java.util.stream.Collectors; import static org.apache.logging.log4j.Level.DEBUG; import static org.apache.logging.log4j.Level.WARN; import static org.cloudfoundry.identity.uaa.authentication.SamlResponseLoggerBinding.X_VCAP_REQUEST_ID_HEADER; -import static org.cloudfoundry.identity.uaa.mock.util.MockMvcUtils.getUaaSecurityContext; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.springframework.http.HttpHeaders.CONTENT_TYPE; import static org.springframework.http.HttpHeaders.HOST; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.securityContext; 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.result.MockMvcResultHandlers.print; @@ -72,7 +61,6 @@ class SamlAuthenticationMockMvcTests { private IdentityZone idpZone; private String spZoneEntityId; private IdentityProvider idp; - private SamlServiceProvider samlServiceProvider; @Autowired private MockMvc mockMvc; @@ -168,29 +156,6 @@ void sendAuthnRequestToIdp() throws Exception { .andExpect(redirectedUrl("http://" + idpZone.getSubdomain() + ".localhost:8080/uaa/login")); } - @Disabled("The test depends on IDP endpoints, which was removed.") - @Test - void validateStaticAttributes( - ) throws Exception { - createIdp(); - - samlServiceProvider.getConfig().getStaticCustomAttributes().put("portal_id", "portal"); - samlServiceProvider.getConfig().getStaticCustomAttributes().put("portal_emails", Arrays.asList("portal1@portal.test", "portal2@portal.test")); - - String samlResponse = performIdpAuthentication(); - String xml = extractAssertion(samlResponse, true); - XPath xpath = XPathFactory.newInstance().newXPath(); - String emails = (String) xpath.evaluate("//*[local-name()='Attribute'][@*[local-name()='Name' and .='portal_emails']]", new InputSource(new StringReader(xml)), XPathConstants.STRING); - assertThat(emails, containsString("portal1@portal.test")); - assertThat(emails, containsString("portal2@portal.test")); - } - - private ResultActions postSamlResponse( - final String xml - ) throws Exception { - return postSamlResponse(xml, "", "", ""); - } - private ResultActions postSamlResponse( final String xml, final String queryString, @@ -306,23 +271,6 @@ public void describeTo(Description description) { } } - private String performIdpAuthentication() throws Exception { - return performIdpAuthentication(Collections.singletonList("uaa.user")); - } - - private String performIdpAuthentication(List authorityNames) throws Exception { - List grantedAuthorityList = authorityNames.stream().map(UaaAuthority::authority).collect(Collectors.toList()); - RequestPostProcessor marissa = securityContext(getUaaSecurityContext("marissa", webApplicationContext, idpZone.getId(), grantedAuthorityList)); - return mockMvc.perform( - get("/saml/idp/initiate") - .header("Host", idpZone.getSubdomain() + ".localhost") - .param("sp", spZoneEntityId) - .with(marissa) - ) - .andDo(print()) - .andReturn().getResponse().getContentAsString(); - } - private String getSamlMetadata(String subdomain, String url) throws Exception { return mockMvc.perform( get(url) @@ -374,11 +322,6 @@ private IdentityZone createZone(String zoneIdPrefix, BaseClientDetails adminClie ).getIdentityZone(); } - private static String extractAssertion(String response, boolean decode) { - String searchFor = "name=\"SAMLResponse\" value=\""; - return extractFormParameter(searchFor, response, decode); - } - private static String extractSamlRequest(String response) { String searchFor = "name=\"SAMLRequest\" value=\""; return extractFormParameter(searchFor, response, false); From 7c9d2963dfacfdf1e037824d4547f7e363b74d05 Mon Sep 17 00:00:00 2001 From: Danny Faught Date: Wed, 21 Feb 2024 17:18:27 -0800 Subject: [PATCH 2/2] delete: another unused test * When this test works, the discovery endpoint redirects to something like this: "http://uaa-acting-as-saml-proxy-zone-isq9kv.localhost:8080/uaa/saml/login/alias/uaa-acting-as-saml-pr[...]aml-idp-zone-bd8ptn.cloudfoundry-saml-login". * To keep the coverage for the part of the test that hits that "saml/login/alias" endpoint, we would need to rewrite it so that it doesn't depend on the SAML IdP features that were removed from UAA. We're deferring the decision to add this coverage back. [#187065237] Co-authored-by: Hongchol Sinn --- .../saml/SamlAuthenticationMockMvcTests.java | 72 ------------------- 1 file changed, 72 deletions(-) diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/saml/SamlAuthenticationMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/saml/SamlAuthenticationMockMvcTests.java index b9f3c73ef7b..ee2ba4f1668 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/saml/SamlAuthenticationMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/saml/SamlAuthenticationMockMvcTests.java @@ -15,7 +15,6 @@ import org.cloudfoundry.identity.uaa.provider.IdentityProvider; import org.cloudfoundry.identity.uaa.provider.JdbcIdentityProviderProvisioning; import org.cloudfoundry.identity.uaa.provider.SamlIdentityProviderDefinition; -import org.cloudfoundry.identity.uaa.provider.saml.idp.SamlServiceProvider; import org.cloudfoundry.identity.uaa.scim.ScimUser; import org.cloudfoundry.identity.uaa.scim.jdbc.JdbcScimUserProvisioning; import org.cloudfoundry.identity.uaa.zone.IdentityZone; @@ -28,11 +27,9 @@ import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; -import org.springframework.mock.web.MockHttpSession; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.ResultActions; import org.springframework.web.context.WebApplicationContext; @@ -48,9 +45,6 @@ import static org.springframework.http.HttpHeaders.HOST; 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.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @DefaultTestContext class SamlAuthenticationMockMvcTests { @@ -113,49 +107,6 @@ void putBackOriginalLogger() { loggingAuditService.setLogger(originalAuditServiceLogger); } - @Disabled("The test depends on IDP endpoints, which was removed.") - @Test - void sendAuthnRequestToIdp() throws Exception { - createIdp(); - - String idpEntityId = idpZone.getSubdomain() + ".cloudfoundry-saml-login"; - MvcResult mvcResult = mockMvc.perform( - get("/uaa/saml/discovery") - .contextPath("/uaa") - .header(HOST, spZone.getSubdomain() + ".localhost:8080") - .param("returnIDParam", "idp") - .param("entityID", spZoneEntityId) - .param("idp", idp.getOriginKey()) - .param("isPassive", "true") - ) - .andExpect(status().isFound()) - .andReturn(); - - mvcResult = mockMvc.perform( - get(mvcResult.getResponse().getRedirectedUrl()) - .contextPath("/uaa") - .header(HOST, spZone.getSubdomain() + ".localhost:8080") - .session((MockHttpSession) mvcResult.getRequest().getSession()) - - ) - .andDo(print()) - .andExpect(status().isOk()) - .andReturn(); - - String body = mvcResult.getResponse().getContentAsString(); - String relayState = extractRelayState(body); - String samlRequest = extractSamlRequest(body); - mockMvc.perform( - post("/uaa/saml/idp/SSO/alias/" + idpEntityId) - .contextPath("/uaa") - .header(HOST, idpZone.getSubdomain() + ".localhost:8080") - .param("RelayState", relayState) - .param("SAMLRequest", samlRequest) - ) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("http://" + idpZone.getSubdomain() + ".localhost:8080/uaa/login")); - } - private ResultActions postSamlResponse( final String xml, final String queryString, @@ -321,27 +272,4 @@ private IdentityZone createZone(String zoneIdPrefix, BaseClientDetails adminClie adminClient, IdentityZoneHolder.getCurrentZoneId() ).getIdentityZone(); } - - private static String extractSamlRequest(String response) { - String searchFor = "name=\"SAMLRequest\" value=\""; - return extractFormParameter(searchFor, response, false); - } - - private static String extractRelayState(String response) { - String searchFor = "name=\"RelayState\" value=\""; - return extractFormParameter(searchFor, response, false); - } - - private static String extractFormParameter(String searchFor, String response, boolean decode) { - int start = response.indexOf(searchFor) + searchFor.length(); - assertThat("Must find the SAML response in output\n" + response, start, greaterThan(searchFor.length())); - int end = response.indexOf("\"/>", start); - assertThat("Must find the SAML response in output\n" + response, end, greaterThan(start)); - String encoded = response.substring(start, end); - if (decode) { - return new String(Base64.getDecoder().decode(encoded)); - } else { - return encoded; - } - } }