When a Pulumi secret is used in a Helm chart resource, its plaintext value ends up in the Pulumi state file where in other resource types its encrypted value is used as expected.
v1.10.1Code to reproduce - https://gist.github.com/clstokes/a9192849a157307438a433162c16dfc1.
pulumi stack init gh-issuepulumi config set mySecret asdf1234pulumi uppulumi stack exportasdf1234 appears multiple times including in kubectl.kubernetes.io/last-applied-configuration annotationsThis happens because we use helm template to render YAML from the provided Chart, and then parse the YAML in a separate step. Information about the "secretness" of resources is currently lost during this process since it happens out of band from Pulumi.
Since we don't have insight into exactly where secret input values appear in the YAML output, this isn't trivial to fix.
A naive solution to this problem would be marking any resulting resources as Secret. It might also be possible to make this more targeted by post-processing the YAML resources and marking fields as secret if they contain a string that was marked secret on input.
The following code should be close to what we need to search the unmarshaled object and mark additionalSecretOutputs prior to creation.
// obj is the unmarshaled object
// {"apiVersion":"v1","kind":"Secret","metadata":{"annotations":[{"secret":"supersecret"}],"name":"mysecret"},"stringData":{"password":"supersecret","username":"produser"},"type":"Opaque"}
const secrets = [];
function checkForValue(value) {
return function check(v, path) {
if (typeof v === "string" && v === value) {
secrets.push(path)
} else if (typeof v === "object") {
for (const [key, val] of Object.entries(v)) {
const newPath = path !== undefined ? `${path}.${key}` : `.${key}`
check(val, newPath)
}
}
}
}
checkForValue("supersecret")(obj)
console.log(secrets)
// [ '.metadata.annotations.0.secret', '.stringData.password' ]
console.log(`hasSecret = ${secrets.length > 0}`)
// hasSecret = true
I encountered the same issue, this is unfortunately a blocker for our company adopting pulumi. Is there a way to perhaps mark the entire rendered helm template as additionalSecretOutputs?
Here's a temporary workaround (see the transformations function):
const redis = new k8s.helm.v3.Chart("redis", {
chart: "redis",
version: "10.7.16",
fetchOpts: {
repo: "https://charts.bitnami.com/bitnami"
},
values: {
password: config.requireSecret("testsecret")
},
transformations: [
(obj: any, opts: pulumi.CustomResourceOptions) => {
if (obj.kind === "Secret") {
for (const key of ['data', 'stringData']) {
if (key in obj) obj[key] = pulumi.secret(obj[key]);
}
}
}
]
}, {
provider: clusterProvider,
});
Most helpful comment
Here's a temporary workaround (see the transformations function):