Skip to content

Sanitize secrets loaded from Secret Manager #4122

@breun

Description

@breun

Is your feature request related to a problem? Please describe.

Spring Boot has support for sanitizing sensitive values when management.endpoint.env.show-values is set to anything other than the default value of never. Currently any secrets loaded from Secret Manager are visible in plain text in the output of actuator endpoints when management.endpoint.env.show-values is set to always or when-authorized, which is a security problem in those scenarios.

To guarantee that secrets are never shown in plain text in the output of actuator endpoints, an appropriate SanitizingFunction should be provided.

Describe the solution you'd like

It would be great if Spring Cloud GCP Secret Manager would auto-configure a SanitizingFunction bean to sanitize secrets loaded from Secret Manager, so that secrets are always protected from leaking via actuator endpoints, even when management.endpoint.env.show-values is set to any value other than never.

The question is how to identify data is being loaded from Secret Manager. The best I've come up with so far is checking the property source for the unresolved value and seeing if this contains a reference which uses one of the supported Secret Manager prefixes.

Here's a sketch of what such a sanitizing function could look like:

import com.google.cloud.spring.secretmanager.SecretManagerSyntaxUtils;
import org.springframework.boot.actuate.endpoint.SanitizableData;
import org.springframework.boot.actuate.endpoint.SanitizingFunction;
import org.springframework.core.env.PropertySource;

/**
 * Sanitize data with secrets from GCP Secret Manager.
 */
class SecretManagerSanitizingFunction implements SanitizingFunction {

    @Override
    public SanitizableData apply(SanitizableData data) {
        PropertySource<?> propertySource = data.getPropertySource();

        if (propertySource == null) {
            return data.withValue(SanitizableData.SANITIZED_VALUE);
        }

        String unresolvedValue = String.valueOf(propertySource.getProperty(data.getKey()));

        for (String secretManagerPrefix : SecretManagerSyntaxUtils.PREFIXES) {
            if (unresolvedValue.contains("${" + secretManagerPrefix)) {
                // Sanitize data by replacing the resolved value which contains secret
                // with the unresolved value which just contains the reference to the secret
                return data.withValue(unresolvedValue);
            }
        }

        return data;
    }
}

This should for instance replace a value of https://username:secret123@hostname/path with an unresolved value like https://username:${sm@my-secret-password}@hostname/path.

Or maybe there is another way to determine that SanitizableData contains a secret loaded from Secret Manager?

Describe alternatives you've considered

The alternative is for users to implement such a SanitizingFunction bean themselves.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions