Allow additional keys to be configured for value sanitization
Closes gh-25384
This commit is contained in:
@@ -49,6 +49,10 @@ public class ConfigurationPropertiesReportEndpointAutoConfiguration {
|
||||
if (keysToSanitize != null) {
|
||||
endpoint.setKeysToSanitize(keysToSanitize);
|
||||
}
|
||||
String[] additionalKeysToSanitize = properties.getAdditionalKeysToSanitize();
|
||||
if (additionalKeysToSanitize != null) {
|
||||
endpoint.keysToSanitize(additionalKeysToSanitize);
|
||||
}
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -34,6 +34,12 @@ public class ConfigurationPropertiesReportEndpointProperties {
|
||||
*/
|
||||
private String[] keysToSanitize;
|
||||
|
||||
/**
|
||||
* Keys that should be sanitized in addition to those already configured. Keys can be
|
||||
* simple strings that the property ends with or regular expressions.
|
||||
*/
|
||||
private String[] additionalKeysToSanitize;
|
||||
|
||||
public String[] getKeysToSanitize() {
|
||||
return this.keysToSanitize;
|
||||
}
|
||||
@@ -42,4 +48,12 @@ public class ConfigurationPropertiesReportEndpointProperties {
|
||||
this.keysToSanitize = keysToSanitize;
|
||||
}
|
||||
|
||||
public String[] getAdditionalKeysToSanitize() {
|
||||
return this.additionalKeysToSanitize;
|
||||
}
|
||||
|
||||
public void setAdditionalKeysToSanitize(String[] additionalKeysToSanitize) {
|
||||
this.additionalKeysToSanitize = additionalKeysToSanitize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -47,6 +47,10 @@ public class EnvironmentEndpointAutoConfiguration {
|
||||
if (keysToSanitize != null) {
|
||||
endpoint.setKeysToSanitize(keysToSanitize);
|
||||
}
|
||||
String[] additionalKeysToSanitize = properties.getAdditionalKeysToSanitize();
|
||||
if (additionalKeysToSanitize != null) {
|
||||
endpoint.keysToSanitize(additionalKeysToSanitize);
|
||||
}
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -34,6 +34,12 @@ public class EnvironmentEndpointProperties {
|
||||
*/
|
||||
private String[] keysToSanitize;
|
||||
|
||||
/**
|
||||
* Keys that should be sanitized in addition to those already configured. Keys can be
|
||||
* simple strings that the property ends with or regular expressions.
|
||||
*/
|
||||
private String[] additionalKeysToSanitize;
|
||||
|
||||
public String[] getKeysToSanitize() {
|
||||
return this.keysToSanitize;
|
||||
}
|
||||
@@ -42,4 +48,12 @@ public class EnvironmentEndpointProperties {
|
||||
this.keysToSanitize = keysToSanitize;
|
||||
}
|
||||
|
||||
public String[] getAdditionalKeysToSanitize() {
|
||||
return this.additionalKeysToSanitize;
|
||||
}
|
||||
|
||||
public void setAdditionalKeysToSanitize(String[] additionalKeysToSanitize) {
|
||||
this.additionalKeysToSanitize = additionalKeysToSanitize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -64,6 +64,14 @@ class ConfigurationPropertiesReportEndpointAutoConfigurationTests {
|
||||
.run(validateTestProperties("******", "******"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void additionalKeysToSanitizeCanBeConfiguredViaTheEnvironment() {
|
||||
this.contextRunner.withUserConfiguration(Config.class)
|
||||
.withPropertyValues("management.endpoint.configprops.additional-keys-to-sanitize: property")
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=configprops")
|
||||
.run(validateTestProperties("******", "******"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenNotExposedShouldNotHaveEndpointBean() {
|
||||
this.contextRunner
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -67,6 +67,14 @@ class EnvironmentEndpointAutoConfigurationTests {
|
||||
.run(validateSystemProperties("******", "123456"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void additionalKeysToSanitizeCanBeConfiguredViaTheEnvironment() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=env")
|
||||
.withSystemProperties("dbPassword=123456", "apiKey=123456")
|
||||
.withPropertyValues("management.endpoint.env.additional-keys-to-sanitize=key")
|
||||
.run(validateSystemProperties("******", "******"));
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableApplicationContext> validateSystemProperties(String dbPassword, String apiKey) {
|
||||
return (context) -> {
|
||||
assertThat(context).hasSingleBean(EnvironmentEndpoint.class);
|
||||
|
||||
@@ -115,6 +115,10 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
this.sanitizer.setKeysToSanitize(keysToSanitize);
|
||||
}
|
||||
|
||||
public void keysToSanitize(String... keysToSanitize) {
|
||||
this.sanitizer.keysToSanitize(keysToSanitize);
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public ApplicationConfigurationProperties configurationProperties() {
|
||||
return extract(this.context, (bean) -> true);
|
||||
|
||||
@@ -67,8 +67,8 @@ public class Sanitizer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Keys that should be sanitized. Keys can be simple strings that the property ends
|
||||
* with or regular expressions.
|
||||
* Set the keys that should be sanitized, overwriting any existing configuration. Keys
|
||||
* can be simple strings that the property ends with or regular expressions.
|
||||
* @param keysToSanitize the keys to sanitize
|
||||
*/
|
||||
public void setKeysToSanitize(String... keysToSanitize) {
|
||||
@@ -79,6 +79,21 @@ public class Sanitizer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds keys that should be sanitized. Keys can be simple strings that the property
|
||||
* ends with or regular expressions.
|
||||
* @param keysToSanitize the keys to sanitize
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public void keysToSanitize(String... keysToSanitize) {
|
||||
Assert.notNull(keysToSanitize, "KeysToSanitize must not be null");
|
||||
int existingKeys = this.keysToSanitize.length;
|
||||
this.keysToSanitize = Arrays.copyOf(this.keysToSanitize, this.keysToSanitize.length + keysToSanitize.length);
|
||||
for (int i = 0; i < keysToSanitize.length; i++) {
|
||||
this.keysToSanitize[i + existingKeys] = getPattern(keysToSanitize[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private Pattern getPattern(String value) {
|
||||
if (isRegex(value)) {
|
||||
return Pattern.compile(value, Pattern.CASE_INSENSITIVE);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2021 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.
|
||||
@@ -76,6 +76,10 @@ public class EnvironmentEndpoint {
|
||||
this.sanitizer.setKeysToSanitize(keysToSanitize);
|
||||
}
|
||||
|
||||
public void keysToSanitize(String... keysToSanitize) {
|
||||
this.sanitizer.keysToSanitize(keysToSanitize);
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public EnvironmentDescriptor environment(@Nullable String pattern) {
|
||||
if (StringUtils.hasText(pattern)) {
|
||||
|
||||
@@ -48,6 +48,23 @@ class SanitizerTests {
|
||||
assertThat(sanitizer.sanitize("sun.java.command", "--spring.redis.password=pa55w0rd")).isEqualTo("******");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenAdditionalKeysAreAddedValuesOfBothThemAndTheDefaultKeysAreSanitized() {
|
||||
Sanitizer sanitizer = new Sanitizer();
|
||||
sanitizer.keysToSanitize("find", "confidential");
|
||||
assertThat(sanitizer.sanitize("password", "secret")).isEqualTo("******");
|
||||
assertThat(sanitizer.sanitize("my-password", "secret")).isEqualTo("******");
|
||||
assertThat(sanitizer.sanitize("my-OTHER.paSSword", "secret")).isEqualTo("******");
|
||||
assertThat(sanitizer.sanitize("somesecret", "secret")).isEqualTo("******");
|
||||
assertThat(sanitizer.sanitize("somekey", "secret")).isEqualTo("******");
|
||||
assertThat(sanitizer.sanitize("token", "secret")).isEqualTo("******");
|
||||
assertThat(sanitizer.sanitize("sometoken", "secret")).isEqualTo("******");
|
||||
assertThat(sanitizer.sanitize("find", "secret")).isEqualTo("******");
|
||||
assertThat(sanitizer.sanitize("sun.java.command", "--spring.redis.password=pa55w0rd")).isEqualTo("******");
|
||||
assertThat(sanitizer.sanitize("confidential", "secret")).isEqualTo("******");
|
||||
assertThat(sanitizer.sanitize("private", "secret")).isEqualTo("secret");
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "key = {0}")
|
||||
@MethodSource("matchingUriUserInfoKeys")
|
||||
void uriWithSingleValueWithPasswordShouldBeSanitized(String key) {
|
||||
|
||||
@@ -2333,14 +2333,10 @@ See also the section on "`<<spring-boot-features.adoc#boot-features-error-handli
|
||||
[[howto-sanitize-sensible-values]]
|
||||
[[howto-sanitize-sensitive-values]]
|
||||
=== Sanitize Sensitive Values
|
||||
Information returned by the `env` and `configprops` endpoints can be somewhat sensitive so keys matching a certain pattern are sanitized by default (i.e. their values are replaced by `+******+`).
|
||||
Information returned by the `env` and `configprops` endpoints can be somewhat sensitive so keys matching certain patterns are sanitized by default (i.e. their values are replaced by `+******+`). Spring Boot uses sensible defaults for such keys: any key ending with the word "password", "secret", "key", "token", "vcap_services", "sun.java.command" is entirely sanitized.
|
||||
Additionally, any key that holds the word `credentials` (configured as a regular expression, i.e. `+*credentials.*+`) as part of the key is also entirely sanitized.
|
||||
|
||||
The patterns to use can be customized using the `management.endpoint.env.keys-to-sanitize` and `management.endpoint.configprops.keys-to-sanitize` respectively.
|
||||
|
||||
Spring Boot uses sensible defaults for such keys: any key ending with the word "password", "secret", "key", "token", "vcap_services", "sun.java.command" is entirely sanitized.
|
||||
Additionally, any key that holds the word `credentials` as part of the key is sanitized (configured as a regular expression, i.e. `+*credentials.*+`).
|
||||
|
||||
Furthermore, Spring Boot only sanitizes the sensitive portion of URI-like values for keys with one of the following endings:
|
||||
Furthermore, Spring Boot sanitizes the sensitive portion of URI-like values for keys with one of the following endings:
|
||||
|
||||
- `address`
|
||||
- `addresses`
|
||||
@@ -2353,6 +2349,9 @@ The sensitive portion of the URI is identified using the format `<scheme>://<use
|
||||
For example, for the property `myclient.uri=http://user1:password1@localhost:8081`, the resulting sanitized value is
|
||||
`++http://user1:******@localhost:8081++`.
|
||||
|
||||
The defaults patterns used by the `env` and `configprops` endpoints can be replaced using configprop:management.endpoint.env.keys-to-sanitize[] and configprop:management.endpoint.configprops.keys-to-sanitize[] respectively.
|
||||
Alternatively, additional patterns can be configured using configprop:management.endpoint.env.additional-keys-to-sanitize[] and configprop:management.endpoint.configprops.additional-keys-to-sanitize[].
|
||||
|
||||
|
||||
|
||||
[[howto-map-health-indicators-to-metrics]]
|
||||
|
||||
Reference in New Issue
Block a user