Skip to content

Advanced Templating

With External Secrets Operator you can transform the data from the external secret provider before it is stored as Kind=Secret. You can do this with the Spec.Target.Template. Each data value is interpreted as a golang template.

Examples

You can use templates to inject your secrets into a configuration file that you mount into your pod:

apiVersion: external-secrets.io/v1alpha1
kind: ExternalSecret
metadata:
  name: template
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: secretstore-sample
    kind: SecretStore
  target:
    name: secret-to-be-created
    # this is how the Kind=Secret will look like
    template:
      type: kubernetes.io/tls
      data:
        # multiline string
        config: |
          datasources:
          - name: Graphite
            type: graphite
            access: proxy
            url: http://localhost:8080
            password: "{{ .password | toString }}" # <-- convert []byte to string
            user: "{{ .user | toString }}"         # <-- convert []byte to string

  data:
  - secretKey: user
    remoteRef:
      key: /grafana/user
  - secretKey: password
    remoteRef:
      key: /grafana/password

You can also use pre-defined functions to extract data from your secrets. Here: extract key/cert from a pkcs12 archive and store it as PEM.

apiVersion: external-secrets.io/v1alpha1
kind: ExternalSecret
metadata:
  name: template
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: secretstore-sample
    kind: SecretStore
  target:
    name: secret-to-be-created
    # this is how the Kind=Secret will look like
    template:
      type: kubernetes.io/tls
      data:
        tls.crt: "{{ .mysecret | pkcs12cert | pemCertificate }}"
        tls.key: "{{ .mysecret | pkcs12key | pemPrivateKey }}"

  data:
  # this is a pkcs12 archive that contains
  # a cert and a private key
  - secretKey: mysecret
    remoteRef:
      key: example

TemplateFrom

You do not have to define your templates inline in an ExternalSecret but you can pull ConfigMaps or other Secrets that contain a template. Consider the following example:

# define your tempalte in a config map
apiVersion: v1
kind: ConfigMap
metadata:
  name: grafana-config-tpl
data:
  config.yaml: |
    datasources:
      - name: Graphite
        type: graphite
        access: proxy
        url: http://localhost:8080
        password: "{{ .password | toString }}" # <-- convert []byte to string
        user: "{{ .user | toString }}"         # <-- convert []byte to string
---
apiVersion: external-secrets.io/v1alpha1
kind: ExternalSecret
metadata:
  name: my-template-example
spec:
  # ...
  target:
    name: secret-to-be-created
    template:
      templateFrom:
      - configMap:
          # name of the configmap to pull in
          name: grafana-config-tpl
          # here you define the keys that should be used as template
          items:
          - key: config.yaml
  data:
  - secretKey: user
    remoteRef:
      key: /grafana/user
  - secretKey: password
    remoteRef:
      key: /grafana/password

Helper functions

We provide a bunch of convenience functions that help you transform your secrets. A secret value is a []byte.

Function Description Input Output
pkcs12key extracts the private key from a pkcs12 archive []byte []byte
pkcs12keyPass extracts the private key from a pkcs12 archive using the provided password password string, data []byte []byte
pkcs12cert extracts the certificate from a pkcs12 archive []byte []byte
pkcs12certPass extracts the certificate from a pkcs12 archive using the provided password password string, data []byte []byte
pemPrivateKey PEM encodes the provided bytes as private key []byte string
pemCertificate PEM encodes the provided bytes as certificate []byte string
jwkPublicKeyPem takes an json-serialized JWK as []byte and returns an PEM block of type PUBLIC KEY that contains the public key (see here) for details []byte string
jwkPrivateKeyPem takes an json-serialized JWK as []byte and returns an PEM block of type PRIVATE KEY that contains the private key in PKCS #8 format (see here) for details []byte string
base64decode decodes the provided bytes as base64 []byte []byte
base64encode encodes the provided bytes as base64 []byte []byte
fromJSON parses the bytes as JSON so you can access individual properties []byte interface{}
toJSON encodes the provided object as json string interface{} string
toString converts bytes to string []byte string
toBytes converts string to bytes string []byte
upper converts all characters to their upper case string string
lower converts all character to their lower case string string