/* * * Copyright 2016 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.netflix.genie.web.security.saml; import com.netflix.genie.test.categories.UnitTest; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.mockito.Mockito; import org.opensaml.saml2.metadata.provider.MetadataProviderException; import org.opensaml.xml.parse.ParserPool; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.security.saml.SAMLAuthenticationProvider; import org.springframework.security.saml.context.SAMLContextProvider; import org.springframework.security.saml.context.SAMLContextProviderLB; import org.springframework.security.saml.key.JKSKeyManager; import org.springframework.security.saml.key.KeyManager; import org.springframework.security.saml.metadata.CachingMetadataManager; import org.springframework.security.saml.metadata.ExtendedMetadataDelegate; import org.springframework.security.saml.metadata.MetadataGenerator; import org.springframework.security.saml.websso.WebSSOProfileConsumerImpl; import org.springframework.security.saml.websso.WebSSOProfileImpl; import org.springframework.security.saml.websso.WebSSOProfileOptions; import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import java.util.UUID; /** * Unit tests for the SAMLConfig class. * * @author tgianos * @since 3.0.0 */ @Category(UnitTest.class) public class SAMLConfigUnitTests { private SAMLConfig config; /** * Setup the tests. */ @Before public void setup() { this.config = new SAMLConfig(); } /** * Make sure we can get a valid SAMLBootstrap object. */ @Test public void canGetSAMLBootstrap() { Assert.assertNotNull(SAMLConfig.samlBootstrap()); } /** * Make sure we can get a valid VelocityEngine object. */ @Test public void canGetVelocityEngine() { final VelocityEngine velocityEngine = this.config.velocityEngine(); Assert.assertNotNull(velocityEngine); Assert.assertThat(velocityEngine.getProperty(RuntimeConstants.ENCODING_DEFAULT), Matchers.is("UTF-8")); } /** * Make sure we get a valid parser pool. */ @Test public void canGetParserPool() { Assert.assertNotNull(this.config.parserPool()); } /** * Make sure we can get a valid parser pool holder. */ @Test public void canGetParserPoolHolder() { Assert.assertNotNull(this.config.parserPoolHolder()); } /** * Make sure we can get a valid http connection manager. */ @Test public void canGetMultiThreadedHttpConnectionManager() { Assert.assertNotNull(this.config.multiThreadedHttpConnectionManager()); } /** * Make sure we can get a valid http client. */ @Test public void canGetHttpClient() { final HttpClient client = this.config.httpClient(); Assert.assertNotNull(client); Assert.assertTrue(client.getHttpConnectionManager() instanceof MultiThreadedHttpConnectionManager); } /** * Make sure we can get a valid SAMLAuthenticationProvider. */ @Test public void canGetSAMLAuthenticationProvider() { final SAMLUserDetailsServiceImpl service = Mockito.mock(SAMLUserDetailsServiceImpl.class); final SAMLAuthenticationProvider provider = this.config.samlAuthenticationProvider(service); Assert.assertNotNull(provider); Assert.assertThat(provider.getUserDetails(), Matchers.is(service)); Assert.assertFalse(provider.isForcePrincipalAsString()); } /** * Make sure we can get a valid SAMLContextProvider. */ @Test public void canGetContextProvider() { final SAMLProperties properties = Mockito.mock(SAMLProperties.class); Mockito.when(properties.getLoadBalancer()).thenReturn(null); SAMLContextProvider provider = this.config.contextProvider(properties); Assert.assertNotNull(provider); Assert.assertFalse(provider instanceof SAMLContextProviderLB); final SAMLProperties.LoadBalancer loadBalancer = new SAMLProperties.LoadBalancer(); final String scheme = UUID.randomUUID().toString(); loadBalancer.setScheme(scheme); final String serverName = UUID.randomUUID().toString(); loadBalancer.setServerName(serverName); final int port = 443; loadBalancer.setServerPort(port); final String contextPath = UUID.randomUUID().toString(); loadBalancer.setContextPath(contextPath); Mockito.when(properties.getLoadBalancer()).thenReturn(loadBalancer); provider = this.config.contextProvider(properties); Assert.assertNotNull(provider); Assert.assertTrue(provider instanceof SAMLContextProviderLB); } /** * Make sure we can get a valid saml logger. */ @Test public void canGetSAMLLogger() { Assert.assertNotNull(this.config.samlLogger()); } /** * Make sure we can get a valid web sso profile consumer. */ @Test public void canGetWebSSOProfileConsumer() { Assert.assertTrue(this.config.webSSOprofileConsumer() instanceof WebSSOProfileConsumerImpl); } /** * Make sure we can get a valid web sso hok consumer. */ @Test public void canGetWebSSOProfileConsumerForHok() { Assert.assertNotNull(this.config.hokWebSSOprofileConsumer()); } /** * Make sure we can get a valid web sso profile. */ @Test public void canGetWebSSOProfile() { Assert.assertTrue(this.config.webSSOprofile() instanceof WebSSOProfileImpl); } /** * Make sure we can get a valid hok web sso profile. */ @Test public void canGetHokWebSSOProfile() { Assert.assertNotNull(this.config.hokWebSSOProfile()); } /** * Make sure we can get a valid ECP profile. */ @Test public void canGetEcpProfile() { Assert.assertNotNull(this.config.ecpprofile()); } /** * Make sure we can get a valid logout profile. */ @Test public void canGetLogoutProfile() { Assert.assertNotNull(this.config.logoutProfile()); } /** * Make sure we can get a valid key manager. */ @Test public void canGetKeyManager() { this.setupForKeyManager(); final KeyManager keyManager = this.config.keyManager(); Assert.assertTrue(keyManager instanceof JKSKeyManager); } /** * Make sure we can get a valid Web SSO profile options. */ @Test public void canGetWebSSOProfileOptions() { final WebSSOProfileOptions options = this.config.defaultWebSSOProfileOptions(); Assert.assertFalse(options.isIncludeScoping()); } /** * Make sure we can get a valid SAMLEntryPoint for authentication. */ @Test public void canGetSAMLEntryPoint() { Assert.assertNotNull(this.config.samlEntryPoint()); } /** * Make sure we can get a valid extended metadata object. */ @Test public void canGetExtendedMetadata() { Assert.assertNotNull(this.config.extendedMetadata()); } /** * Make sure we can get a valid saml IDP discovery object. */ @Test public void canGetSAMLIDPDiscovery() { Assert.assertNotNull(this.config.samlIDPDiscovery()); } /** * Make sure we can get a valid extended metadata delegate. * * @throws MetadataProviderException on exception */ @Test public void canGetExtendedMetdataDelegate() throws MetadataProviderException { final SAMLProperties properties = Mockito.mock(SAMLProperties.class); final String metadataUrl = UUID.randomUUID().toString(); final SAMLProperties.Idp idp = Mockito.mock(SAMLProperties.Idp.class); Mockito.when(idp.getServiceProviderMetadataURL()).thenReturn(metadataUrl); Mockito.when(properties.getIdp()).thenReturn(idp); Assert.assertNotNull(this.config.ssoCircleExtendedMetadataProvider(properties)); } /** * Make sure we can get a valid metadata manager. * * @throws MetadataProviderException on exception */ @Test public void canGetMetadata() throws MetadataProviderException { final SAMLProperties properties = Mockito.mock(SAMLProperties.class); this.config.setSamlProperties(properties); final String metadataUrl = UUID.randomUUID().toString(); final SAMLProperties.Idp idp = Mockito.mock(SAMLProperties.Idp.class); Mockito.when(idp.getServiceProviderMetadataURL()).thenReturn(metadataUrl); Mockito.when(properties.getIdp()).thenReturn(idp); final ExtendedMetadataDelegate extendedMetadataDelegate = Mockito.mock(ExtendedMetadataDelegate.class); final CachingMetadataManager metadataManager = this.config.metadata(extendedMetadataDelegate); Assert.assertNotNull(metadataManager); Assert.assertThat(metadataManager.getAvailableProviders().size(), Matchers.is(1)); Assert.assertThat(metadataManager.getAvailableProviders(), Matchers.hasItem(extendedMetadataDelegate)); } /** * Make sure we can get a valid metadata generator. * * @throws MetadataProviderException on exception */ @Test public void canGetMetadataGenerator() throws MetadataProviderException { final SAMLProperties properties = this.setupForMetadataGenerator(); final MetadataGenerator generator = this.config.metadataGenerator(); Assert.assertNotNull(generator); Assert.assertThat(generator.getEntityId(), Matchers.is(properties.getSp().getEntityId())); Assert.assertFalse(generator.isIncludeDiscoveryExtension()); } /** * Make sure we can get a valid metadata display filter. */ @Test public void canGetMetadataDisplayFilter() { Assert.assertNotNull(this.config.metadataDisplayFilter()); } /** * Make sure we can get a valid successful redirect handler. */ @Test public void canGetSavedRequestAwareAuthenticationSuccessHandler() { Assert.assertNotNull(this.config.successRedirectHandler()); } /** * Make sure we can get a valid authentication failure handler. */ @Test public void canGetAuthenticationFailureHandler() { Assert.assertNotNull(this.config.authenticationFailureHandler()); } /** * Make sure we can get a Web SSO HoK processing filter. * * @throws Exception on any problem */ @Ignore @Test public void canGetSAMLWebSSOHoKProcessingFilter() throws Exception { Assert.assertNotNull(this.config.samlWebSSOHoKProcessingFilter()); } /** * Make sure we can get a Web SSO processing filter. * * @throws Exception on any problem */ @Ignore @Test public void canGetSAMLWebSSOProcessingFilter() throws Exception { Assert.assertNotNull(this.config.samlWebSSOProcessingFilter()); } /** * Make sure we can get metadata generator filter. */ @Test public void canGetMetadataGeneratorFilter() { this.setupForMetadataGenerator(); Assert.assertNotNull(config.metadataGeneratorFilter()); } /** * Make sure we can get a valid logout handler. */ @Test public void canGetSuccessLogoutHandler() { Assert.assertNotNull(this.config.successLogoutHandler()); } /** * Make sure we can get a valid security context logout handler. */ @Test public void canGetSecurityContextLogoutHandler() { final SecurityContextLogoutHandler handler = this.config.logoutHandler(); Assert.assertNotNull(handler); Assert.assertTrue(handler.isInvalidateHttpSession()); } /** * Make sure we can get a valid SAML logout processing filter. */ @Test public void canGetSAMLLogoutProcessingFilter() { Assert.assertNotNull(this.config.samlLogoutProcessingFilter()); } /** * Make sure can get a valid saml logout filter. */ @Test public void canGetSAMLLogoutFilter() { Assert.assertNotNull(this.config.samlLogoutFilter()); } /** * Make sure can get a valid artifact binding. */ @Test public void canGetArtifactBinding() { final ParserPool pool = Mockito.mock(ParserPool.class); final VelocityEngine engine = Mockito.mock(VelocityEngine.class); Assert.assertNotNull(this.config.artifactBinding(pool, engine)); } /** * Make sure can get valid SOAP binding. */ @Test public void canGetSOAPBinding() { Assert.assertNotNull(this.config.soapBinding()); } /** * Make sure can get a valid Http Post binding. */ @Test public void canGetPostBinding() { Assert.assertNotNull(this.config.httpPostBinding()); } /** * Make sure we can get a valid redirect deflate binding. */ @Test public void canGetRedirectDeflateBinding() { Assert.assertNotNull(this.config.httpRedirectDeflateBinding()); } /** * Make sure can get a valid SOAP 11 binding. */ @Test public void canGetHttpSOAP11Binding() { Assert.assertNotNull(this.config.httpSOAP11Binding()); } /** * Make sure can get a valid PAOS 11 binding. */ @Test public void canGetHttpPAOS11Binding() { Assert.assertNotNull(this.config.httpPAOS11Binding()); } /** * Make sure can get a valid SAML processor with all the pertinent bindings. */ @Test public void canGetSAMLProcessor() { Assert.assertNotNull(this.config.processor()); } /** * Make sure we can get a valid SAML security processing filter chain. * * @throws Exception on any problem */ @Ignore @Test public void canGetSAMLFilterChain() throws Exception { final FilterChainProxy filterChainProxy = this.config.samlFilter(); Assert.assertNotNull(filterChainProxy); Assert.assertThat(filterChainProxy.getFilterChains().size(), Matchers.is(7)); } private SAMLProperties setupForKeyManager() { final ResourceLoader resourceLoader = Mockito.mock(ResourceLoader.class); this.config.setResourceLoader(resourceLoader); final Resource storeFile = Mockito.mock(Resource.class); final SAMLProperties properties = Mockito.mock(SAMLProperties.class); this.config.setSamlProperties(properties); final String keyStorePassword = UUID.randomUUID().toString(); final String keyStoreName = UUID.randomUUID().toString() + ".jks"; final String defaultKeyName = UUID.randomUUID().toString(); final String defaultKeyPassword = UUID.randomUUID().toString(); final SAMLProperties.Keystore keyStore = Mockito.mock(SAMLProperties.Keystore.class); final SAMLProperties.Keystore.DefaultKey defaultKey = Mockito.mock(SAMLProperties.Keystore.DefaultKey.class); Mockito.when(properties.getKeystore()).thenReturn(keyStore); Mockito.when(keyStore.getName()).thenReturn(keyStoreName); Mockito.when(keyStore.getPassword()).thenReturn(keyStorePassword); Mockito.when(keyStore.getDefaultKey()).thenReturn(defaultKey); Mockito.when(defaultKey.getName()).thenReturn(defaultKeyName); Mockito.when(defaultKey.getPassword()).thenReturn(defaultKeyPassword); Mockito.when(resourceLoader.getResource(Mockito.eq("classpath:" + keyStoreName))).thenReturn(storeFile); return properties; } private SAMLProperties setupForMetadataGenerator() { final SAMLProperties properties = this.setupForKeyManager(); final String entityId = UUID.randomUUID().toString(); final SAMLProperties.Sp sp = Mockito.mock(SAMLProperties.Sp.class); Mockito.when(sp.getEntityId()).thenReturn(entityId); Mockito.when(properties.getSp()).thenReturn(sp); return properties; } }