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.
You can use templates to inject your secrets into a configuration file that you mount into your pod:
{% include 'multiline-template-v2-external-secret.yaml' %}
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:
{% include 'template-v2-from-secret.yaml' %}
You can use pre-defined functions to extract data from your secrets. Here: extract keys and certificates from a PKCS#12 archive and store it as PEM.
{% include 'pkcs12-template-v2-external-secret.yaml' %}
You can extract the public or private key parts of a JWK and use them as PKCS#8 private key or PEM-encoded PKIX public key.
A JWK looks similar to this:
{
"kty": "RSA",
"kid": "cc34c0a0-bd5a-4a3c-a50d-a2a7db7643df",
"use": "sig",
"n": "pjdss...",
"e": "AQAB"
// ...
}
And what you want may be a PEM-encoded public or private key portion of it. Take a look at this example on how to transform it into the desired format:
{% include 'jwk-template-v2-external-secret.yaml' %}
Consider you have a secret that contains both a certificate and a private key encoded in PEM format and it is your goal to use only the certificate from that secret.
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvxGZOW4IXvGlh
. . .
m8JCpbJXDfSSVxKHgK1Siw4K6pnTsIA2e/Z+Ha2fvtocERjq7VQMAJFaIZSTKo9Q
JwwY+vj0yxWjyzHUzZB33tg=
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDMDCCAhigAwIBAgIQabPaXuZCQaCg+eQAVptGGDANBgkqhkiG9w0BAQsFADAV
. . .
NtFUGA95RGN9s+pl6XY0YARPHf5O76ErC1OZtDTR5RdyQfcM+94gYZsexsXl0aQO
9YD3Wg==
-----END CERTIFICATE-----
You can achieve that by using the filterPEM function to extract a specific type of PEM block from that secret. If multiple blocks of that type (here: CERTIFICATE) exist then all of them are returned in the order they are specified.
!!! info inline end
Note: we removed `env` and `expandenv` from sprig functions for security reasons.
We provide a couple of convenience functions that help you transform your secrets. This is useful when dealing with PKCS#12 archives or JSON Web Keys (JWK).
In addition to that you can use over 200+ sprig functions. If you feel a function is missing or might be valuable feel free to open an issue and submit a pull request.
| Function | Description |
|---|---|
| pkcs12key | Extracts all private keys from a PKCS#12 archive and encodes them in PKCS#8 PEM format. |
| pkcs12keyPass | Same as pkcs12key. Uses the provided password to decrypt the PKCS#12 archive. |
| pkcs12cert | Extracts all certificates from a PKCS#12 archive and orders them if possible. If disjunct or multiple leaf certs are provided they are returned as-is. Sort order: leaf / intermediate(s) / root. |
| pkcs12certPass | Same as pkcs12cert. Uses the provided password to decrypt the PKCS#12 archive. |
| filterPEM | Filters PEM blocks with a specific type from a list of PEM blocks. |
| jwkPublicKeyPem | Takes an json-serialized JWK and returns an PEM block of type PUBLIC KEY that contains the public key. See here for details. |
| jwkPrivateKeyPem | Takes an json-serialized JWK as string and returns an PEM block of type PRIVATE KEY that contains the private key in PKCS #8 format. See here for details. |
| toYaml | Takes an interface, marshals it to yaml. It returns a string, even on marshal error (empty string). |
| fromYaml | Function converts a YAML document into a map[string]interface{}. |
If you are still using v1alpha1, You have to opt-in to use the new engine version by specifying template.engineVersion=v2:
apiVersion: external-secrets.io/v1alpha1
kind: ExternalSecret
metadata:
name: secret
spec:
# ...
target:
template:
engineVersion: v2
# ...
The biggest change was that basically all function parameter types were changed from accepting/returning []byte to string. This is relevant for you because now you don't need to specify toString all the time at the end of a template pipeline.
{% raw %}
apiVersion: external-secrets.io/v1alpha1
kind: ExternalSecret
# ...
spec:
target:
template:
engineVersion: v2
data:
# this used to be {{ .foobar | toString }}
egg: "new: {{ .foobar }}"
{% endraw %}
base64encode was renamed to b64enc.base64decode was renamed to b64dec. Any errors that occurr during decoding are silenced.fromJSON was renamed to fromJson. Any errors that occurr during unmarshalling are silenced.toJSON was renamed to toJson. Any errors that occurr during marshalling are silenced.pkcs12key and pkcs12keyPass encode the PKCS#8 key directly into PEM format. There is no need to call pemPrivateKey anymore. Also, these functions do extract all private keys from the PKCS#12 archive not just the first one.pkcs12cert and pkcs12certPass encode the certs directly into PEM format. There is no need to call pemCertificate anymore. These functions now extract all certificates from the PKCS#12 archive not just the first one.toString implementation was replaced by the sprig implementation and should be api-compatible.toBytes was removed.pemPrivateKey was removed. It's now implemented within the pkcs12* functions.pemCertificate was removed. It's now implemented within the pkcs12* functions.