Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
ff22bd48
Commit
ff22bd48
authored
Nov 19, 2019
by
Madhura Bhave
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '2.1.x' into 2.2.x
Closes gh-19059
parents
a003a5c8
a3a53d29
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
137 additions
and
2 deletions
+137
-2
AutoConfiguredHealthEndpointGroup.java
...toconfigure/health/AutoConfiguredHealthEndpointGroup.java
+30
-2
AutoConfiguredHealthEndpointGroupTests.java
...figure/health/AutoConfiguredHealthEndpointGroupTests.java
+51
-0
HealthWebEndpointResponseMapper.java
.../boot/actuate/health/HealthWebEndpointResponseMapper.java
+21
-0
HealthWebEndpointResponseMapperTests.java
.../actuate/health/HealthWebEndpointResponseMapperTests.java
+35
-0
No files found.
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroup.java
View file @
ff22bd48
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
health
;
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
health
;
import
java.security.Principal
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.function.Predicate
;
import
java.util.function.Predicate
;
...
@@ -24,6 +25,9 @@ import org.springframework.boot.actuate.endpoint.SecurityContext;
...
@@ -24,6 +25,9 @@ import org.springframework.boot.actuate.endpoint.SecurityContext;
import
org.springframework.boot.actuate.health.HealthEndpointGroup
;
import
org.springframework.boot.actuate.health.HealthEndpointGroup
;
import
org.springframework.boot.actuate.health.HttpCodeStatusMapper
;
import
org.springframework.boot.actuate.health.HttpCodeStatusMapper
;
import
org.springframework.boot.actuate.health.StatusAggregator
;
import
org.springframework.boot.actuate.health.StatusAggregator
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.CollectionUtils
;
/**
/**
...
@@ -97,10 +101,34 @@ class AutoConfiguredHealthEndpointGroup implements HealthEndpointGroup {
...
@@ -97,10 +101,34 @@ class AutoConfiguredHealthEndpointGroup implements HealthEndpointGroup {
}
}
private
boolean
isAuthorized
(
SecurityContext
securityContext
)
{
private
boolean
isAuthorized
(
SecurityContext
securityContext
)
{
if
(
securityContext
.
getPrincipal
()
==
null
)
{
Principal
principal
=
securityContext
.
getPrincipal
();
if
(
principal
==
null
)
{
return
false
;
return
false
;
}
}
return
CollectionUtils
.
isEmpty
(
this
.
roles
)
||
this
.
roles
.
stream
().
anyMatch
(
securityContext:
:
isUserInRole
);
if
(
CollectionUtils
.
isEmpty
(
this
.
roles
))
{
return
true
;
}
boolean
checkAuthorities
=
isSpringSecurityAuthentication
(
principal
);
for
(
String
role
:
this
.
roles
)
{
if
(
securityContext
.
isUserInRole
(
role
))
{
return
true
;
}
if
(
checkAuthorities
)
{
Authentication
authentication
=
(
Authentication
)
principal
;
for
(
GrantedAuthority
authority
:
authentication
.
getAuthorities
())
{
String
name
=
authority
.
getAuthority
();
if
(
role
.
equals
(
name
))
{
return
true
;
}
}
}
}
return
false
;
}
private
boolean
isSpringSecurityAuthentication
(
Principal
principal
)
{
return
ClassUtils
.
isPresent
(
"org.springframework.security.core.Authentication"
,
null
)
&&
(
principal
instanceof
Authentication
);
}
}
@Override
@Override
...
...
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroupTests.java
View file @
ff22bd48
...
@@ -29,9 +29,12 @@ import org.springframework.boot.actuate.autoconfigure.health.HealthProperties.Sh
...
@@ -29,9 +29,12 @@ import org.springframework.boot.actuate.autoconfigure.health.HealthProperties.Sh
import
org.springframework.boot.actuate.endpoint.SecurityContext
;
import
org.springframework.boot.actuate.endpoint.SecurityContext
;
import
org.springframework.boot.actuate.health.HttpCodeStatusMapper
;
import
org.springframework.boot.actuate.health.HttpCodeStatusMapper
;
import
org.springframework.boot.actuate.health.StatusAggregator
;
import
org.springframework.boot.actuate.health.StatusAggregator
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.authority.SimpleGrantedAuthority
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
mock
;
/**
/**
* Tests for {@link AutoConfiguredHealthEndpointGroup}.
* Tests for {@link AutoConfiguredHealthEndpointGroup}.
...
@@ -123,6 +126,30 @@ class AutoConfiguredHealthEndpointGroupTests {
...
@@ -123,6 +126,30 @@ class AutoConfiguredHealthEndpointGroupTests {
assertThat
(
group
.
showDetails
(
this
.
securityContext
)).
isFalse
();
assertThat
(
group
.
showDetails
(
this
.
securityContext
)).
isFalse
();
}
}
@Test
void
showDetailsWhenShowDetailsIsWhenAuthorizedAndUserHasRightAuthorityReturnsTrue
()
{
AutoConfiguredHealthEndpointGroup
group
=
new
AutoConfiguredHealthEndpointGroup
((
name
)
->
true
,
this
.
statusAggregator
,
this
.
httpCodeStatusMapper
,
null
,
Show
.
WHEN_AUTHORIZED
,
Arrays
.
asList
(
"admin"
,
"root"
,
"bossmode"
));
Authentication
principal
=
mock
(
Authentication
.
class
);
given
(
principal
.
getAuthorities
())
.
willAnswer
((
invocation
)
->
Collections
.
singleton
(
new
SimpleGrantedAuthority
(
"admin"
)));
given
(
this
.
securityContext
.
getPrincipal
()).
willReturn
(
principal
);
assertThat
(
group
.
showDetails
(
this
.
securityContext
)).
isTrue
();
}
@Test
void
showDetailsWhenShowDetailsIsWhenAuthorizedAndUserDoesNotHaveRightAuthoritiesReturnsFalse
()
{
AutoConfiguredHealthEndpointGroup
group
=
new
AutoConfiguredHealthEndpointGroup
((
name
)
->
true
,
this
.
statusAggregator
,
this
.
httpCodeStatusMapper
,
null
,
Show
.
WHEN_AUTHORIZED
,
Arrays
.
asList
(
"admin"
,
"rot"
,
"bossmode"
));
Authentication
principal
=
mock
(
Authentication
.
class
);
given
(
principal
.
getAuthorities
())
.
willAnswer
((
invocation
)
->
Collections
.
singleton
(
new
SimpleGrantedAuthority
(
"other"
)));
given
(
this
.
securityContext
.
getPrincipal
()).
willReturn
(
principal
);
assertThat
(
group
.
showDetails
(
this
.
securityContext
)).
isFalse
();
}
@Test
@Test
void
showComponentsWhenShowComponentsIsNullDelegatesToShowDetails
()
{
void
showComponentsWhenShowComponentsIsNullDelegatesToShowDetails
()
{
AutoConfiguredHealthEndpointGroup
alwaysGroup
=
new
AutoConfiguredHealthEndpointGroup
((
name
)
->
true
,
AutoConfiguredHealthEndpointGroup
alwaysGroup
=
new
AutoConfiguredHealthEndpointGroup
((
name
)
->
true
,
...
@@ -185,6 +212,30 @@ class AutoConfiguredHealthEndpointGroupTests {
...
@@ -185,6 +212,30 @@ class AutoConfiguredHealthEndpointGroupTests {
assertThat
(
group
.
showComponents
(
this
.
securityContext
)).
isFalse
();
assertThat
(
group
.
showComponents
(
this
.
securityContext
)).
isFalse
();
}
}
@Test
void
showComponentsWhenShowComponentsIsWhenAuthorizedAndUserHasRightAuthoritiesReturnsTrue
()
{
AutoConfiguredHealthEndpointGroup
group
=
new
AutoConfiguredHealthEndpointGroup
((
name
)
->
true
,
this
.
statusAggregator
,
this
.
httpCodeStatusMapper
,
Show
.
WHEN_AUTHORIZED
,
Show
.
NEVER
,
Arrays
.
asList
(
"admin"
,
"root"
,
"bossmode"
));
Authentication
principal
=
mock
(
Authentication
.
class
);
given
(
principal
.
getAuthorities
())
.
willAnswer
((
invocation
)
->
Collections
.
singleton
(
new
SimpleGrantedAuthority
(
"admin"
)));
given
(
this
.
securityContext
.
getPrincipal
()).
willReturn
(
principal
);
assertThat
(
group
.
showComponents
(
this
.
securityContext
)).
isTrue
();
}
@Test
void
showComponentsWhenShowComponentsIsWhenAuthorizedAndUserDoesNotHaveRightAuthoritiesReturnsFalse
()
{
AutoConfiguredHealthEndpointGroup
group
=
new
AutoConfiguredHealthEndpointGroup
((
name
)
->
true
,
this
.
statusAggregator
,
this
.
httpCodeStatusMapper
,
Show
.
WHEN_AUTHORIZED
,
Show
.
NEVER
,
Arrays
.
asList
(
"admin"
,
"rot"
,
"bossmode"
));
Authentication
principal
=
mock
(
Authentication
.
class
);
given
(
principal
.
getAuthorities
())
.
willAnswer
((
invocation
)
->
Collections
.
singleton
(
new
SimpleGrantedAuthority
(
"other"
)));
given
(
this
.
securityContext
.
getPrincipal
()).
willReturn
(
principal
);
assertThat
(
group
.
showComponents
(
this
.
securityContext
)).
isFalse
();
}
@Test
@Test
void
getStatusAggregatorReturnsStatusAggregator
()
{
void
getStatusAggregatorReturnsStatusAggregator
()
{
AutoConfiguredHealthEndpointGroup
group
=
new
AutoConfiguredHealthEndpointGroup
((
name
)
->
true
,
AutoConfiguredHealthEndpointGroup
group
=
new
AutoConfiguredHealthEndpointGroup
((
name
)
->
true
,
...
...
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthWebEndpointResponseMapper.java
View file @
ff22bd48
...
@@ -16,11 +16,15 @@
...
@@ -16,11 +16,15 @@
package
org
.
springframework
.
boot
.
actuate
.
health
;
package
org
.
springframework
.
boot
.
actuate
.
health
;
import
java.security.Principal
;
import
java.util.Set
;
import
java.util.Set
;
import
java.util.function.Supplier
;
import
java.util.function.Supplier
;
import
org.springframework.boot.actuate.endpoint.SecurityContext
;
import
org.springframework.boot.actuate.endpoint.SecurityContext
;
import
org.springframework.boot.actuate.endpoint.web.WebEndpointResponse
;
import
org.springframework.boot.actuate.endpoint.web.WebEndpointResponse
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.CollectionUtils
;
/**
/**
...
@@ -108,12 +112,29 @@ public class HealthWebEndpointResponseMapper {
...
@@ -108,12 +112,29 @@ public class HealthWebEndpointResponseMapper {
if
(
CollectionUtils
.
isEmpty
(
this
.
authorizedRoles
))
{
if
(
CollectionUtils
.
isEmpty
(
this
.
authorizedRoles
))
{
return
true
;
return
true
;
}
}
Principal
principal
=
securityContext
.
getPrincipal
();
boolean
checkAuthorities
=
isSpringSecurityAuthentication
(
principal
);
for
(
String
role
:
this
.
authorizedRoles
)
{
for
(
String
role
:
this
.
authorizedRoles
)
{
if
(
securityContext
.
isUserInRole
(
role
))
{
if
(
securityContext
.
isUserInRole
(
role
))
{
return
true
;
return
true
;
}
}
if
(
checkAuthorities
)
{
Authentication
authentication
=
(
Authentication
)
principal
;
for
(
GrantedAuthority
authority
:
authentication
.
getAuthorities
())
{
String
name
=
authority
.
getAuthority
();
if
(
role
.
equals
(
name
))
{
return
true
;
}
}
}
}
}
return
false
;
return
false
;
}
}
private
boolean
isSpringSecurityAuthentication
(
Principal
principal
)
{
return
ClassUtils
.
isPresent
(
"org.springframework.security.core.Authentication"
,
null
)
&&
(
principal
instanceof
Authentication
);
}
}
}
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthWebEndpointResponseMapperTests.java
View file @
ff22bd48
...
@@ -29,6 +29,8 @@ import org.mockito.stubbing.Answer;
...
@@ -29,6 +29,8 @@ import org.mockito.stubbing.Answer;
import
org.springframework.boot.actuate.endpoint.SecurityContext
;
import
org.springframework.boot.actuate.endpoint.SecurityContext
;
import
org.springframework.boot.actuate.endpoint.web.WebEndpointResponse
;
import
org.springframework.boot.actuate.endpoint.web.WebEndpointResponse
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.authority.SimpleGrantedAuthority
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyString
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyString
;
...
@@ -85,6 +87,39 @@ class HealthWebEndpointResponseMapperTests {
...
@@ -85,6 +87,39 @@ class HealthWebEndpointResponseMapperTests {
verify
(
securityContext
).
isUserInRole
(
"ACTUATOR"
);
verify
(
securityContext
).
isUserInRole
(
"ACTUATOR"
);
}
}
@Test
void
mapDetailsWithRightAuthoritiesInvokesSupplier
()
{
HealthWebEndpointResponseMapper
mapper
=
createMapper
(
ShowDetails
.
WHEN_AUTHORIZED
);
Supplier
<
Health
>
supplier
=
mockSupplier
();
given
(
supplier
.
get
()).
willReturn
(
Health
.
down
().
build
());
SecurityContext
securityContext
=
getSecurityContext
(
"ACTUATOR"
);
WebEndpointResponse
<
Health
>
response
=
mapper
.
mapDetails
(
supplier
,
securityContext
);
assertThat
(
response
.
getStatus
()).
isEqualTo
(
HttpStatus
.
SERVICE_UNAVAILABLE
.
value
());
assertThat
(
response
.
getBody
().
getStatus
()).
isEqualTo
(
Status
.
DOWN
);
verify
(
supplier
).
get
();
}
@Test
void
mapDetailsWithOtherAuthoritiesShouldNotInvokeSupplier
()
{
HealthWebEndpointResponseMapper
mapper
=
createMapper
(
ShowDetails
.
WHEN_AUTHORIZED
);
Supplier
<
Health
>
supplier
=
mockSupplier
();
given
(
supplier
.
get
()).
willReturn
(
Health
.
down
().
build
());
SecurityContext
securityContext
=
getSecurityContext
(
"OTHER"
);
WebEndpointResponse
<
Health
>
response
=
mapper
.
mapDetails
(
supplier
,
securityContext
);
assertThat
(
response
.
getStatus
()).
isEqualTo
(
HttpStatus
.
NOT_FOUND
.
value
());
assertThat
(
response
.
getBody
()).
isNull
();
verifyNoInteractions
(
supplier
);
}
private
SecurityContext
getSecurityContext
(
String
other
)
{
SecurityContext
securityContext
=
mock
(
SecurityContext
.
class
);
Authentication
principal
=
mock
(
Authentication
.
class
);
given
(
securityContext
.
getPrincipal
()).
willReturn
(
principal
);
given
(
principal
.
getAuthorities
())
.
willAnswer
((
invocation
)
->
Collections
.
singleton
(
new
SimpleGrantedAuthority
(
other
)));
return
securityContext
;
}
@Test
@Test
void
mapDetailsWithUnavailableHealth
()
{
void
mapDetailsWithUnavailableHealth
()
{
HealthWebEndpointResponseMapper
mapper
=
createMapper
(
ShowDetails
.
ALWAYS
);
HealthWebEndpointResponseMapper
mapper
=
createMapper
(
ShowDetails
.
ALWAYS
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment