1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-14 11:57:59 +00:00

Adding docs and implementing ConversionStrategy

Signed-off-by: Gustavo Carvalho <gustavo.carvalho@container-solutions.com>
This commit is contained in:
Gustavo Carvalho 2022-03-09 06:48:25 -03:00
parent 2f23fd28ed
commit 164e8776ec
63 changed files with 276 additions and 106 deletions

View file

@ -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"`

View file

@ -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 {

View file

@ -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:

View file

@ -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:

View file

@ -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,14 +141,15 @@ 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
- extract:
key: /dev/config
property: foo.nested
```
@ -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:

View file

@ -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

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: akeyless-external-secret-example

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: akeyless-secret-store

View file

@ -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

View file

@ -1,5 +1,5 @@
---
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: github-ssh-access

View file

@ -1,5 +1,5 @@
---
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: sonarqube-api-token

View file

@ -1,5 +1,5 @@
---
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: harbor-chart-robot

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: secretstore-sample

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: example

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: secretstore-sample

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: example-external-secret

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: example-secret-store

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: example-secret-store

View file

@ -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

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: secretstore-sample

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: controller-custom-example

View file

@ -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
- extract:
key: /foo/baz

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: fake

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: example

View file

@ -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
- 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

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: example

View file

@ -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

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: dk-cfg-example

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: example

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: example

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: example

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: ssh-auth-example

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: template-tls-example

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: example

View file

@ -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
- extract:
key: "myJsonVariable" # Key of the variable on Gitlab

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: gitlab-external-secret-example

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: gitlab-secret-store

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: vault-backend-global

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: ibm-sample

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: external-secret-sample

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: secretstore-sample

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: template

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: template

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: template

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: template

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: template

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: anchore-access-credentials

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: github-ssh-access

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: harbor-chart-robot

View file

@ -1,5 +1,5 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: sonarqube-api-token

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend

View file

@ -1,4 +1,4 @@
apiVersion: external-secrets.io/v1alpha1
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend

View file

@ -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)

View file

@ -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

View file

@ -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)
// 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 {
out[k] = string(r)
newName[rk] = string(rv)
}
}
return strings.Join(out, "")
out[strings.Join(newName, "")] = v
}
return out, nil
}
// MergeStringMap performs a deep clone from src to dest.