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
7da70a52
Commit
7da70a52
authored
Mar 08, 2017
by
Madhura Bhave
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Mask sensitive placeholders in env endpoint
Closes gh-8282
parent
703b7d92
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
126 additions
and
18 deletions
+126
-18
EnvironmentEndpoint.java
...gframework/boot/actuate/endpoint/EnvironmentEndpoint.java
+53
-8
EnvironmentMvcEndpoint.java
...ork/boot/actuate/endpoint/mvc/EnvironmentMvcEndpoint.java
+1
-10
EnvironmentEndpointTests.java
...ework/boot/actuate/endpoint/EnvironmentEndpointTests.java
+61
-0
EnvironmentMvcEndpointTests.java
...oot/actuate/endpoint/mvc/EnvironmentMvcEndpointTests.java
+11
-0
No files found.
spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EnvironmentEndpoint.java
View file @
7da70a52
...
...
@@ -26,7 +26,10 @@ import org.springframework.core.env.ConfigurableEnvironment;
import
org.springframework.core.env.EnumerablePropertySource
;
import
org.springframework.core.env.Environment
;
import
org.springframework.core.env.MutablePropertySources
;
import
org.springframework.core.env.PropertyResolver
;
import
org.springframework.core.env.PropertySource
;
import
org.springframework.core.env.PropertySources
;
import
org.springframework.core.env.PropertySourcesPropertyResolver
;
import
org.springframework.core.env.StandardEnvironment
;
/**
...
...
@@ -35,6 +38,7 @@ import org.springframework.core.env.StandardEnvironment;
* @author Dave Syer
* @author Phillip Webb
* @author Christian Dupuis
* @author Madhura Bhave
*/
@ConfigurationProperties
(
prefix
=
"endpoints.env"
)
public
class
EnvironmentEndpoint
extends
AbstractEndpoint
<
Map
<
String
,
Object
>>
{
...
...
@@ -56,14 +60,15 @@ public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> {
public
Map
<
String
,
Object
>
invoke
()
{
Map
<
String
,
Object
>
result
=
new
LinkedHashMap
<
String
,
Object
>();
result
.
put
(
"profiles"
,
getEnvironment
().
getActiveProfiles
());
for
(
Entry
<
String
,
PropertySource
<?>>
entry
:
getPropertySources
().
entrySet
())
{
PropertyResolver
resolver
=
getResolver
();
for
(
Entry
<
String
,
PropertySource
<?>>
entry
:
getPropertySourcesAsMap
().
entrySet
())
{
PropertySource
<?>
source
=
entry
.
getValue
();
String
sourceName
=
entry
.
getKey
();
if
(
source
instanceof
EnumerablePropertySource
)
{
EnumerablePropertySource
<?>
enumerable
=
(
EnumerablePropertySource
<?>)
source
;
Map
<
String
,
Object
>
properties
=
new
LinkedHashMap
<
String
,
Object
>();
for
(
String
name
:
enumerable
.
getPropertyNames
())
{
properties
.
put
(
name
,
sanitize
(
name
,
enumerable
.
getProperty
(
name
)));
properties
.
put
(
name
,
sanitize
(
name
,
resolver
.
getProperty
(
name
)));
}
properties
=
postProcessSourceProperties
(
sourceName
,
properties
);
if
(
properties
!=
null
)
{
...
...
@@ -74,9 +79,24 @@ public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> {
return
result
;
}
private
Map
<
String
,
PropertySource
<?>>
getPropertySources
()
{
public
PropertyResolver
getResolver
()
{
PlaceholderSanitizingPropertyResolver
resolver
=
new
PlaceholderSanitizingPropertyResolver
(
getPropertySources
(),
this
.
sanitizer
);
resolver
.
setIgnoreUnresolvableNestedPlaceholders
(
true
);
return
resolver
;
}
private
Map
<
String
,
PropertySource
<?>>
getPropertySourcesAsMap
()
{
Map
<
String
,
PropertySource
<?>>
map
=
new
LinkedHashMap
<
String
,
PropertySource
<?>>();
MutablePropertySources
sources
=
null
;
MutablePropertySources
sources
=
getPropertySources
();
for
(
PropertySource
<?>
source
:
sources
)
{
extract
(
""
,
map
,
source
);
}
return
map
;
}
private
MutablePropertySources
getPropertySources
()
{
MutablePropertySources
sources
;
Environment
environment
=
getEnvironment
();
if
(
environment
!=
null
&&
environment
instanceof
ConfigurableEnvironment
)
{
sources
=
((
ConfigurableEnvironment
)
environment
).
getPropertySources
();
...
...
@@ -84,10 +104,7 @@ public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> {
else
{
sources
=
new
StandardEnvironment
().
getPropertySources
();
}
for
(
PropertySource
<?>
source
:
sources
)
{
extract
(
""
,
map
,
source
);
}
return
map
;
return
sources
;
}
private
void
extract
(
String
root
,
Map
<
String
,
PropertySource
<?>>
map
,
...
...
@@ -120,4 +137,32 @@ public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> {
return
properties
;
}
/**
* {@link PropertySourcesPropertyResolver} that sanitizes sensitive placeholders
* if present.
*
* @author Madhura Bhave
*/
private
class
PlaceholderSanitizingPropertyResolver
extends
PropertySourcesPropertyResolver
{
private
final
Sanitizer
sanitizer
;
/**
* Create a new resolver against the given property sources.
* @param propertySources the set of {@link PropertySource} objects to use
* @param sanitizer the sanitizer used to sanitize sensitive values
*/
PlaceholderSanitizingPropertyResolver
(
PropertySources
propertySources
,
Sanitizer
sanitizer
)
{
super
(
propertySources
);
this
.
sanitizer
=
sanitizer
;
}
@Override
protected
String
getPropertyAsRawString
(
String
key
)
{
String
value
=
super
.
getPropertyAsRawString
(
key
);
return
(
String
)
this
.
sanitizer
.
sanitize
(
key
,
value
);
}
}
}
spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EnvironmentMvcEndpoint.java
View file @
7da70a52
...
...
@@ -22,10 +22,8 @@ import org.springframework.context.EnvironmentAware;
import
org.springframework.core.env.ConfigurableEnvironment
;
import
org.springframework.core.env.EnumerablePropertySource
;
import
org.springframework.core.env.Environment
;
import
org.springframework.core.env.PropertyResolver
;
import
org.springframework.core.env.PropertySource
;
import
org.springframework.core.env.PropertySources
;
import
org.springframework.core.env.PropertySourcesPropertyResolver
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.ResponseBody
;
...
...
@@ -95,14 +93,7 @@ public class EnvironmentMvcEndpoint extends EndpointMvcAdapter
@Override
protected
Object
getOptionalValue
(
Environment
source
,
String
name
)
{
PropertyResolver
resolver
=
source
;
if
(
source
instanceof
ConfigurableEnvironment
)
{
resolver
=
new
PropertySourcesPropertyResolver
(
((
ConfigurableEnvironment
)
source
).
getPropertySources
());
((
PropertySourcesPropertyResolver
)
resolver
)
.
setIgnoreUnresolvableNestedPlaceholders
(
true
);
}
Object
result
=
resolver
.
getProperty
(
name
);
Object
result
=
((
EnvironmentEndpoint
)
getDelegate
()).
getResolver
().
getProperty
(
name
);
if
(
result
!=
null
)
{
result
=
((
EnvironmentEndpoint
)
getDelegate
()).
sanitize
(
name
,
result
);
}
...
...
spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/EnvironmentEndpointTests.java
View file @
7da70a52
...
...
@@ -39,6 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Christian Dupuis
* @author Nicolas Lejeune
* @author Stephane Nicoll
* @author Madhura Bhave
*/
public
class
EnvironmentEndpointTests
extends
AbstractEndpointTests
<
EnvironmentEndpoint
>
{
...
...
@@ -194,6 +195,66 @@ public class EnvironmentEndpointTests extends AbstractEndpointTests<EnvironmentE
assertThat
(
systemProperties
.
get
(
"apiKey"
)).
isEqualTo
(
"******"
);
}
@SuppressWarnings
(
"unchecked"
)
@Test
public
void
propertyWithPlaceholderResolved
()
throws
Exception
{
this
.
context
=
new
AnnotationConfigApplicationContext
();
EnvironmentTestUtils
.
addEnvironment
(
this
.
context
,
"my.foo: ${bar.blah}"
,
"bar.blah: hello"
);
this
.
context
.
register
(
Config
.
class
);
this
.
context
.
refresh
();
EnvironmentEndpoint
report
=
getEndpointBean
();
Map
<
String
,
Object
>
env
=
report
.
invoke
();
Map
<
String
,
Object
>
testProperties
=
(
Map
<
String
,
Object
>)
env
.
get
(
"test"
);
assertThat
(
testProperties
.
get
(
"my.foo"
)).
isEqualTo
(
"hello"
);
}
@SuppressWarnings
(
"unchecked"
)
@Test
public
void
propertyWithPlaceholderNotResolved
()
throws
Exception
{
this
.
context
=
new
AnnotationConfigApplicationContext
();
EnvironmentTestUtils
.
addEnvironment
(
this
.
context
,
"my.foo: ${bar.blah}"
);
this
.
context
.
register
(
Config
.
class
);
this
.
context
.
refresh
();
EnvironmentEndpoint
report
=
getEndpointBean
();
Map
<
String
,
Object
>
env
=
report
.
invoke
();
Map
<
String
,
Object
>
testProperties
=
(
Map
<
String
,
Object
>)
env
.
get
(
"test"
);
assertThat
(
testProperties
.
get
(
"my.foo"
)).
isEqualTo
(
"${bar.blah}"
);
}
@SuppressWarnings
(
"unchecked"
)
@Test
public
void
propertyWithSensitivePlaceholderResolved
()
throws
Exception
{
this
.
context
=
new
AnnotationConfigApplicationContext
();
EnvironmentTestUtils
.
addEnvironment
(
this
.
context
,
"my.foo: http://${bar.password}://hello"
,
"bar.password: hello"
);
this
.
context
.
register
(
Config
.
class
);
this
.
context
.
refresh
();
EnvironmentEndpoint
report
=
getEndpointBean
();
Map
<
String
,
Object
>
env
=
report
.
invoke
();
Map
<
String
,
Object
>
testProperties
=
(
Map
<
String
,
Object
>)
env
.
get
(
"test"
);
assertThat
(
testProperties
.
get
(
"my.foo"
)).
isEqualTo
(
"http://******://hello"
);
}
@SuppressWarnings
(
"unchecked"
)
@Test
public
void
propertyWithSensitivePlaceholderNotResolved
()
throws
Exception
{
this
.
context
=
new
AnnotationConfigApplicationContext
();
EnvironmentTestUtils
.
addEnvironment
(
this
.
context
,
"my.foo: http://${bar.password}://hello"
);
this
.
context
.
register
(
Config
.
class
);
this
.
context
.
refresh
();
EnvironmentEndpoint
report
=
getEndpointBean
();
Map
<
String
,
Object
>
env
=
report
.
invoke
();
Map
<
String
,
Object
>
testProperties
=
(
Map
<
String
,
Object
>)
env
.
get
(
"test"
);
assertThat
(
testProperties
.
get
(
"my.foo"
)).
isEqualTo
(
"http://${bar.password}://hello"
);
}
@Configuration
@EnableConfigurationProperties
public
static
class
Config
{
...
...
spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/EnvironmentMvcEndpointTests.java
View file @
7da70a52
...
...
@@ -148,6 +148,17 @@ public class EnvironmentMvcEndpointTests {
.
andExpect
(
content
().
string
(
containsString
(
"\"my.foo\":\"${my.bar}\""
)));
}
@Test
public
void
nestedPathWithSensitivePlaceholderShouldSanitize
()
throws
Exception
{
Map
<
String
,
Object
>
map
=
new
HashMap
<
String
,
Object
>();
map
.
put
(
"my.foo"
,
"${my.password}"
);
map
.
put
(
"my.password"
,
"hello"
);
((
ConfigurableEnvironment
)
this
.
context
.
getEnvironment
()).
getPropertySources
()
.
addFirst
(
new
MapPropertySource
(
"placeholder"
,
map
));
this
.
mvc
.
perform
(
get
(
"/env/my.*"
)).
andExpect
(
status
().
isOk
())
.
andExpect
(
content
().
string
(
containsString
(
"\"my.foo\":\"******\""
)));
}
@Configuration
@Import
({
JacksonAutoConfiguration
.
class
,
HttpMessageConvertersAutoConfiguration
.
class
,
WebMvcAutoConfiguration
.
class
,
...
...
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