diff --git a/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go b/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go index 1e661e1b42a..758eeeb54b6 100644 --- a/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go +++ b/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go @@ -22,6 +22,7 @@ import ( "time" argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1" + "github.com/argoproj-labs/argocd-operator/controllers/argoutil" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture" @@ -175,5 +176,72 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { }) + It("verify redis credential distribution", func() { + + By("creating simple Argo CD instance") + ns, cleanupFunc = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: ns.Name}, + Spec: argov1beta1api.ArgoCDSpec{}, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + + By("waiting for ArgoCD CR to be reconciled and the instance to be ready") + Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) + + By("verify redis creds are correctly passed to pods") + const expectedMsg = "Loading Redis credentials from mounted directory: /app/config/redis-auth/" + expectedComponents := []string{ + "statefulset/" + argoCD.Name + "-" + "application-controller", + "deployment/" + argoCD.Name + "-" + "repo-server", + "deployment/" + argoCD.Name + "-" + "server", + } + for _, component := range expectedComponents { + logOutput, err := osFixture.ExecCommandWithOutputParam(false, true, + "kubectl", "logs", component, "-n", ns.Name, + ) + Expect(err).ToNot(HaveOccurred(), "Output: "+logOutput) + Expect(logOutput).To(ContainSubstring(expectedMsg)) + // This is how redis disconnect manifests + Expect(logOutput).ToNot(ContainSubstring("manifest cache error")) + Expect(logOutput).ToNot(ContainSubstring("WRONGPASS")) + + mountedFiles, err := osFixture.ExecCommandWithOutputParam(false, true, + "kubectl", "exec", component, "-n", ns.Name, "--", "ls", "-1", argoutil.RedisAuthMountPath, + ) + Expect(err).ToNot(HaveOccurred(), "Output: "+logOutput) + Expect(mountedFiles).ToNot(ContainSubstring("users.acl")) + } + + By("verifying redis password is correct") + redisInitialSecret := &corev1.Secret{} + redisPwdSecretKey := client.ObjectKey{ + Name: argoutil.GetSecretNameWithSuffix(argoCD, "redis-initial-password"), + Namespace: ns.Name, + } + Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) + expectedRedisPwd := string(redisInitialSecret.Data["auth"]) + Expect(expectedRedisPwd).ShouldNot(Equal("")) + + redisPingOut, err := osFixture.ExecCommandWithOutputParam(false, false, + "kubectl", "exec", "-n", ns.Name, "-c", "redis", "deployment/argocd-redis", "--", + "redis-cli", "-a", expectedRedisPwd, "--no-auth-warning", "ping", + ) + + Expect(err).ToNot(HaveOccurred(), "Output: "+redisPingOut) + Expect(redisPingOut).NotTo(ContainSubstring("NOAUTH Authentication required")) + Expect(redisPingOut).To(ContainSubstring("PONG")) + + By("verifying redis rejects unauthenticated requests") + redisPingOut, err = osFixture.ExecCommandWithOutputParam(false, false, + "kubectl", "exec", "-n", ns.Name, "-c", "redis", "deployment/argocd-redis", "--", + "redis-cli", "ping", // no auth provided + ) + + Expect(err).ToNot(HaveOccurred(), "Output: "+redisPingOut) + Expect(redisPingOut).To(ContainSubstring("NOAUTH Authentication required")) + Expect(redisPingOut).NotTo(ContainSubstring("PONG")) + }) }) }) diff --git a/test/openshift/e2e/ginkgo/parallel/1-067_validate_redis_secure_comm_no_autotls_ha_test.go b/test/openshift/e2e/ginkgo/parallel/1-067_validate_redis_secure_comm_no_autotls_ha_test.go index d9cd091b663..cf840f168d9 100644 --- a/test/openshift/e2e/ginkgo/parallel/1-067_validate_redis_secure_comm_no_autotls_ha_test.go +++ b/test/openshift/e2e/ginkgo/parallel/1-067_validate_redis_secure_comm_no_autotls_ha_test.go @@ -21,6 +21,7 @@ import ( "os" argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1" + "github.com/argoproj-labs/argocd-operator/controllers/argoutil" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture" @@ -175,19 +176,24 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { } By("extracting the contents of /data/conf/sentinel.conf and checking it contains expected values") - sentinelConf, err := osFixture.ExecCommandWithOutputParam(false, true, "kubectl", "exec", "-i", "pod/argocd-redis-ha-server-0", "-n", ns.Name, "-c", "redis", "--", "cat", "/data/conf/sentinel.conf") + sentinelConf, err := osFixture.ExecCommandWithOutputParam( + false, true, + "kubectl", "exec", "-i", "pod/argocd-redis-ha-server-0", "-n", ns.Name, "-c", "redis", + "--", "cat", "/data/conf/sentinel.conf", + ) Expect(err).ToNot(HaveOccurred()) expectedSentinelConfig := []string{ "port 0", "tls-port 26379", - "tls-cert-file \"/app/config/redis/tls/tls.crt\"", - "tls-ca-cert-file \"/app/config/redis/tls/tls.crt\"", - "tls-key-file \"/app/config/redis/tls/tls.key\"", + // Dynamic changes to the config file can result in doublequotes added unpredictably + `tls-cert-file "?/app/config/redis/tls/tls.crt"?`, + `tls-ca-cert-file "?/app/config/redis/tls/tls.crt"?`, + `tls-key-file "?/app/config/redis/tls/tls.key"?`, "tls-replication yes", "tls-auth-clients no", } for _, line := range expectedSentinelConfig { - Expect(sentinelConf).To(ContainSubstring(line)) + Expect(sentinelConf).To(MatchRegexp(line)) } repoServerDepl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "argocd-repo-server", Namespace: ns.Name}} @@ -210,8 +216,80 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { Expect(applicationControllerSS).To(statefulsetFixture.HaveContainerCommandSubstring("argocd-application-controller --operation-processors 10 --redis argocd-redis-ha-haproxy."+ns.Name+".svc.cluster.local:6379 --redis-use-tls --redis-ca-certificate /app/config/controller/tls/redis/tls.crt --repo-server argocd-repo-server."+ns.Name+".svc.cluster.local:8081 --status-processors 20 --kubectl-parallelism-limit 10 --loglevel info --logformat text", 0), "TLS .spec.template.spec.containers.command for argocd-application-controller statefulsets is wrong") - }) + It("verify redis HA credential distribution", func() { + By("verifying we are running on a cluster with at least 3 nodes. This is required for Redis HA") + nodeFixture.ExpectHasAtLeastXNodes(3) + + By("creating simple Argo CD instance") + ns, cleanupFunc = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: ns.Name}, + Spec: argov1beta1api.ArgoCDSpec{ + HA: argov1beta1api.ArgoCDHASpec{ + Enabled: true, + }, + }, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + + By("waiting for ArgoCD CR to be reconciled and the instance to be ready") + Eventually(argoCD, "10m", "10s").Should(argocdFixture.BeAvailable()) + + By("verify redis creds are correctly passed to pods") + const expectedMsg = "Loading Redis credentials from mounted directory: /app/config/redis-auth/" + expectedComponents := []string{ + "statefulset/" + argoCD.Name + "-" + "application-controller", + "deployment/" + argoCD.Name + "-" + "repo-server", + "deployment/" + argoCD.Name + "-" + "server", + } + for _, component := range expectedComponents { + logOutput, err := osFixture.ExecCommandWithOutputParam(false, true, + "kubectl", "logs", component, "-n", ns.Name, + ) + Expect(err).ToNot(HaveOccurred(), "Output: "+logOutput) + Expect(logOutput).To(ContainSubstring(expectedMsg)) + // This is how redis disconnect manifests + Expect(logOutput).ToNot(ContainSubstring("manifest cache error")) + Expect(logOutput).ToNot(ContainSubstring("WRONGPASS")) + + mountedFiles, err := osFixture.ExecCommandWithOutputParam(false, true, + "kubectl", "exec", component, "-n", ns.Name, "--", "ls", "-1", argoutil.RedisAuthMountPath, + ) + Expect(err).ToNot(HaveOccurred(), "Output: "+logOutput) + Expect(mountedFiles).ToNot(ContainSubstring("users.acl")) + } + + By("verifying redis password is correct") + redisInitialSecret := &corev1.Secret{} + redisPwdSecretKey := client.ObjectKey{ + Name: argoutil.GetSecretNameWithSuffix(argoCD, "redis-initial-password"), + Namespace: ns.Name, + } + Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) + expectedRedisPwd := string(redisInitialSecret.Data["auth"]) + Expect(expectedRedisPwd).ShouldNot(Equal("")) + + redisPingOut, err := osFixture.ExecCommandWithOutputParam(false, false, + "kubectl", "exec", "-n", ns.Name, "-c", "redis", "pod/argocd-redis-ha-server-0", "--", + "redis-cli", "-a", expectedRedisPwd, "--no-auth-warning", "ping", + ) + + Expect(err).ToNot(HaveOccurred(), "Output: "+redisPingOut) + Expect(redisPingOut).NotTo(ContainSubstring("NOAUTH Authentication required")) + Expect(redisPingOut).To(ContainSubstring("PONG")) + + By("verifying redis rejects unauthenticated requests") + redisPingOut, err = osFixture.ExecCommandWithOutputParam(false, false, + "kubectl", "exec", "-n", ns.Name, "-c", "redis", "pod/argocd-redis-ha-server-0", "--", + "redis-cli", "ping", // no auth provided + ) + + Expect(err).ToNot(HaveOccurred(), "Output: "+redisPingOut) + Expect(redisPingOut).To(ContainSubstring("NOAUTH Authentication required")) + Expect(redisPingOut).NotTo(ContainSubstring("PONG")) + }) }) }) diff --git a/test/openshift/e2e/ginkgo/parallel/1-096-validate_home_env_argocd_controller_test.go b/test/openshift/e2e/ginkgo/parallel/1-096-validate_home_env_argocd_controller_test.go index f6d92d6f4df..b27411f9fd1 100644 --- a/test/openshift/e2e/ginkgo/parallel/1-096-validate_home_env_argocd_controller_test.go +++ b/test/openshift/e2e/ginkgo/parallel/1-096-validate_home_env_argocd_controller_test.go @@ -50,9 +50,9 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { By("verifying REDIS_PASSWORD env var is no longer set (replaced by redis-initial-pass volume mount)") container := ss.Spec.Template.Spec.Containers[0] - for _, env := range container.Env { - Expect(env.Name).NotTo(Equal("REDIS_PASSWORD")) - } + Expect(container.Env).NotTo(ContainElement( + HaveField("Name", "REDIS_PASSWORD"), + ), "REDIS_PASSWORD should not be set") By("verifying redis-initial-pass volume mount is present") hasRedisAuthMount := false diff --git a/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go b/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go index d9d25c16f4b..d602471edfc 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go @@ -390,6 +390,10 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) } + Expect(container.Env).NotTo(ContainElement( + HaveField("Name", "REDIS_PASSWORD"), + ), "REDIS_PASSWORD should not be set") + By("Disable principal") Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) diff --git a/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go b/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go index 26238107e5a..0ff34a638ae 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go @@ -346,6 +346,10 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) } + Expect(container.Env).NotTo(ContainElement( + HaveField("Name", "REDIS_PASSWORD"), + ), "REDIS_PASSWORD should not be set") + By("Verify custom environment variable is present") Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: "TEST_ENV", Value: "test_value"}), "Custom environment variable TEST_ENV should be set") diff --git a/test/openshift/e2e/ginkgo/sequential/1-053_validate_argocd_agent_principal_connected_test.go b/test/openshift/e2e/ginkgo/sequential/1-053_validate_argocd_agent_principal_connected_test.go index a45be78d7a3..c651e12b65b 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-053_validate_argocd_agent_principal_connected_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-053_validate_argocd_agent_principal_connected_test.go @@ -35,6 +35,7 @@ import ( appFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/application" deploymentFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/deployment" k8sFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/k8s" + osFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/os" fixtureUtils "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -366,6 +367,23 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { cancellableContext, cancelFunc := context.WithCancel(context.Background()) defer cancelFunc() + injectedRedisPwd, err := osFixture.ExecCommandWithOutputParam( + false, false, + "kubectl", "exec", "deployment/argocd-hub-agent-principal", "-n", namespaceAgentPrincipal, + "--", "cat", "/app/config/redis-auth/auth", + ) + Expect(err).NotTo(HaveOccurred()) + Expect(strings.TrimSpace(injectedRedisPwd)).ToNot(BeEmpty()) + + principalEnv, err := osFixture.ExecCommandWithOutputParam( + false, false, + "kubectl", "exec", "deployment/argocd-hub-agent-principal", "-n", namespaceAgentPrincipal, + "--", "cat", "/proc/1/environ", + ) + Expect(err).NotTo(HaveOccurred()) + Expect(principalEnv).To(ContainSubstring("REDIS_CREDS_DIR_PATH=/app/config/redis-auth/")) + Expect(principalEnv).NotTo(ContainSubstring("REDIS_PASSWORD")) + resourceTreeURL := "https://" + argoEndpoint + "/api/v1/stream/applications/" + appOnPrincipal.Name + "/resource-tree?appNamespace=" + appOnPrincipal.Namespace // Wait for successful connection to resource tree event source API, on principal Argo CD @@ -472,6 +490,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { Eventually(func() bool { for { // drain channel looking for name of new pod + GinkgoWriter.Println("Awaiting message") select { case msg := <-msgChan: GinkgoWriter.Println("Processing message:", msg) @@ -502,7 +521,6 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { } } Expect(matchFound).To(BeTrue()) - } // This test verifies that: