Change info endpoint to be secure and unexposed by default
See gh-24715
This commit is contained in:
		
							parent
							
								
									0fc33b020d
								
							
						
					
					
						commit
						53c1e79810
					
				| 
						 | 
					@ -178,7 +178,7 @@ public class IncludeExcludeEndpointFilter<E extends ExposableEndpoint<?>> implem
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * The default set of include patterns used for web.
 | 
							 * The default set of include patterns used for web.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		WEB("info", "health");
 | 
							WEB("health");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private final EndpointPatterns patterns;
 | 
							private final EndpointPatterns patterns;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,6 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAu
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
 | 
					import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
 | 
					import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
 | 
				
			||||||
import org.springframework.boot.actuate.health.HealthEndpoint;
 | 
					import org.springframework.boot.actuate.health.HealthEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.info.InfoEndpoint;
 | 
					 | 
				
			||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
 | 
					import org.springframework.boot.autoconfigure.AutoConfigureAfter;
 | 
				
			||||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
 | 
					import org.springframework.boot.autoconfigure.AutoConfigureBefore;
 | 
				
			||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 | 
					import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 | 
				
			||||||
| 
						 | 
					@ -38,10 +37,8 @@ import org.springframework.security.web.SecurityFilterChain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * {@link EnableAutoConfiguration Auto-configuration} for Spring Security when actuator is
 | 
					 * {@link EnableAutoConfiguration Auto-configuration} for Spring Security when actuator is
 | 
				
			||||||
 * on the classpath. It allows unauthenticated access to the {@link HealthEndpoint} and
 | 
					 * on the classpath. It allows unauthenticated access to the {@link HealthEndpoint}. If
 | 
				
			||||||
 * {@link InfoEndpoint}. If the user specifies their own
 | 
					 * the user specifies their own{@link SecurityFilterChain} bean, this will back-off
 | 
				
			||||||
 * {@link org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
 | 
					 | 
				
			||||||
 * WebSecurityConfigurerAdapter} or {@link SecurityFilterChain} bean, this will back-off
 | 
					 | 
				
			||||||
 * completely and the user should specify all the bits that they want to configure as part
 | 
					 * completely and the user should specify all the bits that they want to configure as part
 | 
				
			||||||
 * of the custom security configuration.
 | 
					 * of the custom security configuration.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -60,7 +57,7 @@ public class ManagementWebSecurityAutoConfiguration {
 | 
				
			||||||
	@Bean
 | 
						@Bean
 | 
				
			||||||
	SecurityFilterChain managementSecurityFilterChain(HttpSecurity http) throws Exception {
 | 
						SecurityFilterChain managementSecurityFilterChain(HttpSecurity http) throws Exception {
 | 
				
			||||||
		http.authorizeRequests((requests) -> {
 | 
							http.authorizeRequests((requests) -> {
 | 
				
			||||||
			requests.requestMatchers(EndpointRequest.to(HealthEndpoint.class, InfoEndpoint.class)).permitAll();
 | 
								requests.requestMatchers(EndpointRequest.to(HealthEndpoint.class)).permitAll();
 | 
				
			||||||
			requests.anyRequest().authenticated();
 | 
								requests.anyRequest().authenticated();
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		http.formLogin(Customizer.withDefaults());
 | 
							http.formLogin(Customizer.withDefaults());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,8 +91,7 @@
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "name": "management.endpoints.web.exposure.include",
 | 
					      "name": "management.endpoints.web.exposure.include",
 | 
				
			||||||
      "defaultValue": [
 | 
					      "defaultValue": [
 | 
				
			||||||
        "health",
 | 
					        "health"
 | 
				
			||||||
        "info"
 | 
					 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,8 +40,8 @@ class ConditionalOnAvailableEndpointTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	void outcomeShouldMatchDefaults() {
 | 
						void outcomeShouldMatchDefaults() {
 | 
				
			||||||
		this.contextRunner.run((context) -> assertThat(context).hasBean("info").hasBean("health")
 | 
							this.contextRunner.run((context) -> assertThat(context).hasBean("health").doesNotHaveBean("spring")
 | 
				
			||||||
				.doesNotHaveBean("spring").doesNotHaveBean("test").doesNotHaveBean("shutdown"));
 | 
									.doesNotHaveBean("test").doesNotHaveBean("shutdown"));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ class ConditionalOnAvailableEndpointTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	void outcomeWhenIncludeAllJmxButJmxDisabledShouldMatchDefaults() {
 | 
						void outcomeWhenIncludeAllJmxButJmxDisabledShouldMatchDefaults() {
 | 
				
			||||||
		this.contextRunner.withPropertyValues("management.endpoints.jmx.exposure.include=*")
 | 
							this.contextRunner.withPropertyValues("management.endpoints.jmx.exposure.include=*")
 | 
				
			||||||
				.run((context) -> assertThat(context).hasBean("info").hasBean("health").doesNotHaveBean("spring")
 | 
									.run((context) -> assertThat(context).hasBean("health").doesNotHaveBean("spring")
 | 
				
			||||||
						.doesNotHaveBean("test").doesNotHaveBean("shutdown"));
 | 
											.doesNotHaveBean("test").doesNotHaveBean("shutdown"));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,8 +95,8 @@ class ConditionalOnAvailableEndpointTests {
 | 
				
			||||||
		this.contextRunner
 | 
							this.contextRunner
 | 
				
			||||||
				.withPropertyValues("management.endpoints.jmx.exposure.include=*", "spring.jmx.enabled=true",
 | 
									.withPropertyValues("management.endpoints.jmx.exposure.include=*", "spring.jmx.enabled=true",
 | 
				
			||||||
						"management.endpoint.shutdown.enabled=true")
 | 
											"management.endpoint.shutdown.enabled=true")
 | 
				
			||||||
				.run((context) -> assertThat(context).hasBean("info").hasBean("health").hasBean("test")
 | 
									.run((context) -> assertThat(context).hasBean("health").hasBean("test").hasBean("spring")
 | 
				
			||||||
						.hasBean("spring").hasBean("shutdown"));
 | 
											.hasBean("shutdown"));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,18 +34,6 @@ class InfoEndpointAutoConfigurationTests {
 | 
				
			||||||
	private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
 | 
						private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
 | 
				
			||||||
			.withConfiguration(AutoConfigurations.of(InfoEndpointAutoConfiguration.class));
 | 
								.withConfiguration(AutoConfigurations.of(InfoEndpointAutoConfiguration.class));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void runShouldHaveEndpointBean() {
 | 
					 | 
				
			||||||
		this.contextRunner.withPropertyValues("management.endpoint.shutdown.enabled:true")
 | 
					 | 
				
			||||||
				.run((context) -> assertThat(context).hasSingleBean(InfoEndpoint.class));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void runShouldHaveEndpointBeanEvenIfDefaultIsDisabled() {
 | 
					 | 
				
			||||||
		this.contextRunner.withPropertyValues("management.endpoint.default.enabled:false")
 | 
					 | 
				
			||||||
				.run((context) -> assertThat(context).hasSingleBean(InfoEndpoint.class));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
 | 
						void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
 | 
				
			||||||
		this.contextRunner.withPropertyValues("management.endpoint.info.enabled:false")
 | 
							this.contextRunner.withPropertyValues("management.endpoint.info.enabled:false")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,7 +91,7 @@ class WebMvcEndpointExposureIntegrationTests {
 | 
				
			||||||
			assertThat(isExposed(client, HttpMethod.GET, "customservlet")).isFalse();
 | 
								assertThat(isExposed(client, HttpMethod.GET, "customservlet")).isFalse();
 | 
				
			||||||
			assertThat(isExposed(client, HttpMethod.GET, "env")).isFalse();
 | 
								assertThat(isExposed(client, HttpMethod.GET, "env")).isFalse();
 | 
				
			||||||
			assertThat(isExposed(client, HttpMethod.GET, "health")).isTrue();
 | 
								assertThat(isExposed(client, HttpMethod.GET, "health")).isTrue();
 | 
				
			||||||
			assertThat(isExposed(client, HttpMethod.GET, "info")).isTrue();
 | 
								assertThat(isExposed(client, HttpMethod.GET, "info")).isFalse();
 | 
				
			||||||
			assertThat(isExposed(client, HttpMethod.GET, "mappings")).isFalse();
 | 
								assertThat(isExposed(client, HttpMethod.GET, "mappings")).isFalse();
 | 
				
			||||||
			assertThat(isExposed(client, HttpMethod.POST, "shutdown")).isFalse();
 | 
								assertThat(isExposed(client, HttpMethod.POST, "shutdown")).isFalse();
 | 
				
			||||||
			assertThat(isExposed(client, HttpMethod.GET, "threaddump")).isFalse();
 | 
								assertThat(isExposed(client, HttpMethod.GET, "threaddump")).isFalse();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,11 +78,6 @@ class ReactiveManagementWebSecurityAutoConfigurationTests {
 | 
				
			||||||
		this.contextRunner.run((context) -> assertThat(getAuthenticateHeader(context, "/actuator/health")).isNull());
 | 
							this.contextRunner.run((context) -> assertThat(getAuthenticateHeader(context, "/actuator/health")).isNull());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void permitAllForInfo() {
 | 
					 | 
				
			||||||
		this.contextRunner.run((context) -> assertThat(getAuthenticateHeader(context, "/actuator/info")).isNull());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	void securesEverythingElse() {
 | 
						void securesEverythingElse() {
 | 
				
			||||||
		this.contextRunner.run((context) -> {
 | 
							this.contextRunner.run((context) -> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,14 +73,6 @@ class ManagementWebSecurityAutoConfigurationTests {
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void permitAllForInfo() {
 | 
					 | 
				
			||||||
		this.contextRunner.run((context) -> {
 | 
					 | 
				
			||||||
			HttpStatus status = getResponseStatus(context, "/actuator/info");
 | 
					 | 
				
			||||||
			assertThat(status).isEqualTo(HttpStatus.OK);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	void securesEverythingElse() {
 | 
						void securesEverythingElse() {
 | 
				
			||||||
		this.contextRunner.run((context) -> {
 | 
							this.contextRunner.run((context) -> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3960,10 +3960,10 @@ You can register multiple relying parties under the `spring.security.saml2.relyi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[boot-features-security-actuator]]
 | 
					[[boot-features-security-actuator]]
 | 
				
			||||||
=== Actuator Security
 | 
					=== Actuator Security
 | 
				
			||||||
For security purposes, all actuators other than `/health` and `/info` are disabled by default.
 | 
					For security purposes, all actuators other than `/health` are disabled by default.
 | 
				
			||||||
The configprop:management.endpoints.web.exposure.include[] property can be used to enable the actuators.
 | 
					The configprop:management.endpoints.web.exposure.include[] property can be used to enable the actuators.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If Spring Security is on the classpath and no other `WebSecurityConfigurerAdapter` or `SecurityFilterChain` bean is present, all actuators other than `/health` and `/info` are secured by Spring Boot auto-configuration.
 | 
					If Spring Security is on the classpath and no other `WebSecurityConfigurerAdapter` or `SecurityFilterChain` bean is present, all actuators other than `/health` are secured by Spring Boot auto-configuration.
 | 
				
			||||||
If you define a custom `WebSecurityConfigurerAdapter` or `SecurityFilterChain` bean, Spring Boot auto-configuration will back off and you will be in full control of actuator access rules.
 | 
					If you define a custom `WebSecurityConfigurerAdapter` or `SecurityFilterChain` bean, Spring Boot auto-configuration will back off and you will be in full control of actuator access rules.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NOTE: Before setting the `management.endpoints.web.exposure.include`, ensure that the exposed actuators do not contain sensitive information and/or are secured by placing them behind a firewall or by something like Spring Security.
 | 
					NOTE: Before setting the `management.endpoints.web.exposure.include`, ensure that the exposed actuators do not contain sensitive information and/or are secured by placing them behind a firewall or by something like Spring Security.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ public class SecurityConfiguration {
 | 
				
			||||||
	SecurityFilterChain configure(HttpSecurity http) throws Exception {
 | 
						SecurityFilterChain configure(HttpSecurity http) throws Exception {
 | 
				
			||||||
		http.authorizeRequests((requests) -> {
 | 
							http.authorizeRequests((requests) -> {
 | 
				
			||||||
			requests.mvcMatchers("/actuator/beans").hasRole("BEANS");
 | 
								requests.mvcMatchers("/actuator/beans").hasRole("BEANS");
 | 
				
			||||||
			requests.requestMatchers(EndpointRequest.to("health", "info")).permitAll();
 | 
								requests.requestMatchers(EndpointRequest.to("health")).permitAll();
 | 
				
			||||||
			requests.requestMatchers(EndpointRequest.toAnyEndpoint().excluding(MappingsEndpoint.class))
 | 
								requests.requestMatchers(EndpointRequest.toAnyEndpoint().excluding(MappingsEndpoint.class))
 | 
				
			||||||
					.hasRole("ACTUATOR");
 | 
										.hasRole("ACTUATOR");
 | 
				
			||||||
			requests.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
 | 
								requests.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,16 +110,6 @@ class SampleActuatorApplicationTests {
 | 
				
			||||||
		assertThat(entity.getBody()).doesNotContain("\"hello\":\"1\"");
 | 
							assertThat(entity.getBody()).doesNotContain("\"hello\":\"1\"");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void infoInsecureByDefault() {
 | 
					 | 
				
			||||||
		ResponseEntity<String> entity = this.restTemplate.getForEntity("/actuator/info", String.class);
 | 
					 | 
				
			||||||
		assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
 | 
					 | 
				
			||||||
		assertThat(entity.getBody()).contains("\"artifact\":\"spring-boot-smoke-test-actuator\"");
 | 
					 | 
				
			||||||
		assertThat(entity.getBody()).contains("\"someKey\":\"someValue\"");
 | 
					 | 
				
			||||||
		assertThat(entity.getBody()).contains("\"java\":{", "\"source\":\"1.8\"", "\"target\":\"1.8\"");
 | 
					 | 
				
			||||||
		assertThat(entity.getBody()).contains("\"encoding\":{", "\"source\":\"UTF-8\"", "\"reporting\":\"UTF-8\"");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	void testErrorPage() {
 | 
						void testErrorPage() {
 | 
				
			||||||
		ResponseEntity<String> entity = this.restTemplate.withBasicAuth("user", "password").getForEntity("/foo",
 | 
							ResponseEntity<String> entity = this.restTemplate.withBasicAuth("user", "password").getForEntity("/foo",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ public class SecurityConfiguration {
 | 
				
			||||||
	SecurityFilterChain configure(HttpSecurity http) throws Exception {
 | 
						SecurityFilterChain configure(HttpSecurity http) throws Exception {
 | 
				
			||||||
		// @formatter:off
 | 
							// @formatter:off
 | 
				
			||||||
		http.authorizeRequests()
 | 
							http.authorizeRequests()
 | 
				
			||||||
				.requestMatchers(EndpointRequest.to("health", "info")).permitAll()
 | 
									.requestMatchers(EndpointRequest.to("health")).permitAll()
 | 
				
			||||||
				.requestMatchers(EndpointRequest.toAnyEndpoint().excluding(MappingsEndpoint.class)).hasRole("ACTUATOR")
 | 
									.requestMatchers(EndpointRequest.toAnyEndpoint().excluding(MappingsEndpoint.class)).hasRole("ACTUATOR")
 | 
				
			||||||
				.antMatchers("/**").hasRole("USER")
 | 
									.antMatchers("/**").hasRole("USER")
 | 
				
			||||||
				.and()
 | 
									.and()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ class ManagementPortSampleSecureWebFluxTests {
 | 
				
			||||||
		@Bean
 | 
							@Bean
 | 
				
			||||||
		SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws Exception {
 | 
							SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws Exception {
 | 
				
			||||||
			http.authorizeExchange((exchanges) -> {
 | 
								http.authorizeExchange((exchanges) -> {
 | 
				
			||||||
				exchanges.matchers(EndpointRequest.to("health", "info")).permitAll();
 | 
									exchanges.matchers(EndpointRequest.to("health")).permitAll();
 | 
				
			||||||
				exchanges.matchers(EndpointRequest.toAnyEndpoint().excluding(MappingsEndpoint.class))
 | 
									exchanges.matchers(EndpointRequest.toAnyEndpoint().excluding(MappingsEndpoint.class))
 | 
				
			||||||
						.hasRole("ACTUATOR");
 | 
											.hasRole("ACTUATOR");
 | 
				
			||||||
				exchanges.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
 | 
									exchanges.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,10 +55,9 @@ class SampleSecureWebFluxCustomSecurityTests {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	void healthAndInfoDoNotRequireAuthentication() {
 | 
						void healthDoesNotRequireAuthentication() {
 | 
				
			||||||
		this.webClient.get().uri("/actuator/health").accept(MediaType.APPLICATION_JSON).exchange().expectStatus()
 | 
							this.webClient.get().uri("/actuator/health").accept(MediaType.APPLICATION_JSON).exchange().expectStatus()
 | 
				
			||||||
				.isOk();
 | 
									.isOk();
 | 
				
			||||||
		this.webClient.get().uri("/actuator/info").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
| 
						 | 
					@ -117,7 +116,7 @@ class SampleSecureWebFluxCustomSecurityTests {
 | 
				
			||||||
		@Bean
 | 
							@Bean
 | 
				
			||||||
		SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws Exception {
 | 
							SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws Exception {
 | 
				
			||||||
			http.authorizeExchange((exchanges) -> {
 | 
								http.authorizeExchange((exchanges) -> {
 | 
				
			||||||
				exchanges.matchers(EndpointRequest.to("health", "info")).permitAll();
 | 
									exchanges.matchers(EndpointRequest.to("health")).permitAll();
 | 
				
			||||||
				exchanges.matchers(EndpointRequest.toAnyEndpoint().excluding(MappingsEndpoint.class))
 | 
									exchanges.matchers(EndpointRequest.toAnyEndpoint().excluding(MappingsEndpoint.class))
 | 
				
			||||||
						.hasRole("ACTUATOR");
 | 
											.hasRole("ACTUATOR");
 | 
				
			||||||
				exchanges.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
 | 
									exchanges.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue