From 57242295ded1076cc436d050276457a02cffce07 Mon Sep 17 00:00:00 2001 From: Patryk Wasielewski Date: Fri, 16 Jan 2026 18:01:03 +0100 Subject: [PATCH 1/5] Initial draft: dummy validation webhook + kustomize config --- api/v4/webhook.go | 60 +++++++++++++++++++ cmd/main.go | 6 ++ config/certmanager/certificate.yaml | 38 ++++++++++++ config/certmanager/kustomization.yaml | 2 + config/certmanager/kustomizeconfig.yaml | 13 +++++ config/default/kustomization.yaml | 61 ++++++++++---------- config/default/manager_webhook_patch.yaml | 23 ++++++++ config/default/webhookcainjection_patch.yaml | 15 +++++ config/webhook/kustomization.yaml | 6 ++ config/webhook/kustomizeconfig.yaml | 25 ++++++++ config/webhook/manifests.yaml | 31 ++++++++++ config/webhook/service.yaml | 12 ++++ 12 files changed, 262 insertions(+), 30 deletions(-) create mode 100644 api/v4/webhook.go create mode 100644 config/certmanager/certificate.yaml create mode 100644 config/certmanager/kustomization.yaml create mode 100644 config/certmanager/kustomizeconfig.yaml create mode 100644 config/default/manager_webhook_patch.yaml create mode 100644 config/default/webhookcainjection_patch.yaml create mode 100644 config/webhook/kustomization.yaml create mode 100644 config/webhook/kustomizeconfig.yaml create mode 100644 config/webhook/manifests.yaml create mode 100644 config/webhook/service.yaml diff --git a/api/v4/webhook.go b/api/v4/webhook.go new file mode 100644 index 000000000..03206772f --- /dev/null +++ b/api/v4/webhook.go @@ -0,0 +1,60 @@ +/* +Copyright (c) 2018-2022 Splunk Inc. All rights reserved. + +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 v4 + +import ( + "context" + + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +var webhooklog = logf.Log.WithName("splunk-webhook") + +// SplunkValidator handles validation for all Splunk Enterprise CRDs +// This is a dummy implementation to test webhook connectivity +type SplunkValidator struct{} + +// SetupWebhookWithManager registers the centralized webhook with the manager +func SetupWebhookWithManager(mgr ctrl.Manager) error { + validator := &SplunkValidator{} + + mgr.GetWebhookServer().Register("/validate-splunk-enterprise", &admission.Webhook{ + Handler: validator, + }) + + return nil +} + +// Handle implements the admission.Handler interface +// This is a dummy implementation that just logs and allows all requests +func (v *SplunkValidator) Handle(ctx context.Context, req admission.Request) admission.Response { + // Dummy webhook - just log and allow everything + webhooklog.Info("WEBHOOK CALLED - Validation webhook is working!", + "kind", req.Kind.Kind, + "name", req.Name, + "namespace", req.Namespace, + "operation", req.Operation, + "user", req.UserInfo.Username) + + // Always allow - this is just for testing webhook connectivity + return admission.Allowed("webhook is working - all requests allowed") +} + +// Ensure SplunkValidator implements admission.Handler +var _ admission.Handler = &SplunkValidator{} diff --git a/cmd/main.go b/cmd/main.go index f8aba0ae1..86b17a4b5 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -221,6 +221,12 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "Standalone") os.Exit(1) } + + // Setup centralized validation webhook for all CRDs + if err = enterpriseApi.SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create validation webhook") + os.Exit(1) + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/config/certmanager/certificate.yaml b/config/certmanager/certificate.yaml new file mode 100644 index 000000000..f133e9848 --- /dev/null +++ b/config/certmanager/certificate.yaml @@ -0,0 +1,38 @@ +# The following manifests contain a self-signed issuer CR and a certificate CR. +# More document can be found at https://docs.cert-manager.io +# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes. +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/name: issuer + app.kubernetes.io/instance: selfsigned-issuer + app.kubernetes.io/component: certificate + app.kubernetes.io/created-by: splunk-operator + app.kubernetes.io/part-of: splunk-operator + app.kubernetes.io/managed-by: kustomize + name: selfsigned-issuer + namespace: system +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/name: certificate + app.kubernetes.io/instance: serving-cert + app.kubernetes.io/component: certificate + app.kubernetes.io/created-by: splunk-operator + app.kubernetes.io/part-of: splunk-operator + app.kubernetes.io/managed-by: kustomize + name: serving-cert + namespace: system +spec: + dnsNames: + - splunk-operator-webhook-service.splunk-operator.svc + - splunk-operator-webhook-service.splunk-operator.svc.cluster.local + issuerRef: + kind: Issuer + name: splunk-operator-selfsigned-issuer + secretName: webhook-server-cert diff --git a/config/certmanager/kustomization.yaml b/config/certmanager/kustomization.yaml new file mode 100644 index 000000000..2cebb8f69 --- /dev/null +++ b/config/certmanager/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- certificate.yaml diff --git a/config/certmanager/kustomizeconfig.yaml b/config/certmanager/kustomizeconfig.yaml new file mode 100644 index 000000000..ebc9836b1 --- /dev/null +++ b/config/certmanager/kustomizeconfig.yaml @@ -0,0 +1,13 @@ +# This configuration is for teaching kustomize how to update name ref and var substitution +nameReference: +- kind: Issuer + group: cert-manager.io + fieldSpecs: + - kind: Certificate + group: cert-manager.io + path: spec/issuerRef/name + +varReference: +- kind: Certificate + group: cert-manager.io + path: spec/dnsNames diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 15c98e24a..51c196393 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -20,9 +20,9 @@ bases: - ../manager # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml -#- ../webhook +- ../webhook # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. -#- ../certmanager +- ../certmanager # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. #- ../prometheus # [METRICS] Expose the controller manager metrics service. @@ -35,42 +35,43 @@ patchesStrategicMerge: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml -#- manager_webhook_patch.yaml +- manager_webhook_patch.yaml # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. # 'CERTMANAGER' needs to be enabled to use ca injection -#- webhookcainjection_patch.yaml +- webhookcainjection_patch.yaml # the following config is for teaching kustomize how to do var substitution vars: # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldref: -# fieldpath: metadata.namespace -#- name: CERTIFICATE_NAME -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -#- name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -#- name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service +- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR + objref: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # this name should match the one in certificate.yaml + fieldref: + fieldpath: metadata.namespace +- name: CERTIFICATE_NAME + objref: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # this name should match the one in certificate.yaml +# SERVICE_NAMESPACE and SERVICE_NAME are hardcoded in certificate.yaml +# - name: SERVICE_NAMESPACE # namespace of the service +# objref: +# kind: Service +# version: v1 +# name: webhook-service +# fieldref: +# fieldpath: metadata.namespace +# - name: SERVICE_NAME +# objref: +# kind: Service +# version: v1 +# name: webhook-service #patches: #- target: diff --git a/config/default/manager_webhook_patch.yaml b/config/default/manager_webhook_patch.yaml new file mode 100644 index 000000000..738de350b --- /dev/null +++ b/config/default/manager_webhook_patch.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: webhook-server-cert diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml new file mode 100644 index 000000000..50ca12118 --- /dev/null +++ b/config/default/webhookcainjection_patch.yaml @@ -0,0 +1,15 @@ +# This patch add annotation to admission webhook config and +# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/name: validatingwebhookconfiguration + app.kubernetes.io/instance: validating-webhook-configuration + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: splunk-operator + app.kubernetes.io/part-of: splunk-operator + app.kubernetes.io/managed-by: kustomize + name: validating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/config/webhook/kustomization.yaml b/config/webhook/kustomization.yaml new file mode 100644 index 000000000..9cf26134e --- /dev/null +++ b/config/webhook/kustomization.yaml @@ -0,0 +1,6 @@ +resources: +- manifests.yaml +- service.yaml + +configurations: +- kustomizeconfig.yaml diff --git a/config/webhook/kustomizeconfig.yaml b/config/webhook/kustomizeconfig.yaml new file mode 100644 index 000000000..25e21e3c9 --- /dev/null +++ b/config/webhook/kustomizeconfig.yaml @@ -0,0 +1,25 @@ +# the following config is for teaching kustomize where to look at when substituting vars. +# It requires kustomize v2.1.0 or newer to work properly. +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + - kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + +namespace: +- kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/namespace + create: true +- kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/namespace + create: true + +varReference: +- path: metadata/annotations diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml new file mode 100644 index 000000000..d2ba6cb90 --- /dev/null +++ b/config/webhook/manifests.yaml @@ -0,0 +1,31 @@ +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-splunk-enterprise + failurePolicy: Fail + name: vsplunk.kb.io + rules: + - apiGroups: + - enterprise.splunk.com + apiVersions: + - v4 + operations: + - CREATE + - UPDATE + resources: + - standalones + - indexerclusters + - searchheadclusters + - clustermanagers + - licensemanagers + - monitoringconsoles + sideEffects: None diff --git a/config/webhook/service.yaml b/config/webhook/service.yaml new file mode 100644 index 000000000..567677934 --- /dev/null +++ b/config/webhook/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: webhook-service + namespace: system +spec: + ports: + - port: 443 + protocol: TCP + targetPort: 9443 + selector: + control-plane: controller-manager From 7b6d6d8516ba96c640e2bb243b73ce0bc75e13fd Mon Sep 17 00:00:00 2001 From: Patryk Wasielewski Date: Fri, 16 Jan 2026 20:10:01 +0100 Subject: [PATCH 2/5] add vars to config --- config/certmanager/certificate.yaml | 6 +++--- config/certmanager/kustomization.yaml | 3 +++ config/default/kustomization.yaml | 25 ++++++++++++------------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/config/certmanager/certificate.yaml b/config/certmanager/certificate.yaml index f133e9848..6ce642c7c 100644 --- a/config/certmanager/certificate.yaml +++ b/config/certmanager/certificate.yaml @@ -30,9 +30,9 @@ metadata: namespace: system spec: dnsNames: - - splunk-operator-webhook-service.splunk-operator.svc - - splunk-operator-webhook-service.splunk-operator.svc.cluster.local + - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc + - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local issuerRef: kind: Issuer - name: splunk-operator-selfsigned-issuer + name: selfsigned-issuer secretName: webhook-server-cert diff --git a/config/certmanager/kustomization.yaml b/config/certmanager/kustomization.yaml index 2cebb8f69..bebea5a59 100644 --- a/config/certmanager/kustomization.yaml +++ b/config/certmanager/kustomization.yaml @@ -1,2 +1,5 @@ resources: - certificate.yaml + +configurations: +- kustomizeconfig.yaml diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 51c196393..a4fc4576d 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -59,19 +59,18 @@ vars: group: cert-manager.io version: v1 name: serving-cert # this name should match the one in certificate.yaml -# SERVICE_NAMESPACE and SERVICE_NAME are hardcoded in certificate.yaml -# - name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -# - name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service +- name: SERVICE_NAMESPACE # namespace of the service + objref: + kind: Service + version: v1 + name: webhook-service + fieldref: + fieldpath: metadata.namespace +- name: SERVICE_NAME + objref: + kind: Service + version: v1 + name: webhook-service #patches: #- target: From 3881d0246e187ea38e603d3f59e810aa34841df6 Mon Sep 17 00:00:00 2001 From: Patryk Wasielewski Date: Mon, 19 Jan 2026 12:11:10 +0100 Subject: [PATCH 3/5] address comments --- api/v4/webhook.go | 4 ++-- cmd/main.go | 5 +---- config/webhook/manifests.yaml | 2 ++ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/api/v4/webhook.go b/api/v4/webhook.go index 03206772f..0e34ebc0b 100644 --- a/api/v4/webhook.go +++ b/api/v4/webhook.go @@ -31,14 +31,14 @@ var webhooklog = logf.Log.WithName("splunk-webhook") type SplunkValidator struct{} // SetupWebhookWithManager registers the centralized webhook with the manager -func SetupWebhookWithManager(mgr ctrl.Manager) error { +func SetupWebhookWithManager(mgr ctrl.Manager) { validator := &SplunkValidator{} mgr.GetWebhookServer().Register("/validate-splunk-enterprise", &admission.Webhook{ Handler: validator, }) - return nil + webhooklog.Info("Validation webhook registered", "path", "/validate-splunk-enterprise") } // Handle implements the admission.Handler interface diff --git a/cmd/main.go b/cmd/main.go index 86b17a4b5..e93c85f92 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -223,10 +223,7 @@ func main() { } // Setup centralized validation webhook for all CRDs - if err = enterpriseApi.SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create validation webhook") - os.Exit(1) - } + enterpriseApi.SetupWebhookWithManager(mgr) //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index d2ba6cb90..bd8d2eecb 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -26,6 +26,8 @@ webhooks: - indexerclusters - searchheadclusters - clustermanagers + - clustermasters - licensemanagers + - licensemasters - monitoringconsoles sideEffects: None From 3f1c747d657f8ddeddaa7b9cb97b9aca635a56dc Mon Sep 17 00:00:00 2001 From: Patryk Wasielewski Date: Mon, 19 Jan 2026 12:12:38 +0100 Subject: [PATCH 4/5] comments --- api/v4/webhook.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v4/webhook.go b/api/v4/webhook.go index 0e34ebc0b..7da00cf0f 100644 --- a/api/v4/webhook.go +++ b/api/v4/webhook.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2018-2022 Splunk Inc. All rights reserved. +Copyright (c) 2018-2026 Splunk Inc. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 38a9dd8633ffe32c6a007f9f137f9b1ec5b8ef9c Mon Sep 17 00:00:00 2001 From: Patryk Wasielewski Date: Mon, 19 Jan 2026 12:16:02 +0100 Subject: [PATCH 5/5] update biased lang conf --- .biased_lang_exclude | 1 + 1 file changed, 1 insertion(+) diff --git a/.biased_lang_exclude b/.biased_lang_exclude index 32a3a3699..80b251425 100644 --- a/.biased_lang_exclude +++ b/.biased_lang_exclude @@ -19,6 +19,7 @@ config/examples/licensemaster/default.yaml config/rbac/licensemaster_editor_role.yaml config/rbac/licensemaster_viewer_role.yaml config/samples/enterprise_v3_licensemaster.yaml +config/webhook/manifests.yaml tools/make_bundle.sh config/samples/kustomization.yaml config/manifests/bases/splunk-operator.clusterserviceversion.yaml