GoogleCloudPlatform / GoogleCloudPlatform/spring-cloud-gcp

Sanitize secrets loaded from Secret Manager

Open
#4,122 0 comments 0 reactions 0 assignees View on GitHub
priority: p2 type: enhancement
Dominant language
Java
Stars
551
Forks
349
Avg merge
1d 13h
Merged PRs (30d)
14

Description

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

Spring Boot has [support for sanitizing sensitive values](https://docs.spring.io/spring-boot/reference/actuator/endpoints.html#actuator.endpoints.sanitization) 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](https://docs.spring.io/spring-boot/how-to/actuator.html#howto.actuator.customizing-sanitization) 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:

```java
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.

Contributor guide

Open the contributing guide

Research direction

Review SecretManagerSyntaxUtils.PREFIXES and Spring Boot's SanitizingFunction and SanitizableData APIs first. Determine how an auto-configured bean can identify unresolved Secret Manager references; done means actuator output never exposes resolved secret values when show-values is enabled.

Written by the indexing model from the issue text.

Assessment

Tech stack
google-cloud, java, spring, spring-boot
Domain
backend, cloud, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.