Support list based role properties
Update `HealthMvcEndpoint` to respect `ManagementServerProperties` roles. Prior to this commit the `HealthMvcEndpoint` directly loaded roles rather than using bound properties. This meant that list values from yaml were not respected. Fixes gh-8314
This commit is contained in:
parent
987b6c956e
commit
c06a9771c2
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2016 the original author or authors.
|
* Copyright 2012-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -144,9 +144,10 @@ public class EndpointWebMvcManagementContextConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnBean(HealthEndpoint.class)
|
@ConditionalOnBean(HealthEndpoint.class)
|
||||||
@ConditionalOnEnabledEndpoint("health")
|
@ConditionalOnEnabledEndpoint("health")
|
||||||
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate) {
|
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate,
|
||||||
|
ManagementServerProperties managementServerProperties) {
|
||||||
HealthMvcEndpoint healthMvcEndpoint = new HealthMvcEndpoint(delegate,
|
HealthMvcEndpoint healthMvcEndpoint = new HealthMvcEndpoint(delegate,
|
||||||
isHealthSecure());
|
isHealthSecure(), managementServerProperties.getSecurity().getRoles());
|
||||||
if (this.healthMvcEndpointProperties.getMapping() != null) {
|
if (this.healthMvcEndpointProperties.getMapping() != null) {
|
||||||
healthMvcEndpoint
|
healthMvcEndpoint
|
||||||
.addStatusMapping(this.healthMvcEndpointProperties.getMapping());
|
.addStatusMapping(this.healthMvcEndpointProperties.getMapping());
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2016 the original author or authors.
|
* Copyright 2012-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -57,6 +57,8 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
|
||||||
|
|
||||||
private final boolean secure;
|
private final boolean secure;
|
||||||
|
|
||||||
|
private final List<String> roles;
|
||||||
|
|
||||||
private Map<String, HttpStatus> statusMapping = new HashMap<String, HttpStatus>();
|
private Map<String, HttpStatus> statusMapping = new HashMap<String, HttpStatus>();
|
||||||
|
|
||||||
private RelaxedPropertyResolver healthPropertyResolver;
|
private RelaxedPropertyResolver healthPropertyResolver;
|
||||||
|
|
@ -70,13 +72,19 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
|
||||||
private Health cached;
|
private Health cached;
|
||||||
|
|
||||||
public HealthMvcEndpoint(HealthEndpoint delegate) {
|
public HealthMvcEndpoint(HealthEndpoint delegate) {
|
||||||
this(delegate, true);
|
this(delegate, true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HealthMvcEndpoint(HealthEndpoint delegate, boolean secure) {
|
public HealthMvcEndpoint(HealthEndpoint delegate, boolean secure) {
|
||||||
|
this(delegate, secure, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HealthMvcEndpoint(HealthEndpoint delegate, boolean secure,
|
||||||
|
List<String> roles) {
|
||||||
super(delegate);
|
super(delegate);
|
||||||
this.secure = secure;
|
this.secure = secure;
|
||||||
setupDefaultStatusMapping();
|
setupDefaultStatusMapping();
|
||||||
|
this.roles = roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupDefaultStatusMapping() {
|
private void setupDefaultStatusMapping() {
|
||||||
|
|
@ -192,12 +200,9 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
|
||||||
}
|
}
|
||||||
if (isSpringSecurityAuthentication(principal)) {
|
if (isSpringSecurityAuthentication(principal)) {
|
||||||
Authentication authentication = (Authentication) principal;
|
Authentication authentication = (Authentication) principal;
|
||||||
List<String> roles = Arrays.asList(StringUtils
|
|
||||||
.trimArrayElements(StringUtils.commaDelimitedListToStringArray(
|
|
||||||
this.roleResolver.getProperty("roles", "ROLE_ADMIN"))));
|
|
||||||
for (GrantedAuthority authority : authentication.getAuthorities()) {
|
for (GrantedAuthority authority : authentication.getAuthorities()) {
|
||||||
String name = authority.getAuthority();
|
String name = authority.getAuthority();
|
||||||
for (String role : roles) {
|
for (String role : getRoles()) {
|
||||||
if (role.equals(name) || ("ROLE_" + role).equals(name)) {
|
if (role.equals(name) || ("ROLE_" + role).equals(name)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -207,6 +212,15 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<String> getRoles() {
|
||||||
|
if (this.roles != null) {
|
||||||
|
return this.roles;
|
||||||
|
}
|
||||||
|
return Arrays.asList(
|
||||||
|
StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(
|
||||||
|
this.roleResolver.getProperty("roles", "ROLE_ADMIN"))));
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isSpringSecurityAuthentication(Principal principal) {
|
private boolean isSpringSecurityAuthentication(Principal principal) {
|
||||||
return ClassUtils.isPresent("org.springframework.security.core.Authentication",
|
return ClassUtils.isPresent("org.springframework.security.core.Authentication",
|
||||||
null) && (principal instanceof Authentication);
|
null) && (principal instanceof Authentication);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2016 the original author or authors.
|
* Copyright 2012-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure;
|
package org.springframework.boot.actuate.autoconfigure;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|
@ -33,6 +35,7 @@ import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.mock.web.MockServletContext;
|
import org.springframework.mock.web.MockServletContext;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
@ -81,6 +84,20 @@ public class HealthMvcEndpointAutoConfigurationTests {
|
||||||
assertThat(map.getDetails().get("foo")).isEqualTo("bar");
|
assertThat(map.getDetails().get("foo")).isEqualTo("bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetRoles() throws Exception {
|
||||||
|
// gh-8314
|
||||||
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
|
this.context.setServletContext(new MockServletContext());
|
||||||
|
this.context.register(TestConfiguration.class);
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"management.security.roles[0]=super");
|
||||||
|
this.context.refresh();
|
||||||
|
HealthMvcEndpoint health = this.context.getBean(HealthMvcEndpoint.class);
|
||||||
|
assertThat(ReflectionTestUtils.getField(health, "roles"))
|
||||||
|
.isEqualTo(Arrays.asList("super"));
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ImportAutoConfiguration({ SecurityAutoConfiguration.class,
|
@ImportAutoConfiguration({ SecurityAutoConfiguration.class,
|
||||||
JacksonAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
JacksonAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2016 the original author or authors.
|
* Copyright 2012-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.endpoint.mvc;
|
package org.springframework.boot.actuate.endpoint.mvc;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
@ -164,6 +165,19 @@ public class HealthMvcEndpointTests {
|
||||||
assertThat(((Health) result).getDetails().get("foo")).isEqualTo("bar");
|
assertThat(((Health) result).getDetails().get("foo")).isEqualTo("bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void secureCustomRoleList() {
|
||||||
|
// gh-8314
|
||||||
|
this.mvc = new HealthMvcEndpoint(this.endpoint, true,
|
||||||
|
Arrays.asList("HERO", "USER"));
|
||||||
|
given(this.endpoint.invoke())
|
||||||
|
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
|
||||||
|
Object result = this.mvc.invoke(this.hero);
|
||||||
|
assertThat(result instanceof Health).isTrue();
|
||||||
|
assertThat(((Health) result).getStatus() == Status.UP).isTrue();
|
||||||
|
assertThat(((Health) result).getDetails().get("foo")).isEqualTo("bar");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void secureCustomRoleNoAccess() {
|
public void secureCustomRoleNoAccess() {
|
||||||
this.environment.getPropertySources().addLast(SECURITY_ROLES);
|
this.environment.getPropertySources().addLast(SECURITY_ROLES);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue