K8s publisher: Helm secret value path mismatch between template expression and values.yaml
- Dominant language
- C#
- Stars
- 6.3k
- Forks
- 991
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 201
Description
## Description
The Kubernetes publisher generates mismatched Helm paths for secret values: the template expression uses the **parameter name** while `values.yaml` uses the **environment variable key**. This causes secrets to always resolve to empty, breaking resources like Redis that depend on passwords.
## Root Cause
In `KubernetesResource.cs`, `AllocateParameter()` (line ~506) creates the Helm expression using `parameter.Name`:
```csharp
var formattedName = parameter.Name.ToHelmValuesSectionName();
var expression = parameter.Secret ?
formattedName.ToHelmSecretExpression(resource.Name) : // → {{ .Values.secrets.cache.cache_password }}
formattedName.ToHelmConfigExpression(resource.Name);
```
But in `KubernetesPublishingContext.cs`, `AddValuesToHelmSectionAsync()` (line ~146) writes the values.yaml entry using the **environment variable key** from the `Secrets` dictionary:
```csharp
paramValues[key.ToHelmValuesSectionName()] = value ?? string.Empty;
// key = "REDIS_PASSWORD" (the env var name, not the parameter name)
```
## Example: Redis
For `builder.AddRedis("cache")`:
- Parameter name: `cache-password` (from `CreateDefaultPasswordParameter(builder, $"{name}-password")`)
- Environment variable key: `REDIS_PASSWORD` (from `WithEnvironment` callback)
**Generated Helm template** (K8s Secret):
```yaml
data:
REDIS_PASSWORD: {{ .Values.secrets.cache.cache_password | b64enc | quote }}
```
**Generated values.yaml**:
```yaml
secrets:
cache:
REDIS_PASSWORD: ""
```
The template looks for `.Values.secrets.cache.cache_password` but the values file has the key `REDIS_PASSWORD`. The password always resolves to empty/nil.
## Impact
- Redis crashes with `redis-server --requirepass` receiving no argument
- Users cannot set the password via `--set secrets.cache.REDIS_PASSWORD=value` because the template reads from a different path
- The workaround is to use `--set secrets.cache.cache_password=value` (matching the parameter name path), which is non-obvious
## Suggested Fix
Either:
1. Use the environment variable key (not the parameter name) when building the Helm expression in `AllocateParameter`, or
2. Use the parameter name (not the env var key) when writing the values.yaml key in `AddValuesToHelmSectionAsync`
The key and the expression must use the same name to be consistent.
## Related Issues
- #14370 — Cross-resource secret references generate broken Helm value paths (same area, different bug)
- The ExecutionContext bug in `ProcessArgumentsAsync` was fixed separately (missing `ExecutionContext = executionContext` causing container command generation to use run-mode args instead of publish-mode)
Contributor guide
Assessment
This issue has not been assessed yet.