Commit c06a9771 authored by Phillip Webb's avatar Phillip Webb

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
parent 987b6c95
/*
* 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");
* you may not use this file except in compliance with the License.
......@@ -144,9 +144,10 @@ public class EndpointWebMvcManagementContextConfiguration {
@Bean
@ConditionalOnBean(HealthEndpoint.class)
@ConditionalOnEnabledEndpoint("health")
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate) {
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate,
ManagementServerProperties managementServerProperties) {
HealthMvcEndpoint healthMvcEndpoint = new HealthMvcEndpoint(delegate,
isHealthSecure());
isHealthSecure(), managementServerProperties.getSecurity().getRoles());
if (this.healthMvcEndpointProperties.getMapping() != null) {
healthMvcEndpoint
.addStatusMapping(this.healthMvcEndpointProperties.getMapping());
......
/*
* 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");
* 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 List<String> roles;
private Map<String, HttpStatus> statusMapping = new HashMap<String, HttpStatus>();
private RelaxedPropertyResolver healthPropertyResolver;
......@@ -70,13 +72,19 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
private Health cached;
public HealthMvcEndpoint(HealthEndpoint delegate) {
this(delegate, true);
this(delegate, true, null);
}
public HealthMvcEndpoint(HealthEndpoint delegate, boolean secure) {
this(delegate, secure, null);
}
public HealthMvcEndpoint(HealthEndpoint delegate, boolean secure,
List<String> roles) {
super(delegate);
this.secure = secure;
setupDefaultStatusMapping();
this.roles = roles;
}
private void setupDefaultStatusMapping() {
......@@ -192,12 +200,9 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
}
if (isSpringSecurityAuthentication(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()) {
String name = authority.getAuthority();
for (String role : roles) {
for (String role : getRoles()) {
if (role.equals(name) || ("ROLE_" + role).equals(name)) {
return true;
}
......@@ -207,6 +212,15 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
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) {
return ClassUtils.isPresent("org.springframework.security.core.Authentication",
null) && (principal instanceof Authentication);
......
/*
* 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");
* you may not use this file except in compliance with the License.
......@@ -16,6 +16,8 @@
package org.springframework.boot.actuate.autoconfigure;
import java.util.Arrays;
import org.junit.After;
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.Configuration;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
......@@ -81,6 +84,20 @@ public class HealthMvcEndpointAutoConfigurationTests {
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
@ImportAutoConfiguration({ SecurityAutoConfiguration.class,
JacksonAutoConfiguration.class, WebMvcAutoConfiguration.class,
......
/*
* 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");
* you may not use this file except in compliance with the License.
......@@ -16,6 +16,7 @@
package org.springframework.boot.actuate.endpoint.mvc;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Before;
......@@ -164,6 +165,19 @@ public class HealthMvcEndpointTests {
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
public void secureCustomRoleNoAccess() {
this.environment.getPropertySources().addLast(SECURITY_ROLES);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment