From 8c5973f93b53af2bc366815c17cf22d22f137d55 Mon Sep 17 00:00:00 2001 From: emmajiafan Date: Wed, 24 Dec 2025 20:14:59 +0800 Subject: [PATCH] add the eso aws test cases remove the ssm related update the region update the vendor rmove the ai generate scripts --- test/e2e/e2e_test.go | 424 +++++++++++++++++- .../testdata/aws_external_secret_binary.yaml | 21 + .../aws_external_secret_datafrom.yaml | 19 + .../aws_external_secret_jsonpath.yaml | 21 + .../aws_external_secret_multi_key.yaml | 29 ++ .../testdata/aws_external_secret_refresh.yaml | 21 + .../aws_external_secret_template.yaml | 32 ++ .../testdata/aws_invalid_secret_store.yaml | 23 + .../testdata/aws_k8s_secret_multi_key.yaml | 13 + test/e2e/testdata/aws_secret_store.yaml | 2 +- .../testdata/aws_secret_store_namespace.yaml | 20 + .../e2e/testdata/aws_ssm_external_secret.yaml | 20 + test/e2e/testdata/aws_ssm_secret_store.yaml | 22 + test/utils/conditions.go | 58 ++- 14 files changed, 721 insertions(+), 4 deletions(-) create mode 100644 test/e2e/testdata/aws_external_secret_binary.yaml create mode 100644 test/e2e/testdata/aws_external_secret_datafrom.yaml create mode 100644 test/e2e/testdata/aws_external_secret_jsonpath.yaml create mode 100644 test/e2e/testdata/aws_external_secret_multi_key.yaml create mode 100644 test/e2e/testdata/aws_external_secret_refresh.yaml create mode 100644 test/e2e/testdata/aws_external_secret_template.yaml create mode 100644 test/e2e/testdata/aws_invalid_secret_store.yaml create mode 100644 test/e2e/testdata/aws_k8s_secret_multi_key.yaml create mode 100644 test/e2e/testdata/aws_secret_store_namespace.yaml create mode 100644 test/e2e/testdata/aws_ssm_external_secret.yaml create mode 100644 test/e2e/testdata/aws_ssm_secret_store.yaml diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 2a6a61fa3..4c39d73a5 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -22,6 +22,7 @@ import ( "context" "embed" "encoding/base64" + "encoding/json" "fmt" "testing" "time" @@ -65,6 +66,7 @@ const ( clusterSecretStoresKind = "clustersecretstores" PushSecretsKind = "pushsecrets" externalSecretsKind = "externalsecrets" + awsSecretRegionName = "ap-south-1" ) var _ = Describe("External Secrets Operator End-to-End test scenarios", Ordered, func() { @@ -139,7 +141,6 @@ var _ = Describe("External Secrets Operator End-to-End test scenarios", Ordered, awsSecretNamePattern = "${AWS_SECRET_KEY_NAME}" awsSecretValuePattern = "${SECRET_VALUE}" awsClusterSecretStoreNamePattern = "${CLUSTERSECRETSTORE_NAME}" - awsSecretRegionName = "ap-south-1" ) AfterAll(func() { @@ -171,7 +172,10 @@ var _ = Describe("External Secrets Operator End-to-End test scenarios", Ordered, defer loader.DeleteFromFile(testassets.ReadFile, awsSecretToPushFile, testNamespace) By("Creating ClusterSecretStore") - cssAssetFunc := utils.ReplacePatternInAsset(awsClusterSecretStoreNamePattern, clusterSecretStoreResourceName) + cssAssetFunc := utils.ReplacePatternInAsset( + awsClusterSecretStoreNamePattern, clusterSecretStoreResourceName, + "${AWS_REGION}", awsSecretRegionName, + ) loader.CreateFromFile(cssAssetFunc, clusterSecretStoreFile, testNamespace) defer loader.DeleteFromFile(cssAssetFunc, clusterSecretStoreFile, testNamespace) @@ -227,4 +231,420 @@ var _ = Describe("External Secrets Operator End-to-End test scenarios", Ordered, }, time.Minute, 10*time.Second).Should(Succeed()) }) }) + + Context("Basic Operations", Label("Platform:AWS"), func() { + It("should work with namespace-scoped SecretStore", func() { + secretStoreName := fmt.Sprintf("aws-secret-store-ns-%s", utils.GetRandomString(5)) + awsSecretName := fmt.Sprintf("eso-e2e-secret-ns-%s", utils.GetRandomString(5)) + secretValue := `{"value":"test-namespace-scoped-secret"}` + + defer func() { + By("Cleaning up AWS secret") + Expect(utils.DeleteAWSSecret(ctx, clientset, awsSecretName, awsSecretRegionName)). + NotTo(HaveOccurred()) + }() + + By("Creating AWS secret") + Expect(utils.CreateAWSSecret(ctx, clientset, awsSecretName, secretValue, awsSecretRegionName)). + NotTo(HaveOccurred()) + + By("Copying AWS credentials to test namespace") + awsCreds, err := clientset.CoreV1().Secrets("kube-system").Get(ctx, "aws-creds", metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + + awsCredsSecretName := fmt.Sprintf("aws-creds-ns-%s", utils.GetRandomString(5)) + namespacedCreds := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: awsCredsSecretName, + Namespace: testNamespace, + }, + Data: awsCreds.Data, + } + _, err = clientset.CoreV1().Secrets(testNamespace).Create(ctx, namespacedCreds, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + defer clientset.CoreV1().Secrets(testNamespace).Delete(ctx, awsCredsSecretName, metav1.DeleteOptions{}) + + By("Creating namespace-scoped SecretStore") + storeAssetFunc := utils.ReplacePatternInAsset( + "${SECRETSTORE_NAME}", secretStoreName, + "${SECRETNAME}", awsCredsSecretName, + "${AWS_REGION}", awsSecretRegionName, + ) + loader.CreateFromFile(storeAssetFunc, "testdata/aws_secret_store_namespace.yaml", testNamespace) + defer loader.DeleteFromFile(storeAssetFunc, "testdata/aws_secret_store_namespace.yaml", testNamespace) + + By("Waiting for SecretStore to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: "secretstores", + }, + testNamespace, secretStoreName, time.Minute, + )).To(Succeed()) + + By("Creating ExternalSecret") + esAssetFunc := utils.ReplacePatternInAsset( + "${SECRETSTORE_NAME}", secretStoreName, + "${SECRETSTORE_KIND}", "SecretStore", + "${AWS_SECRET_KEY_NAME}", awsSecretName, + ) + loader.CreateFromFile(esAssetFunc, "testdata/aws_external_secret_datafrom.yaml", testNamespace) + defer loader.DeleteFromFile(testassets.ReadFile, "testdata/aws_external_secret_datafrom.yaml", testNamespace) + + By("Waiting for ExternalSecret to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: externalSecretsKind, + }, + testNamespace, "aws-external-secret-datafrom", time.Minute, + )).To(Succeed()) + + By("Verifying target secret contains the data") + Eventually(func(g Gomega) { + secret, err := loader.KubeClient.CoreV1().Secrets(testNamespace).Get(ctx, "aws-secret-datafrom", metav1.GetOptions{}) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(secret.Data).To(HaveKey("value")) + g.Expect(string(secret.Data["value"])).To(Equal("test-namespace-scoped-secret")) + }, time.Minute, 10*time.Second).Should(Succeed()) + }) + + It("should handle binary data correctly", func() { + awsSecretName := fmt.Sprintf("eso-e2e-secret-binary-%s", utils.GetRandomString(5)) + secretStoreName := fmt.Sprintf("aws-secret-store-%s", utils.GetRandomString(5)) + binaryData := []byte("binary-test-data-12345") + encodedData := base64.StdEncoding.EncodeToString(binaryData) + secretValue := fmt.Sprintf(`{"binary_data":"%s"}`, encodedData) + + defer func() { + By("Cleaning up AWS secret") + Expect(utils.DeleteAWSSecret(ctx, clientset, awsSecretName, awsSecretRegionName)). + NotTo(HaveOccurred()) + }() + + By("Creating AWS secret with binary data") + Expect(utils.CreateAWSSecret(ctx, clientset, awsSecretName, secretValue, awsSecretRegionName)). + NotTo(HaveOccurred()) + + By("Creating ClusterSecretStore") + cssAssetFunc := utils.ReplacePatternInAsset( + "${CLUSTERSECRETSTORE_NAME}", secretStoreName, + "${AWS_REGION}", awsSecretRegionName, + ) + loader.CreateFromFile(cssAssetFunc, "testdata/aws_secret_store.yaml", testNamespace) + defer loader.DeleteFromFile(cssAssetFunc, "testdata/aws_secret_store.yaml", testNamespace) + + By("Waiting for ClusterSecretStore to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: clusterSecretStoresKind, + }, + "", secretStoreName, time.Minute, + )).To(Succeed()) + + By("Creating ExternalSecret for binary data") + esAssetFunc := utils.ReplacePatternInAsset( + "${SECRETSTORE_NAME}", secretStoreName, + "${SECRETSTORE_KIND}", "ClusterSecretStore", + "${AWS_SECRET_KEY_NAME}", awsSecretName, + ) + loader.CreateFromFile(esAssetFunc, "testdata/aws_external_secret_binary.yaml", testNamespace) + defer loader.DeleteFromFile(testassets.ReadFile, "testdata/aws_external_secret_binary.yaml", testNamespace) + + By("Waiting for ExternalSecret to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: externalSecretsKind, + }, + testNamespace, "aws-external-secret-binary", time.Minute, + )).To(Succeed()) + + By("Verifying binary data is correctly decoded") + Eventually(func(g Gomega) { + secret, err := loader.KubeClient.CoreV1().Secrets(testNamespace).Get(ctx, "aws-secret-binary", metav1.GetOptions{}) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(secret.Data).To(HaveKey("binary_data")) + g.Expect(string(secret.Data["binary_data"])).To(Equal(encodedData)) + }, time.Minute, 10*time.Second).Should(Succeed()) + }) + }) + + Context("Advanced Features", Label("Platform:AWS"), func() { + It("should refresh secret when AWS secret is updated", func() { + awsSecretName := fmt.Sprintf("eso-e2e-secret-refresh-%s", utils.GetRandomString(5)) + secretStoreName := fmt.Sprintf("aws-secret-store-%s", utils.GetRandomString(5)) + initialValue := `{"value":"initial-value"}` + updatedValue := `{"value":"updated-value"}` + + defer func() { + By("Cleaning up AWS secret") + Expect(utils.DeleteAWSSecret(ctx, clientset, awsSecretName, awsSecretRegionName)). + NotTo(HaveOccurred()) + }() + + By("Creating AWS secret with initial value") + Expect(utils.CreateAWSSecret(ctx, clientset, awsSecretName, initialValue, awsSecretRegionName)). + NotTo(HaveOccurred()) + + By("Creating ClusterSecretStore") + cssAssetFunc := utils.ReplacePatternInAsset( + "${CLUSTERSECRETSTORE_NAME}", secretStoreName, + "${AWS_REGION}", awsSecretRegionName, + ) + loader.CreateFromFile(cssAssetFunc, "testdata/aws_secret_store.yaml", testNamespace) + defer loader.DeleteFromFile(cssAssetFunc, "testdata/aws_secret_store.yaml", testNamespace) + + By("Waiting for ClusterSecretStore to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: clusterSecretStoresKind, + }, + "", secretStoreName, time.Minute, + )).To(Succeed()) + + By("Creating ExternalSecret with short refresh interval") + esAssetFunc := utils.ReplacePatternInAsset( + "${SECRETSTORE_NAME}", secretStoreName, + "${SECRETSTORE_KIND}", "ClusterSecretStore", + "${AWS_SECRET_KEY_NAME}", awsSecretName, + ) + loader.CreateFromFile(esAssetFunc, "testdata/aws_external_secret_refresh.yaml", testNamespace) + defer loader.DeleteFromFile(testassets.ReadFile, "testdata/aws_external_secret_refresh.yaml", testNamespace) + + By("Waiting for ExternalSecret to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: externalSecretsKind, + }, + testNamespace, "aws-external-secret-refresh", time.Minute, + )).To(Succeed()) + + By("Verifying initial value") + Eventually(func(g Gomega) { + secret, err := loader.KubeClient.CoreV1().Secrets(testNamespace).Get(ctx, "aws-secret-refresh", metav1.GetOptions{}) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(secret.Data).To(HaveKey("refresh_value")) + g.Expect(string(secret.Data["refresh_value"])).To(Equal("initial-value")) + }, time.Minute, 10*time.Second).Should(Succeed()) + + By("Updating AWS secret") + Expect(utils.UpdateAWSSecret(ctx, clientset, awsSecretName, updatedValue, awsSecretRegionName)). + NotTo(HaveOccurred()) + + By("Waiting for secret to be refreshed (30s refresh interval + buffer)") + Eventually(func(g Gomega) { + secret, err := loader.KubeClient.CoreV1().Secrets(testNamespace).Get(ctx, "aws-secret-refresh", metav1.GetOptions{}) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(secret.Data).To(HaveKey("refresh_value")) + g.Expect(string(secret.Data["refresh_value"])).To(Equal("updated-value")) + }, 2*time.Minute, 10*time.Second).Should(Succeed()) + }) + + It("should apply template transformation to secret data", func() { + awsSecretName := fmt.Sprintf("eso-e2e-secret-template-%s", utils.GetRandomString(5)) + secretStoreName := fmt.Sprintf("aws-secret-store-%s", utils.GetRandomString(5)) + secretValue := `{"username":"testuser","password":"testpass123"}` + + defer func() { + By("Cleaning up AWS secret") + Expect(utils.DeleteAWSSecret(ctx, clientset, awsSecretName, awsSecretRegionName)). + NotTo(HaveOccurred()) + }() + + By("Creating AWS secret") + Expect(utils.CreateAWSSecret(ctx, clientset, awsSecretName, secretValue, awsSecretRegionName)). + NotTo(HaveOccurred()) + + By("Creating ClusterSecretStore") + cssAssetFunc := utils.ReplacePatternInAsset( + "${CLUSTERSECRETSTORE_NAME}", secretStoreName, + "${AWS_REGION}", awsSecretRegionName, + ) + loader.CreateFromFile(cssAssetFunc, "testdata/aws_secret_store.yaml", testNamespace) + defer loader.DeleteFromFile(cssAssetFunc, "testdata/aws_secret_store.yaml", testNamespace) + + By("Waiting for ClusterSecretStore to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: clusterSecretStoresKind, + }, + "", secretStoreName, time.Minute, + )).To(Succeed()) + + By("Creating ExternalSecret with template") + esAssetFunc := utils.ReplacePatternInAsset( + "${SECRETSTORE_NAME}", secretStoreName, + "${SECRETSTORE_KIND}", "ClusterSecretStore", + "${AWS_SECRET_KEY_NAME}", awsSecretName, + ) + loader.CreateFromFile(esAssetFunc, "testdata/aws_external_secret_template.yaml", testNamespace) + defer loader.DeleteFromFile(testassets.ReadFile, "testdata/aws_external_secret_template.yaml", testNamespace) + + By("Waiting for ExternalSecret to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: externalSecretsKind, + }, + testNamespace, "aws-external-secret-template", time.Minute, + )).To(Succeed()) + + By("Verifying template transformation applied") + expectedConfig := "database:\n username: testuser\n password: testpass123\n" + Eventually(func(g Gomega) { + secret, err := loader.KubeClient.CoreV1().Secrets(testNamespace).Get(ctx, "aws-secret-template", metav1.GetOptions{}) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(secret.Data).To(HaveKey("config.yaml")) + g.Expect(string(secret.Data["config.yaml"])).To(Equal(expectedConfig)) + }, time.Minute, 10*time.Second).Should(Succeed()) + }) + + It("should fetch entire secret using dataFrom", func() { + awsSecretName := fmt.Sprintf("eso-e2e-secret-datafrom-%s", utils.GetRandomString(5)) + secretStoreName := fmt.Sprintf("aws-secret-store-%s", utils.GetRandomString(5)) + secretValue := `{"api_key":"key123","api_secret":"secret456","endpoint":"https://api.example.com"}` + + defer func() { + By("Cleaning up AWS secret") + Expect(utils.DeleteAWSSecret(ctx, clientset, awsSecretName, awsSecretRegionName)). + NotTo(HaveOccurred()) + }() + + By("Creating AWS secret with multiple fields") + Expect(utils.CreateAWSSecret(ctx, clientset, awsSecretName, secretValue, awsSecretRegionName)). + NotTo(HaveOccurred()) + + By("Creating ClusterSecretStore") + cssAssetFunc := utils.ReplacePatternInAsset( + "${CLUSTERSECRETSTORE_NAME}", secretStoreName, + "${AWS_REGION}", awsSecretRegionName, + ) + loader.CreateFromFile(cssAssetFunc, "testdata/aws_secret_store.yaml", testNamespace) + defer loader.DeleteFromFile(cssAssetFunc, "testdata/aws_secret_store.yaml", testNamespace) + + By("Waiting for ClusterSecretStore to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: clusterSecretStoresKind, + }, + "", secretStoreName, time.Minute, + )).To(Succeed()) + + By("Creating ExternalSecret with dataFrom") + esAssetFunc := utils.ReplacePatternInAsset( + "${SECRETSTORE_NAME}", secretStoreName, + "${SECRETSTORE_KIND}", "ClusterSecretStore", + "${AWS_SECRET_KEY_NAME}", awsSecretName, + ) + loader.CreateFromFile(esAssetFunc, "testdata/aws_external_secret_datafrom.yaml", testNamespace) + defer loader.DeleteFromFile(testassets.ReadFile, "testdata/aws_external_secret_datafrom.yaml", testNamespace) + + By("Waiting for ExternalSecret to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: externalSecretsKind, + }, + testNamespace, "aws-external-secret-datafrom", time.Minute, + )).To(Succeed()) + + By("Verifying all keys imported without explicit mapping") + Eventually(func(g Gomega) { + secret, err := loader.KubeClient.CoreV1().Secrets(testNamespace).Get(ctx, "aws-secret-datafrom", metav1.GetOptions{}) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(secret.Data).To(HaveKey("api_key")) + g.Expect(secret.Data).To(HaveKey("api_secret")) + g.Expect(secret.Data).To(HaveKey("endpoint")) + g.Expect(string(secret.Data["api_key"])).To(Equal("key123")) + g.Expect(string(secret.Data["api_secret"])).To(Equal("secret456")) + g.Expect(string(secret.Data["endpoint"])).To(Equal("https://api.example.com")) + }, time.Minute, 10*time.Second).Should(Succeed()) + }) + + It("should extract nested JSON values using property path", func() { + awsSecretName := fmt.Sprintf("eso-e2e-secret-json-%s", utils.GetRandomString(5)) + secretStoreName := fmt.Sprintf("aws-secret-store-%s", utils.GetRandomString(5)) + nestedSecret := map[string]interface{}{ + "db": map[string]interface{}{ + "credentials": map[string]interface{}{ + "password": "nested-password-123", + }, + }, + } + secretBytes, _ := json.Marshal(nestedSecret) + secretValue := string(secretBytes) + + defer func() { + By("Cleaning up AWS secret") + Expect(utils.DeleteAWSSecret(ctx, clientset, awsSecretName, awsSecretRegionName)). + NotTo(HaveOccurred()) + }() + + By("Creating AWS secret with nested JSON") + Expect(utils.CreateAWSSecret(ctx, clientset, awsSecretName, secretValue, awsSecretRegionName)). + NotTo(HaveOccurred()) + + By("Creating ClusterSecretStore") + cssAssetFunc := utils.ReplacePatternInAsset( + "${CLUSTERSECRETSTORE_NAME}", secretStoreName, + "${AWS_REGION}", awsSecretRegionName, + ) + loader.CreateFromFile(cssAssetFunc, "testdata/aws_secret_store.yaml", testNamespace) + defer loader.DeleteFromFile(cssAssetFunc, "testdata/aws_secret_store.yaml", testNamespace) + + By("Waiting for ClusterSecretStore to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: clusterSecretStoresKind, + }, + "", secretStoreName, time.Minute, + )).To(Succeed()) + + By("Creating ExternalSecret with JSON path extraction") + esAssetFunc := utils.ReplacePatternInAsset( + "${SECRETSTORE_NAME}", secretStoreName, + "${SECRETSTORE_KIND}", "ClusterSecretStore", + "${AWS_SECRET_KEY_NAME}", awsSecretName, + ) + loader.CreateFromFile(esAssetFunc, "testdata/aws_external_secret_jsonpath.yaml", testNamespace) + defer loader.DeleteFromFile(testassets.ReadFile, "testdata/aws_external_secret_jsonpath.yaml", testNamespace) + + By("Waiting for ExternalSecret to become Ready") + Expect(utils.WaitForESOResourceReady(ctx, dynamicClient, + schema.GroupVersionResource{ + Group: externalSecretsGroupName, + Version: v1APIVersion, + Resource: externalSecretsKind, + }, + testNamespace, "aws-external-secret-jsonpath", time.Minute, + )).To(Succeed()) + + By("Verifying nested value extracted correctly") + Eventually(func(g Gomega) { + secret, err := loader.KubeClient.CoreV1().Secrets(testNamespace).Get(ctx, "aws-secret-jsonpath", metav1.GetOptions{}) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(secret.Data).To(HaveKey("nested_value")) + g.Expect(string(secret.Data["nested_value"])).To(Equal("nested-password-123")) + }, time.Minute, 10*time.Second).Should(Succeed()) + }) + }) + }) diff --git a/test/e2e/testdata/aws_external_secret_binary.yaml b/test/e2e/testdata/aws_external_secret_binary.yaml new file mode 100644 index 000000000..ae4229013 --- /dev/null +++ b/test/e2e/testdata/aws_external_secret_binary.yaml @@ -0,0 +1,21 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + labels: + app.kubernetes.io/name: aws-external-secret-binary + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: aws-external-secret-binary + namespace: external-secrets +spec: + refreshInterval: 1h + secretStoreRef: + name: ${SECRETSTORE_NAME} + kind: ${SECRETSTORE_KIND} + target: + name: aws-secret-binary + creationPolicy: Owner + data: + - secretKey: binary_data + remoteRef: + key: "${AWS_SECRET_KEY_NAME}" + property: binary_data diff --git a/test/e2e/testdata/aws_external_secret_datafrom.yaml b/test/e2e/testdata/aws_external_secret_datafrom.yaml new file mode 100644 index 000000000..fa7041486 --- /dev/null +++ b/test/e2e/testdata/aws_external_secret_datafrom.yaml @@ -0,0 +1,19 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + labels: + app.kubernetes.io/name: aws-external-secret-datafrom + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: aws-external-secret-datafrom + namespace: external-secrets +spec: + refreshInterval: 1h + secretStoreRef: + name: ${SECRETSTORE_NAME} + kind: ${SECRETSTORE_KIND} + target: + name: aws-secret-datafrom + creationPolicy: Owner + dataFrom: + - extract: + key: "${AWS_SECRET_KEY_NAME}" diff --git a/test/e2e/testdata/aws_external_secret_jsonpath.yaml b/test/e2e/testdata/aws_external_secret_jsonpath.yaml new file mode 100644 index 000000000..ff7b74926 --- /dev/null +++ b/test/e2e/testdata/aws_external_secret_jsonpath.yaml @@ -0,0 +1,21 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + labels: + app.kubernetes.io/name: aws-external-secret-jsonpath + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: aws-external-secret-jsonpath + namespace: external-secrets +spec: + refreshInterval: 1h + secretStoreRef: + name: ${SECRETSTORE_NAME} + kind: ${SECRETSTORE_KIND} + target: + name: aws-secret-jsonpath + creationPolicy: Owner + data: + - secretKey: nested_value + remoteRef: + key: "${AWS_SECRET_KEY_NAME}" + property: db.credentials.password diff --git a/test/e2e/testdata/aws_external_secret_multi_key.yaml b/test/e2e/testdata/aws_external_secret_multi_key.yaml new file mode 100644 index 000000000..a62661abe --- /dev/null +++ b/test/e2e/testdata/aws_external_secret_multi_key.yaml @@ -0,0 +1,29 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + labels: + app.kubernetes.io/name: aws-external-secret-multi-key + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: aws-external-secret-multi-key + namespace: external-secrets +spec: + refreshInterval: 1h + secretStoreRef: + name: ${SECRETSTORE_NAME} + kind: ${SECRETSTORE_KIND} + target: + name: aws-secret-multi-key + creationPolicy: Owner + data: + - secretKey: key1 + remoteRef: + key: "${AWS_SECRET_KEY_NAME}" + property: key1 + - secretKey: key2 + remoteRef: + key: "${AWS_SECRET_KEY_NAME}" + property: key2 + - secretKey: key3 + remoteRef: + key: "${AWS_SECRET_KEY_NAME}" + property: key3 diff --git a/test/e2e/testdata/aws_external_secret_refresh.yaml b/test/e2e/testdata/aws_external_secret_refresh.yaml new file mode 100644 index 000000000..9be710de4 --- /dev/null +++ b/test/e2e/testdata/aws_external_secret_refresh.yaml @@ -0,0 +1,21 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + labels: + app.kubernetes.io/name: aws-external-secret-refresh + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: aws-external-secret-refresh + namespace: external-secrets +spec: + refreshInterval: 30s + secretStoreRef: + name: ${SECRETSTORE_NAME} + kind: ${SECRETSTORE_KIND} + target: + name: aws-secret-refresh + creationPolicy: Owner + data: + - secretKey: refresh_value + remoteRef: + key: "${AWS_SECRET_KEY_NAME}" + property: value diff --git a/test/e2e/testdata/aws_external_secret_template.yaml b/test/e2e/testdata/aws_external_secret_template.yaml new file mode 100644 index 000000000..0929086e2 --- /dev/null +++ b/test/e2e/testdata/aws_external_secret_template.yaml @@ -0,0 +1,32 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + labels: + app.kubernetes.io/name: aws-external-secret-template + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: aws-external-secret-template + namespace: external-secrets +spec: + refreshInterval: 1h + secretStoreRef: + name: ${SECRETSTORE_NAME} + kind: ${SECRETSTORE_KIND} + target: + name: aws-secret-template + creationPolicy: Owner + template: + type: Opaque + data: + config.yaml: | + database: + username: {{ .username }} + password: {{ .password }} + data: + - secretKey: username + remoteRef: + key: "${AWS_SECRET_KEY_NAME}" + property: username + - secretKey: password + remoteRef: + key: "${AWS_SECRET_KEY_NAME}" + property: password diff --git a/test/e2e/testdata/aws_invalid_secret_store.yaml b/test/e2e/testdata/aws_invalid_secret_store.yaml new file mode 100644 index 000000000..6a6ff4c9f --- /dev/null +++ b/test/e2e/testdata/aws_invalid_secret_store.yaml @@ -0,0 +1,23 @@ +apiVersion: external-secrets.io/v1 +kind: SecretStore +metadata: + labels: + app.kubernetes.io/name: aws-invalid-secret-store + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: ${SECRETSTORE_NAME} + namespace: external-secrets +spec: + provider: + aws: + service: SecretsManager + region: ap-south-1 + auth: + secretRef: + accessKeyIDSecretRef: + name: ${INVALID_CREDS_SECRET_NAME} + key: aws_access_key_id + namespace: external-secrets + secretAccessKeySecretRef: + name: ${INVALID_CREDS_SECRET_NAME} + key: aws_secret_access_key + namespace: external-secrets diff --git a/test/e2e/testdata/aws_k8s_secret_multi_key.yaml b/test/e2e/testdata/aws_k8s_secret_multi_key.yaml new file mode 100644 index 000000000..662cd4a0d --- /dev/null +++ b/test/e2e/testdata/aws_k8s_secret_multi_key.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/name: aws-k8s-secret-multi-key + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: aws-k8s-secret-multi-key + namespace: external-secrets +data: + key1: ${KEY1_VALUE} + key2: ${KEY2_VALUE} + key3: ${KEY3_VALUE} +type: Opaque diff --git a/test/e2e/testdata/aws_secret_store.yaml b/test/e2e/testdata/aws_secret_store.yaml index 089da2360..6b6a5916e 100644 --- a/test/e2e/testdata/aws_secret_store.yaml +++ b/test/e2e/testdata/aws_secret_store.yaml @@ -9,7 +9,7 @@ spec: provider: aws: service: SecretsManager - region: ap-south-1 + region: ${AWS_REGION} auth: secretRef: accessKeyIDSecretRef: diff --git a/test/e2e/testdata/aws_secret_store_namespace.yaml b/test/e2e/testdata/aws_secret_store_namespace.yaml new file mode 100644 index 000000000..ce9ad125c --- /dev/null +++ b/test/e2e/testdata/aws_secret_store_namespace.yaml @@ -0,0 +1,20 @@ +apiVersion: external-secrets.io/v1 +kind: SecretStore +metadata: + labels: + app.kubernetes.io/name: aws-secret-store-namespace + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: ${SECRETSTORE_NAME} +spec: + provider: + aws: + service: SecretsManager + region: ${AWS_REGION} + auth: + secretRef: + accessKeyIDSecretRef: + name: "${SECRETNAME}" + key: aws_access_key_id + secretAccessKeySecretRef: + name: "${SECRETNAME}" + key: aws_secret_access_key diff --git a/test/e2e/testdata/aws_ssm_external_secret.yaml b/test/e2e/testdata/aws_ssm_external_secret.yaml new file mode 100644 index 000000000..f28259c83 --- /dev/null +++ b/test/e2e/testdata/aws_ssm_external_secret.yaml @@ -0,0 +1,20 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + labels: + app.kubernetes.io/name: aws-ssm-external-secret + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: aws-ssm-external-secret + namespace: external-secrets +spec: + refreshInterval: 1h + secretStoreRef: + name: ${CLUSTERSECRETSTORE_NAME} + kind: ClusterSecretStore + target: + name: aws-ssm-secret + creationPolicy: Owner + data: + - secretKey: parameter_value + remoteRef: + key: "${AWS_PARAMETER_NAME}" diff --git a/test/e2e/testdata/aws_ssm_secret_store.yaml b/test/e2e/testdata/aws_ssm_secret_store.yaml new file mode 100644 index 000000000..90565b436 --- /dev/null +++ b/test/e2e/testdata/aws_ssm_secret_store.yaml @@ -0,0 +1,22 @@ +apiVersion: external-secrets.io/v1 +kind: ClusterSecretStore +metadata: + labels: + app.kubernetes.io/name: aws-ssm-secret-store + app.kubernetes.io/managed-by: external-secrets-operator-e2e + name: ${CLUSTERSECRETSTORE_NAME} +spec: + provider: + aws: + service: ParameterStore + region: ${AWS_REGION} + auth: + secretRef: + accessKeyIDSecretRef: + name: aws-creds + key: aws_access_key_id + namespace: kube-system + secretAccessKeySecretRef: + name: aws-creds + key: aws_secret_access_key + namespace: kube-system diff --git a/test/utils/conditions.go b/test/utils/conditions.go index 54cb0463b..817a69efe 100644 --- a/test/utils/conditions.go +++ b/test/utils/conditions.go @@ -146,6 +146,62 @@ func fetchAWSCreds(ctx context.Context, k8sClient *kubernetes.Clientset) (string return id, key, nil } +func CreateAWSSecret(ctx context.Context, k8sClient *kubernetes.Clientset, secretName, secretValue, region string) error { + id, key, err := fetchAWSCreds(ctx, k8sClient) + if err != nil { + return err + } + + sess, err := session.NewSession(&aws.Config{ + Credentials: awscred.NewCredentials(&awscred.StaticProvider{Value: awscred.Value{ + AccessKeyID: id, + SecretAccessKey: key, + }}), + Region: aws.String(region), + }) + if err != nil { + return fmt.Errorf("failed to create AWS session: %w", err) + } + + svc := secretsmanager.New(sess) + _, err = svc.CreateSecret(&secretsmanager.CreateSecretInput{ + Name: aws.String(secretName), + SecretString: aws.String(secretValue), + }) + if err != nil { + return fmt.Errorf("failed to create AWS secret: %w", err) + } + return nil +} + +func UpdateAWSSecret(ctx context.Context, k8sClient *kubernetes.Clientset, secretName, secretValue, region string) error { + id, key, err := fetchAWSCreds(ctx, k8sClient) + if err != nil { + return err + } + + sess, err := session.NewSession(&aws.Config{ + Credentials: awscred.NewCredentials(&awscred.StaticProvider{Value: awscred.Value{ + AccessKeyID: id, + SecretAccessKey: key, + }}), + Region: aws.String(region), + }) + if err != nil { + return fmt.Errorf("failed to create AWS session: %w", err) + } + + svc := secretsmanager.New(sess) + _, err = svc.UpdateSecret(&secretsmanager.UpdateSecretInput{ + SecretId: aws.String(secretName), + SecretString: aws.String(secretValue), + }) + if err != nil { + return fmt.Errorf("failed to update AWS secret: %w", err) + } + return nil +} + func DeleteAWSSecret(ctx context.Context, k8sClient *kubernetes.Clientset, secretName, region string) error { id, key, err := fetchAWSCreds(ctx, k8sClient) if err != nil { @@ -201,4 +257,4 @@ func ReplacePatternInAsset(replacePatternString ...string) AssetFunc { replacedFileContent := replacer.Replace(string(fileContent)) return []byte(replacedFileContent), nil } -} +} \ No newline at end of file