Skip to content

Pulumi ESC

Pulumi ESC

Sync environments, configs and secrets from Pulumi ESC to Kubernetes using the External Secrets Operator.

Pulumi ESC

More information about setting up Pulumi ESC can be found in the Pulumi ESC documentation.

Authentication

Pulumi Access Tokens are recommended to access Pulumi ESC.

Creating a SecretStore

A Pulumi SecretStore can be created by specifying the organization, project and environment and referencing a Kubernetes secret containing the accessToken.

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: secret-store
spec:
  provider:
    pulumi:
      organization: <NAME_OF_THE_ORGANIZATION>
      project: <NAME_OF_THE_PROJECT>
      environment: <NAME_OF_THE_ENVIRONMENT>
      accessToken:
        secretRef:
          name: <NAME_OF_KUBE_SECRET>
          key: <KEY_IN_KUBE_SECRET>

If required, the API URL (apiUrl) can be customized as well. If not specified, the default value is https://api.pulumi.com/api/esc.

Creating a ClusterSecretStore

Similarly, a ClusterSecretStore can be created by specifying the namespace and referencing a Kubernetes secret containing the accessToken.

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: secret-store
spec:
  provider:
    pulumi:
      organization: <NAME_OF_THE_ORGANIZATION>
      project: <NAME_OF_THE_PROJECT>
      environment: <NAME_OF_THE_ENVIRONMENT>
      accessToken:
        secretRef:
          name: <NAME_OF_KUBE_SECRET>
          key: <KEY_IN_KUBE_SECRET>
          namespace: <NAMESPACE>

Referencing Secrets

Secrets can be referenced by defining the key containing the JSON path to the secret. Pulumi ESC secrets are internally organized as a JSON object.

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: secret
spec:
  refreshInterval: 1h
  secretStoreRef:
    kind: SecretStore
    name: secret-store
  data:
  - secretKey: <KEY_IN_KUBE_SECRET>
    remoteRef:
      key: <PULUMI_PATH_SYNTAX>

Note: key is not following the JSON Path syntax, but rather the Pulumi path syntax.

Examples

  • root
  • root.nested
  • root["nested"]
  • root.double.nest
  • root["double"].nest
  • root["double"]["nest"]
  • root.array[0]
  • root.array[100]
  • root.array[0].nested
  • root.array[0][1].nested
  • root.nested.array[0].double[1]
  • root["key with \"escaped\" quotes"]
  • root["key with a ."]
  • ["root key with \"escaped\" quotes"].nested
  • ["root key with a ."][100]
  • root.array[*].field
  • root.array["*"].field

See Pulumi's documentation for more information.

PushSecrets

With the latest release of Pulumi ESC, secrets can be pushed to the Pulumi service. This can be done by creating a PushSecrets object.

Here is a basic example of how to define a PushSecret object:

apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
  name: push-secret-example
spec:
  refreshInterval: 1h
  selector:
    secret:
      name: <NAME_OF_KUBE_SECRET>
  secretStoreRefs:
  - kind: ClusterSecretStore
    name: secret-store
  data:
  - match:
      secretKey: <KEY_IN_KUBE_SECRET>
      remoteRef:
        remoteKey: <PULUMI_PATH_SYNTAX>

This will then push the secret to the Pulumi service. If the secret already exists, it will be updated.

Limitations

Currently, the Pulumi provider only supports nested objects up to a depth of 1. Any nested objects beyond this depth will be stored as a string with the JSON representation.

This Pulumi ESC example:

values:
  backstage:
    my: test
    test: hello
    test22:
      my: hello
    test33:
      world: true
    x: true
    num: 42

Will result in the following Kubernetes secret:

my: test
num: "42"
test: hello
test22: '{"my":{"trace":{"def":{"begin":{"byte":72,"column":11,"line":6},"end":{"byte":77,"column":16,"line":6},"environment":"tgif-demo"}},"value":"hello"}}'
test33: '{"world":{"trace":{"def":{"begin":{"byte":103,"column":14,"line":8},"end":{"byte":107,"column":18,"line":8},"environment":"tgif-demo"}},"value":true}}'
x: "true"