/*
* 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);
}
}