--- layout: docs page_title: Secret data transformation description: >- Learn how to transform secret data with the Vault Secrets Operator. --- # Secret data transformation Utilizing advanced templating and data filters, the Vault Secrets Operator for Kubernetes (VSO) can transform source secret data, secret metadata, resource labels and annotations into a format that is compatible with your application. All secret data sources are supported. Secret transformations can be specified directly within a secret custom resource (CR), or by references to one or more [SecretTransformation](/vault/docs/platform/k8s/vso/api-reference#secrettransformation) custom resource instances, or both. ## Templating VSO utilizes the data-driven [templates for Golang](https://pkg.go.dev/text/template) to generate secret data output. The template data input holds the secret data, secret metadata, resource labels and annotations. Templates are configured in a secret custom resource's [spec.Destination.Transformation.Templates](/vault/docs/platform/k8s/vso/api-reference#transformation), or in a SecretTransformation resource's [spec.templates](/vault/docs/platform/k8s/vso/api-reference#secrettransformationspec). VSO provides access to a large library of template functions, some of which are documented [below](#template-functions). ### Secret data input Secret data is accessed through the `.Secrets` input member. It contains a map of secret key-value pairs, which are assumed to be sensitive information fetched from a [secret source](/vault/docs/platform/k8s/vso/sources). For example, to include a password in your application's secret, you might specify a template like: ```go {{- printf "password=%s" (get .Secrets "password") -}} ``` ### Secret metadata input Secret metadata is accessed through the `.Metadata` input member. It contains a map of metadata key to its value. The data should not contain any confidential information. For example, to include a secret metadata value in your application's secret, you might specify a template like: ```go {{- printf "secretGroup=%s" (get .Metadata "secretGroup") -}} ``` ### Resource annotations input Resource annotations are accessed through the `.Annotations` input member. The annotations consist of all `metadata.annotations` configured on the secret custom resource. For example, to include a value from the resource's annotations in your application's secret, you might specify a template like: ```go {{- printf "host=%s" (get .Annotations "myapp.config/host") -}} ``` ### Resource labels input Resource labels are accessed through the `.Labels` input member. The labels consist of all `metadata.labels` configured on the secret custom resource. For example, to include a value from the resource's labels in your application's secret, you might specify a template like: ```go {{- printf "appType=%s" (get .Labels "appType") -}} ``` ## Filters Filters are used to control which source secret data fields are included in the destination secret's data. They are specified as a set of exclude/include RE2 accepted [regular expressions](https://golang.org/s/re2syntax). Filters are configured in the `excludes` and `includes` fields of a secret custom resource's [spec.Destination.Transformation](/vault/docs/platform/k8s/vso/api-reference#transformation), or in a SecretTransformation resource's [spec](/vault/docs/platform/k8s/vso/api-reference#secrettransformationspec). All exclude patterns take precedence over any include patterns, and are never applied to templated keys. ## Examples ### Local transformation A VaultDynamicSecret configured to sync Postgres database credentials from Vault to the Kubernetes secret named `example-vds`. ```yaml --- apiVersion: secrets.hashicorp.com/v1beta1 kind: VaultDynamicSecret metadata: namespace: example-ns name: example-vds annotations: myapp.config/postgres-host: postgres-postgresql.postgres.svc.cluster.local:5432 spec: destination: create: true name: app-secret transformation: excludes: - .* templates: url: text: | {{- $host := get .Annotations "myapp.config/postgres-host" -}} {{- printf "postgresql://%s:%s@%s/postgres?sslmode=disable" (get .Secrets "username") (get .Secrets "password") $host -}} path: creds/dev-postgres ``` The resulting Kubernetes secret includes a single key named `url`, with a valid Postgres connection URL as its value. ```yaml url: postgresql://v-postgres-user:XUpah-password@postgres-postgresql.postgres.svc.cluster.local:5432/postgres?sslmode=disable ``` ### Shared transformation The following manifest contains shared transformation templates and filters. All `templates` it provides will be included in the destination k8s secret. It also provides `sourceTemplates` that can be included in any template text configured in a secret CR or within the same resource instance. ```yaml --- apiVersion: secrets.hashicorp.com/v1beta1 kind: SecretTransformation metadata: name: vso-templates namespace: example-vds spec: excludes: - password|username templates: url: text: '{{- template "dbUrl" . -}}' sourceTemplates: - name: helpers text: | {{/* create a Java props from SecretInput for this app */}} {{- define "appProps" -}} {{- $host := get .Annotations "myapp.config/postgres-host" -}} {{- printf "db.host=%s\n" $host -}} {{- range $k, $v := .Secrets -}} {{- printf "db.%s=%s\n" $k $v -}} {{- end -}} {{- end -}} {{/* create a JSON config from SecretInput for this app */}} {{- define "appJson" -}} {{- $host := get .Annotations "myapp.config/postgres-host" -}} {{- $copy := .Secrets | mustDeepCopy -}} {{- $_ := set $copy "host" $host -}} {{- mustToPrettyJson $copy -}} {{- end -}} {{/* compose a Postgres URL from SecretInput for this app */}} {{- define "dbUrl" -}} {{- $host := get .Annotations "myapp.config/postgres-host" -}} {{- printf "postgresql://%s:%s@%s/postgres?sslmode=disable" (get .Secrets "username") (get .Secrets "password") $host -}} {{- end -}} {{/* get the app name from the VSO resource's label */}} {{- define "appName" -}} {{- get .Labels "myapp/name" -}} {{- end -}} ``` The following `VaultDynamicSecret` manifest references the `SecretTransformation` above. All templates and filters from the reference object will be applied to the destination secret data. ```yaml --- apiVersion: secrets.hashicorp.com/v1beta1 kind: VaultDynamicSecret metadata: namespace: example-ns name: example-vds annotations: myapp.config/postgres-host: postgres-postgresql.postgres.svc.cluster.local:5432 spec: destination: create: true name: app-secret transformation: transformationRefs: - name: vso-templates path: creds/dev-postgres ``` The resulting Kubernetes secret includes a single key named `url`, with a valid Postgres connection URL as its value ```yaml url: postgresql://v-postgres-user:XUpah-password@postgres-postgresql.postgres.svc.cluster.local:5432/postgres?sslmode=disable ``` ### Template functions All template functions are provided by the [sprig](http://masterminds.github.io/sprig) library. Some common functions are mentioned below. For the complete list of functions see [allowedSprigFuncs](https://github.com/hashicorp/vault-secrets-operator/blob/main/template/funcs.go#L26) ### String functions `trim` removes any leading or trailing whitespaces from the input: ``` trim " host " -> `host` ``` ### Encoding functions `b64enc` base64 encodes an input value ``` b64enc "host" -> `aG9zdAo=` ``` `b64dec` base64 decodes an input value ``` b64dec "aG9zdAo=" -> `host` ``` ### Map functions `get` retrieves a value from a `map` input: ``` get .Secrets "baz" -> `qux` ``` Given a nested `map` input: ```json { "foo": { "bar": "baz", "quz": "quux" } } ``` `get` can retrieve a specific value: ``` get (get .Secrets "foo") "bar" -> `baz` ``` `dig` can also retrieve a specific value, or return a default if any of the keys are not found: ``` dig "foo" "quz" "" .Secrets -> `quux` dig "foo" "nux" "" .Secrets -> `` ``` ## Related API references - [Transformation](/vault/docs/platform/k8s/vso/api-reference#transformation) - [HCPVaultSecretsApp](/vault/docs/platform/k8s/vso/api-reference#hcpvaultsecretsapp) - [VaultDynamicSecret](/vault/docs/platform/k8s/vso/api-reference#vaultdynamicsecret) - [VaultPKISecret](/vault/docs/platform/k8s/vso/api-reference#vaultpkisecret) - [VaultStaticSecret](/vault/docs/platform/k8s/vso/api-reference#vaultstaticsecret) - [SecretTransformation](/vault/docs/platform/k8s/vso/api-reference#secrettransformation)