From 164e8776ecea1aea3981edf31c009db1900cf686 Mon Sep 17 00:00:00 2001 From: Gustavo Carvalho Date: Wed, 9 Mar 2022 06:48:25 -0300 Subject: [PATCH] Adding docs and implementing ConversionStrategy Signed-off-by: Gustavo Carvalho --- .../v1alpha1/externalsecret_types.go | 11 +++ .../v1beta1/externalsecret_types.go | 18 +++- .../external-secrets.io_externalsecrets.yaml | 22 ++++- deploy/crds/bundle.yaml | 22 ++++- docs/provider-hashicorp-vault.md | 89 +++++++++++++++++-- .../akeyless-external-secret-json.yaml | 5 +- docs/snippets/akeyless-external-secret.yaml | 2 +- docs/snippets/akeyless-secret-store.yaml | 2 +- ...ne-access-credentials-external-secret.yaml | 5 +- ...credential-github-ssh-external-secret.yaml | 2 +- ...l-sonarqube-api-token-external-secret.yaml | 2 +- ...ls-harbor-chart-robot-external-secret.yaml | 2 +- docs/snippets/aws-parameter-store.yaml | 2 +- docs/snippets/aws-sm-external-secret.yaml | 2 +- docs/snippets/aws-sm-store.yaml | 2 +- docs/snippets/azkv-external-secret.yaml | 2 +- docs/snippets/azkv-secret-store-mi.yaml | 2 +- docs/snippets/azkv-secret-store.yaml | 2 +- docs/snippets/basic-external-secret.yaml | 5 +- docs/snippets/basic-secret-store.yaml | 2 +- docs/snippets/controller-class-store.yaml | 2 +- docs/snippets/fake-provider-es.yaml | 5 +- docs/snippets/fake-provider-store.yaml | 2 +- docs/snippets/full-cluster-secret-store.yaml | 2 +- docs/snippets/full-external-secret.yaml | 17 +++- docs/snippets/full-secret-store.yaml | 2 +- .../gcpsm-data-from-external-secret.yaml | 5 +- .../gcpsm-docker-config-externalsecret.yaml | 2 +- docs/snippets/gcpsm-external-secret.yaml | 2 +- docs/snippets/gcpsm-pod-wi-secret-store.yaml | 2 +- docs/snippets/gcpsm-secret-store.yaml | 2 +- .../gcpsm-ssh-auth-externalsecret.yaml | 2 +- docs/snippets/gcpsm-tls-externalsecret.yaml | 2 +- docs/snippets/gcpsm-wi-secret-store.yaml | 2 +- .../snippets/gitlab-external-secret-json.yaml | 5 +- docs/snippets/gitlab-external-secret.yaml | 2 +- docs/snippets/gitlab-secret-store.yaml | 2 +- .../gitops/crs/clusterSecretStore.yaml | 2 +- docs/snippets/ibm-es-types.yaml | 2 +- docs/snippets/ibm-external-secret.yaml | 2 +- docs/snippets/ibm-secret-store.yaml | 2 +- .../jwk-template-v2-external-secret.yaml | 2 +- ...multiline-template-v1-external-secret.yaml | 2 +- ...multiline-template-v2-external-secret.yaml | 2 +- docs/snippets/oracle-external-secret.yaml | 5 +- docs/snippets/oracle-secret-store.yaml | 4 +- .../pkcs12-template-v1-external-secret.yaml | 2 +- .../pkcs12-template-v2-external-secret.yaml | 2 +- docs/snippets/provider-aws-access.md | 6 +- docs/snippets/template-v1-from-secret.yaml | 2 +- docs/snippets/template-v2-from-secret.yaml | 2 +- ...ne-access-credentials-external-secret.yaml | 2 +- docs/snippets/vault-approle-store.yaml | 2 +- ...ial-github-ssh-access-external-secret.yaml | 2 +- ...al-harbor-chart-robot-external-secret.yaml | 2 +- ...l-sonarqube-api-token-external-secret.yaml | 2 +- docs/snippets/vault-jwt-store.yaml | 2 +- docs/snippets/vault-kubernetes-store.yaml | 2 +- docs/snippets/vault-ldap-store.yaml | 2 +- docs/snippets/vault-token-store.yaml | 2 +- .../externalsecret_controller.go | 12 ++- pkg/provider/vault/vault.go | 14 ++- pkg/utils/utils.go | 42 +++++---- 63 files changed, 276 insertions(+), 106 deletions(-) diff --git a/apis/externalsecrets/v1alpha1/externalsecret_types.go b/apis/externalsecrets/v1alpha1/externalsecret_types.go index ab6ee51c1..394da8fd0 100644 --- a/apis/externalsecrets/v1alpha1/externalsecret_types.go +++ b/apis/externalsecrets/v1alpha1/externalsecret_types.go @@ -141,8 +141,19 @@ type ExternalSecretDataRemoteRef struct { // +optional // Used to select a specific property of the Provider value (if a map), if supported Property string `json:"property,omitempty"` + // +optional + // Used to define a conversion Strategy + // +kubebuilder:default="Default" + ConversionStrategy ExternalSecretConversionStrategy `json:"conversionStrategy,omitempty"` } +type ExternalSecretConversionStrategy string + +const ( + ExternalSecretConversionDefault ExternalSecretConversionStrategy = "Default" + ExternalSecretConversionUnicode ExternalSecretConversionStrategy = "Unicode" +) + // ExternalSecretSpec defines the desired state of ExternalSecret. type ExternalSecretSpec struct { SecretStoreRef SecretStoreRef `json:"secretStoreRef"` diff --git a/apis/externalsecrets/v1beta1/externalsecret_types.go b/apis/externalsecrets/v1beta1/externalsecret_types.go index ee92a818a..82c8c50fb 100644 --- a/apis/externalsecrets/v1beta1/externalsecret_types.go +++ b/apis/externalsecrets/v1beta1/externalsecret_types.go @@ -159,8 +159,20 @@ type ExternalSecretDataRemoteRef struct { // +optional // Used to select a specific property of the Provider value (if a map), if supported Property string `json:"property,omitempty"` + + // +optional + // Used to define a conversion Strategy + // +kubebuilder:default="Default" + ConversionStrategy ExternalSecretConversionStrategy `json:"conversionStrategy,omitempty"` } +type ExternalSecretConversionStrategy string + +const ( + ExternalSecretConversionDefault ExternalSecretConversionStrategy = "Default" + ExternalSecretConversionUnicode ExternalSecretConversionStrategy = "Unicode" +) + // +kubebuilder:validation:MinProperties=1 // +kubebuilder:validation:MaxProperties=1 type ExternalSecretDataFromRemoteRef struct { @@ -172,8 +184,6 @@ type ExternalSecretDataFromRemoteRef struct { Find *ExternalSecretFind `json:"find,omitempty"` } -// +kubebuilder:validation:MinProperties=1 -// +kubebuilder:validation:MaxProperties=1 type ExternalSecretFind struct { // A root path to start the find operations. // +optional @@ -185,6 +195,10 @@ type ExternalSecretFind struct { // Find secrets based on tags. // +optional Tags map[string]string `json:"tags,omitempty"` + // +optional + // Used to define a conversion Strategy + // +kubebuilder:default="Default" + ConversionStrategy ExternalSecretConversionStrategy `json:"conversionStrategy,omitempty"` } type FindName struct { diff --git a/config/crds/bases/external-secrets.io_externalsecrets.yaml b/config/crds/bases/external-secrets.io_externalsecrets.yaml index 2097adbc2..8c22321b8 100644 --- a/config/crds/bases/external-secrets.io_externalsecrets.yaml +++ b/config/crds/bases/external-secrets.io_externalsecrets.yaml @@ -59,6 +59,10 @@ spec: description: ExternalSecretDataRemoteRef defines Provider data location. properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string key: description: Key is the key used in the Provider, mandatory type: string @@ -87,6 +91,10 @@ spec: items: description: ExternalSecretDataRemoteRef defines Provider data location. properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string key: description: Key is the key used in the Provider, mandatory type: string @@ -294,6 +302,10 @@ spec: description: ExternalSecretDataRemoteRef defines Provider data location. properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string key: description: Key is the key used in the Provider, mandatory type: string @@ -327,6 +339,10 @@ spec: description: Used to extract multiple key/value pairs from one secret properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string key: description: Key is the key used in the Provider, mandatory type: string @@ -343,9 +359,11 @@ spec: type: object find: description: Used to find secrets based on tags or regular expressions - maxProperties: 1 - minProperties: 1 properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string name: description: Finds secrets based on the name. properties: diff --git a/deploy/crds/bundle.yaml b/deploy/crds/bundle.yaml index e09d352a1..c80e03293 100644 --- a/deploy/crds/bundle.yaml +++ b/deploy/crds/bundle.yaml @@ -2019,6 +2019,10 @@ spec: remoteRef: description: ExternalSecretDataRemoteRef defines Provider data location. properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string key: description: Key is the key used in the Provider, mandatory type: string @@ -2043,6 +2047,10 @@ spec: items: description: ExternalSecretDataRemoteRef defines Provider data location. properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string key: description: Key is the key used in the Provider, mandatory type: string @@ -2226,6 +2234,10 @@ spec: remoteRef: description: ExternalSecretDataRemoteRef defines Provider data location. properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string key: description: Key is the key used in the Provider, mandatory type: string @@ -2254,6 +2266,10 @@ spec: extract: description: Used to extract multiple key/value pairs from one secret properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string key: description: Key is the key used in the Provider, mandatory type: string @@ -2268,9 +2284,11 @@ spec: type: object find: description: Used to find secrets based on tags or regular expressions - maxProperties: 1 - minProperties: 1 properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string name: description: Finds secrets based on the name. properties: diff --git a/docs/provider-hashicorp-vault.md b/docs/provider-hashicorp-vault.md index 01029e6e6..e7dba0a63 100644 --- a/docs/provider-hashicorp-vault.md +++ b/docs/provider-hashicorp-vault.md @@ -11,7 +11,7 @@ management. Vault itself implements lots of different secret engines, as of now First, create a SecretStore with a vault backend. For the sake of simplicity we'll use a static token `root`: ```yaml -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: vault-backend @@ -46,7 +46,7 @@ vault kv put secret/foo my-value=s3cr3t Now create a ExternalSecret that uses the above SecretStore: ```yaml -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: vault-example @@ -76,7 +76,7 @@ data: You can fetch all key/value pairs for a given path If you leave the `remoteRef.property` empty. This returns the json-encoded secret value for that path. ```yaml -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: vault-example @@ -105,7 +105,7 @@ Given the following secret - assume its path is `/dev/config`: You can set the `remoteRef.property` to point to the nested key using a [gjson](https://github.com/tidwall/gjson) expression. ```yaml -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: vault-example @@ -141,15 +141,16 @@ Given the following secret - assume its path is `/dev/config`: You can set the `remoteRef.property` to point to the nested key using a [gjson](https://github.com/tidwall/gjson) expression. ```yaml -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: vault-example spec: # ... dataFrom: - - key: /dev/config - property: foo.nested + - extract: + key: /dev/config + property: foo.nested ``` That results in a secret with these values: @@ -158,6 +159,80 @@ bar=mysecret baz=bang ``` +#### Getting multiple secrets + +You can extract multiple secrets from Hashicorp vault by using `dataFrom.Find` + +Currently, `dataFrom.Find` allows users to fetch secret names that match a given regexp pattern, or fetch secrets whose `custom_metadata` tags match a predefined set. + +Given the following secret - assume its path is `/dev/config`: +```json +{ + "foo": { + "nested": { + "bar": "mysecret", + "baz": "bang" + } + } +} +``` + +Also consider the following secret has the following `custom_metadata`: +```json +{ + "environment": "dev", + "component": "app-1" +} +``` + +It is possible to find this secret by all the following possibilities: +```yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: vault-example +spec: + # ... + dataFrom: + - find: #will return every secret with 'dev' in it (including paths) + name: + regexp: dev + - find: #will return every secret matching environment:dev tags from dev/ folder and beyond + tags: + environment: dev +``` +will generate a secret with: +```json +{ + "dev_config":"{\"foo\": {\"nested\": {\"bar\": \"mysecret\",\"baz\": \"bang\"}}}" +} +``` + +Currently, `Find` operations are recursive throughout a given vault folder, starting on `provider.Path` definition. It is recommended to narrow down the scope of search by setting a `find.path` variable. This is also useful to automatically reduce the resulting secret key names: +```yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: vault-example +spec: + # ... + dataFrom: + - find: #will return every secret from dev/ folder + path: dev + name: + regexp: ".*" + - find: #will return every secret matching environment:dev tags from dev/ folder + path: dev + tags: + environment: dev +``` +Will generate a secret with: +```json +{ + "config":"{\"foo\": {\"nested\": {\"bar\": \"mysecret\",\"baz\": \"bang\"}}}" +} + +``` ### Authentication We support five different modes for authentication: diff --git a/docs/snippets/akeyless-external-secret-json.yaml b/docs/snippets/akeyless-external-secret-json.yaml index 20744db62..682b8a0a8 100644 --- a/docs/snippets/akeyless-external-secret-json.yaml +++ b/docs/snippets/akeyless-external-secret-json.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: akeyless-external-secret-example-json @@ -15,4 +15,5 @@ spec: # for json formatted secrets: each key in the json will be used as the secret key in the SECRET k8s target object dataFrom: - - key: secret-name # Full path of the secret on Akeyless + - extract: + key: secret-name # Full path of the secret on Akeyless diff --git a/docs/snippets/akeyless-external-secret.yaml b/docs/snippets/akeyless-external-secret.yaml index 27eed4ba5..dd02f350b 100644 --- a/docs/snippets/akeyless-external-secret.yaml +++ b/docs/snippets/akeyless-external-secret.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: akeyless-external-secret-example diff --git a/docs/snippets/akeyless-secret-store.yaml b/docs/snippets/akeyless-secret-store.yaml index b41b2643c..7ea0c210b 100644 --- a/docs/snippets/akeyless-secret-store.yaml +++ b/docs/snippets/akeyless-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: akeyless-secret-store diff --git a/docs/snippets/aws-anchore-engine-access-credentials-external-secret.yaml b/docs/snippets/aws-anchore-engine-access-credentials-external-secret.yaml index 16b6a43b3..a2a0a95f6 100644 --- a/docs/snippets/aws-anchore-engine-access-credentials-external-secret.yaml +++ b/docs/snippets/aws-anchore-engine-access-credentials-external-secret.yaml @@ -1,5 +1,5 @@ --- -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: anchore-access-credentials @@ -12,4 +12,5 @@ spec: target: name: anchore-access-credentials dataFrom: - - key: service/anchore-engine/engineAccess + - extract: + key: service/anchore-engine/engineAccess diff --git a/docs/snippets/aws-jenkins-credential-github-ssh-external-secret.yaml b/docs/snippets/aws-jenkins-credential-github-ssh-external-secret.yaml index 42e4c7cec..d52917eb3 100644 --- a/docs/snippets/aws-jenkins-credential-github-ssh-external-secret.yaml +++ b/docs/snippets/aws-jenkins-credential-github-ssh-external-secret.yaml @@ -1,5 +1,5 @@ --- -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: github-ssh-access diff --git a/docs/snippets/aws-jenkins-credential-sonarqube-api-token-external-secret.yaml b/docs/snippets/aws-jenkins-credential-sonarqube-api-token-external-secret.yaml index 904f25c39..c4404dc4f 100644 --- a/docs/snippets/aws-jenkins-credential-sonarqube-api-token-external-secret.yaml +++ b/docs/snippets/aws-jenkins-credential-sonarqube-api-token-external-secret.yaml @@ -1,5 +1,5 @@ --- -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: sonarqube-api-token diff --git a/docs/snippets/aws-jenkins-credentials-harbor-chart-robot-external-secret.yaml b/docs/snippets/aws-jenkins-credentials-harbor-chart-robot-external-secret.yaml index 4b9bc32e6..fa8c27167 100644 --- a/docs/snippets/aws-jenkins-credentials-harbor-chart-robot-external-secret.yaml +++ b/docs/snippets/aws-jenkins-credentials-harbor-chart-robot-external-secret.yaml @@ -1,5 +1,5 @@ --- -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: harbor-chart-robot diff --git a/docs/snippets/aws-parameter-store.yaml b/docs/snippets/aws-parameter-store.yaml index 4c9d5966e..05be0bb88 100644 --- a/docs/snippets/aws-parameter-store.yaml +++ b/docs/snippets/aws-parameter-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: secretstore-sample diff --git a/docs/snippets/aws-sm-external-secret.yaml b/docs/snippets/aws-sm-external-secret.yaml index b099e53f5..bdf9dea68 100644 --- a/docs/snippets/aws-sm-external-secret.yaml +++ b/docs/snippets/aws-sm-external-secret.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: example diff --git a/docs/snippets/aws-sm-store.yaml b/docs/snippets/aws-sm-store.yaml index 5a2d34f8e..5442a1757 100644 --- a/docs/snippets/aws-sm-store.yaml +++ b/docs/snippets/aws-sm-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: secretstore-sample diff --git a/docs/snippets/azkv-external-secret.yaml b/docs/snippets/azkv-external-secret.yaml index 7f456c210..2f24c0c3c 100644 --- a/docs/snippets/azkv-external-secret.yaml +++ b/docs/snippets/azkv-external-secret.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: example-external-secret diff --git a/docs/snippets/azkv-secret-store-mi.yaml b/docs/snippets/azkv-secret-store-mi.yaml index 4773dd1c1..4cd297702 100644 --- a/docs/snippets/azkv-secret-store-mi.yaml +++ b/docs/snippets/azkv-secret-store-mi.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: example-secret-store diff --git a/docs/snippets/azkv-secret-store.yaml b/docs/snippets/azkv-secret-store.yaml index 530949e1a..42dbdb82c 100644 --- a/docs/snippets/azkv-secret-store.yaml +++ b/docs/snippets/azkv-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: example-secret-store diff --git a/docs/snippets/basic-external-secret.yaml b/docs/snippets/basic-external-secret.yaml index cf29a5edc..1356fc933 100644 --- a/docs/snippets/basic-external-secret.yaml +++ b/docs/snippets/basic-external-secret.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: example @@ -17,4 +17,5 @@ spec: version: provider-key-version property: provider-key-property dataFrom: - - key: remote-key-in-the-provider + - extract: + key: remote-key-in-the-provider diff --git a/docs/snippets/basic-secret-store.yaml b/docs/snippets/basic-secret-store.yaml index 47337fb98..9b3506c34 100644 --- a/docs/snippets/basic-secret-store.yaml +++ b/docs/snippets/basic-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: secretstore-sample diff --git a/docs/snippets/controller-class-store.yaml b/docs/snippets/controller-class-store.yaml index 8d01f31af..0b94088ac 100644 --- a/docs/snippets/controller-class-store.yaml +++ b/docs/snippets/controller-class-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: controller-custom-example diff --git a/docs/snippets/fake-provider-es.yaml b/docs/snippets/fake-provider-es.yaml index cb3498836..42da09ce8 100644 --- a/docs/snippets/fake-provider-es.yaml +++ b/docs/snippets/fake-provider-es.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: example @@ -15,4 +15,5 @@ spec: key: /foo/bar version: v1 dataFrom: - - key: /foo/baz \ No newline at end of file + - extract: + key: /foo/baz \ No newline at end of file diff --git a/docs/snippets/fake-provider-store.yaml b/docs/snippets/fake-provider-store.yaml index 6d429235e..bfd25904e 100644 --- a/docs/snippets/fake-provider-store.yaml +++ b/docs/snippets/fake-provider-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ClusterSecretStore metadata: name: fake diff --git a/docs/snippets/full-cluster-secret-store.yaml b/docs/snippets/full-cluster-secret-store.yaml index c88d46c43..6e54de35a 100644 --- a/docs/snippets/full-cluster-secret-store.yaml +++ b/docs/snippets/full-cluster-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ClusterSecretStore metadata: name: example diff --git a/docs/snippets/full-external-secret.yaml b/docs/snippets/full-external-secret.yaml index f07a81238..d50461375 100644 --- a/docs/snippets/full-external-secret.yaml +++ b/docs/snippets/full-external-secret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: "hello-world" @@ -73,9 +73,18 @@ spec: # Used to fetch all properties from the Provider key # If multiple dataFrom are specified, secrets are merged in the specified order dataFrom: - - key: provider-key - version: provider-key-version - property: provider-key-property + - extract: + key: provider-key + version: provider-key-version + property: provider-key-property + conversionStrategy: Default + - find: + path: path-to-filter + name: + regexp: ".*foobar.*" + tags: + foo: bar + conversionStrategy: Unicode status: # refreshTime is the time and date the external secret was fetched and diff --git a/docs/snippets/full-secret-store.yaml b/docs/snippets/full-secret-store.yaml index c668effe4..29c0155b3 100644 --- a/docs/snippets/full-secret-store.yaml +++ b/docs/snippets/full-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: example diff --git a/docs/snippets/gcpsm-data-from-external-secret.yaml b/docs/snippets/gcpsm-data-from-external-secret.yaml index 57fd126f9..027a1526b 100644 --- a/docs/snippets/gcpsm-data-from-external-secret.yaml +++ b/docs/snippets/gcpsm-data-from-external-secret.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: example @@ -11,4 +11,5 @@ spec: name: secret-to-be-created # name of the k8s Secret to be created creationPolicy: Owner dataFrom: - - key: all-keys-example-secret # name of the GCPSM secret + - extract: + key: all-keys-example-secret # name of the GCPSM secret diff --git a/docs/snippets/gcpsm-docker-config-externalsecret.yaml b/docs/snippets/gcpsm-docker-config-externalsecret.yaml index 6ba7f2e06..48da5bfc7 100644 --- a/docs/snippets/gcpsm-docker-config-externalsecret.yaml +++ b/docs/snippets/gcpsm-docker-config-externalsecret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: dk-cfg-example diff --git a/docs/snippets/gcpsm-external-secret.yaml b/docs/snippets/gcpsm-external-secret.yaml index 6cf722af4..a1e4effc2 100644 --- a/docs/snippets/gcpsm-external-secret.yaml +++ b/docs/snippets/gcpsm-external-secret.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: example diff --git a/docs/snippets/gcpsm-pod-wi-secret-store.yaml b/docs/snippets/gcpsm-pod-wi-secret-store.yaml index 35a89443e..e35bf71f3 100644 --- a/docs/snippets/gcpsm-pod-wi-secret-store.yaml +++ b/docs/snippets/gcpsm-pod-wi-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: example diff --git a/docs/snippets/gcpsm-secret-store.yaml b/docs/snippets/gcpsm-secret-store.yaml index c9d3bed74..a70d625d1 100644 --- a/docs/snippets/gcpsm-secret-store.yaml +++ b/docs/snippets/gcpsm-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: example diff --git a/docs/snippets/gcpsm-ssh-auth-externalsecret.yaml b/docs/snippets/gcpsm-ssh-auth-externalsecret.yaml index 36f20691b..12040b0ba 100644 --- a/docs/snippets/gcpsm-ssh-auth-externalsecret.yaml +++ b/docs/snippets/gcpsm-ssh-auth-externalsecret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: ssh-auth-example diff --git a/docs/snippets/gcpsm-tls-externalsecret.yaml b/docs/snippets/gcpsm-tls-externalsecret.yaml index 9fa16afdc..69dd2b20f 100644 --- a/docs/snippets/gcpsm-tls-externalsecret.yaml +++ b/docs/snippets/gcpsm-tls-externalsecret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: template-tls-example diff --git a/docs/snippets/gcpsm-wi-secret-store.yaml b/docs/snippets/gcpsm-wi-secret-store.yaml index 13f31194b..073ea65e8 100644 --- a/docs/snippets/gcpsm-wi-secret-store.yaml +++ b/docs/snippets/gcpsm-wi-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ClusterSecretStore metadata: name: example diff --git a/docs/snippets/gitlab-external-secret-json.yaml b/docs/snippets/gitlab-external-secret-json.yaml index 9733ab805..db60833f5 100644 --- a/docs/snippets/gitlab-external-secret-json.yaml +++ b/docs/snippets/gitlab-external-secret-json.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: gitlab-external-secret-example @@ -15,4 +15,5 @@ spec: # each secret name in the KV will be used as the secret key in the SECRET k8s target object dataFrom: - - key: "myJsonVariable" # Key of the variable on Gitlab \ No newline at end of file + - extract: + key: "myJsonVariable" # Key of the variable on Gitlab \ No newline at end of file diff --git a/docs/snippets/gitlab-external-secret.yaml b/docs/snippets/gitlab-external-secret.yaml index c48228f68..8f168cd31 100644 --- a/docs/snippets/gitlab-external-secret.yaml +++ b/docs/snippets/gitlab-external-secret.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: gitlab-external-secret-example diff --git a/docs/snippets/gitlab-secret-store.yaml b/docs/snippets/gitlab-secret-store.yaml index d2ae32793..9f8814047 100644 --- a/docs/snippets/gitlab-secret-store.yaml +++ b/docs/snippets/gitlab-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: gitlab-secret-store diff --git a/docs/snippets/gitops/crs/clusterSecretStore.yaml b/docs/snippets/gitops/crs/clusterSecretStore.yaml index 9693ad4ed..ca67d6a1b 100644 --- a/docs/snippets/gitops/crs/clusterSecretStore.yaml +++ b/docs/snippets/gitops/crs/clusterSecretStore.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ClusterSecretStore metadata: name: vault-backend-global diff --git a/docs/snippets/ibm-es-types.yaml b/docs/snippets/ibm-es-types.yaml index 9c65c21da..186122d7e 100644 --- a/docs/snippets/ibm-es-types.yaml +++ b/docs/snippets/ibm-es-types.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: ibm-sample diff --git a/docs/snippets/ibm-external-secret.yaml b/docs/snippets/ibm-external-secret.yaml index bcfd618ef..45777bcd2 100644 --- a/docs/snippets/ibm-external-secret.yaml +++ b/docs/snippets/ibm-external-secret.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: external-secret-sample diff --git a/docs/snippets/ibm-secret-store.yaml b/docs/snippets/ibm-secret-store.yaml index b46ac2524..4c589a02e 100644 --- a/docs/snippets/ibm-secret-store.yaml +++ b/docs/snippets/ibm-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: secretstore-sample diff --git a/docs/snippets/jwk-template-v2-external-secret.yaml b/docs/snippets/jwk-template-v2-external-secret.yaml index 91eb4c5f7..bf3585861 100644 --- a/docs/snippets/jwk-template-v2-external-secret.yaml +++ b/docs/snippets/jwk-template-v2-external-secret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: template diff --git a/docs/snippets/multiline-template-v1-external-secret.yaml b/docs/snippets/multiline-template-v1-external-secret.yaml index 936127829..fe9abd932 100644 --- a/docs/snippets/multiline-template-v1-external-secret.yaml +++ b/docs/snippets/multiline-template-v1-external-secret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: template diff --git a/docs/snippets/multiline-template-v2-external-secret.yaml b/docs/snippets/multiline-template-v2-external-secret.yaml index c65b396bb..579a23734 100644 --- a/docs/snippets/multiline-template-v2-external-secret.yaml +++ b/docs/snippets/multiline-template-v2-external-secret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: template diff --git a/docs/snippets/oracle-external-secret.yaml b/docs/snippets/oracle-external-secret.yaml index e9038092b..03208dbda 100644 --- a/docs/snippets/oracle-external-secret.yaml +++ b/docs/snippets/oracle-external-secret.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: example @@ -11,4 +11,5 @@ spec: name: secret-to-be-created # Name for the secret on the cluster creationPolicy: Owner dataFrom: - - key: the-secret-name + - extract: + key: the-secret-name diff --git a/docs/snippets/oracle-secret-store.yaml b/docs/snippets/oracle-secret-store.yaml index ee3abe857..752add65c 100644 --- a/docs/snippets/oracle-secret-store.yaml +++ b/docs/snippets/oracle-secret-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: example-instance-principal @@ -10,7 +10,7 @@ spec: --- -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: example-auth diff --git a/docs/snippets/pkcs12-template-v1-external-secret.yaml b/docs/snippets/pkcs12-template-v1-external-secret.yaml index 2fd935035..04dbf2fa5 100644 --- a/docs/snippets/pkcs12-template-v1-external-secret.yaml +++ b/docs/snippets/pkcs12-template-v1-external-secret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: template diff --git a/docs/snippets/pkcs12-template-v2-external-secret.yaml b/docs/snippets/pkcs12-template-v2-external-secret.yaml index f39d07efb..3ca488e1f 100644 --- a/docs/snippets/pkcs12-template-v2-external-secret.yaml +++ b/docs/snippets/pkcs12-template-v2-external-secret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: template diff --git a/docs/snippets/provider-aws-access.md b/docs/snippets/provider-aws-access.md index 25a3cf551..887f92b6d 100644 --- a/docs/snippets/provider-aws-access.md +++ b/docs/snippets/provider-aws-access.md @@ -13,7 +13,7 @@ You can attach a role to the pod using [IRSA](https://docs.aws.amazon.com/eks/la Based on the Pod's identity you can do a `sts:assumeRole` before fetching the secrets to limit access to certain keys in your provider. This is optional. ```yaml -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: team-b-store @@ -33,7 +33,7 @@ spec: You can store Access Key ID & Secret Access Key in a `Kind=Secret` and reference it from a SecretStore. ```yaml -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: team-b-store @@ -78,7 +78,7 @@ metadata: Reference the service account from above in the Secret Store: ```yaml -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: secretstore-sample diff --git a/docs/snippets/template-v1-from-secret.yaml b/docs/snippets/template-v1-from-secret.yaml index 2410df631..e38778cee 100644 --- a/docs/snippets/template-v1-from-secret.yaml +++ b/docs/snippets/template-v1-from-secret.yaml @@ -14,7 +14,7 @@ data: password: "{{ .password | toString }}" # <-- convert []byte to string user: "{{ .user | toString }}" # <-- convert []byte to string --- -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: my-template-example diff --git a/docs/snippets/template-v2-from-secret.yaml b/docs/snippets/template-v2-from-secret.yaml index 033c57bef..8889fb259 100644 --- a/docs/snippets/template-v2-from-secret.yaml +++ b/docs/snippets/template-v2-from-secret.yaml @@ -14,7 +14,7 @@ data: password: "{{ .password }}" user: "{{ .user }}" --- -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: my-template-example diff --git a/docs/snippets/vault-anchore-engine-access-credentials-external-secret.yaml b/docs/snippets/vault-anchore-engine-access-credentials-external-secret.yaml index e127ba74b..613c2410c 100644 --- a/docs/snippets/vault-anchore-engine-access-credentials-external-secret.yaml +++ b/docs/snippets/vault-anchore-engine-access-credentials-external-secret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: anchore-access-credentials diff --git a/docs/snippets/vault-approle-store.yaml b/docs/snippets/vault-approle-store.yaml index 65065ef44..94e349487 100644 --- a/docs/snippets/vault-approle-store.yaml +++ b/docs/snippets/vault-approle-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: vault-backend diff --git a/docs/snippets/vault-jenkins-credential-github-ssh-access-external-secret.yaml b/docs/snippets/vault-jenkins-credential-github-ssh-access-external-secret.yaml index 169793449..9b5d3e368 100644 --- a/docs/snippets/vault-jenkins-credential-github-ssh-access-external-secret.yaml +++ b/docs/snippets/vault-jenkins-credential-github-ssh-access-external-secret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: github-ssh-access diff --git a/docs/snippets/vault-jenkins-credential-harbor-chart-robot-external-secret.yaml b/docs/snippets/vault-jenkins-credential-harbor-chart-robot-external-secret.yaml index ed98f4802..4622e2ba8 100644 --- a/docs/snippets/vault-jenkins-credential-harbor-chart-robot-external-secret.yaml +++ b/docs/snippets/vault-jenkins-credential-harbor-chart-robot-external-secret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: harbor-chart-robot diff --git a/docs/snippets/vault-jenkins-credential-sonarqube-api-token-external-secret.yaml b/docs/snippets/vault-jenkins-credential-sonarqube-api-token-external-secret.yaml index dc626aca3..1915a98c7 100644 --- a/docs/snippets/vault-jenkins-credential-sonarqube-api-token-external-secret.yaml +++ b/docs/snippets/vault-jenkins-credential-sonarqube-api-token-external-secret.yaml @@ -1,5 +1,5 @@ {% raw %} -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: sonarqube-api-token diff --git a/docs/snippets/vault-jwt-store.yaml b/docs/snippets/vault-jwt-store.yaml index a06a5eded..4c71e264a 100644 --- a/docs/snippets/vault-jwt-store.yaml +++ b/docs/snippets/vault-jwt-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: vault-backend diff --git a/docs/snippets/vault-kubernetes-store.yaml b/docs/snippets/vault-kubernetes-store.yaml index 2dcc01957..22944e162 100644 --- a/docs/snippets/vault-kubernetes-store.yaml +++ b/docs/snippets/vault-kubernetes-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: vault-backend diff --git a/docs/snippets/vault-ldap-store.yaml b/docs/snippets/vault-ldap-store.yaml index 56cb747b9..f3b32bf79 100644 --- a/docs/snippets/vault-ldap-store.yaml +++ b/docs/snippets/vault-ldap-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: vault-backend diff --git a/docs/snippets/vault-token-store.yaml b/docs/snippets/vault-token-store.yaml index ca979f285..95ed6e909 100644 --- a/docs/snippets/vault-token-store.yaml +++ b/docs/snippets/vault-token-store.yaml @@ -1,4 +1,4 @@ -apiVersion: external-secrets.io/v1alpha1 +apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: vault-backend diff --git a/pkg/controllers/externalsecret/externalsecret_controller.go b/pkg/controllers/externalsecret/externalsecret_controller.go index 2676474dd..847a28b94 100644 --- a/pkg/controllers/externalsecret/externalsecret_controller.go +++ b/pkg/controllers/externalsecret/externalsecret_controller.go @@ -46,6 +46,8 @@ const ( requeueAfter = time.Second * 30 errGetES = "could not get ExternalSecret" + errConvert = "could not apply conversion strategy to keys: %v" + errFindSecretKey = "could not find secret %v: %v" errUpdateSecret = "could not update Secret" errPatchStatus = "unable to patch status" errGetSecretStore = "could not get SecretStore %q, %w" @@ -400,13 +402,21 @@ func (r *Reconciler) getProviderSecretData(ctx context.Context, providerClient e if remoteRef.Find != nil { secretMap, err = providerClient.GetAllSecrets(ctx, *remoteRef.Find) if err != nil { - return nil, fmt.Errorf(errGetSecretKey, remoteRef.Extract.Key, externalSecret.Name, err) + return nil, fmt.Errorf(errFindSecretKey, externalSecret.Name, err) + } + secretMap, err = utils.ConvertKeys(remoteRef.Find.ConversionStrategy, secretMap) + if err != nil { + return nil, fmt.Errorf(errConvert, err) } } else if remoteRef.Extract != nil { secretMap, err = providerClient.GetSecretMap(ctx, *remoteRef.Extract) if err != nil { return nil, fmt.Errorf(errGetSecretKey, remoteRef.Extract.Key, externalSecret.Name, err) } + secretMap, err = utils.ConvertKeys(remoteRef.Extract.ConversionStrategy, secretMap) + if err != nil { + return nil, fmt.Errorf(errConvert, err) + } } providerData = utils.MergeByteMap(providerData, secretMap) diff --git a/pkg/provider/vault/vault.go b/pkg/provider/vault/vault.go index e1a237273..ca492185d 100644 --- a/pkg/provider/vault/vault.go +++ b/pkg/provider/vault/vault.go @@ -276,11 +276,10 @@ func (v *client) findSecretsFromTags(ctx context.Context, candidates []string, t if removeFromName != "" { name = strings.TrimPrefix(name, removeFromName) } - newName := utils.ConvertName(name) - if _, exists := secrets[newName]; exists { - return nil, fmt.Errorf(errDuplicateSecret, newName) + if _, exists := secrets[name]; exists { + return nil, fmt.Errorf(errDuplicateSecret, name) } - secrets[newName] = secret + secrets[name] = secret } } return secrets, nil @@ -301,11 +300,10 @@ func (v *client) findSecretsFromName(ctx context.Context, candidates []string, r if removeFromName != "" { name = strings.TrimPrefix(name, removeFromName) } - newName := utils.ConvertName(name) - if _, exists := secrets[newName]; exists { - return nil, fmt.Errorf(errDuplicateSecret, newName) + if _, exists := secrets[name]; exists { + return nil, fmt.Errorf(errDuplicateSecret, name) } - secrets[newName] = secret + secrets[name] = secret } } return secrets, nil diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 5fac1a19b..6bb8fc2b8 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -21,7 +21,6 @@ import ( "fmt" "reflect" "strings" - "unicode" esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" @@ -36,23 +35,34 @@ func MergeByteMap(dst, src map[string][]byte) map[string][]byte { return dst } -// ConvertName converts a string into a secret-key compatible string. -// Replaces any non-alphanumeric characters with its unicode code. -func ConvertName(in string) string { - out := make([]string, len(in)) - rs := []rune(in) - for k, r := range rs { - if !unicode.IsNumber(r) && - !unicode.IsLetter(r) && - r != '-' && - r != '.' && - r != '_' { - out[k] = fmt.Sprintf("_U%04x_", r) - } else { - out[k] = string(r) +// ConvertKeys converts a secret map into a valid key. +// Replaces any non-alphanumeric characters depending on convert strategy. +func ConvertKeys(strategy esv1beta1.ExternalSecretConversionStrategy, in map[string][]byte) (map[string][]byte, error) { + out := make(map[string][]byte) + for k, v := range in { + rs := []rune(k) + newName := make([]string, len(rs)) + for rk, rv := range rs { + if !unicode.IsNumber(rv) && + !unicode.IsLetter(rv) && + rv != '-' && + rv != '.' && + rv != '_' { + switch strategy { + case esv1beta1.ExternalSecretConversionDefault: + newName[rk] = "_" + case esv1beta1.ExternalSecretConversionUnicode: + newName[rk] = fmt.Sprintf("_U%04x_", rv) + default: + return nil, fmt.Errorf("unknown conversion strategy: %s", strategy) + } + } else { + newName[rk] = string(rv) + } } + out[strings.Join(newName, "")] = v } - return strings.Join(out, "") + return out, nil } // MergeStringMap performs a deep clone from src to dest.