diff --git a/.secrets.baseline b/.secrets.baseline index daa82b24..d2f0e74e 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -75,10 +75,6 @@ { "path": "detect_secrets.filters.allowlist.is_line_allowlisted" }, - { - "path": "detect_secrets.filters.common.is_baseline_file", - "filename": ".secrets.baseline" - }, { "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", "min_level": 2 @@ -118,6 +114,15 @@ } ], "results": { + ".git/config": [ + { + "type": "Base64 High Entropy String", + "filename": ".git/config", + "hashed_secret": "a16bf940eb9599e3a77ae599906a4e71e4e52243", + "is_verified": false, + "line_number": 23 + } + ], "apis/clusterresources/v1beta1/cassandrauser_types.go": [ { "type": "Secret Keyword", @@ -185,21 +190,21 @@ "filename": "apis/clusters/v1beta1/cassandra_types.go", "hashed_secret": "331cc743251c3b9504229de4d139c539da121a33", "is_verified": false, - "line_number": 238 + "line_number": 239 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/cassandra_types.go", "hashed_secret": "0ad8d7005e084d4f028a4277b73c6fab24269c17", "is_verified": false, - "line_number": 324 + "line_number": 325 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/cassandra_types.go", "hashed_secret": "e0a46b27231f798fe22dc4d5d82b5feeb5dcf085", "is_verified": false, - "line_number": 412 + "line_number": 413 } ], "apis/clusters/v1beta1/cassandra_webhook.go": [ @@ -208,7 +213,7 @@ "filename": "apis/clusters/v1beta1/cassandra_webhook.go", "hashed_secret": "e0a46b27231f798fe22dc4d5d82b5feeb5dcf085", "is_verified": false, - "line_number": 235 + "line_number": 236 } ], "apis/clusters/v1beta1/kafka_types.go": [ @@ -217,14 +222,14 @@ "filename": "apis/clusters/v1beta1/kafka_types.go", "hashed_secret": "964c67cddfe8e6707157152dcf319126502199dc", "is_verified": false, - "line_number": 293 + "line_number": 271 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/kafka_types.go", "hashed_secret": "589a0ad3cc6bc886a00c46a22e5065c48bd8e1b2", "is_verified": false, - "line_number": 439 + "line_number": 418 } ], "apis/clusters/v1beta1/kafkaconnect_types.go": [ @@ -233,84 +238,70 @@ "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", "hashed_secret": "46fe9b29395041087f91b33bd8c5c6177cd42fd1", "is_verified": false, - "line_number": 253 + "line_number": 251 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", "hashed_secret": "4b3af1508421e2fa591c5b260c36dd06fdd872a5", "is_verified": false, - "line_number": 297 + "line_number": 295 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", "hashed_secret": "cf45830dd81b7e1a8b5ffbc2d95b112771524117", "is_verified": false, - "line_number": 307 + "line_number": 305 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", "hashed_secret": "138905ac46675150bf790088ec56b2efc6a64697", "is_verified": false, - "line_number": 318 + "line_number": 316 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", "hashed_secret": "3948059919ffeee8ecc42149cb386f43d2f06f74", "is_verified": false, - "line_number": 323 + "line_number": 321 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", "hashed_secret": "87f1180476a944c4162d1af55efedc8f3e3b609c", "is_verified": false, - "line_number": 474 + "line_number": 472 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", "hashed_secret": "f0f06c9167ce61a586749bb183ac6a3756dd6010", "is_verified": false, - "line_number": 484 + "line_number": 482 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", "hashed_secret": "2042128e13ef5ede4af44271160c72f64564c632", "is_verified": false, - "line_number": 495 + "line_number": 493 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", "hashed_secret": "82dc9ca8ba09262ce948227aeb5d9db8084eeb5d", "is_verified": false, - "line_number": 500 + "line_number": 498 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", "hashed_secret": "5f915325aef923cdc945f639f14c2f854b4214d6", "is_verified": false, - "line_number": 524 - }, - { - "type": "Secret Keyword", - "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", - "hashed_secret": "5ffe533b830f08a0326348a9160afafc8ada44db", - "is_verified": false, - "line_number": 557 - }, - { - "type": "Secret Keyword", - "filename": "apis/clusters/v1beta1/kafkaconnect_types.go", - "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", - "is_verified": false, - "line_number": 562 + "line_number": 522 } ], "apis/clusters/v1beta1/postgresql_types.go": [ @@ -319,21 +310,21 @@ "filename": "apis/clusters/v1beta1/postgresql_types.go", "hashed_secret": "5ffe533b830f08a0326348a9160afafc8ada44db", "is_verified": false, - "line_number": 355 + "line_number": 354 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/postgresql_types.go", "hashed_secret": "a3d7d4a96d18c8fc5a1cf9c9c01c45b4690b4008", "is_verified": false, - "line_number": 361 + "line_number": 360 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/postgresql_types.go", "hashed_secret": "a57ce131bd944bdf8ba2f2f93e179dc416ed0315", "is_verified": false, - "line_number": 481 + "line_number": 480 } ], "apis/clusters/v1beta1/redis_types.go": [ @@ -342,21 +333,21 @@ "filename": "apis/clusters/v1beta1/redis_types.go", "hashed_secret": "bc1c5ae5fd4a238d86261f422e62c489de408c22", "is_verified": false, - "line_number": 168 + "line_number": 169 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/redis_types.go", "hashed_secret": "d62d56668a8c859e768e8250ed2fb690d03cead3", "is_verified": false, - "line_number": 223 + "line_number": 225 }, { "type": "Secret Keyword", "filename": "apis/clusters/v1beta1/redis_types.go", "hashed_secret": "d0e8e6fc5dce4d2b452e344ae41900b566ac01d1", "is_verified": false, - "line_number": 268 + "line_number": 270 } ], "apis/clusters/v1beta1/redis_webhook.go": [ @@ -365,23 +356,7 @@ "filename": "apis/clusters/v1beta1/redis_webhook.go", "hashed_secret": "bc1c5ae5fd4a238d86261f422e62c489de408c22", "is_verified": false, - "line_number": 322 - } - ], - "apis/clusters/v1beta1/zookeeper_types.go": [ - { - "type": "Secret Keyword", - "filename": "apis/clusters/v1beta1/zookeeper_types.go", - "hashed_secret": "5ffe533b830f08a0326348a9160afafc8ada44db", - "is_verified": false, - "line_number": 235 - }, - { - "type": "Secret Keyword", - "filename": "apis/clusters/v1beta1/zookeeper_types.go", - "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", - "is_verified": false, - "line_number": 240 + "line_number": 323 } ], "apis/clusters/v1beta1/zz_generated.deepcopy.go": [ @@ -390,7 +365,7 @@ "filename": "apis/clusters/v1beta1/zz_generated.deepcopy.go", "hashed_secret": "44e17306b837162269a410204daaa5ecee4ec22c", "is_verified": false, - "line_number": 1322 + "line_number": 601 } ], "apis/kafkamanagement/v1beta1/kafkauser_types.go": [ @@ -559,6 +534,22 @@ "line_number": 51 } ], + "controllers/clusters/helpers.go": [ + { + "type": "Secret Keyword", + "filename": "controllers/clusters/helpers.go", + "hashed_secret": "5ffe533b830f08a0326348a9160afafc8ada44db", + "is_verified": false, + "line_number": 241 + }, + { + "type": "Secret Keyword", + "filename": "controllers/clusters/helpers.go", + "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", + "is_verified": false, + "line_number": 246 + } + ], "controllers/clusters/kafkaconnect_controller_test.go": [ { "type": "Secret Keyword", @@ -739,7 +730,7 @@ "filename": "pkg/instaclustr/client.go", "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", "is_verified": false, - "line_number": 2060 + "line_number": 2066 } ], "pkg/instaclustr/mock/client.go": [ @@ -1146,5 +1137,5 @@ } ] }, - "generated_at": "2024-02-20T12:39:50Z" + "generated_at": "2024-02-27T11:00:19Z" } diff --git a/apis/clusters/v1beta1/cassandra_types.go b/apis/clusters/v1beta1/cassandra_types.go index afd326d3..921ac7ef 100644 --- a/apis/clusters/v1beta1/cassandra_types.go +++ b/apis/clusters/v1beta1/cassandra_types.go @@ -65,8 +65,9 @@ type CassandraSpec struct { // CassandraStatus defines the observed state of Cassandra type CassandraStatus struct { - GenericStatus `json:",inline"` - DataCentres []*CassandraDataCentreStatus `json:"dataCentres,omitempty"` + GenericStatus `json:",inline"` + DataCentres []*CassandraDataCentreStatus `json:"dataCentres,omitempty"` + DefaultUserSecretRef *Reference `json:"defaultUserSecretRef,omitempty"` AvailableUsers References `json:"availableUsers,omitempty"` } diff --git a/apis/clusters/v1beta1/kafkaconnect_types.go b/apis/clusters/v1beta1/kafkaconnect_types.go index 8ae043e6..c436f261 100644 --- a/apis/clusters/v1beta1/kafkaconnect_types.go +++ b/apis/clusters/v1beta1/kafkaconnect_types.go @@ -17,8 +17,6 @@ limitations under the License. package v1beta1 import ( - "fmt" - k8scorev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -543,27 +541,6 @@ func (tc *TargetCluster) ManagedClustersToInstAPI() (iClusters []*models.Managed return } -func (k *KafkaConnect) NewDefaultUserSecret(username, password string) *k8scorev1.Secret { - return &k8scorev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: models.SecretKind, - APIVersion: models.K8sAPIVersionV1, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(models.DefaultUserSecretNameTemplate, models.DefaultUserSecretPrefix, k.Name), - Namespace: k.Namespace, - Labels: map[string]string{ - models.ControlledByLabel: k.Name, - models.DefaultSecretLabel: "true", - }, - }, - StringData: map[string]string{ - models.Username: username, - models.Password: password, - }, - } -} - func (k *KafkaConnect) GetExposePorts() []k8scorev1.ServicePort { var exposePorts []k8scorev1.ServicePort if !k.Spec.PrivateNetwork { diff --git a/apis/clusters/v1beta1/zookeeper_types.go b/apis/clusters/v1beta1/zookeeper_types.go index 95cc39d9..0666d17f 100644 --- a/apis/clusters/v1beta1/zookeeper_types.go +++ b/apis/clusters/v1beta1/zookeeper_types.go @@ -18,9 +18,6 @@ package v1beta1 import ( "encoding/json" - "fmt" - - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -220,24 +217,3 @@ func (rs *ZookeeperSpec) areDCsEqual(b []*ZookeeperDataCentre) bool { return true } - -func (a *Zookeeper) NewDefaultUserSecret(username, password string) *v1.Secret { - return &v1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: models.SecretKind, - APIVersion: models.K8sAPIVersionV1, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(models.DefaultUserSecretNameTemplate, models.DefaultUserSecretPrefix, a.Name), - Namespace: a.Namespace, - Labels: map[string]string{ - models.ControlledByLabel: a.Name, - models.DefaultSecretLabel: "true", - }, - }, - StringData: map[string]string{ - models.Username: username, - models.Password: password, - }, - } -} diff --git a/apis/clusters/v1beta1/zz_generated.deepcopy.go b/apis/clusters/v1beta1/zz_generated.deepcopy.go index 204f11f2..9db91bf0 100644 --- a/apis/clusters/v1beta1/zz_generated.deepcopy.go +++ b/apis/clusters/v1beta1/zz_generated.deepcopy.go @@ -598,6 +598,11 @@ func (in *CassandraStatus) DeepCopyInto(out *CassandraStatus) { } } } + if in.DefaultUserSecretRef != nil { + in, out := &in.DefaultUserSecretRef, &out.DefaultUserSecretRef + *out = new(apiextensions.ObjectReference) + **out = **in + } if in.AvailableUsers != nil { in, out := &in.AvailableUsers, &out.AvailableUsers *out = make(References, len(*in)) diff --git a/config/crd/bases/clusters.instaclustr.com_cassandras.yaml b/config/crd/bases/clusters.instaclustr.com_cassandras.yaml index 5ef89908..78f78d17 100644 --- a/config/crd/bases/clusters.instaclustr.com_cassandras.yaml +++ b/config/crd/bases/clusters.instaclustr.com_cassandras.yaml @@ -449,6 +449,17 @@ spec: - nodes type: object type: array + defaultUserSecretRef: + description: ObjectReference is namespaced reference to an object + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object id: type: string maintenanceEvents: diff --git a/config/samples/clusters_v1beta1_cassandra.yaml b/config/samples/clusters_v1beta1_cassandra.yaml index e843da1b..c34827e7 100644 --- a/config/samples/clusters_v1beta1_cassandra.yaml +++ b/config/samples/clusters_v1beta1_cassandra.yaml @@ -4,7 +4,7 @@ metadata: name: cassandra-cluster-2 spec: name: "example-cassandra" #(immutable) - version: "4.0.10" #(immutable) + version: "4.1.3" #(immutable) privateNetwork: false #(immutable) dataCentres: - name: "AWS_cassandra" #(mutable) diff --git a/controllers/clusters/cassandra_controller.go b/controllers/clusters/cassandra_controller.go index 24d06faa..4450bfd7 100644 --- a/controllers/clusters/cassandra_controller.go +++ b/controllers/clusters/cassandra_controller.go @@ -316,6 +316,25 @@ func (r *CassandraReconciler) handleCreateCluster( } } + err := r.createDefaultSecret(ctx, c, l) + if err != nil { + l.Error(err, "Cannot create default secret for Cassandra", + "cluster name", c.Spec.Name, + "clusterID", c.Status.ID, + ) + r.EventRecorder.Eventf( + c, models.Warning, models.CreationFailed, + "Default user secret creation on the Instaclustr is failed. Reason: %v", + err, + ) + + return reconcile.Result{}, err + } + + l.Info("Cassandra cluster has been created", + "cluster ID", c.Status.ID, + ) + if c.Status.State != models.DeletedStatus { patch := c.NewPatch() c.Annotations[models.ResourceStateAnnotation] = models.CreatedEvent @@ -895,6 +914,59 @@ func (r *CassandraReconciler) newWatchBackupsJob(c *v1beta1.Cassandra) scheduler } } +func (r *CassandraReconciler) createDefaultSecret(ctx context.Context, c *v1beta1.Cassandra, l logr.Logger) error { + username, password, err := r.API.GetDefaultCredentialsV1(c.Status.ID) + if err != nil { + l.Error(err, "Cannot get default user creds for Cassandra cluster from the Instaclustr API", + "cluster ID", c.Status.ID, + ) + r.EventRecorder.Eventf(c, models.Warning, models.FetchFailed, + "Default user password fetch from the Instaclustr API is failed. Reason: %v", err, + ) + + return err + } + + patch := c.NewPatch() + secret := newDefaultUserSecret(username, password, c.Name, c.Namespace) + err = r.Create(ctx, secret) + if err != nil { + l.Error(err, "Cannot create secret with default user credentials", + "cluster ID", c.Status.ID, + ) + r.EventRecorder.Eventf(c, models.Warning, models.CreationFailed, + "Creating secret with default user credentials is failed. Reason: %v", err, + ) + + return err + } + + l.Info("Default secret was created", + "secret name", secret.Name, + "secret namespace", secret.Namespace, + ) + + c.Status.DefaultUserSecretRef = &v1beta1.Reference{ + Name: secret.Name, + Namespace: secret.Namespace, + } + + err = r.Status().Patch(ctx, c, patch) + if err != nil { + l.Error(err, "Cannot patch Cassandra resource", + "cluster name", c.Spec.Name, + "status", c.Status) + + r.EventRecorder.Eventf( + c, models.Warning, models.PatchFailed, + "Cluster resource patch is failed. Reason: %v", err) + + return err + } + + return nil +} + func (r *CassandraReconciler) newUsersCreationJob(c *v1beta1.Cassandra) scheduler.Job { l := log.Log.WithValues("component", "cassandraUsersCreationJob") diff --git a/controllers/clusters/helpers.go b/controllers/clusters/helpers.go index d093b990..d01b19ed 100644 --- a/controllers/clusters/helpers.go +++ b/controllers/clusters/helpers.go @@ -25,8 +25,10 @@ import ( "github.com/go-logr/logr" "github.com/hashicorp/go-version" + k8scorev1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" "k8s.io/utils/strings/slices" @@ -225,6 +227,27 @@ func createSpecDifferenceMessage(k8sSpec, iSpec any) (string, error) { return fmt.Sprintf("%s Diffs: %s", models.ExternalChangesBaseMessage, prepareDiffMessage(diffs)), nil } +func newDefaultUserSecret(username, password, name, namespace string) *k8scorev1.Secret { + return &k8scorev1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: models.SecretKind, + APIVersion: models.K8sAPIVersionV1, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf(models.DefaultUserSecretNameTemplate, models.DefaultUserSecretPrefix, name), + Namespace: namespace, + Labels: map[string]string{ + models.ControlledByLabel: name, + models.DefaultSecretLabel: "true", + }, + }, + StringData: map[string]string{ + models.Username: username, + models.Password: password, + }, + } +} + func prepareDiffMessage(diffs dcomparison.ObjectDiffs) string { var diffMessages []string for _, diff := range diffs { diff --git a/controllers/clusters/kafkaconnect_controller.go b/controllers/clusters/kafkaconnect_controller.go index 4bbaa86e..6c4a858e 100644 --- a/controllers/clusters/kafkaconnect_controller.go +++ b/controllers/clusters/kafkaconnect_controller.go @@ -413,7 +413,7 @@ func (r *KafkaConnectReconciler) createDefaultSecret(ctx context.Context, kc *v1 } patch := kc.NewPatch() - secret := kc.NewDefaultUserSecret(username, password) + secret := newDefaultUserSecret(username, password, kc.Name, kc.Namespace) err = r.Create(ctx, secret) if err != nil { l.Error(err, "Cannot create secret with default user credentials", diff --git a/controllers/clusters/kafkaconnect_controller_test.go b/controllers/clusters/kafkaconnect_controller_test.go index a305c6b4..9ac0f6d0 100644 --- a/controllers/clusters/kafkaconnect_controller_test.go +++ b/controllers/clusters/kafkaconnect_controller_test.go @@ -68,7 +68,7 @@ var _ = Describe("Kafka Connect Controller", func() { <-done By("creating secret with the default user credentials") - secret := kafkaConnect.NewDefaultUserSecret("", "") + secret := newDefaultUserSecret("", "", kafkaConnect.Name, kafkaConnectManifest.Namespace) secretNamespacedName := types.NamespacedName{ Namespace: secret.Namespace, Name: secret.Name, diff --git a/controllers/clusters/zookeeper_controller.go b/controllers/clusters/zookeeper_controller.go index 38a892a9..33cd6035 100644 --- a/controllers/clusters/zookeeper_controller.go +++ b/controllers/clusters/zookeeper_controller.go @@ -212,7 +212,7 @@ func (r *ZookeeperReconciler) createDefaultSecret(ctx context.Context, zk *v1bet } patch := zk.NewPatch() - secret := zk.NewDefaultUserSecret(username, password) + secret := newDefaultUserSecret(username, password, zk.Name, zk.Namespace) err = r.Create(ctx, secret) if err != nil { l.Error(err, "Cannot create secret with default user credentials", diff --git a/controllers/clusters/zookeeper_controller_test.go b/controllers/clusters/zookeeper_controller_test.go index aee94333..2a4a320c 100644 --- a/controllers/clusters/zookeeper_controller_test.go +++ b/controllers/clusters/zookeeper_controller_test.go @@ -66,7 +66,7 @@ var _ = Describe("Zookeeper Controller", func() { <-done By("creating secret with the default user credentials") - secret := zookeeper.NewDefaultUserSecret("", "") + secret := newDefaultUserSecret("", "", zookeeper.Name, zookeeper.Namespace) secretNamespacedName := types.NamespacedName{ Namespace: secret.Namespace, Name: secret.Name,