https://pulumi.com logo
Title
e

enough-truck-34175

05/13/2021, 11:31 PM
Is there a strategy for encrypting Kubernetes secret resources? There is sensitive data in them being saved in state that I would like to protect. The output value can be encrypted, but the input is not encrypted.
s

steep-toddler-94095

05/14/2021, 7:16 AM
What do you mean by "the input is not encrypted"? Do you think this would solve your issue: https://www.pulumi.com/docs/reference/pkg/nodejs/pulumi/pulumi/#secret
e

enough-truck-34175

05/14/2021, 3:35 PM
I don’t think so, but maybe I’m not implementing this correctly. I’m using Golang. This is what I wrote
TestSecret := pulumi.ToSecret("something-secret")

TestSecret.ApplyT(func(secret string) (*core.Secret, error) {
	b64 := base64.StdEncoding.EncodeToString([]byte(secret))

	return core.NewSecret(ctx, "test-secret", &core.SecretArgs{
		ApiVersion: pulumi.StringPtr("v1"),
		Metadata: &meta.ObjectMetaArgs{
			Name:      pulumi.StringPtr("test"),
			Namespace: pulumi.StringPtr("harness-delegate"),
		},
		Type: pulumi.StringPtr("Opaque"),
		Data: pulumi.ToStringMap(map[string]string{
			"test": b64,
		}),
	})
})
and this is the state
{
    "urn": "urn:pulumi:esus-k8s-play-5-a::r1-compute-infra::kubernetes:core/v1:Secret::test-secret",
    "custom": true,
    "id": "harness-delegate/test",
    "type": "kubernetes:core/v1:Secret",
    "inputs": {
        "apiVersion": "v1",
        "data": {
            "test": "c29tZXRoaW5nLXNlY3JldA=="
        },
        "kind": "Secret",
        "metadata": {
            "labels": {
                "<http://app.kubernetes.io/managed-by|app.kubernetes.io/managed-by>": "pulumi"
            },
            "name": "test",
            "namespace": "harness-delegate"
        },
        "type": "Opaque"
    },
    "outputs": {
        "__initialApiVersion": "v1",
        "__inputs": {
            "apiVersion": "v1",
            "data": {
                "test": "c29tZXRoaW5nLXNlY3JldA=="
            },
            "kind": "Secret",
            "metadata": {
                "labels": {
                    "<http://app.kubernetes.io/managed-by|app.kubernetes.io/managed-by>": "pulumi"
                },
                "name": "test",
                "namespace": "harness-delegate"
            },
            "type": "Opaque"
        },
        "apiVersion": "v1",
        "data": {
            "4dabf18193072939515e22adb298388d": "1b47061264138c4ac30d75fd1eb44270",
            "ciphertext": "v1:yRpxGYFgl0f6ceE+:zOvx3ZrvJWKAYeu8N3A+1PN2K1VtA7vCwFXceVY1qJNnEHucxtuyZWAPWMG9vA9zbwZv"
        },
        "kind": "Secret",
        "metadata": {
            "annotations": {
                "<http://kubectl.kubernetes.io/last-applied-configuration|kubectl.kubernetes.io/last-applied-configuration>": "{\"apiVersion\":\"v1\",\"data\":{\"test\":\"c29tZXRoaW5nLXNlY3JldA==\"},\"kind\":\"Secret\",\"metadata\":{\"labels\":{\"<http://app.kubernetes.io/managed-by\|app.kubernetes.io/managed-by\>":\"pulumi\"},\"name\":\"test\",\"namespace\":\"harness-delegate\"},\"type\":\"Opaque\"}\n"
            },
            "creationTimestamp": "2021-05-14T15:30:31Z",
            "labels": {
                "<http://app.kubernetes.io/managed-by|app.kubernetes.io/managed-by>": "pulumi"
            },
            "managedFields": [
                {
                    "apiVersion": "v1",
                    "fieldsType": "FieldsV1",
                    "fieldsV1": {
                        "f:data": {
                            ".": {},
                            "f:test": {}
                        },
                        "f:metadata": {
                            "f:annotations": {
                                ".": {},
                                "f:<http://kubectl.kubernetes.io/last-applied-configuration|kubectl.kubernetes.io/last-applied-configuration>": {}
                            },
                            "f:labels": {
                                ".": {},
                                "f:<http://app.kubernetes.io/managed-by|app.kubernetes.io/managed-by>": {}
                            }
                        },
                        "f:type": {}
                    },
                    "manager": "pulumi-resource-kubernetes",
                    "operation": "Update",
                    "time": "2021-05-14T15:30:31Z"
                }
            ],
            "name": "test",
            "namespace": "harness-delegate",
            "resourceVersion": "52444093",
            "selfLink": "/api/v1/namespaces/harness-delegate/secrets/test",
            "uid": "7831e616-ec55-490c-a7df-62cf1c3a4192"
        },
        "type": "Opaque"
    },
    "parent": "urn:pulumi:esus-k8s-play-5-a::r1-compute-infra::pulumi:pulumi:Stack::r1-compute-infra-esus-k8s-play-5-a",
    "provider": "urn:pulumi:esus-k8s-play-5-a::r1-compute-infra::pulumi:providers:kubernetes::default::a5b90831-b0d4-4814-8c74-e2496b95e19f",
    "propertyDependencies": {
        "apiVersion": [],
        "data": [],
        "kind": [],
        "metadata": [],
        "type": []
    },
    "additionalSecretOutputs": [
        "data",
        "stringData"
    ]
}
You can see the secret is not encrypted. This a security problem. I think something like this is more ideal, but
Data
needs to accept a
map[string]pulumi.StringOutput
for it to work.
core.NewSecret(ctx, "test-secret", &core.SecretArgs{
		ApiVersion: pulumi.StringPtr("v1"),
		Metadata: &meta.ObjectMetaArgs{
			Name:      pulumi.StringPtr("test"),
			Namespace: pulumi.StringPtr("test"),
		},
		Type: pulumi.StringPtr("Opaque"),
		Data: pulumi.ToStringMap(map[string]string{
			"test": TestSecret.ApplyT(func(secret string) string {
					b64 := base64.StdEncoding.EncodeToString([]byte(secret))
					return b64
				}).(pulumi.StringOutput),
			}),
		})
g

gorgeous-egg-16927

05/14/2021, 5:37 PM
_, err = corev1.NewSecret(ctx, "test", &corev1.SecretArgs{
			StringData: pulumi.StringMap{"mysecret": pulumi.ToSecret(pulumi.String("secret")).(pulumi.StringOutput)},
		})
This should do what you want.
ToSecret
returns an
Output
, but you can use a type assertion if you’re wrapping a
pulumi.String
value like this.
We automatically mark k8s Secret
data
and
stringData
outputs as secret, but your original example was just representing the inputs as raw string data, so Pulumi didn’t know to mark it as secret.
e

enough-truck-34175

05/15/2021, 12:51 AM
Thanks Levi! This is great! I also saw your PR improvement too.
🎉 1
Using map[string]string was a result of my autocomplete. I’ll be more careful to stay in the Pulumi work using your objects. Very happy to have this resolved now!