Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide role-based sanitization for actuator endpoints #32156

Closed
mbhave opened this issue Aug 23, 2022 · 1 comment
Closed

Provide role-based sanitization for actuator endpoints #32156

mbhave opened this issue Aug 23, 2022 · 1 comment
Assignees
Milestone

Comments

@mbhave
Copy link
Contributor

mbhave commented Aug 23, 2022

At the moment, we sanitize the output of the /env and /configprops endpoints based on an initial set of sensitive keys. While these keys can be customized using properties, it is hard to get the defaults right.

We have decided to remove the keys-based approach in favor of a role based approach, similar to the health endpoint details. Whether unsanitized values are shown or not can be configured using a property which can have the following values:

  • NEVER - All values are sanitized.
  • ALWAYS - All values are present in the output (sanitizing functions will apply).
  • WHEN_AUTHORIZED - Values are present in the output only if a user is authorized (sanitizing functions will apply).

For JMX, users are always considered to be authorized. For HTTP, users are considered to be authorized if they are authenticated and have the specified roles.

Sanitization for the QuartzEndpoint will also be configurable in the same way.

@mbhave mbhave added this to the 3.0.x milestone Aug 23, 2022
@mbhave mbhave self-assigned this Aug 23, 2022
@mbhave mbhave modified the milestones: 3.0.x, 3.0.0-M5 Aug 24, 2022
@mbhave mbhave closed this as completed in 47effdc Aug 24, 2022
@welsh
Copy link

welsh commented Mar 15, 2023

@mbhave I don't see this mentioned at all in the Spring Boot Actuator Documentation but I did find it in the Migration Guide.

For those that want to get back something similar to the old behaviour, you need to add these:

management.endpoint.env.show-values=ALWAYS
management.endpoint.configprops.show-values=ALWAYS

Or if your actuator endpoints are authenticated use:

management.endpoint.env.show-values=WHEN_AUTHORIZED
management.endpoint.configprops.show-values=WHEN_AUTHORIZED

And then you can implement your own SanitizingFunction, which i've done based off the Spring 2.7 version:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.endpoint.SanitizableData;
import org.springframework.boot.actuate.endpoint.SanitizingFunction;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Component
public class ActuatorSanitizer implements SanitizingFunction {

    private static final String[] REGEX_PARTS = {"*", "$", "^", "+"};

    private static final Set<String> DEFAULT_KEYS_TO_SANITIZE = Set.of(
            "password", "secret", "key", "token", ".*credentials.*", "vcap_services", "^vcap\\.services.*$", "sun.java.command", "^spring[._]application[._]json$"
    );

    private static final Set<String> URI_USERINFO_KEYS = Set.of(
            "uri", "uris", "url", "urls", "address", "addresses"
    );

    private static final Pattern URI_USERINFO_PATTERN = Pattern.compile("^\\[?[A-Za-z][A-Za-z0-9\\+\\.\\-]+://.+:(.*)@.+$");

    private List<Pattern> keysToSanitize = new ArrayList<>();

    public ActuatorSanitizer(@Value("${management.endpoint.additionalKeysToSanitize:}") List<String> additionalKeysToSanitize) {
        addKeysToSanitize(DEFAULT_KEYS_TO_SANITIZE);
        addKeysToSanitize(URI_USERINFO_KEYS);
        addKeysToSanitize(additionalKeysToSanitize);
    }

    @Override
    public SanitizableData apply(SanitizableData data) {
        if (data.getValue() == null) {
            return data;
        }

        for (Pattern pattern : keysToSanitize) {
            if (pattern.matcher(data.getKey()).matches()) {
                if (keyIsUriWithUserInfo(pattern)) {
                    return data.withValue(sanitizeUris(data.getValue().toString()));
                }

                return data.withValue(SanitizableData.SANITIZED_VALUE);
            }
        }

        return data;
    }

    private void addKeysToSanitize(Collection<String> keysToSanitize) {
        for (String key : keysToSanitize) {
            this.keysToSanitize.add(getPattern(key));
        }
    }

    private Pattern getPattern(String value) {
        if (isRegex(value)) {
            return Pattern.compile(value, Pattern.CASE_INSENSITIVE);
        }
        return Pattern.compile(".*" + value + "$", Pattern.CASE_INSENSITIVE);
    }

    private boolean isRegex(String value) {
        for (String part : REGEX_PARTS) {
            if (value.contains(part)) {
                return true;
            }
        }
        return false;
    }

    private boolean keyIsUriWithUserInfo(Pattern pattern) {
        for (String uriKey : URI_USERINFO_KEYS) {
            if (pattern.matcher(uriKey).matches()) {
                return true;
            }
        }
        return false;
    }

    private Object sanitizeUris(String value) {
        return Arrays.stream(value.split(",")).map(this::sanitizeUri).collect(Collectors.joining(","));
    }

    private String sanitizeUri(String value) {
        Matcher matcher = URI_USERINFO_PATTERN.matcher(value);
        String password = matcher.matches() ? matcher.group(1) : null;
        if (password != null) {
            return StringUtils.replace(value, ":" + password + "@", ":" + SanitizableData.SANITIZED_VALUE + "@");
        }
        return value;
    }
}

And then you're able to add additional configurations in by setting:

management.endpoint.additionalKeysToSanitize="my-value-1,my-value-2"

j-sandy added a commit to j-sandy/kork that referenced this issue Dec 12, 2024
…ith spring boot upgrade to 3.x

While upgrading the spring boot to 3.0.13 and spring cloud 2022.0.5, encountered the below errors during build process of kork-actuator module:
```
> Task :kork-actuator:compileJava FAILED
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/ActuatorEndpointsConfiguration.java:26: error: cannot find symbol
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
                                                                       ^
  symbol:   class WebSecurityConfigurerAdapter
  location: package org.springframework.security.config.annotation.web.configuration
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/ActuatorEndpointsConfiguration.java:30: error: cannot find symbol
public class ActuatorEndpointsConfiguration extends WebSecurityConfigurerAdapter {
                                                    ^
  symbol: class WebSecurityConfigurerAdapter
2 errors
```
With spring boot upgrade, spring security also upgrades from 5.x to 6.x. As per the migration [steps](https://www.baeldung.com/spring-security-migrate-5-to-6), `WebSecurityConfigurerAdapter` has been removed. So, it is not required to be extended, instead bean can be registered.

```
> Task :kork-actuator:compileJava FAILED
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/endpoint/ResolvedEnvironmentEndpoint.java:45: error: invalid method reference
        .ifPresent(sanitizer::setKeysToSanitize);
                   ^
  cannot find symbol
    symbol:   method setKeysToSanitize(T)
    location: class Sanitizer
  where T is a type-variable:
    T extends Object declared in class Optional
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/endpoint/ResolvedEnvironmentEndpoint.java:56: error: incompatible types: String cannot be converted to SanitizableData
                    return sanitizer.sanitize(property, environment.getProperty(property));
                                              ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
2 errors
```
In spring boot 3, changes are introduced in sanitization of actuator [endpoints](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide#actuator-endpoints-sanitization).
Default `Sanitizer` implementation has been removed and replaced with `SanitizingFunction`.
spring-projects/spring-boot#33448
spring-projects/spring-boot#39243
spring-projects/spring-boot#32156
So, added the `ActuatorSanitizingFunction` class to provide the default implementation of `SanitizingFunction`.
j-sandy added a commit to j-sandy/kork that referenced this issue Dec 17, 2024
…ith spring boot upgrade to 3.x

While upgrading the spring boot to 3.0.13 and spring cloud 2022.0.5, encountered the below errors during build process of kork-actuator module:
```
> Task :kork-actuator:compileJava FAILED
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/ActuatorEndpointsConfiguration.java:26: error: cannot find symbol
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
                                                                       ^
  symbol:   class WebSecurityConfigurerAdapter
  location: package org.springframework.security.config.annotation.web.configuration
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/ActuatorEndpointsConfiguration.java:30: error: cannot find symbol
public class ActuatorEndpointsConfiguration extends WebSecurityConfigurerAdapter {
                                                    ^
  symbol: class WebSecurityConfigurerAdapter
2 errors
```
With spring boot upgrade, spring security also upgrades from 5.x to 6.x. As per the migration [steps](https://www.baeldung.com/spring-security-migrate-5-to-6), `WebSecurityConfigurerAdapter` has been removed. So, it is not required to be extended, instead bean can be registered.

```
> Task :kork-actuator:compileJava FAILED
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/endpoint/ResolvedEnvironmentEndpoint.java:45: error: invalid method reference
        .ifPresent(sanitizer::setKeysToSanitize);
                   ^
  cannot find symbol
    symbol:   method setKeysToSanitize(T)
    location: class Sanitizer
  where T is a type-variable:
    T extends Object declared in class Optional
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/endpoint/ResolvedEnvironmentEndpoint.java:56: error: incompatible types: String cannot be converted to SanitizableData
                    return sanitizer.sanitize(property, environment.getProperty(property));
                                              ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
2 errors
```
In spring boot 3, changes are introduced in sanitization of actuator [endpoints](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide#actuator-endpoints-sanitization).
Default `Sanitizer` implementation has been removed and replaced with `SanitizingFunction`.
spring-projects/spring-boot#33448
spring-projects/spring-boot#39243
spring-projects/spring-boot#32156
So, added the `ActuatorSanitizingFunction` class to provide the default implementation of `SanitizingFunction`.
j-sandy added a commit to j-sandy/kork that referenced this issue Dec 19, 2024
…ith spring boot upgrade to 3.x

While upgrading the spring boot to 3.0.13 and spring cloud 2022.0.5, encountered the below errors during build process of kork-actuator module:
```
> Task :kork-actuator:compileJava FAILED
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/ActuatorEndpointsConfiguration.java:26: error: cannot find symbol
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
                                                                       ^
  symbol:   class WebSecurityConfigurerAdapter
  location: package org.springframework.security.config.annotation.web.configuration
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/ActuatorEndpointsConfiguration.java:30: error: cannot find symbol
public class ActuatorEndpointsConfiguration extends WebSecurityConfigurerAdapter {
                                                    ^
  symbol: class WebSecurityConfigurerAdapter
2 errors
```
With spring boot upgrade, spring security also upgrades from 5.x to 6.x. As per the migration [steps](https://www.baeldung.com/spring-security-migrate-5-to-6), `WebSecurityConfigurerAdapter` has been removed. So, it is not required to be extended, instead bean can be registered.

```
> Task :kork-actuator:compileJava FAILED
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/endpoint/ResolvedEnvironmentEndpoint.java:45: error: invalid method reference
        .ifPresent(sanitizer::setKeysToSanitize);
                   ^
  cannot find symbol
    symbol:   method setKeysToSanitize(T)
    location: class Sanitizer
  where T is a type-variable:
    T extends Object declared in class Optional
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/endpoint/ResolvedEnvironmentEndpoint.java:56: error: incompatible types: String cannot be converted to SanitizableData
                    return sanitizer.sanitize(property, environment.getProperty(property));
                                              ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
2 errors
```
In spring boot 3, changes are introduced in sanitization of actuator [endpoints](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide#actuator-endpoints-sanitization).
Default `Sanitizer` implementation has been removed and replaced with `SanitizingFunction`.
spring-projects/spring-boot#33448
spring-projects/spring-boot#39243
spring-projects/spring-boot#32156
So, added the `ActuatorSanitizingFunction` class to provide the default implementation of `SanitizingFunction`.
j-sandy added a commit to j-sandy/kork that referenced this issue Dec 19, 2024
…ith spring boot upgrade to 3.x

While upgrading the spring boot to 3.0.13 and spring cloud 2022.0.5, encountered the below errors during build process of kork-actuator module:
```
> Task :kork-actuator:compileJava FAILED
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/ActuatorEndpointsConfiguration.java:26: error: cannot find symbol
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
                                                                       ^
  symbol:   class WebSecurityConfigurerAdapter
  location: package org.springframework.security.config.annotation.web.configuration
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/ActuatorEndpointsConfiguration.java:30: error: cannot find symbol
public class ActuatorEndpointsConfiguration extends WebSecurityConfigurerAdapter {
                                                    ^
  symbol: class WebSecurityConfigurerAdapter
2 errors
```
With spring boot upgrade, spring security also upgrades from 5.x to 6.x. As per the migration [steps](https://www.baeldung.com/spring-security-migrate-5-to-6), `WebSecurityConfigurerAdapter` has been removed. So, it is not required to be extended, instead bean can be registered.

```
> Task :kork-actuator:compileJava FAILED
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/endpoint/ResolvedEnvironmentEndpoint.java:45: error: invalid method reference
        .ifPresent(sanitizer::setKeysToSanitize);
                   ^
  cannot find symbol
    symbol:   method setKeysToSanitize(T)
    location: class Sanitizer
  where T is a type-variable:
    T extends Object declared in class Optional
/kork/kork-actuator/src/main/java/com/netflix/spinnaker/kork/actuator/endpoint/ResolvedEnvironmentEndpoint.java:56: error: incompatible types: String cannot be converted to SanitizableData
                    return sanitizer.sanitize(property, environment.getProperty(property));
                                              ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
2 errors
```
In spring boot 3, changes are introduced in sanitization of actuator [endpoints](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide#actuator-endpoints-sanitization).
Default `Sanitizer` implementation has been removed and replaced with `SanitizingFunction`.
spring-projects/spring-boot#33448
spring-projects/spring-boot#39243
spring-projects/spring-boot#32156
So, added the `ActuatorSanitizingFunction` class to provide the default implementation of `SanitizingFunction`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants