From 22672f0ca13a80562359ee00525ee8f15cc56870 Mon Sep 17 00:00:00 2001 From: Bychkov Date: Thu, 27 Jul 2023 17:50:16 +0300 Subject: [PATCH] immutable webhook for Cassandra User --- .../v1beta1/cassandrauser_webhook.go | 71 +++++++++++++++++++ .../v1beta1/opensearchuser_webhook.go | 8 +-- .../v1beta1/webhook_suite_test.go | 3 + config/webhook/manifests.yaml | 20 ++++++ main.go | 4 ++ pkg/models/errors.go | 2 + 6 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 apis/clusterresources/v1beta1/cassandrauser_webhook.go diff --git a/apis/clusterresources/v1beta1/cassandrauser_webhook.go b/apis/clusterresources/v1beta1/cassandrauser_webhook.go new file mode 100644 index 000000000..3d97865c3 --- /dev/null +++ b/apis/clusterresources/v1beta1/cassandrauser_webhook.go @@ -0,0 +1,71 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + "github.com/instaclustr/operator/pkg/models" +) + +// log is for logging in this package. +var cassandrauserlog = logf.Log.WithName("cassandrauser-resource") + +func (r *CassandraUser) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-clusterresources-instaclustr-com-v1beta1-cassandrauser,mutating=false,failurePolicy=fail,sideEffects=None,groups=clusterresources.instaclustr.com,resources=cassandrausers,verbs=create;update,versions=v1beta1,name=vcassandrauser.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &CassandraUser{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (u *CassandraUser) ValidateCreate() error { + cassandrauserlog.Info("validate create", "name", u.Name) + + if u.Spec.SecretRef.Name == "" || u.Spec.SecretRef.Namespace == "" { + return models.ErrEmptySecretRef + } + + return nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (u *CassandraUser) ValidateUpdate(old runtime.Object) error { + cassandrauserlog.Info("validate update", "name", u.Name) + + oldUser := old.(*CassandraUser) + if *u.Spec.SecretRef != *oldUser.Spec.SecretRef { + return models.ErrImmutableSecretRef + } + + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *CassandraUser) ValidateDelete() error { + cassandrauserlog.Info("validate delete", "name", r.Name) + + // TODO(user): fill in your validation logic upon object deletion. + return nil +} diff --git a/apis/clusterresources/v1beta1/opensearchuser_webhook.go b/apis/clusterresources/v1beta1/opensearchuser_webhook.go index 350943d8c..85b02f353 100644 --- a/apis/clusterresources/v1beta1/opensearchuser_webhook.go +++ b/apis/clusterresources/v1beta1/opensearchuser_webhook.go @@ -17,12 +17,12 @@ limitations under the License. package v1beta1 import ( - "fmt" - "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + + "github.com/instaclustr/operator/pkg/models" ) // log is for logging in this package. @@ -43,7 +43,7 @@ func (u *OpenSearchUser) ValidateCreate() error { opensearchuserlog.Info("validate create", "name", u.Name) if u.Spec.SecretRef.Name == "" || u.Spec.SecretRef.Namespace == "" { - return fmt.Errorf("secretRef.name and secretRef.namespace should not be empty") + return models.ErrEmptySecretRef } return nil @@ -55,7 +55,7 @@ func (u *OpenSearchUser) ValidateUpdate(old runtime.Object) error { oldUser := old.(*OpenSearchUser) if *u.Spec.SecretRef != *oldUser.Spec.SecretRef { - return fmt.Errorf("spec.secretRef field is immutable") + return models.ErrImmutableSecretRef } return nil diff --git a/apis/clusterresources/v1beta1/webhook_suite_test.go b/apis/clusterresources/v1beta1/webhook_suite_test.go index de849c848..866573867 100644 --- a/apis/clusterresources/v1beta1/webhook_suite_test.go +++ b/apis/clusterresources/v1beta1/webhook_suite_test.go @@ -123,6 +123,9 @@ var _ = BeforeSuite(func() { err = (&OpenSearchUser{}).SetupWebhookWithManager(mgr) Expect(err).NotTo(HaveOccurred()) + err = (&CassandraUser{}).SetupWebhookWithManager(mgr) + Expect(err).NotTo(HaveOccurred()) + //+kubebuilder:scaffold:webhook go func() { diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 130eccda5..4740a9f00 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -252,6 +252,26 @@ webhooks: resources: - azurevnetpeerings sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-clusterresources-instaclustr-com-v1beta1-cassandrauser + failurePolicy: Fail + name: vcassandrauser.kb.io + rules: + - apiGroups: + - clusterresources.instaclustr.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - cassandrausers + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/main.go b/main.go index 104381ab8..194513c05 100644 --- a/main.go +++ b/main.go @@ -424,6 +424,10 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "OpenSearchUser") os.Exit(1) } + if err = (&clusterresourcesv1beta1.CassandraUser{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "CassandraUser") + os.Exit(1) + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/pkg/models/errors.go b/pkg/models/errors.go index c7545e11d..dbf0cafb6 100644 --- a/pkg/models/errors.go +++ b/pkg/models/errors.go @@ -51,6 +51,8 @@ var ( ErrImmutableAdvancedVisibility = errors.New("AdvancedVisibility array is immutable") ErrImmutablePrivateLink = errors.New("PrivateLink array is immutable") ErrImmutableNodesNumber = errors.New("nodes number is immutable") + ErrImmutableSecretRef = errors.New("secret reference is immutable") + ErrEmptySecretRef = errors.New("secretRef.name and secretRef.namespace should not be empty") ErrMissingSecretKeys = errors.New("the secret is missing the correct keys for the user") ErrUserStillExist = errors.New("the user is still attached to cluster") )