/** * Copyright 2016 StreamSets Inc. * * Licensed under the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.streamsets.lib.security.http; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.streamsets.datacollector.util.Configuration; import org.junit.Assert; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import java.io.IOException; import java.net.HttpURLConnection; import java.util.Collections; import java.util.Map; public class TestRemoteSSOService { @Test public void testDefaultConfigs() throws Exception { RemoteSSOService service = Mockito.spy(new RemoteSSOService()); Configuration conf = new Configuration(); conf.set(RemoteSSOService.SECURITY_SERVICE_APP_AUTH_TOKEN_CONFIG, "authToken"); conf.set(RemoteSSOService.SECURITY_SERVICE_COMPONENT_ID_CONFIG, "serviceComponentId"); service.setConfiguration(conf); Assert.assertEquals(RemoteSSOService.DPM_BASE_URL_DEFAULT + "/security/login", service.getLoginPageUrl()); Assert.assertEquals(RemoteSSOService.DPM_BASE_URL_DEFAULT + "/security/_logout", service.getLogoutUrl()); Assert.assertEquals(10000, service.getConnectionTimeout()); } @Test public void testCustomConfigs() throws Exception { RemoteSSOService service = Mockito.spy(new RemoteSSOService()); Configuration conf = new Configuration(); conf.set(RemoteSSOService.DPM_BASE_URL_CONFIG, "http://foo"); conf.set(RemoteSSOService.SECURITY_SERVICE_APP_AUTH_TOKEN_CONFIG, "authToken"); conf.set(RemoteSSOService.SECURITY_SERVICE_COMPONENT_ID_CONFIG, "serviceComponentId"); conf.set(RemoteSSOService.SECURITY_SERVICE_VALIDATE_AUTH_TOKEN_FREQ_CONFIG, 30); conf.set(RemoteSSOService.SECURITY_SERVICE_CONNECTION_TIMEOUT_CONFIG, 2000); service.setConfiguration(conf); Assert.assertEquals("http://foo/security/login", service.getLoginPageUrl()); Assert.assertEquals("http://foo/security/_logout", service.getLogoutUrl()); Assert.assertEquals(2000, service.getConnectionTimeout()); } @Test(expected = IllegalArgumentException.class) public void testLowValidateAuthTokenFrequency() throws Exception { RemoteSSOService service = Mockito.spy(new RemoteSSOService()); Configuration conf = new Configuration(); conf.set(RemoteSSOService.DPM_BASE_URL_CONFIG, "http://foo"); conf.set(RemoteSSOService.SECURITY_SERVICE_APP_AUTH_TOKEN_CONFIG, "authToken"); conf.set(RemoteSSOService.SECURITY_SERVICE_COMPONENT_ID_CONFIG, "serviceComponentId"); conf.set(RemoteSSOService.SECURITY_SERVICE_VALIDATE_AUTH_TOKEN_FREQ_CONFIG, 29); conf.set(RemoteSSOService.SECURITY_SERVICE_CONNECTION_TIMEOUT_CONFIG, 2000); service.setConfiguration(conf); } @Test public void testValidateUserTokenWithSecurityService() throws Exception { Configuration conf = new Configuration(); conf.set(RemoteSSOService.DPM_BASE_URL_CONFIG, "http://foo"); conf.set(RemoteSSOService.SECURITY_SERVICE_APP_AUTH_TOKEN_CONFIG, "serviceToken"); conf.set(RemoteSSOService.SECURITY_SERVICE_COMPONENT_ID_CONFIG, "serviceComponentId"); conf.set(RemoteSSOService.SECURITY_SERVICE_VALIDATE_AUTH_TOKEN_FREQ_CONFIG, 30); RemoteSSOService service = Mockito.spy(new RemoteSSOService()); service.setConfiguration(conf); Mockito.doReturn(true).when(service).checkServiceActive(); SSOPrincipalJson principal = TestSSOPrincipalJson.createPrincipal(); RestClient.Response response = Mockito.mock(RestClient.Response.class); RestClient restClient = Mockito.mock(RestClient.class); RestClient.Builder builder = Mockito.mock(RestClient.Builder.class); Mockito.doReturn(restClient).when(builder).build(); Mockito.doReturn(builder).when(service).getUserAuthClientBuilder(); Mockito.doReturn(response).when(restClient).post(Mockito.any()); // valid token Mockito.when(response.getStatus()).thenReturn(HttpURLConnection.HTTP_OK); Mockito.when(response.getData(Mockito.eq(SSOPrincipalJson.class))).thenReturn(principal); Assert.assertEquals(principal, service.validateUserTokenWithSecurityService("foo")); Assert.assertEquals("foo", principal.getTokenStr()); // invalid token Mockito.when(response.getData(Mockito.eq(SSOPrincipalJson.class))).thenReturn(null); Assert.assertNull(service.validateUserTokenWithSecurityService("foo")); } @Test public void testValidateAppTokenWithSecurityService() throws Exception { Configuration conf = new Configuration(); conf.set(RemoteSSOService.DPM_BASE_URL_CONFIG, "http://foo"); conf.set(RemoteSSOService.SECURITY_SERVICE_APP_AUTH_TOKEN_CONFIG, "serviceToken"); conf.set(RemoteSSOService.SECURITY_SERVICE_COMPONENT_ID_CONFIG, "serviceComponentId"); conf.set(RemoteSSOService.SECURITY_SERVICE_VALIDATE_AUTH_TOKEN_FREQ_CONFIG, 30); RemoteSSOService service = Mockito.spy(new RemoteSSOService()); service.setConfiguration(conf); Mockito.doReturn(true).when(service).checkServiceActive(); SSOPrincipalJson principal = TestSSOPrincipalJson.createPrincipal(); RestClient.Response response = Mockito.mock(RestClient.Response.class); RestClient restClient = Mockito.mock(RestClient.class); RestClient.Builder builder = Mockito.mock(RestClient.Builder.class); Mockito.doReturn(restClient).when(builder).build(); Mockito.doReturn(builder).when(service).getAppAuthClientBuilder(); Mockito.doReturn(response).when(restClient).post(Mockito.any()); // valid token Mockito.when(response.getStatus()).thenReturn(HttpURLConnection.HTTP_OK); Mockito.when(response.getData(Mockito.eq(SSOPrincipalJson.class))).thenReturn(principal); Assert.assertEquals(principal, service.validateAppTokenWithSecurityService("foo", "bar")); Assert.assertEquals("foo", principal.getTokenStr()); // invalid token Mockito.when(response.getData(Mockito.eq(SSOPrincipalJson.class))).thenReturn(null); Assert.assertNull(service.validateAppTokenWithSecurityService("foo", "bar")); } @Test public void testRegisterOK() throws Exception { Configuration conf = new Configuration(); conf.set(RemoteSSOService.DPM_BASE_URL_CONFIG, "http://foo"); RemoteSSOService service = Mockito.spy(new RemoteSSOService()); service.setConfiguration(conf); service.setApplicationAuthToken("appToken"); service.setComponentId("componentId"); RestClient.Response response = Mockito.mock(RestClient.Response.class); RestClient restClient = Mockito.mock(RestClient.class); RestClient.Builder builder = Mockito.mock(RestClient.Builder.class); Mockito.doReturn(restClient).when(builder).build(); Mockito.doReturn(builder).when(service).getRegisterClientBuilder(); Mockito.doReturn(response).when(restClient).post(Mockito.any()); Mockito.when(response.getStatus()).thenReturn(HttpURLConnection.HTTP_OK); Map<String, String> attributes = ImmutableMap.of("a", "A"); service.register(attributes); ArgumentCaptor<Map> registrationData = ArgumentCaptor.forClass(Map.class); Mockito.verify(restClient, Mockito.times(1)).post(registrationData.capture()); Assert.assertNotNull(registrationData.getValue()); Assert.assertEquals("appToken", registrationData.getValue().get("authToken")); Assert.assertEquals("componentId", registrationData.getValue().get("componentId")); Assert.assertEquals(attributes, registrationData.getValue().get("attributes")); } @Test(expected = RuntimeException.class) public void testRegisterForbidden() throws Exception { Configuration conf = new Configuration(); conf.set(RemoteSSOService.DPM_BASE_URL_CONFIG, "http://foo"); RemoteSSOService service = Mockito.spy(new RemoteSSOService()); service.setConfiguration(conf); service.setApplicationAuthToken("appToken"); service.setComponentId("componentId"); RestClient.Response response = Mockito.mock(RestClient.Response.class); RestClient restClient = Mockito.mock(RestClient.class); RestClient.Builder builder = Mockito.mock(RestClient.Builder.class); Mockito.doReturn(restClient).when(builder).build(); Mockito.doReturn(builder).when(service).getRegisterClientBuilder(); Mockito.doReturn(response).when(restClient).post(Mockito.any()); Mockito.when(response.getStatus()).thenReturn(HttpURLConnection.HTTP_FORBIDDEN); Map<String, String> attributes = ImmutableMap.of("a", "A"); service.register(attributes); } private void testRegisterRetries(boolean unavailable) throws Exception { Configuration conf = new Configuration(); conf.set(RemoteSSOService.DPM_BASE_URL_CONFIG, "http://notAValidDPMURL"); conf.set(RemoteSSOService.DPM_REGISTRATION_RETRY_ATTEMPTS, "7"); RemoteSSOService service = Mockito.spy(new RemoteSSOService()); service.setConfiguration(conf); service.setApplicationAuthToken("appToken"); service.setComponentId("componentId"); Mockito.doNothing().when(service).sleep(Mockito.anyInt()); RestClient.Response response = Mockito.mock(RestClient.Response.class); RestClient restClient = Mockito.mock(RestClient.class); RestClient.Builder builder = Mockito.mock(RestClient.Builder.class); Mockito.doReturn(restClient).when(builder).build(); Mockito.doReturn(builder).when(service).getRegisterClientBuilder(); Mockito.doReturn(response).when(restClient).post(Mockito.any()); if (unavailable) { Mockito.when(response.getStatus()).thenReturn(HttpURLConnection.HTTP_UNAVAILABLE); } else { Mockito.when(response.getStatus()).thenThrow(new IOException()); } service.register(Collections.<String, String>emptyMap()); Assert.assertFalse(service.isServiceActive(false)); ArgumentCaptor<Integer> sleepCaptor = ArgumentCaptor.forClass(Integer.class); Mockito.verify(service, Mockito.times(6)).sleep(sleepCaptor.capture()); Assert.assertEquals(ImmutableList.of(2, 4, 8, 16, 16, 16), sleepCaptor.getAllValues()); } @Test public void testRegisterRetriesUnavailable() throws Exception { testRegisterRetries(true); } @Test public void testRegisterRetriesException() throws Exception { testRegisterRetries(false); } @Test public void testServiceActive() throws Exception { Configuration conf = new Configuration(); conf.set(RemoteSSOService.DPM_BASE_URL_CONFIG, "http://foo"); RemoteSSOService service = Mockito.spy(new RemoteSSOService()); service.setConfiguration(conf); service.setApplicationAuthToken("appToken"); service.setComponentId("componentId"); Assert.assertFalse(service.isServiceActive(false)); Mockito.verify(service, Mockito.never()).checkServiceActive(); Mockito.verify(service, Mockito.never()).getLoginPageUrl(); Assert.assertFalse(service.isServiceActive(true)); Mockito.verify(service, Mockito.times(1)).checkServiceActive(); Mockito.verify(service, Mockito.times(1)).getLoginPageUrl(); } }