فهرست منبع

Merge branch 'main' into getall-Secrets

Sebastian Gomez 4 سال پیش
والد
کامیت
43e4eb320a

+ 0 - 5
.github/codecov.yml

@@ -1,5 +0,0 @@
-ignore:
-- pkg/provider/**/fake
-coverage:
-  round: down
-  precision: 2

+ 97 - 0
e2e/suite/aws/common.go

@@ -0,0 +1,97 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package common
+
+import (
+	"context"
+
+	// nolint
+	. "github.com/onsi/gomega"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	esmetav1 "github.com/external-secrets/external-secrets/apis/meta/v1"
+	"github.com/external-secrets/external-secrets/e2e/framework"
+)
+
+const (
+	WithReferencedIRSA          = "with referenced IRSA"
+	WithMountedIRSA             = "with mounted IRSA"
+	StaticCredentialsSecretName = "provider-secret"
+)
+
+func ReferencedIRSAStoreName(f *framework.Framework) string {
+	return "irsa-ref-" + f.Namespace.Name
+}
+
+func MountedIRSAStoreName(f *framework.Framework) string {
+	return "irsa-mounted-" + f.Namespace.Name
+}
+
+func UseClusterSecretStore(tc *framework.TestCase) {
+	tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.ClusterSecretStoreKind
+	tc.ExternalSecret.Spec.SecretStoreRef.Name = ReferencedIRSAStoreName(tc.Framework)
+}
+
+func UseMountedIRSAStore(tc *framework.TestCase) {
+	tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.SecretStoreKind
+	tc.ExternalSecret.Spec.SecretStoreRef.Name = MountedIRSAStoreName(tc.Framework)
+}
+
+// StaticStore is namespaced and references
+// static credentials from a secret.
+func SetupStaticStore(f *framework.Framework, kid, sak, region string, serviceType esv1alpha1.AWSServiceType) {
+	awsCreds := &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      StaticCredentialsSecretName,
+			Namespace: f.Namespace.Name,
+		},
+		StringData: map[string]string{
+			"kid": kid,
+			"sak": sak,
+		},
+	}
+	err := f.CRClient.Create(context.Background(), awsCreds)
+	Expect(err).ToNot(HaveOccurred())
+
+	secretStore := &esv1alpha1.SecretStore{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      f.Namespace.Name,
+			Namespace: f.Namespace.Name,
+		},
+		Spec: esv1alpha1.SecretStoreSpec{
+			Provider: &esv1alpha1.SecretStoreProvider{
+				AWS: &esv1alpha1.AWSProvider{
+					Service: serviceType,
+					Region:  region,
+					Auth: esv1alpha1.AWSAuth{
+						SecretRef: &esv1alpha1.AWSAuthSecretRef{
+							AccessKeyID: esmetav1.SecretKeySelector{
+								Name: StaticCredentialsSecretName,
+								Key:  "kid",
+							},
+							SecretAccessKey: esmetav1.SecretKeySelector{
+								Name: StaticCredentialsSecretName,
+								Key:  "sak",
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	err = f.CRClient.Create(context.Background(), secretStore)
+	Expect(err).ToNot(HaveOccurred())
+}

+ 45 - 0
e2e/suite/aws/parameterstore/parameterstore.go

@@ -0,0 +1,45 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package aws
+
+import (
+
+	// nolint
+	. "github.com/onsi/ginkgo/v2"
+
+	"github.com/external-secrets/external-secrets/e2e/framework"
+	"github.com/external-secrets/external-secrets/e2e/suite/common"
+)
+
+var _ = Describe("[aws] ", Label("aws", "parameterstore"), func() {
+	f := framework.New("eso-aws-ps")
+	prov := NewFromEnv(f)
+
+	DescribeTable("sync secrets",
+		framework.TableFunc(f,
+			prov),
+		Entry(common.SimpleDataSync(f)),
+		Entry(common.NestedJSONWithGJSON(f)),
+		Entry(common.JSONDataFromSync(f)),
+		Entry(common.JSONDataWithProperty(f)),
+		Entry(common.JSONDataWithTemplate(f)),
+		Entry(common.DockerJSONConfig(f)),
+		Entry(common.DataPropertyDockerconfigJSON(f)),
+		Entry(common.SSHKeySync(f)),
+		Entry(common.SSHKeySyncDataProperty(f)),
+		Entry(common.SyncWithoutTargetName(f)),
+		Entry(common.JSONDataWithoutTargetName(f)),
+	)
+})

+ 85 - 0
e2e/suite/aws/parameterstore/parameterstore_managed.go

@@ -0,0 +1,85 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package aws
+
+import (
+
+	// nolint
+	. "github.com/onsi/ginkgo/v2"
+
+	"github.com/external-secrets/external-secrets/e2e/framework"
+	"github.com/external-secrets/external-secrets/e2e/framework/addon"
+	awscommon "github.com/external-secrets/external-secrets/e2e/suite/aws"
+	"github.com/external-secrets/external-secrets/e2e/suite/common"
+)
+
+// here we use the global eso instance
+// that uses the service account in the default namespace
+// which was created by terraform.
+var _ = Describe("[awsmanaged] IRSA via referenced service account", Label("aws", "parameterstore", "managed"), func() {
+	f := framework.New("eso-aws-ps-managed")
+	prov := NewFromEnv(f)
+
+	// nolint
+	DescribeTable("sync secrets",
+		framework.TableFunc(f,
+			prov),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.SimpleDataSync, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.NestedJSONWithGJSON, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataFromSync, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithProperty, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithTemplate, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.DockerJSONConfig, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.DataPropertyDockerconfigJSON, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.SSHKeySync, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.SSHKeySyncDataProperty, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.SyncWithoutTargetName, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithoutTargetName, awscommon.UseClusterSecretStore),
+	)
+})
+
+// here we create a central eso instance in the default namespace
+// that mounts the service account which was created by terraform.
+var _ = Describe("[awsmanaged] with mounted IRSA", Label("aws", "parameterstore", "managed"), func() {
+	f := framework.New("eso-aws-ps-irsa-managed")
+	prov := NewFromEnv(f)
+
+	// each test case gets its own ESO instance
+	BeforeEach(func() {
+		f.Install(addon.NewESO(
+			addon.WithControllerClass(f.BaseName),
+			addon.WithServiceAccount(prov.ServiceAccountName),
+			addon.WithReleaseName(f.Namespace.Name),
+			addon.WithNamespace("default"),
+		))
+	})
+
+	// nolint
+	DescribeTable("sync secrets",
+		framework.TableFunc(f,
+			prov),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.SimpleDataSync, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.NestedJSONWithGJSON, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataFromSync, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithProperty, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithTemplate, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.DockerJSONConfig, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.DataPropertyDockerconfigJSON, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.SSHKeySync, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.SSHKeySyncDataProperty, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.SyncWithoutTargetName, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithoutTargetName, awscommon.UseMountedIRSAStore),
+	)
+})

+ 165 - 0
e2e/suite/aws/parameterstore/provider.go

@@ -0,0 +1,165 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package aws
+
+import (
+	"context"
+	"os"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/credentials"
+	"github.com/aws/aws-sdk-go/aws/session"
+	"github.com/aws/aws-sdk-go/service/ssm"
+
+	//nolint
+	. "github.com/onsi/ginkgo/v2"
+
+	// nolint
+	. "github.com/onsi/gomega"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	esmetav1 "github.com/external-secrets/external-secrets/apis/meta/v1"
+	"github.com/external-secrets/external-secrets/e2e/framework"
+	"github.com/external-secrets/external-secrets/e2e/framework/log"
+	common "github.com/external-secrets/external-secrets/e2e/suite/aws"
+)
+
+type Provider struct {
+	ServiceAccountName      string
+	ServiceAccountNamespace string
+
+	region    string
+	client    *ssm.SSM
+	framework *framework.Framework
+}
+
+func NewProvider(f *framework.Framework, kid, sak, region, saName, saNamespace string) *Provider {
+	sess, err := session.NewSessionWithOptions(session.Options{
+		Config: aws.Config{
+			Credentials: credentials.NewStaticCredentials(kid, sak, ""),
+			Region:      aws.String(region),
+		},
+	})
+	if err != nil {
+		Fail(err.Error())
+	}
+	sm := ssm.New(sess)
+	prov := &Provider{
+		ServiceAccountName:      saName,
+		ServiceAccountNamespace: saNamespace,
+		region:                  region,
+		client:                  sm,
+		framework:               f,
+	}
+
+	BeforeEach(func() {
+		common.SetupStaticStore(f, kid, sak, region, esv1alpha1.AWSServiceParameterStore)
+		prov.SetupReferencedIRSAStore()
+		prov.SetupMountedIRSAStore()
+	})
+
+	AfterEach(func() {
+		// Cleanup ClusterSecretStore
+		err := prov.framework.CRClient.Delete(context.Background(), &esv1alpha1.ClusterSecretStore{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: common.ReferencedIRSAStoreName(f),
+			},
+		})
+		Expect(err).ToNot(HaveOccurred())
+	})
+
+	return prov
+}
+
+func NewFromEnv(f *framework.Framework) *Provider {
+	kid := os.Getenv("AWS_ACCESS_KEY_ID")
+	sak := os.Getenv("AWS_SECRET_ACCESS_KEY")
+	region := "eu-west-1"
+	saName := os.Getenv("AWS_SA_NAME")
+	saNamespace := os.Getenv("AWS_SA_NAMESPACE")
+	return NewProvider(f, kid, sak, region, saName, saNamespace)
+}
+
+// CreateSecret creates a secret at the provider.
+func (s *Provider) CreateSecret(key, val string) {
+	_, err := s.client.PutParameter(&ssm.PutParameterInput{
+		Name:     aws.String(key),
+		Value:    aws.String(val),
+		DataType: aws.String("text"),
+		Type:     aws.String("String"),
+	})
+	Expect(err).ToNot(HaveOccurred())
+}
+
+// DeleteSecret deletes a secret at the provider.
+func (s *Provider) DeleteSecret(key string) {
+	_, err := s.client.DeleteParameter(&ssm.DeleteParameterInput{
+		Name: aws.String(key),
+	})
+	Expect(err).ToNot(HaveOccurred())
+}
+
+// MountedIRSAStore is a SecretStore without auth config
+// ESO relies on the pod-mounted ServiceAccount when using this store.
+func (s *Provider) SetupMountedIRSAStore() {
+	secretStore := &esv1alpha1.SecretStore{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      common.MountedIRSAStoreName(s.framework),
+			Namespace: s.framework.Namespace.Name,
+		},
+		Spec: esv1alpha1.SecretStoreSpec{
+			Provider: &esv1alpha1.SecretStoreProvider{
+				AWS: &esv1alpha1.AWSProvider{
+					Service: esv1alpha1.AWSServiceParameterStore,
+					Region:  s.region,
+					Auth:    esv1alpha1.AWSAuth{},
+				},
+			},
+		},
+	}
+	err := s.framework.CRClient.Create(context.Background(), secretStore)
+	Expect(err).ToNot(HaveOccurred())
+}
+
+// ReferncedIRSAStore is a ClusterStore
+// that references a (IRSA-) ServiceAccount in the default namespace.
+func (s *Provider) SetupReferencedIRSAStore() {
+	log.Logf("creating IRSA ClusterSecretStore %s", s.framework.Namespace.Name)
+	secretStore := &esv1alpha1.ClusterSecretStore{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: common.ReferencedIRSAStoreName(s.framework),
+		},
+	}
+	_, err := controllerutil.CreateOrUpdate(context.Background(), s.framework.CRClient, secretStore, func() error {
+		secretStore.Spec.Provider = &esv1alpha1.SecretStoreProvider{
+			AWS: &esv1alpha1.AWSProvider{
+				Service: esv1alpha1.AWSServiceParameterStore,
+				Region:  s.region,
+				Auth: esv1alpha1.AWSAuth{
+					JWTAuth: &esv1alpha1.AWSJWTAuth{
+						ServiceAccountRef: &esmetav1.ServiceAccountSelector{
+							Name:      s.ServiceAccountName,
+							Namespace: &s.ServiceAccountNamespace,
+						},
+					},
+				},
+			},
+		}
+		return nil
+	})
+	Expect(err).ToNot(HaveOccurred())
+}

+ 14 - 76
e2e/suite/aws/provider.go

@@ -29,7 +29,6 @@ import (
 
 
 	// nolint
 	// nolint
 	. "github.com/onsi/gomega"
 	. "github.com/onsi/gomega"
-	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 
 
@@ -37,24 +36,19 @@ import (
 	esmetav1 "github.com/external-secrets/external-secrets/apis/meta/v1"
 	esmetav1 "github.com/external-secrets/external-secrets/apis/meta/v1"
 	"github.com/external-secrets/external-secrets/e2e/framework"
 	"github.com/external-secrets/external-secrets/e2e/framework"
 	"github.com/external-secrets/external-secrets/e2e/framework/log"
 	"github.com/external-secrets/external-secrets/e2e/framework/log"
+	common "github.com/external-secrets/external-secrets/e2e/suite/aws"
 )
 )
 
 
-type SMProvider struct {
+type Provider struct {
 	ServiceAccountName      string
 	ServiceAccountName      string
 	ServiceAccountNamespace string
 	ServiceAccountNamespace string
 
 
-	kid       string
-	sak       string
 	region    string
 	region    string
 	client    *secretsmanager.SecretsManager
 	client    *secretsmanager.SecretsManager
 	framework *framework.Framework
 	framework *framework.Framework
 }
 }
 
 
-const (
-	staticCredentialsSecretName = "provider-secret"
-)
-
-func NewSMProvider(f *framework.Framework, kid, sak, region, saName, saNamespace string) *SMProvider {
+func NewProvider(f *framework.Framework, kid, sak, region, saName, saNamespace string) *Provider {
 	sess, err := session.NewSessionWithOptions(session.Options{
 	sess, err := session.NewSessionWithOptions(session.Options{
 		Config: aws.Config{
 		Config: aws.Config{
 			Credentials: credentials.NewStaticCredentials(kid, sak, ""),
 			Credentials: credentials.NewStaticCredentials(kid, sak, ""),
@@ -65,18 +59,16 @@ func NewSMProvider(f *framework.Framework, kid, sak, region, saName, saNamespace
 		Fail(err.Error())
 		Fail(err.Error())
 	}
 	}
 	sm := secretsmanager.New(sess)
 	sm := secretsmanager.New(sess)
-	prov := &SMProvider{
+	prov := &Provider{
 		ServiceAccountName:      saName,
 		ServiceAccountName:      saName,
 		ServiceAccountNamespace: saNamespace,
 		ServiceAccountNamespace: saNamespace,
-		kid:                     kid,
-		sak:                     sak,
 		region:                  region,
 		region:                  region,
 		client:                  sm,
 		client:                  sm,
 		framework:               f,
 		framework:               f,
 	}
 	}
 
 
 	BeforeEach(func() {
 	BeforeEach(func() {
-		prov.SetupStaticStore()
+		common.SetupStaticStore(f, kid, sak, region, esv1alpha1.AWSServiceSecretsManager)
 		prov.SetupReferencedIRSAStore()
 		prov.SetupReferencedIRSAStore()
 		prov.SetupMountedIRSAStore()
 		prov.SetupMountedIRSAStore()
 	})
 	})
@@ -85,7 +77,7 @@ func NewSMProvider(f *framework.Framework, kid, sak, region, saName, saNamespace
 		// Cleanup ClusterSecretStore
 		// Cleanup ClusterSecretStore
 		err := prov.framework.CRClient.Delete(context.Background(), &esv1alpha1.ClusterSecretStore{
 		err := prov.framework.CRClient.Delete(context.Background(), &esv1alpha1.ClusterSecretStore{
 			ObjectMeta: metav1.ObjectMeta{
 			ObjectMeta: metav1.ObjectMeta{
-				Name: prov.ReferencedIRSAStoreName(),
+				Name: common.ReferencedIRSAStoreName(f),
 			},
 			},
 		})
 		})
 		Expect(err).ToNot(HaveOccurred())
 		Expect(err).ToNot(HaveOccurred())
@@ -94,17 +86,17 @@ func NewSMProvider(f *framework.Framework, kid, sak, region, saName, saNamespace
 	return prov
 	return prov
 }
 }
 
 
-func NewFromEnv(f *framework.Framework) *SMProvider {
+func NewFromEnv(f *framework.Framework) *Provider {
 	kid := os.Getenv("AWS_ACCESS_KEY_ID")
 	kid := os.Getenv("AWS_ACCESS_KEY_ID")
 	sak := os.Getenv("AWS_SECRET_ACCESS_KEY")
 	sak := os.Getenv("AWS_SECRET_ACCESS_KEY")
 	region := "eu-west-1"
 	region := "eu-west-1"
 	saName := os.Getenv("AWS_SA_NAME")
 	saName := os.Getenv("AWS_SA_NAME")
 	saNamespace := os.Getenv("AWS_SA_NAMESPACE")
 	saNamespace := os.Getenv("AWS_SA_NAMESPACE")
-	return NewSMProvider(f, kid, sak, region, saName, saNamespace)
+	return NewProvider(f, kid, sak, region, saName, saNamespace)
 }
 }
 
 
 // CreateSecret creates a secret at the provider.
 // CreateSecret creates a secret at the provider.
-func (s *SMProvider) CreateSecret(key, val string) {
+func (s *Provider) CreateSecret(key, val string) {
 	// we re-use some secret names throughout our test suite
 	// we re-use some secret names throughout our test suite
 	// due to the fact that there is a short delay before the secret is actually deleted
 	// due to the fact that there is a short delay before the secret is actually deleted
 	// we have to retry creating the secret
 	// we have to retry creating the secret
@@ -129,7 +121,7 @@ func (s *SMProvider) CreateSecret(key, val string) {
 // DeleteSecret deletes a secret at the provider.
 // DeleteSecret deletes a secret at the provider.
 // There may be a short delay between calling this function
 // There may be a short delay between calling this function
 // and the removal of the secret on the provider side.
 // and the removal of the secret on the provider side.
-func (s *SMProvider) DeleteSecret(key string) {
+func (s *Provider) DeleteSecret(key string) {
 	log.Logf("deleting secret %s", key)
 	log.Logf("deleting secret %s", key)
 	_, err := s.client.DeleteSecret(&secretsmanager.DeleteSecretInput{
 	_, err := s.client.DeleteSecret(&secretsmanager.DeleteSecretInput{
 		SecretId:                   aws.String(key),
 		SecretId:                   aws.String(key),
@@ -140,10 +132,10 @@ func (s *SMProvider) DeleteSecret(key string) {
 
 
 // MountedIRSAStore is a SecretStore without auth config
 // MountedIRSAStore is a SecretStore without auth config
 // ESO relies on the pod-mounted ServiceAccount when using this store.
 // ESO relies on the pod-mounted ServiceAccount when using this store.
-func (s *SMProvider) SetupMountedIRSAStore() {
+func (s *Provider) SetupMountedIRSAStore() {
 	secretStore := &esv1alpha1.SecretStore{
 	secretStore := &esv1alpha1.SecretStore{
 		ObjectMeta: metav1.ObjectMeta{
 		ObjectMeta: metav1.ObjectMeta{
-			Name:      s.MountedIRSAStoreName(),
+			Name:      common.MountedIRSAStoreName(s.framework),
 			Namespace: s.framework.Namespace.Name,
 			Namespace: s.framework.Namespace.Name,
 		},
 		},
 		Spec: esv1alpha1.SecretStoreSpec{
 		Spec: esv1alpha1.SecretStoreSpec{
@@ -160,17 +152,13 @@ func (s *SMProvider) SetupMountedIRSAStore() {
 	Expect(err).ToNot(HaveOccurred())
 	Expect(err).ToNot(HaveOccurred())
 }
 }
 
 
-func (s *SMProvider) MountedIRSAStoreName() string {
-	return "irsa-mounted-" + s.framework.Namespace.Name
-}
-
 // ReferncedIRSAStore is a ClusterStore
 // ReferncedIRSAStore is a ClusterStore
 // that references a (IRSA-) ServiceAccount in the default namespace.
 // that references a (IRSA-) ServiceAccount in the default namespace.
-func (s *SMProvider) SetupReferencedIRSAStore() {
+func (s *Provider) SetupReferencedIRSAStore() {
 	log.Logf("creating IRSA ClusterSecretStore %s", s.framework.Namespace.Name)
 	log.Logf("creating IRSA ClusterSecretStore %s", s.framework.Namespace.Name)
 	secretStore := &esv1alpha1.ClusterSecretStore{
 	secretStore := &esv1alpha1.ClusterSecretStore{
 		ObjectMeta: metav1.ObjectMeta{
 		ObjectMeta: metav1.ObjectMeta{
-			Name: s.ReferencedIRSAStoreName(),
+			Name: common.ReferencedIRSAStoreName(s.framework),
 		},
 		},
 	}
 	}
 	_, err := controllerutil.CreateOrUpdate(context.Background(), s.framework.CRClient, secretStore, func() error {
 	_, err := controllerutil.CreateOrUpdate(context.Background(), s.framework.CRClient, secretStore, func() error {
@@ -192,53 +180,3 @@ func (s *SMProvider) SetupReferencedIRSAStore() {
 	})
 	})
 	Expect(err).ToNot(HaveOccurred())
 	Expect(err).ToNot(HaveOccurred())
 }
 }
-
-func (s *SMProvider) ReferencedIRSAStoreName() string {
-	return "irsa-ref-" + s.framework.Namespace.Name
-}
-
-// StaticStore is namespaced and references
-// static credentials from a secret.
-func (s *SMProvider) SetupStaticStore() {
-	awsCreds := &v1.Secret{
-		ObjectMeta: metav1.ObjectMeta{
-			Name:      staticCredentialsSecretName,
-			Namespace: s.framework.Namespace.Name,
-		},
-		StringData: map[string]string{
-			"kid": s.kid,
-			"sak": s.sak,
-		},
-	}
-	err := s.framework.CRClient.Create(context.Background(), awsCreds)
-	Expect(err).ToNot(HaveOccurred())
-
-	secretStore := &esv1alpha1.SecretStore{
-		ObjectMeta: metav1.ObjectMeta{
-			Name:      s.framework.Namespace.Name,
-			Namespace: s.framework.Namespace.Name,
-		},
-		Spec: esv1alpha1.SecretStoreSpec{
-			Provider: &esv1alpha1.SecretStoreProvider{
-				AWS: &esv1alpha1.AWSProvider{
-					Service: esv1alpha1.AWSServiceSecretsManager,
-					Region:  s.region,
-					Auth: esv1alpha1.AWSAuth{
-						SecretRef: &esv1alpha1.AWSAuthSecretRef{
-							AccessKeyID: esmetav1.SecretKeySelector{
-								Name: staticCredentialsSecretName,
-								Key:  "kid",
-							},
-							SecretAccessKey: esmetav1.SecretKeySelector{
-								Name: staticCredentialsSecretName,
-								Key:  "sak",
-							},
-						},
-					},
-				},
-			},
-		},
-	}
-	err = s.framework.CRClient.Create(context.Background(), secretStore)
-	Expect(err).ToNot(HaveOccurred())
-}

e2e/suite/aws/secretsmanager.go → e2e/suite/aws/secretsmanager/secretsmanager.go


+ 85 - 0
e2e/suite/aws/secretsmanager/secretsmanager_managed.go

@@ -0,0 +1,85 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package aws
+
+import (
+
+	// nolint
+	. "github.com/onsi/ginkgo/v2"
+
+	"github.com/external-secrets/external-secrets/e2e/framework"
+	"github.com/external-secrets/external-secrets/e2e/framework/addon"
+	awscommon "github.com/external-secrets/external-secrets/e2e/suite/aws"
+	"github.com/external-secrets/external-secrets/e2e/suite/common"
+)
+
+// here we use the global eso instance
+// that uses the service account in the default namespace
+// which was created by terraform.
+var _ = Describe("[awsmanaged] IRSA via referenced service account", Label("aws", "secretsmanager", "managed"), func() {
+	f := framework.New("eso-aws-managed")
+	prov := NewFromEnv(f)
+
+	// nolint
+	DescribeTable("sync secretsmanager secrets",
+		framework.TableFunc(f,
+			prov),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.SimpleDataSync, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.NestedJSONWithGJSON, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataFromSync, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithProperty, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithTemplate, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.DockerJSONConfig, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.DataPropertyDockerconfigJSON, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.SSHKeySync, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.SSHKeySyncDataProperty, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.SyncWithoutTargetName, awscommon.UseClusterSecretStore),
+		framework.Compose(awscommon.WithReferencedIRSA, f, common.JSONDataWithoutTargetName, awscommon.UseClusterSecretStore),
+	)
+})
+
+// here we create a central eso instance in the default namespace
+// that mounts the service account which was created by terraform.
+var _ = Describe("[awsmanaged] with mounted IRSA", Label("aws", "secretsmanager", "managed"), func() {
+	f := framework.New("eso-aws-managed")
+	prov := NewFromEnv(f)
+
+	// each test case gets its own ESO instance
+	BeforeEach(func() {
+		f.Install(addon.NewESO(
+			addon.WithControllerClass(f.BaseName),
+			addon.WithServiceAccount(prov.ServiceAccountName),
+			addon.WithReleaseName(f.Namespace.Name),
+			addon.WithNamespace("default"),
+		))
+	})
+
+	// nolint
+	DescribeTable("sync secretsmanager secrets",
+		framework.TableFunc(f,
+			prov),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.SimpleDataSync, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.NestedJSONWithGJSON, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataFromSync, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithProperty, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithTemplate, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.DockerJSONConfig, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.DataPropertyDockerconfigJSON, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.SSHKeySync, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.SSHKeySyncDataProperty, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.SyncWithoutTargetName, awscommon.UseMountedIRSAStore),
+		framework.Compose(awscommon.WithMountedIRSA, f, common.JSONDataWithoutTargetName, awscommon.UseMountedIRSAStore),
+	)
+})

+ 0 - 102
e2e/suite/aws/secretsmanager_managed.go

@@ -1,102 +0,0 @@
-/*
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package aws
-
-import (
-
-	// nolint
-	. "github.com/onsi/ginkgo/v2"
-
-	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
-	"github.com/external-secrets/external-secrets/e2e/framework"
-	"github.com/external-secrets/external-secrets/e2e/framework/addon"
-	"github.com/external-secrets/external-secrets/e2e/suite/common"
-)
-
-const (
-	withReferencedIRSA = "with referenced IRSA"
-	withMountedIRSA    = "with mounted IRSA"
-)
-
-// here we use the global eso instance
-// that uses the service account in the default namespace
-// which was created by terraform.
-var _ = Describe("[awsmanaged] IRSA via referenced service account", Label("aws", "secretsmanager", "managed"), func() {
-	f := framework.New("eso-aws-managed")
-	prov := NewFromEnv(f)
-
-	DescribeTable("sync secrets",
-		framework.TableFunc(f,
-			prov),
-		framework.Compose(withReferencedIRSA, f, common.SimpleDataSync, useClusterSecretStore(prov)),
-		framework.Compose(withReferencedIRSA, f, common.NestedJSONWithGJSON, useClusterSecretStore(prov)),
-		framework.Compose(withReferencedIRSA, f, common.JSONDataFromSync, useClusterSecretStore(prov)),
-		framework.Compose(withReferencedIRSA, f, common.JSONDataWithProperty, useClusterSecretStore(prov)),
-		framework.Compose(withReferencedIRSA, f, common.JSONDataWithTemplate, useClusterSecretStore(prov)),
-		framework.Compose(withReferencedIRSA, f, common.DockerJSONConfig, useClusterSecretStore(prov)),
-		framework.Compose(withReferencedIRSA, f, common.DataPropertyDockerconfigJSON, useClusterSecretStore(prov)),
-		framework.Compose(withReferencedIRSA, f, common.SSHKeySync, useClusterSecretStore(prov)),
-		framework.Compose(withReferencedIRSA, f, common.SSHKeySyncDataProperty, useClusterSecretStore(prov)),
-		framework.Compose(withReferencedIRSA, f, common.SyncWithoutTargetName, useClusterSecretStore(prov)),
-		framework.Compose(withReferencedIRSA, f, common.JSONDataWithoutTargetName, useClusterSecretStore(prov)),
-	)
-})
-
-// here we create a central eso instance in the default namespace
-// that mounts the service account which was created by terraform.
-var _ = Describe("[awsmanaged] with mounted IRSA", Label("aws", "secretsmanager", "managed"), func() {
-	f := framework.New("eso-aws-managed")
-	prov := NewFromEnv(f)
-
-	// each test case gets its own ESO instance
-	BeforeEach(func() {
-		f.Install(addon.NewESO(
-			addon.WithControllerClass(f.BaseName),
-			addon.WithServiceAccount(prov.ServiceAccountName),
-			addon.WithReleaseName(f.Namespace.Name),
-			addon.WithNamespace("default"),
-		))
-	})
-
-	DescribeTable("sync secrets",
-		framework.TableFunc(f,
-			prov),
-		framework.Compose(withMountedIRSA, f, common.SimpleDataSync, useMountedIRSAStore(prov)),
-		framework.Compose(withMountedIRSA, f, common.NestedJSONWithGJSON, useMountedIRSAStore(prov)),
-		framework.Compose(withMountedIRSA, f, common.JSONDataFromSync, useMountedIRSAStore(prov)),
-		framework.Compose(withMountedIRSA, f, common.JSONDataWithProperty, useMountedIRSAStore(prov)),
-		framework.Compose(withMountedIRSA, f, common.JSONDataWithTemplate, useMountedIRSAStore(prov)),
-		framework.Compose(withMountedIRSA, f, common.DockerJSONConfig, useMountedIRSAStore(prov)),
-		framework.Compose(withMountedIRSA, f, common.DataPropertyDockerconfigJSON, useMountedIRSAStore(prov)),
-		framework.Compose(withMountedIRSA, f, common.SSHKeySync, useMountedIRSAStore(prov)),
-		framework.Compose(withMountedIRSA, f, common.SSHKeySyncDataProperty, useMountedIRSAStore(prov)),
-		framework.Compose(withMountedIRSA, f, common.SyncWithoutTargetName, useMountedIRSAStore(prov)),
-		framework.Compose(withMountedIRSA, f, common.JSONDataWithoutTargetName, useMountedIRSAStore(prov)),
-	)
-})
-
-func useClusterSecretStore(prov *SMProvider) func(*framework.TestCase) {
-	return func(tc *framework.TestCase) {
-		tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.ClusterSecretStoreKind
-		tc.ExternalSecret.Spec.SecretStoreRef.Name = prov.ReferencedIRSAStoreName()
-	}
-}
-
-func useMountedIRSAStore(prov *SMProvider) func(*framework.TestCase) {
-	return func(tc *framework.TestCase) {
-		tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.SecretStoreKind
-		tc.ExternalSecret.Spec.SecretStoreRef.Name = prov.MountedIRSAStoreName()
-	}
-}

+ 2 - 1
e2e/suite/import.go

@@ -16,7 +16,8 @@ package suite
 import (
 import (
 
 
 	// import different e2e test suites.
 	// import different e2e test suites.
-	_ "github.com/external-secrets/external-secrets/e2e/suite/aws"
+	_ "github.com/external-secrets/external-secrets/e2e/suite/aws/parameterstore"
+	_ "github.com/external-secrets/external-secrets/e2e/suite/aws/secretsmanager"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/azure"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/azure"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/gcp"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/gcp"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/vault"
 	_ "github.com/external-secrets/external-secrets/e2e/suite/vault"

+ 1 - 3
pkg/controllers/externalsecret/externalsecret_controller_template.go

@@ -64,9 +64,7 @@ func (r *Reconciler) applyTemplate(ctx context.Context, es *esv1alpha1.ExternalS
 	// if no data was provided by template fallback
 	// if no data was provided by template fallback
 	// to value from the provider
 	// to value from the provider
 	if len(es.Spec.Target.Template.Data) == 0 {
 	if len(es.Spec.Target.Template.Data) == 0 {
-		for k, v := range dataMap {
-			secret.Data[k] = v
-		}
+		secret.Data = dataMap
 	}
 	}
 	secret.Annotations[esv1alpha1.AnnotationDataHash] = utils.ObjectHash(secret.Data)
 	secret.Annotations[esv1alpha1.AnnotationDataHash] = utils.ObjectHash(secret.Data)
 
 

+ 81 - 0
pkg/controllers/externalsecret/externalsecret_controller_test.go

@@ -658,6 +658,85 @@ var _ = Describe("ExternalSecret controller", func() {
 		}
 		}
 	}
 	}
 
 
+	// when a provider secret was deleted it must be deleted from
+	// the secret aswell
+	refreshSecretValueMap := func(tc *testCase) {
+		fakeProvider.WithGetSecretMap(map[string][]byte{
+			"foo": []byte("1111"),
+			"bar": []byte("2222"),
+		}, nil)
+		tc.externalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{}
+		tc.externalSecret.Spec.DataFrom = []esv1alpha1.ExternalSecretDataRemoteRef{
+			{
+				Key: remoteKey,
+			},
+		}
+		tc.externalSecret.Spec.RefreshInterval = &metav1.Duration{Duration: time.Second}
+		tc.checkSecret = func(es *esv1alpha1.ExternalSecret, secret *v1.Secret) {
+			// check values
+			Expect(string(secret.Data["foo"])).To(Equal("1111"))
+			Expect(string(secret.Data["bar"])).To(Equal("2222"))
+
+			// update provider secret
+			sec := &v1.Secret{}
+			fakeProvider.WithGetSecretMap(map[string][]byte{
+				"foo": []byte("1111"),
+			}, nil)
+			secretLookupKey := types.NamespacedName{
+				Name:      ExternalSecretTargetSecretName,
+				Namespace: ExternalSecretNamespace,
+			}
+			Eventually(func() bool {
+				err := k8sClient.Get(context.Background(), secretLookupKey, sec)
+				if err != nil {
+					return false
+				}
+				return string(sec.Data["foo"]) == "1111" &&
+					sec.Data["bar"] == nil // must not be defined, it was deleted
+			}, timeout, interval).Should(BeTrue())
+		}
+	}
+
+	// when a provider secret was deleted it must be deleted from
+	// the secret aswell when using a template
+	refreshSecretValueMapTemplate := func(tc *testCase) {
+		fakeProvider.WithGetSecretMap(map[string][]byte{
+			"foo": []byte("1111"),
+			"bar": []byte("2222"),
+		}, nil)
+		tc.externalSecret.Spec.Target.Template = &esv1alpha1.ExternalSecretTemplate{}
+		tc.externalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{}
+		tc.externalSecret.Spec.DataFrom = []esv1alpha1.ExternalSecretDataRemoteRef{
+			{
+				Key: remoteKey,
+			},
+		}
+		tc.externalSecret.Spec.RefreshInterval = &metav1.Duration{Duration: time.Second}
+		tc.checkSecret = func(es *esv1alpha1.ExternalSecret, secret *v1.Secret) {
+			// check values
+			Expect(string(secret.Data["foo"])).To(Equal("1111"))
+			Expect(string(secret.Data["bar"])).To(Equal("2222"))
+
+			// update provider secret
+			sec := &v1.Secret{}
+			fakeProvider.WithGetSecretMap(map[string][]byte{
+				"foo": []byte("1111"),
+			}, nil)
+			secretLookupKey := types.NamespacedName{
+				Name:      ExternalSecretTargetSecretName,
+				Namespace: ExternalSecretNamespace,
+			}
+			Eventually(func() bool {
+				err := k8sClient.Get(context.Background(), secretLookupKey, sec)
+				if err != nil {
+					return false
+				}
+				return string(sec.Data["foo"]) == "1111" &&
+					sec.Data["bar"] == nil // must not be defined, it was deleted
+			}, timeout, interval).Should(BeTrue())
+		}
+	}
+
 	refreshintervalZero := func(tc *testCase) {
 	refreshintervalZero := func(tc *testCase) {
 		const targetProp = "targetProperty"
 		const targetProp = "targetProperty"
 		const secretVal = "someValue"
 		const secretVal = "someValue"
@@ -979,6 +1058,8 @@ var _ = Describe("ExternalSecret controller", func() {
 		Entry("should refresh secret from template", refreshWithTemplate),
 		Entry("should refresh secret from template", refreshWithTemplate),
 		Entry("should be able to use only metadata from template", onlyMetadataFromTemplate),
 		Entry("should be able to use only metadata from template", onlyMetadataFromTemplate),
 		Entry("should refresh secret value when provider secret changes", refreshSecretValue),
 		Entry("should refresh secret value when provider secret changes", refreshSecretValue),
+		Entry("should refresh secret map when provider secret changes", refreshSecretValueMap),
+		Entry("should refresh secret map when provider secret changes when using a template", refreshSecretValueMapTemplate),
 		Entry("should not refresh secret value when provider secret changes but refreshInterval is zero", refreshintervalZero),
 		Entry("should not refresh secret value when provider secret changes but refreshInterval is zero", refreshintervalZero),
 		Entry("should fetch secret using dataFrom", syncWithDataFrom),
 		Entry("should fetch secret using dataFrom", syncWithDataFrom),
 		Entry("should fetch secret using dataFrom and a template", syncWithDataFromTemplate),
 		Entry("should fetch secret using dataFrom and a template", syncWithDataFromTemplate),

+ 57 - 0
pkg/controllers/externalsecret/metrics.go

@@ -16,6 +16,7 @@ package externalsecret
 
 
 import (
 import (
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus"
+	v1 "k8s.io/api/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/metrics"
 	"sigs.k8s.io/controller-runtime/pkg/metrics"
 
 
 	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
 	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
@@ -50,6 +51,62 @@ var (
 
 
 // updateExternalSecretCondition updates the ExternalSecret conditions.
 // updateExternalSecretCondition updates the ExternalSecret conditions.
 func updateExternalSecretCondition(es *esv1alpha1.ExternalSecret, condition *esv1alpha1.ExternalSecretStatusCondition, value float64) {
 func updateExternalSecretCondition(es *esv1alpha1.ExternalSecret, condition *esv1alpha1.ExternalSecretStatusCondition, value float64) {
+	switch condition.Type {
+	case esv1alpha1.ExternalSecretDeleted:
+		// Remove condition=Ready metrics when the object gets deleted.
+		externalSecretCondition.Delete(prometheus.Labels{
+			"name":      es.Name,
+			"namespace": es.Namespace,
+			"condition": string(esv1alpha1.ExternalSecretReady),
+			"status":    string(v1.ConditionFalse),
+		})
+		externalSecretCondition.Delete(prometheus.Labels{
+			"name":      es.Name,
+			"namespace": es.Namespace,
+			"condition": string(esv1alpha1.ExternalSecretReady),
+			"status":    string(v1.ConditionTrue),
+		})
+
+	case esv1alpha1.ExternalSecretReady:
+		// Remove condition=Deleted metrics when the object gets ready.
+		externalSecretCondition.Delete(prometheus.Labels{
+			"name":      es.Name,
+			"namespace": es.Namespace,
+			"condition": string(esv1alpha1.ExternalSecretDeleted),
+			"status":    string(v1.ConditionFalse),
+		})
+		externalSecretCondition.Delete(prometheus.Labels{
+			"name":      es.Name,
+			"namespace": es.Namespace,
+			"condition": string(esv1alpha1.ExternalSecretDeleted),
+			"status":    string(v1.ConditionTrue),
+		})
+		// Toggle opposite Status to 0
+		switch condition.Status {
+		case v1.ConditionFalse:
+			externalSecretCondition.With(prometheus.Labels{
+				"name":      es.Name,
+				"namespace": es.Namespace,
+				"condition": string(esv1alpha1.ExternalSecretReady),
+				"status":    string(v1.ConditionTrue),
+			}).Set(0)
+		case v1.ConditionTrue:
+			externalSecretCondition.With(prometheus.Labels{
+				"name":      es.Name,
+				"namespace": es.Namespace,
+				"condition": string(esv1alpha1.ExternalSecretReady),
+				"status":    string(v1.ConditionFalse),
+			}).Set(0)
+		case v1.ConditionUnknown:
+			break
+		default:
+			break
+		}
+
+	default:
+		break
+	}
+
 	externalSecretCondition.With(prometheus.Labels{
 	externalSecretCondition.With(prometheus.Labels{
 		"name":      es.Name,
 		"name":      es.Name,
 		"namespace": es.Namespace,
 		"namespace": es.Namespace,

+ 3 - 1
pkg/provider/webhook/webhook_test.go

@@ -300,7 +300,9 @@ func testGetSecret(tc testCase, t *testing.T, client provider.SecretsClient) {
 		Key:     tc.Args.Key,
 		Key:     tc.Args.Key,
 		Version: tc.Args.Version,
 		Version: tc.Args.Version,
 	}
 	}
-	secret, err := client.GetSecret(context.Background(), testRef)
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+	secret, err := client.GetSecret(ctx, testRef)
 	errStr := ""
 	errStr := ""
 	if err != nil {
 	if err != nil {
 		errStr = err.Error()
 		errStr = err.Error()

+ 19 - 0
terraform/aws/modules/cluster/irsa.tf

@@ -37,6 +37,25 @@ resource "aws_iam_role" "eso-e2e-irsa" {
     "arn:aws:iam::aws:policy/SecretsManagerReadWrite"
     "arn:aws:iam::aws:policy/SecretsManagerReadWrite"
   ]
   ]
 
 
+  inline_policy {
+    name = "aws_ssm_parameterstore"
+
+    policy = jsonencode({
+      Version = "2012-10-17"
+      Statement = [
+        {
+          Action = [
+            "ssm:GetParameter",
+            "ssm:PutParameter",
+          ]
+          Effect   = "Allow"
+          Resource = "*"
+        },
+      ]
+    })
+  }
+
+
 }
 }
 
 
 resource "null_resource" "apply_sa" {
 resource "null_resource" "apply_sa" {