Ver Fonte

v1 of the GetAll secrets in Azure using the old dataFrom

Sebastian Gomez há 4 anos atrás
pai
commit
410ad286ce

+ 27 - 7
apis/externalsecrets/v1alpha1/externalsecret_types.go

@@ -118,8 +118,24 @@ type ExternalSecretData struct {
 
 // ExternalSecretDataRemoteRef defines Provider data location.
 type ExternalSecretDataRemoteRef struct {
-	// Key is the key used in the Provider, mandatory
-	Key string `json:"key"`
+	// Key is the key used in the Provider
+	// +optional
+	Key string `json:"key,omitempty"`
+
+	// Used to select multiple secrets based on a pattern
+	// +optional
+	MatchKey string `json:"matchKey,omitempty"`
+
+	// List of tags used to filter the secrets
+	Tags map[string]string `json:"tags,omitempty"`
+
+	// Used to select multiple secrets based on the name
+	// +optional
+	Name string `json:"name,omitempty"`
+
+	// Used to select multiple secrets based on a regular expression of the name
+	// +optional
+	RegExp string `json:"regexp,omitempty"`
 
 	// Used to select a specific version of the Provider value, if supported
 	// +optional
@@ -130,6 +146,15 @@ type ExternalSecretDataRemoteRef struct {
 	Property string `json:"property,omitempty"`
 }
 
+// type ExternalSecretDataRemoteMatchKey struct {
+
+// 	//A regular expression used to get the secrets
+// 	//Name string `json:"name,omitempty"`
+
+// 	// List of tags used to filter the secrets
+// 	Tags map[string]string `json:"tags,omitempty"`
+// }
+
 // ExternalSecretSpec defines the desired state of ExternalSecret.
 type ExternalSecretSpec struct {
 	SecretStoreRef SecretStoreRef `json:"secretStoreRef"`
@@ -150,11 +175,6 @@ type ExternalSecretSpec struct {
 	// If multiple entries are specified, the Secret keys are merged in the specified order
 	// +optional
 	DataFrom []ExternalSecretDataRemoteRef `json:"dataFrom,omitempty"`
-
-	// DataAll is used to fetch ALL data in the defined Provider
-	// If multiple entries are specified, the Secret keys are merged in the specified order
-	// +optional
-	DataAll []ExternalSecretDataRemoteRef `json:"dataAll,omitempty"`
 }
 
 type ExternalSecretConditionType string

+ 14 - 8
apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go

@@ -389,7 +389,7 @@ func (in *ExternalSecret) DeepCopyObject() runtime.Object {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ExternalSecretData) DeepCopyInto(out *ExternalSecretData) {
 	*out = *in
-	out.RemoteRef = in.RemoteRef
+	in.RemoteRef.DeepCopyInto(&out.RemoteRef)
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretData.
@@ -405,6 +405,13 @@ func (in *ExternalSecretData) DeepCopy() *ExternalSecretData {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ExternalSecretDataRemoteRef) DeepCopyInto(out *ExternalSecretDataRemoteRef) {
 	*out = *in
+	if in.Tags != nil {
+		in, out := &in.Tags, &out.Tags
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretDataRemoteRef.
@@ -462,17 +469,16 @@ func (in *ExternalSecretSpec) DeepCopyInto(out *ExternalSecretSpec) {
 	if in.Data != nil {
 		in, out := &in.Data, &out.Data
 		*out = make([]ExternalSecretData, len(*in))
-		copy(*out, *in)
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
 	}
 	if in.DataFrom != nil {
 		in, out := &in.DataFrom, &out.DataFrom
 		*out = make([]ExternalSecretDataRemoteRef, len(*in))
-		copy(*out, *in)
-	}
-	if in.DataAll != nil {
-		in, out := &in.DataAll, &out.DataAll
-		*out = make([]ExternalSecretDataRemoteRef, len(*in))
-		copy(*out, *in)
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
 	}
 }
 

+ 32 - 26
deploy/crds/external-secrets.io_externalsecrets.yaml

@@ -60,18 +60,33 @@ spec:
                         location.
                       properties:
                         key:
-                          description: Key is the key used in the Provider, mandatory
+                          description: Key is the key used in the Provider
+                          type: string
+                        matchKey:
+                          description: Used to select multiple secrets based on a
+                            pattern
+                          type: string
+                        name:
+                          description: Used to select multiple secrets based on the
+                            name
                           type: string
                         property:
                           description: Used to select a specific property of the Provider
                             value (if a map), if supported
                           type: string
+                        regexp:
+                          description: Used to select multiple secrets based on a
+                            regular expression of the name
+                          type: string
+                        tags:
+                          additionalProperties:
+                            type: string
+                          description: List of tags used to filter the secrets
+                          type: object
                         version:
                           description: Used to select a specific version of the Provider
                             value, if supported
                           type: string
-                      required:
-                      - key
                       type: object
                     secretKey:
                       type: string
@@ -88,40 +103,31 @@ spec:
                   description: ExternalSecretDataRemoteRef defines Provider data location.
                   properties:
                     key:
-                      description: Key is the key used in the Provider, mandatory
+                      description: Key is the key used in the Provider
                       type: string
-                    property:
-                      description: Used to select a specific property of the Provider
-                        value (if a map), if supported
+                    matchKey:
+                      description: Used to select multiple secrets based on a pattern
                       type: string
-                    version:
-                      description: Used to select a specific version of the Provider
-                        value, if supported
-                      type: string
-                  required:
-                  - key
-                  type: object
-                type: array
-              dataAll:
-                description: DataAll is used to fetch all properties from a specific
-                  Provider Backend If multiple entries are specified, the Secret keys
-                  are merged in the specified order
-                items:
-                  description: ExternalSecretDataRemoteRef defines Provider data location.
-                  properties:
-                    key:
-                      description: Key is the key used in the Provider, mandatory
+                    name:
+                      description: Used to select multiple secrets based on the name
                       type: string
                     property:
                       description: Used to select a specific property of the Provider
                         value (if a map), if supported
                       type: string
+                    regexp:
+                      description: Used to select multiple secrets based on a regular
+                        expression of the name
+                      type: string
+                    tags:
+                      additionalProperties:
+                        type: string
+                      description: List of tags used to filter the secrets
+                      type: object
                     version:
                       description: Used to select a specific version of the Provider
                         value, if supported
                       type: string
-                  required:
-                  - key
                   type: object
                 type: array
               refreshInterval:

+ 15 - 13
pkg/controllers/externalsecret/externalsecret_controller.go

@@ -388,21 +388,23 @@ func (r *Reconciler) getProviderSecretData(ctx context.Context, providerClient p
 	providerData := make(map[string][]byte)
 
 	for _, remoteRef := range externalSecret.Spec.DataFrom {
-		secretMap, err := providerClient.GetSecretMap(ctx, remoteRef)
-		if err != nil {
-			return nil, fmt.Errorf(errGetSecretKey, remoteRef.Key, externalSecret.Name, err)
-		}
-
-		providerData = utils.MergeByteMap(providerData, secretMap)
-	}
+		var secretMap map[string][]byte
+		var err error
 
-	for _, allSecretsRef := range externalSecret.Spec.DataAll {
-		secretAll, err := providerClient.GetAllSecrets(ctx, allSecretsRef)
-		if err != nil {
-			return nil, fmt.Errorf(errGetSecretKey, allSecretsRef.Key, externalSecret.Name, err)
+		// If tags were added get all secret by tags
+		// Also if a regular expression was entered
+		if len(remoteRef.Tags) > 0 || len(remoteRef.RegExp) > 0 {
+			secretMap, err = providerClient.GetAllSecrets(ctx, remoteRef)
+			if err != nil {
+				return nil, fmt.Errorf(errGetSecretKey, remoteRef.Key, externalSecret.Name, err)
+			}
+		} else {
+			secretMap, err = providerClient.GetSecretMap(ctx, remoteRef)
+			if err != nil {
+				return nil, fmt.Errorf(errGetSecretKey, remoteRef.Key, externalSecret.Name, err)
+			}
 		}
-
-		providerData = utils.MergeByteMap(providerData, secretAll)
+		providerData = utils.MergeByteMap(providerData, secretMap)
 	}
 
 	for _, secretRef := range externalSecret.Spec.Data {

+ 31 - 0
pkg/provider/azure/keyvault/keyvault.go

@@ -19,6 +19,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"path"
+	"regexp"
 	"strings"
 
 	"github.com/Azure/azure-sdk-for-go/profiles/latest/keyvault/keyvault"
@@ -94,6 +95,10 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretData
 	basicClient := a.baseClient
 	objectType, secretName := getObjType(ref)
 
+	if secretName == "" {
+		return nil, fmt.Errorf("%s name cannot be empty", objectType)
+	}
+
 	if ref.Version != "" {
 		version = ref.Version
 	}
@@ -174,6 +179,8 @@ func (a *Azure) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretD
 func (a *Azure) GetAllSecrets(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
 	basicClient := a.baseClient
 	secretsMap := make(map[string][]byte)
+	checkTags := len(ref.Tags) > 0
+	checkName := len(ref.RegExp) > 0
 
 	secretListIter, err := basicClient.GetSecretsComplete(context.Background(), a.vaultURL, nil)
 
@@ -186,7 +193,15 @@ func (a *Azure) GetAllSecrets(ctx context.Context, ref esv1alpha1.ExternalSecret
 			if !*secret.Attributes.Enabled {
 				continue
 			}
+
+			if checkTags && !okByTags(ref, secret) {
+				continue
+			}
+
 			secretName := path.Base(*secret.ID)
+			if checkName && !okByName(ref, secretName) {
+				continue
+			}
 			secretResp, err := basicClient.GetSecret(context.Background(), a.vaultURL, secretName, "")
 			secretValue := *secretResp.Value
 
@@ -203,6 +218,22 @@ func (a *Azure) GetAllSecrets(ctx context.Context, ref esv1alpha1.ExternalSecret
 	return secretsMap, nil
 }
 
+func okByName(ref esv1alpha1.ExternalSecretDataRemoteRef, secretName string) bool {
+	matches, _ := regexp.MatchString(ref.RegExp, secretName)
+	return matches
+}
+
+func okByTags(ref esv1alpha1.ExternalSecretDataRemoteRef, secret keyvault.SecretItem) bool {
+	tagFound := true
+	for k, v := range ref.Tags {
+		if val, ok := secret.Tags[k]; !ok || *val != v {
+			tagFound = false
+			break
+		}
+	}
+	return tagFound
+}
+
 func (a *Azure) setAzureClientWithManagedIdentity() (bool, error) {
 	spec := *a.store.GetSpec().Provider.AzureKV