From 2ed94dce306f498d07a83580729952fc662a2fa2 Mon Sep 17 00:00:00 2001 From: Nick Venenga Date: Thu, 16 May 2024 22:15:26 -0400 Subject: [PATCH] Fix bootstrapping with default credentials - Set a more complex default password--not sure if there are documentation updates that need to go with this. - Consolidate env var generation that's the same between STS/Bootstrap into a convient function. - Update the example password in docs to fulfill complexity requirements. --- docs/userguide/main.md | 6 +- opensearch-operator/pkg/builders/cluster.go | 128 ++++++++---------- .../pkg/builders/cluster_test.go | 106 +++++++++------ opensearch-operator/pkg/helpers/helpers.go | 4 +- .../pkg/reconcilers/cluster.go | 11 +- 5 files changed, 134 insertions(+), 121 deletions(-) diff --git a/docs/userguide/main.md b/docs/userguide/main.md index 7f55780e9..9d9dce267 100644 --- a/docs/userguide/main.md +++ b/docs/userguide/main.md @@ -1221,14 +1221,14 @@ type: Opaque data: # admin username: YWRtaW4= - # admin123 - password: YWRtaW4xMjM= + # 0penS3@rch! + password: MHBlblMzQHJjaCE= ``` Then you have to create your own securityconfig and store it in a secret (`securityconfig-secret` in this example). You can take a look at [securityconfig-secret.yaml](../../opensearch-operator/examples/securityconfig-secret.yaml) for how such a secret should look like. Make sure that the password hash of the admin user corresponds to the password you stored in the `admin-credentials-secret`. -Notice that inside `securityconfig-secret` You must edit the `hash` of the admin user before creating the secret. if you have python 3.x installed on your machine you can use the following command to hash your password: `python -c 'import bcrypt; print(bcrypt.hashpw("admin123".encode("utf-8"), bcrypt.gensalt(12, prefix=b"2a")).decode("utf-8"))'` +Notice that inside `securityconfig-secret` You must edit the `hash` of the admin user before creating the secret. if you have python 3.x installed on your machine you can use the following command to hash your password: `python -c 'import bcrypt; print(bcrypt.hashpw("0penS3@rch!".encode("utf-8"), bcrypt.gensalt(12, prefix=b"2a")).decode("utf-8"))'` ```yaml internal_users.yml: |- diff --git a/opensearch-operator/pkg/builders/cluster.go b/opensearch-operator/pkg/builders/cluster.go index 760a498c9..d475fb1ef 100644 --- a/opensearch-operator/pkg/builders/cluster.go +++ b/opensearch-operator/pkg/builders/cluster.go @@ -30,13 +30,13 @@ const ( ) func NewSTSForNodePool( - username string, cr *opsterv1.OpenSearchCluster, node opsterv1.NodePool, configChecksum string, volumes []corev1.Volume, volumeMounts []corev1.VolumeMount, extraConfig map[string]string, + envVars []corev1.EnvVar, ) *appsv1.StatefulSet { // To make sure disksize is not passed as empty var disksize string @@ -466,41 +466,13 @@ func NewSTSForNodePool( Spec: corev1.PodSpec{ Containers: []corev1.Container{ { - Env: []corev1.EnvVar{ - { - Name: "cluster.initial_master_nodes", - Value: BootstrapPodName(cr), - }, - { - Name: "discovery.seed_hosts", - Value: DiscoveryServiceName(cr), - }, - { - Name: "cluster.name", - Value: cr.Name, - }, - { - Name: "network.bind_host", - Value: "0.0.0.0", - }, - { - // Make elasticsearch announce its hostname instead of IP so that certificates using the hostname can be verified - Name: "network.publish_host", - ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.name"}}, - }, - { - Name: "OPENSEARCH_JAVA_OPTS", - Value: jvm, - }, - { - Name: "node.roles", - Value: strings.Join(selectedRoles, ","), - }, - { - Name: "http.port", - Value: fmt.Sprint(cr.Spec.General.HttpPort), - }, - }, + Env: append(envVars, corev1.EnvVar{ + Name: "OPENSEARCH_JAVA_OPTS", + Value: jvm, + }, corev1.EnvVar{ + Name: "node.roles", + Value: strings.Join(selectedRoles, ","), + }), Name: "opensearch", Command: mainCommand, Image: image.GetImage(), @@ -757,6 +729,7 @@ func NewBootstrapPod( cr *opsterv1.OpenSearchCluster, volumes []corev1.Volume, volumeMounts []corev1.VolumeMount, + envVars []corev1.EnvVar, ) *corev1.Pod { labels := map[string]string{ helpers.ClusterLabel: cr.Name, @@ -798,41 +771,13 @@ func NewBootstrapPod( podSecurityContext := cr.Spec.General.PodSecurityContext securityContext := cr.Spec.General.SecurityContext - env := []corev1.EnvVar{ - { - Name: "cluster.initial_master_nodes", - Value: BootstrapPodName(cr), - }, - { - Name: "discovery.seed_hosts", - Value: DiscoveryServiceName(cr), - }, - { - Name: "cluster.name", - Value: cr.Name, - }, - { - Name: "network.bind_host", - Value: "0.0.0.0", - }, - { - // Make elasticsearch announce its hostname instead of IP so that certificates using the hostname can be verified - Name: "network.publish_host", - ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.name"}}, - }, - { - Name: "OPENSEARCH_JAVA_OPTS", - Value: jvm, - }, - { - Name: "node.roles", - Value: masterRole, - }, - { - Name: "http.port", - Value: fmt.Sprint(cr.Spec.General.HttpPort), - }, - } + env := append(envVars, corev1.EnvVar{ + Name: "OPENSEARCH_JAVA_OPTS", + Value: jvm, + }, corev1.EnvVar{ + Name: "node.roles", + Value: masterRole, + }) // Append additional config to env vars, use General.AdditionalConfig by default, overwrite with Bootstrap.AdditionalConfig extraConfig := cr.Spec.General.AdditionalConfig @@ -981,6 +926,47 @@ func STSInNodePools(sts appsv1.StatefulSet, nodepools []opsterv1.NodePool) bool return false } +func CommonEnvVars(cr *opsterv1.OpenSearchCluster, passwordSecretName string) []corev1.EnvVar { + return []corev1.EnvVar{ + { + Name: "cluster.initial_master_nodes", + Value: BootstrapPodName(cr), + }, + { + Name: "discovery.seed_hosts", + Value: DiscoveryServiceName(cr), + }, + { + Name: "cluster.name", + Value: cr.Name, + }, + { + Name: "network.bind_host", + Value: "0.0.0.0", + }, + { + // Make OpenSearch announce its hostname instead of IP so that certificates using the hostname can be verified + Name: "network.publish_host", + ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "metadata.name", + }}, + }, + { + Name: "OPENSEARCH_INITIAL_ADMIN_PASSWORD", + ValueFrom: &corev1.EnvVarSource{SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: passwordSecretName}, + Key: "password", + Optional: pointer.Bool(false), + }}, + }, + { + Name: "http.port", + Value: fmt.Sprint(cr.Spec.General.HttpPort), + }, + } +} + func NewSecurityconfigUpdateJob( instance *opsterv1.OpenSearchCluster, jobName string, diff --git a/opensearch-operator/pkg/builders/cluster_test.go b/opensearch-operator/pkg/builders/cluster_test.go index c7f22c538..2fb9414d0 100644 --- a/opensearch-operator/pkg/builders/cluster_test.go +++ b/opensearch-operator/pkg/builders/cluster_test.go @@ -59,25 +59,25 @@ var _ = Describe("Builders", func() { When("Constructing a STS for a NodePool", func() { It("should include the init containers as SKIP_INIT_CONTAINER is not set", func() { clusterObject := ClusterDescWithVersion("2.2.1") - result := NewSTSForNodePool("foobar", &clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(len(result.Spec.Template.Spec.InitContainers)).To(Equal(1)) }) It("should skip the init container as SKIP_INIT_CONTAINER is set", func() { _ = os.Setenv(helpers.SkipInitContainerEnvVariable, "true") clusterObject := ClusterDescWithVersion("2.2.1") - result := NewSTSForNodePool("foobar", &clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(len(result.Spec.Template.Spec.InitContainers)).To(Equal(0)) _ = os.Unsetenv(helpers.SkipInitContainerEnvVariable) }) It("should include the init containers as SKIP_INIT_CONTAINER is not set", func() { clusterObject := ClusterDescWithVersion("2.2.1") - result := NewBootstrapPod(&clusterObject, nil, nil) + result := NewBootstrapPod(&clusterObject, nil, nil, []corev1.EnvVar{}) Expect(len(result.Spec.InitContainers)).To(Equal(1)) }) It("should skip the init container as SKIP_INIT_CONTAINER is set", func() { _ = os.Setenv(helpers.SkipInitContainerEnvVariable, "true") clusterObject := ClusterDescWithVersion("2.2.1") - result := NewBootstrapPod(&clusterObject, nil, nil) + result := NewBootstrapPod(&clusterObject, nil, nil, []corev1.EnvVar{}) Expect(len(result.Spec.InitContainers)).To(Equal(0)) _ = os.Unsetenv(helpers.SkipInitContainerEnvVariable) }) @@ -87,7 +87,7 @@ var _ = Describe("Builders", func() { Component: "masters", Roles: []string{"cluster_manager", "foobar", "ingest"}, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "node.roles", Value: "cluster_manager,ingest", @@ -99,7 +99,7 @@ var _ = Describe("Builders", func() { Component: "masters", Roles: []string{"master"}, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "node.roles", Value: "cluster_manager", @@ -111,7 +111,7 @@ var _ = Describe("Builders", func() { Component: "masters", Roles: []string{"cluster_manager"}, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "node.roles", Value: "master", @@ -126,7 +126,7 @@ var _ = Describe("Builders", func() { "testAnnotationKey": "testAnnotationValue", }, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Annotations).To(Equal(map[string]string{ ConfigurationChecksumAnnotation: "foobar", "testAnnotationKey": "testAnnotationValue", @@ -141,7 +141,7 @@ var _ = Describe("Builders", func() { "testAnnotationKey": "testAnnotationValue", }, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Annotations).To(Equal(map[string]string{ ConfigurationChecksumAnnotation: "foobar", "testAnnotationKey": "testAnnotationValue", @@ -154,14 +154,14 @@ var _ = Describe("Builders", func() { Roles: []string{"cluster_manager"}, PriorityClassName: "default", } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.PriorityClassName).To(Equal("default")) }) It("should use General.DefaultRepo for the InitHelper image if configured", func() { clusterObject := ClusterDescWithVersion("2.2.1") customRepository := "mycustomrepo.cr" clusterObject.Spec.General.DefaultRepo = &customRepository - result := NewSTSForNodePool("foobar", &clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.InitContainers[0].Image).To(Equal("mycustomrepo.cr/busybox:latest")) }) It("should use InitHelper.Image as InitHelper image if configured", func() { @@ -172,12 +172,12 @@ var _ = Describe("Builders", func() { Image: &customImage, }, } - result := NewSTSForNodePool("foobar", &clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.InitContainers[0].Image).To(Equal("mycustomrepo.cr/custombusybox:1.2.3")) }) It("should use defaults when no custom image is configured for InitHelper image", func() { clusterObject := ClusterDescWithVersion("2.2.1") - result := NewSTSForNodePool("foobar", &clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.InitContainers[0].Image).To(Equal("docker.io/busybox:latest")) }) It("should use a custom dns name when env variable is set as cluster url", func() { @@ -205,7 +205,7 @@ var _ = Describe("Builders", func() { pluginB := "another-plugin" clusterObject.Spec.General.PluginsList = []string{pluginA, pluginB} - result := NewSTSForNodePool("foobar", &clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil, []corev1.EnvVar{}) installCmd := fmt.Sprintf( "./bin/opensearch-plugin install --batch '%s' '%s' && ./opensearch-docker-entrypoint.sh", @@ -230,7 +230,7 @@ var _ = Describe("Builders", func() { Component: "masters", Roles: []string{"search"}, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, CommonEnvVars(&clusterObject, "")) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "node.roles", Value: "search", @@ -248,7 +248,7 @@ var _ = Describe("Builders", func() { Component: "masters", Roles: []string{"search"}, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, CommonEnvVars(&clusterObject, "")) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "node.roles", Value: "search", @@ -280,7 +280,7 @@ var _ = Describe("Builders", func() { Roles: []string{"cluster_manager", "data"}, } clusterObject.Spec.NodePools = append(clusterObject.Spec.NodePools, nodePool) - result := NewSTSForNodePool("foobar", &clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.SecurityContext).To(Equal(podSecurityContext)) Expect(result.Spec.Template.Spec.Containers[0].SecurityContext).To(Equal(securityContext)) }) @@ -297,7 +297,7 @@ var _ = Describe("Builders", func() { }}, } clusterObject.Spec.NodePools = append(clusterObject.Spec.NodePools, nodePool) - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) var expected *string = nil actual := result.Spec.VolumeClaimTemplates[0].Spec.StorageClassName Expect(expected).To(Equal(actual)) @@ -311,7 +311,7 @@ var _ = Describe("Builders", func() { }, }, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "OPENSEARCH_JAVA_OPTS", Value: "-Xmx1024M -Xms1024M -Dopensearch.transport.cname_in_publish_address=true", @@ -326,7 +326,7 @@ var _ = Describe("Builders", func() { }, }, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "OPENSEARCH_JAVA_OPTS", Value: "-Xmx768M -Xms768M -Dopensearch.transport.cname_in_publish_address=true", @@ -342,7 +342,7 @@ var _ = Describe("Builders", func() { }, }, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "OPENSEARCH_JAVA_OPTS", Value: "-Xmx953M -Xms953M -Dopensearch.transport.cname_in_publish_address=true", @@ -351,7 +351,7 @@ var _ = Describe("Builders", func() { It("should set jvm to default when memory request and jvm are not provided", func() { clusterObject := ClusterDescWithVersion("2.2.1") nodePool := opsterv1.NodePool{} - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "OPENSEARCH_JAVA_OPTS", Value: "-Xmx512M -Xms512M -Dopensearch.transport.cname_in_publish_address=true", @@ -362,7 +362,7 @@ var _ = Describe("Builders", func() { nodePool := opsterv1.NodePool{ Jvm: "-Xmx1024M -Xms1024M", } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "OPENSEARCH_JAVA_OPTS", Value: "-Xmx1024M -Xms1024M -Dopensearch.transport.cname_in_publish_address=true", @@ -378,7 +378,7 @@ var _ = Describe("Builders", func() { }, }, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: "OPENSEARCH_JAVA_OPTS", Value: "-Xmx1024M -Xms1024M -Dopensearch.transport.cname_in_publish_address=true", @@ -391,7 +391,7 @@ var _ = Describe("Builders", func() { clusterObject := ClusterDescWithVersion("2.2.1") customRepository := "mycustomrepo.cr" clusterObject.Spec.General.DefaultRepo = &customRepository - result := NewBootstrapPod(&clusterObject, nil, nil) + result := NewBootstrapPod(&clusterObject, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.InitContainers[0].Image).To(Equal("mycustomrepo.cr/busybox:latest")) }) @@ -402,7 +402,7 @@ var _ = Describe("Builders", func() { mockKey: "/opensearch-operated", } clusterObject := ClusterDescWithAdditionalConfigs(nil, mockConfig) - result := NewBootstrapPod(&clusterObject, nil, nil) + result := NewBootstrapPod(&clusterObject, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: mockKey, @@ -410,6 +410,28 @@ var _ = Describe("Builders", func() { })) }) + It("should include OPENSEARCH_INITIAL_ADMIN_PASSWORD env var pointing to the supplied secret name", func() { + mockKey := "server.basePath" + mockSecretName := "fake-secret" + + mockConfig := map[string]string{ + mockKey: "/opensearch-operated", + } + clusterObject := ClusterDescWithAdditionalConfigs(mockConfig, nil) + result := NewBootstrapPod(&clusterObject, nil, nil, CommonEnvVars(&clusterObject, mockSecretName)) + + Expect(result.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ + Name: "OPENSEARCH_INITIAL_ADMIN_PASSWORD", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: mockSecretName}, + Key: "password", + Optional: pointer.Bool(false), + }, + }, + })) + }) + It("should apply the General.AdditionalConfig to the env variables if not overwritten", func() { mockKey := "server.basePath" @@ -417,7 +439,7 @@ var _ = Describe("Builders", func() { mockKey: "/opensearch-operated", } clusterObject := ClusterDescWithAdditionalConfigs(mockConfig, nil) - result := NewBootstrapPod(&clusterObject, nil, nil) + result := NewBootstrapPod(&clusterObject, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ Name: mockKey, @@ -437,7 +459,7 @@ var _ = Describe("Builders", func() { } clusterObject := ClusterDescWithAdditionalConfigs(mockGeneralConfig, mockBootstrapConfig) - result := NewBootstrapPod(&clusterObject, nil, nil) + result := NewBootstrapPod(&clusterObject, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Containers[0].Env).NotTo(ContainElement(corev1.EnvVar{ Name: mockKey1, @@ -460,7 +482,7 @@ var _ = Describe("Builders", func() { Roles: []string{"cluster_manager", "foobar", "ingest"}, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.InitContainers[1].VolumeMounts).To(ContainElements([]corev1.VolumeMount{ { Name: "keystore", @@ -480,7 +502,7 @@ var _ = Describe("Builders", func() { Component: "masters", Roles: []string{"cluster_manager", "foobar", "ingest"}, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].VolumeMounts).To(ContainElement(corev1.VolumeMount{ Name: "keystore", MountPath: "/usr/share/opensearch/config/opensearch.keystore", @@ -501,7 +523,7 @@ var _ = Describe("Builders", func() { Component: "masters", Roles: []string{"cluster_manager", "foobar", "ingest"}, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.InitContainers[1].VolumeMounts).To(ContainElement(corev1.VolumeMount{ Name: "keystore-" + mockSecretName, MountPath: "/tmp/keystoreSecrets/" + mockSecretName + "/" + newKey, @@ -525,7 +547,7 @@ var _ = Describe("Builders", func() { } clusterObject.Spec.NodePools = append(clusterObject.Spec.NodePools, nodePool) - sts := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + sts := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) sts.Status.ReadyReplicas = 2 Expect(k8sClient.Create(context.Background(), sts)).To(Not(HaveOccurred())) result := AllMastersReady(context.Background(), k8sClient, &clusterObject) @@ -546,7 +568,7 @@ var _ = Describe("Builders", func() { } clusterObject.Spec.NodePools = append(clusterObject.Spec.NodePools, nodePool) - sts := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + sts := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) sts.Status.ReadyReplicas = 2 Expect(k8sClient.Create(context.Background(), sts)).To(Not(HaveOccurred())) result := AllMastersReady(context.Background(), k8sClient, &clusterObject) @@ -567,7 +589,7 @@ var _ = Describe("Builders", func() { } clusterObject.Spec.NodePools = append(clusterObject.Spec.NodePools, nodePool) - sts := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + sts := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) sts.Status.ReadyReplicas = 2 Expect(k8sClient.Create(context.Background(), sts)).To(Not(HaveOccurred())) result := AllMastersReady(context.Background(), k8sClient, &clusterObject) @@ -590,7 +612,7 @@ var _ = Describe("Builders", func() { } clusterObject.Spec.NodePools = append(clusterObject.Spec.NodePools, nodePool) - sts := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + sts := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(sts.Spec.Template.Spec.Containers[0].Command[2]).To(Equal(customCommand)) }) }) @@ -609,7 +631,7 @@ var _ = Describe("Builders", func() { } clusterObject.Spec.NodePools = append(clusterObject.Spec.NodePools, nodePool) - sts := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + sts := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(sts.Spec.Template.Spec.ServiceAccountName).To(Equal(serviceAccount)) job := NewSecurityconfigUpdateJob(&clusterObject, "foobar", "foobar", "foobar", "admin-cert", "cmd", nil, nil) @@ -675,7 +697,7 @@ var _ = Describe("Builders", func() { Component: "masters", Roles: []string{"search"}, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].LivenessProbe.InitialDelaySeconds).To(Equal(int32(10))) Expect(result.Spec.Template.Spec.Containers[0].LivenessProbe.TimeoutSeconds).To(Equal(int32(5))) Expect(result.Spec.Template.Spec.Containers[0].LivenessProbe.PeriodSeconds).To(Equal(int32(20))) @@ -711,7 +733,7 @@ var _ = Describe("Builders", func() { }, }, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].LivenessProbe.InitialDelaySeconds).To(Equal(int32(10))) Expect(result.Spec.Template.Spec.Containers[0].LivenessProbe.TimeoutSeconds).To(Equal(int32(5))) Expect(result.Spec.Template.Spec.Containers[0].LivenessProbe.PeriodSeconds).To(Equal(int32(20))) @@ -758,7 +780,7 @@ var _ = Describe("Builders", func() { }, }, } - result := NewSTSForNodePool("foobar", &clusterObject, nodePool, "foobar", nil, nil, nil) + result := NewSTSForNodePool(&clusterObject, nodePool, "foobar", nil, nil, nil, []corev1.EnvVar{}) Expect(result.Spec.Template.Spec.Containers[0].LivenessProbe.InitialDelaySeconds).To(Equal(int32(12))) Expect(result.Spec.Template.Spec.Containers[0].LivenessProbe.TimeoutSeconds).To(Equal(int32(6))) Expect(result.Spec.Template.Spec.Containers[0].LivenessProbe.PeriodSeconds).To(Equal(int32(25))) @@ -777,7 +799,7 @@ var _ = Describe("Builders", func() { Expect(result.Spec.Template.Spec.Containers[0].ReadinessProbe.FailureThreshold).To(Equal(int32(9))) }) }) - + When("Configuring InitHelper Resources", func() { It("should propagate Resources to all init containers", func() { clusterObject := ClusterDescWithVersion("2.2.1") @@ -793,11 +815,11 @@ var _ = Describe("Builders", func() { }, }, } - nodePoolSts := NewSTSForNodePool("foobar", &clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil) + nodePoolSts := NewSTSForNodePool(&clusterObject, opsterv1.NodePool{}, "foobar", nil, nil, nil, []corev1.EnvVar{}) for _, container := range nodePoolSts.Spec.Template.Spec.InitContainers { Expect(container.Resources).To(Equal(clusterObject.Spec.InitHelper.Resources)) } - bootstrapPod := NewBootstrapPod(&clusterObject, nil, nil) + bootstrapPod := NewBootstrapPod(&clusterObject, nil, nil, []corev1.EnvVar{}) for _, container := range bootstrapPod.Spec.InitContainers { Expect(container.Resources).To(Equal(clusterObject.Spec.InitHelper.Resources)) } diff --git a/opensearch-operator/pkg/helpers/helpers.go b/opensearch-operator/pkg/helpers/helpers.go index 7795f2602..319e0929c 100644 --- a/opensearch-operator/pkg/helpers/helpers.go +++ b/opensearch-operator/pkg/helpers/helpers.go @@ -112,7 +112,9 @@ func UsernameAndPassword(k8sClient k8s.K8sClient, cr *opsterv1.OpenSearchCluster return string(username), string(password), nil } else { // Use default demo credentials - return "admin", "admin", nil + // minimum 8 character password and must contain at least one uppercase letter, + // one lowercase letter, one digit, and one special character + return "admin", "0penS3@rch!", nil } } diff --git a/opensearch-operator/pkg/reconcilers/cluster.go b/opensearch-operator/pkg/reconcilers/cluster.go index 6cea13bfd..dbcc2093b 100644 --- a/opensearch-operator/pkg/reconcilers/cluster.go +++ b/opensearch-operator/pkg/reconcilers/cluster.go @@ -3,6 +3,7 @@ package reconcilers import ( "context" "fmt" + corev1 "k8s.io/api/core/v1" "strings" "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/reconcilers/k8s" @@ -95,7 +96,9 @@ func (r *ClusterReconciler) Reconcile() (ctrl.Result, error) { result.CombineErr(ctrl.SetControllerReference(r.instance, passwordSecret, r.client.Scheme())) result.Combine(r.client.ReconcileResource(passwordSecret, reconciler.StatePresent)) - bootstrapPod := builders.NewBootstrapPod(r.instance, r.reconcilerContext.Volumes, r.reconcilerContext.VolumeMounts) + commonEnvVars := builders.CommonEnvVars(r.instance, passwordSecret.Name) + + bootstrapPod := builders.NewBootstrapPod(r.instance, r.reconcilerContext.Volumes, r.reconcilerContext.VolumeMounts, commonEnvVars) result.CombineErr(ctrl.SetControllerReference(r.instance, bootstrapPod, r.client.Scheme())) if r.instance.Status.Initialized { result.Combine(r.client.ReconcileResource(bootstrapPod, reconciler.StateAbsent)) @@ -108,7 +111,7 @@ func (r *ClusterReconciler) Reconcile() (ctrl.Result, error) { result.CombineErr(ctrl.SetControllerReference(r.instance, headlessService, r.client.Scheme())) result.Combine(r.client.ReconcileResource(headlessService, reconciler.StatePresent)) - result.Combine(r.reconcileNodeStatefulSet(nodePool, username)) + result.Combine(r.reconcileNodeStatefulSet(nodePool, commonEnvVars)) } // if Version isn't set we set it now to check for upgrades later. @@ -130,7 +133,7 @@ func (r *ClusterReconciler) Reconcile() (ctrl.Result, error) { return result.Result, result.Err } -func (r *ClusterReconciler) reconcileNodeStatefulSet(nodePool opsterv1.NodePool, username string) (*ctrl.Result, error) { +func (r *ClusterReconciler) reconcileNodeStatefulSet(nodePool opsterv1.NodePool, envVars []corev1.EnvVar) (*ctrl.Result, error) { found, nodePoolConfig := r.reconcilerContext.fetchNodePoolHash(nodePool.Component) // If config hasn't been set up for the node pool requeue @@ -143,13 +146,13 @@ func (r *ClusterReconciler) reconcileNodeStatefulSet(nodePool opsterv1.NodePool, extraConfig := helpers.MergeConfigs(r.instance.Spec.General.AdditionalConfig, nodePool.AdditionalConfig) sts := builders.NewSTSForNodePool( - username, r.instance, nodePool, nodePoolConfig.ConfigHash, r.reconcilerContext.Volumes, r.reconcilerContext.VolumeMounts, extraConfig, + envVars, ) if err := ctrl.SetControllerReference(r.instance, sts, r.client.Scheme()); err != nil { return &ctrl.Result{}, err