Skip to content

Commit 2d1e85c

Browse files
committed
Merge pull request #6540 from eddumelendez:health-endpoint-visibility
* pr/6540: Polish contribution Fix health endpoint security
2 parents 4229165 + 4882544 commit 2d1e85c

File tree

2 files changed

+47
-9
lines changed

2 files changed

+47
-9
lines changed

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HealthMvcEndpoint.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
package org.springframework.boot.actuate.endpoint.mvc;
1818

1919
import java.security.Principal;
20+
import java.util.Arrays;
2021
import java.util.HashMap;
22+
import java.util.List;
2123
import java.util.Map;
2224

2325
import org.springframework.boot.actuate.endpoint.HealthEndpoint;
@@ -35,6 +37,7 @@
3537
import org.springframework.security.core.GrantedAuthority;
3638
import org.springframework.util.Assert;
3739
import org.springframework.util.ClassUtils;
40+
import org.springframework.util.StringUtils;
3841
import org.springframework.web.bind.annotation.RequestMapping;
3942
import org.springframework.web.bind.annotation.ResponseBody;
4043

@@ -45,6 +48,7 @@
4548
* @author Dave Syer
4649
* @author Andy Wilkinson
4750
* @author Phillip Webb
51+
* @author Eddú Meléndez
4852
* @since 1.1.0
4953
*/
5054
@ConfigurationProperties(prefix = "endpoints.health")
@@ -184,11 +188,14 @@ private boolean isSecure(Principal principal) {
184188
}
185189
if (isSpringSecurityAuthentication(principal)) {
186190
Authentication authentication = (Authentication) principal;
187-
String role = this.roleResolver.getProperty("role", "ROLE_ADMIN");
191+
List<String> roles = Arrays.asList(StringUtils.trimArrayElements(StringUtils
192+
.commaDelimitedListToStringArray(this.roleResolver.getProperty("roles", "ROLE_ADMIN"))));
188193
for (GrantedAuthority authority : authentication.getAuthorities()) {
189194
String name = authority.getAuthority();
190-
if (role.equals(name) || ("ROLE_" + role).equals(name)) {
191-
return true;
195+
for (String role : roles) {
196+
if (role.equals(name) || ("ROLE_" + role).equals(name)) {
197+
return true;
198+
}
192199
}
193200
}
194201
}

spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/HealthMvcEndpointTests.java

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,35 @@
4242
* @author Christian Dupuis
4343
* @author Dave Syer
4444
* @author Andy Wilkinson
45+
* @author Eddú Meléndez
4546
*/
4647
public class HealthMvcEndpointTests {
4748

4849
private static final PropertySource<?> NON_SENSITIVE = new MapPropertySource("test",
4950
Collections.<String, Object>singletonMap("endpoints.health.sensitive",
5051
"false"));
5152

53+
private static final PropertySource<?> SECURITY_ROLES = new MapPropertySource("test",
54+
Collections.<String, Object>singletonMap("management.security.roles",
55+
"HERO, USER"));
56+
5257
private HealthEndpoint endpoint = null;
5358

5459
private HealthMvcEndpoint mvc = null;
5560

5661
private MockEnvironment environment;
5762

58-
private UsernamePasswordAuthenticationToken user = new UsernamePasswordAuthenticationToken(
59-
"user", "password",
60-
AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
63+
private UsernamePasswordAuthenticationToken user = createAuthenticationToken("ROLE_USER");
64+
65+
private UsernamePasswordAuthenticationToken admin = createAuthenticationToken("ROLE_ADMIN");
66+
67+
private UsernamePasswordAuthenticationToken hero = createAuthenticationToken("ROLE_HERO");
6168

62-
private UsernamePasswordAuthenticationToken admin = new UsernamePasswordAuthenticationToken(
63-
"user", "password",
64-
AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN"));
69+
private UsernamePasswordAuthenticationToken createAuthenticationToken(String authority) {
70+
return new UsernamePasswordAuthenticationToken(
71+
"user", "password",
72+
AuthorityUtils.commaSeparatedStringToAuthorityList(authority));
73+
}
6574

6675
@Before
6776
public void init() {
@@ -140,6 +149,28 @@ public void secureNonAdmin() {
140149
assertThat(((Health) result).getDetails().get("foo")).isNull();
141150
}
142151

152+
@Test
153+
public void secureCustomRole() {
154+
this.environment.getPropertySources().addLast(SECURITY_ROLES);
155+
given(this.endpoint.invoke())
156+
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
157+
Object result = this.mvc.invoke(this.hero);
158+
assertThat(result instanceof Health).isTrue();
159+
assertThat(((Health) result).getStatus() == Status.UP).isTrue();
160+
assertThat(((Health) result).getDetails().get("foo")).isEqualTo("bar");
161+
}
162+
163+
@Test
164+
public void secureCustomRoleNoAccess() {
165+
this.environment.getPropertySources().addLast(SECURITY_ROLES);
166+
given(this.endpoint.invoke())
167+
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
168+
Object result = this.mvc.invoke(this.admin);
169+
assertThat(result instanceof Health).isTrue();
170+
assertThat(((Health) result).getStatus() == Status.UP).isTrue();
171+
assertThat(((Health) result).getDetails().get("foo")).isNull();
172+
}
173+
143174
@Test
144175
public void healthIsCached() {
145176
given(this.endpoint.getTimeToLive()).willReturn(10000L);

0 commit comments

Comments
 (0)