Overhaul actuator endpoint code
Refactor several areas of the actuator endpoint code in order to make future extensions easier. The primary goal is to introduce the concept of an `ExposableEndpoint` that has technology specific subclasses and can carry additional data for filters to use. Many other changes have been made along the way including: * A new EndpointSupplier interface that allows cleaner separation of supplying vs discovering endpoints. This allows cleaner class names and allows for better auto-configuration since a user can choose to provide their own supplier entirely. * A `DiscoveredEndpoint` interface that allows the `EndpointFilter` to be greatly simplified. A filter now doesn't need to know about discovery concerns unless absolutely necessary. * Improved naming and package structure. Many technology specific concerns are now grouped in a better way. Related concerns are co-located and concepts from one area no longer leakage into another. * Simplified `HandlerMapping` implementations. Many common concerns have been pulled up helping to create simpler subclasses. * Simplified JMX adapters. Many of the intermediary `Info` classes have been removed. The `DiscoveredJmxOperation` is now responsible for mapping methods to operations. * A specific @`HealthEndpointCloudFoundryExtension` for Cloud Foundry. The extension logic used to create a "full" health endpoint extension has been made explicit. Fixes gh-11428 Fixes gh-11581
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@@ -23,7 +23,9 @@ import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.LocalHostUriTemplateHandler;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
@@ -32,18 +34,19 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Madhura Bhave
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class SampleActuatorCustomSecurityApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
private Environment environment;
|
||||
|
||||
@Test
|
||||
public void homeIsSecure() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> entity = this.restTemplate.getForEntity("/", Map.class);
|
||||
ResponseEntity<Map> entity = restTemplate().getForEntity("/", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> body = entity.getBody();
|
||||
@@ -54,7 +57,7 @@ public class SampleActuatorCustomSecurityApplicationTests {
|
||||
@Test
|
||||
public void testInsecureApplicationPath() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> entity = this.restTemplate.getForEntity("/foo", Map.class);
|
||||
ResponseEntity<Map> entity = restTemplate().getForEntity("/foo", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> body = entity.getBody();
|
||||
@@ -64,26 +67,64 @@ public class SampleActuatorCustomSecurityApplicationTests {
|
||||
|
||||
@Test
|
||||
public void testInsecureStaticResources() {
|
||||
ResponseEntity<String> entity = this.restTemplate
|
||||
ResponseEntity<String> entity = restTemplate()
|
||||
.getForEntity("/css/bootstrap.min.css", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("body");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insecureActuator() {
|
||||
ResponseEntity<String> entity = this.restTemplate.getForEntity("/actuator/health",
|
||||
public void actuatorInsecureEndpoint() {
|
||||
ResponseEntity<String> entity = restTemplate().getForEntity("/actuator/health",
|
||||
String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void secureActuator() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> entity = this.restTemplate.getForEntity("/actuator/env",
|
||||
Map.class);
|
||||
public void actuatorSecureEndpointWithAnonymous() {
|
||||
ResponseEntity<Object> entity = restTemplate().getForEntity("/actuator/env",
|
||||
Object.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorSecureEndpointWithUnauthorizedUser() {
|
||||
ResponseEntity<Object> entity = userRestTemplate().getForEntity("/actuator/env",
|
||||
Object.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorSecureEndpointWithAuthorizedUser() {
|
||||
ResponseEntity<Object> entity = adminRestTemplate().getForEntity("/actuator/env",
|
||||
Object.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorCustomMvcSecureEndpointWithAnonymous() {
|
||||
ResponseEntity<String> entity = restTemplate()
|
||||
.getForEntity("/actuator/example/echo?text={t}", String.class, "test");
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
private TestRestTemplate restTemplate() {
|
||||
return configure(new TestRestTemplate());
|
||||
}
|
||||
|
||||
private TestRestTemplate adminRestTemplate() {
|
||||
return configure(new TestRestTemplate("admin", "admin"));
|
||||
}
|
||||
|
||||
private TestRestTemplate userRestTemplate() {
|
||||
return configure(new TestRestTemplate("user", "password"));
|
||||
}
|
||||
|
||||
private TestRestTemplate configure(TestRestTemplate restTemplate) {
|
||||
restTemplate
|
||||
.setUriTemplateHandler(new LocalHostUriTemplateHandler(this.environment));
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user