/* * Copyright 2012-2017 the original author or authors. * * 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 org.springframework.boot.actuate.cloudfoundry; import java.util.Arrays; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.EndpointWebMvcManagementContextConfiguration; import org.springframework.boot.actuate.autoconfigure.ManagementWebSecurityAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.security.IgnoredRequestCustomizer; import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration; import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.context.properties.source.ConfigurationPropertySources; import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.http.HttpMethod; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockServletContext; import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.cors.CorsConfiguration; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; /** * Tests for {@link CloudFoundryActuatorAutoConfiguration}. * * @author Madhura Bhave */ public class CloudFoundryActuatorAutoConfigurationTests { private AnnotationConfigWebApplicationContext context; @Before public void setup() { this.context = new AnnotationConfigWebApplicationContext(); this.context.setServletContext(new MockServletContext()); this.context.register(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class, JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, RestTemplateAutoConfiguration.class, EndpointWebMvcManagementContextConfiguration.class, CloudFoundryActuatorAutoConfiguration.class); } @After public void close() { if (this.context != null) { this.context.close(); } } @Test public void cloudFoundryPlatformActive() throws Exception { CloudFoundryEndpointHandlerMapping handlerMapping = getHandlerMapping(); assertThat(handlerMapping.getPrefix()).isEqualTo("/cloudfoundryapplication"); CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils .getField(handlerMapping, "corsConfiguration"); assertThat(corsConfiguration.getAllowedOrigins()).contains("*"); assertThat(corsConfiguration.getAllowedMethods()).containsAll( Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name())); assertThat(corsConfiguration.getAllowedHeaders()).containsAll( Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type")); } @Test public void cloudFoundryPlatformActiveSetsApplicationId() throws Exception { CloudFoundryEndpointHandlerMapping handlerMapping = getHandlerMapping(); Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); String applicationId = (String) ReflectionTestUtils.getField(interceptor, "applicationId"); assertThat(applicationId).isEqualTo("my-app-id"); } @Test public void cloudFoundryPlatformActiveSetsCloudControllerUrl() throws Exception { CloudFoundryEndpointHandlerMapping handlerMapping = getHandlerMapping(); Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, "cloudFoundrySecurityService"); String cloudControllerUrl = (String) ReflectionTestUtils .getField(interceptorSecurityService, "cloudControllerUrl"); assertThat(cloudControllerUrl).isEqualTo("http://my-cloud-controller.com"); } @Test public void skipSslValidation() throws Exception { EnvironmentTestUtils.addEnvironment(this.context, "management.cloudfoundry.skipSslValidation:true"); ConfigurationPropertySources.attach(this.context.getEnvironment()); this.context.refresh(); CloudFoundryEndpointHandlerMapping handlerMapping = getHandlerMapping(); Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, "cloudFoundrySecurityService"); RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils .getField(interceptorSecurityService, "restTemplate"); assertThat(restTemplate.getRequestFactory()) .isInstanceOf(SkipSslVerificationHttpRequestFactory.class); } @Test public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() throws Exception { EnvironmentTestUtils.addEnvironment(this.context, "VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id"); this.context.refresh(); CloudFoundryEndpointHandlerMapping handlerMapping = this.context.getBean( "cloudFoundryEndpointHandlerMapping", CloudFoundryEndpointHandlerMapping.class); Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); Object interceptorSecurityService = ReflectionTestUtils .getField(securityInterceptor, "cloudFoundrySecurityService"); assertThat(interceptorSecurityService).isNull(); } @Test public void cloudFoundryPathsIgnoredBySpringSecurity() throws Exception { EnvironmentTestUtils.addEnvironment(this.context, "VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id"); this.context.refresh(); IgnoredRequestCustomizer customizer = (IgnoredRequestCustomizer) this.context .getBean("cloudFoundryIgnoredRequestCustomizer"); IgnoredRequestConfigurer configurer = mock(IgnoredRequestConfigurer.class); customizer.customize(configurer); ArgumentCaptor<RequestMatcher> requestMatcher = ArgumentCaptor .forClass(RequestMatcher.class); verify(configurer).requestMatchers(requestMatcher.capture()); RequestMatcher matcher = requestMatcher.getValue(); MockHttpServletRequest request = new MockHttpServletRequest(); request.setServletPath("/cloudfoundryapplication/my-path"); assertThat(matcher.matches(request)).isTrue(); request.setServletPath("/some-other-path"); assertThat(matcher.matches(request)).isFalse(); } @Test public void cloudFoundryPlatformInactive() throws Exception { this.context.refresh(); assertThat(this.context.containsBean("cloudFoundryEndpointHandlerMapping")) .isFalse(); } @Test public void cloudFoundryManagementEndpointsDisabled() throws Exception { EnvironmentTestUtils.addEnvironment(this.context, "VCAP_APPLICATION=---", "management.cloudfoundry.enabled:false"); this.context.refresh(); assertThat(this.context.containsBean("cloudFoundryEndpointHandlerMapping")) .isFalse(); } private CloudFoundryEndpointHandlerMapping getHandlerMapping() { EnvironmentTestUtils.addEnvironment(this.context, "VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", "vcap.application.cf_api:http://my-cloud-controller.com"); this.context.refresh(); return this.context.getBean("cloudFoundryEndpointHandlerMapping", CloudFoundryEndpointHandlerMapping.class); } }