From c9da873799a3e2a2a598533fb041bb2072280f34 Mon Sep 17 00:00:00 2001 From: Johannes Aubart Date: Tue, 21 Oct 2025 15:57:30 +0200 Subject: [PATCH 1/3] enable webhooks --- .../openmcp.cloud_clusterproviders.yaml | 11 ++++++++ .../openmcp.cloud_platformservices.yaml | 11 ++++++++ .../openmcp.cloud_serviceproviders.yaml | 11 ++++++++ api/provider/v1alpha1/deployment_types.go | 10 +++++++ .../v1alpha1/zz_generated.deepcopy.go | 20 ++++++++++++++ .../provider/install/deployment.go | 27 +++++++++++++++++-- lib/utils/utils.go | 10 +++++++ 7 files changed, 98 insertions(+), 2 deletions(-) diff --git a/api/crds/manifests/openmcp.cloud_clusterproviders.yaml b/api/crds/manifests/openmcp.cloud_clusterproviders.yaml index 6a84d34..8336b09 100644 --- a/api/crds/manifests/openmcp.cloud_clusterproviders.yaml +++ b/api/crds/manifests/openmcp.cloud_clusterproviders.yaml @@ -2265,6 +2265,17 @@ spec: - info - error type: string + webhook: + description: Webhook contains the webhook configuration for the provider, + if any. + properties: + enabled: + default: false + description: Enabled indicates whether the webhook is enabled. + type: boolean + required: + - enabled + type: object required: - image type: object diff --git a/api/crds/manifests/openmcp.cloud_platformservices.yaml b/api/crds/manifests/openmcp.cloud_platformservices.yaml index 9b5b857..f25ea3f 100644 --- a/api/crds/manifests/openmcp.cloud_platformservices.yaml +++ b/api/crds/manifests/openmcp.cloud_platformservices.yaml @@ -2265,6 +2265,17 @@ spec: - info - error type: string + webhook: + description: Webhook contains the webhook configuration for the provider, + if any. + properties: + enabled: + default: false + description: Enabled indicates whether the webhook is enabled. + type: boolean + required: + - enabled + type: object required: - image type: object diff --git a/api/crds/manifests/openmcp.cloud_serviceproviders.yaml b/api/crds/manifests/openmcp.cloud_serviceproviders.yaml index f870c74..e21b3bc 100644 --- a/api/crds/manifests/openmcp.cloud_serviceproviders.yaml +++ b/api/crds/manifests/openmcp.cloud_serviceproviders.yaml @@ -2265,6 +2265,17 @@ spec: - info - error type: string + webhook: + description: Webhook contains the webhook configuration for the provider, + if any. + properties: + enabled: + default: false + description: Enabled indicates whether the webhook is enabled. + type: boolean + required: + - enabled + type: object required: - image type: object diff --git a/api/provider/v1alpha1/deployment_types.go b/api/provider/v1alpha1/deployment_types.go index e36193e..396d2be 100644 --- a/api/provider/v1alpha1/deployment_types.go +++ b/api/provider/v1alpha1/deployment_types.go @@ -94,6 +94,16 @@ type DeploymentSpec struct { // +listType=map // +listMapKey=topologyKey TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty" patchStrategy:"merge" patchMergeKey:"topologyKey"` + + // Webhook contains the webhook configuration for the provider, if any. + // +optional + Webhook *WebhookConfiguration `json:"webhook,omitempty"` +} + +type WebhookConfiguration struct { + // Enabled indicates whether the webhook is enabled. + // +kubebuilder:default=false + Enabled bool `json:"enabled"` } // DeploymentStatus defines the observed state of a provider. diff --git a/api/provider/v1alpha1/zz_generated.deepcopy.go b/api/provider/v1alpha1/zz_generated.deepcopy.go index c4826b5..8eca713 100644 --- a/api/provider/v1alpha1/zz_generated.deepcopy.go +++ b/api/provider/v1alpha1/zz_generated.deepcopy.go @@ -147,6 +147,11 @@ func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Webhook != nil { + in, out := &in.Webhook, &out.Webhook + *out = new(WebhookConfiguration) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentSpec. @@ -382,3 +387,18 @@ func (in *ServiceProviderStatus) DeepCopy() *ServiceProviderStatus { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConfiguration. +func (in *WebhookConfiguration) DeepCopy() *WebhookConfiguration { + if in == nil { + return nil + } + out := new(WebhookConfiguration) + in.DeepCopyInto(out) + return out +} diff --git a/internal/controllers/provider/install/deployment.go b/internal/controllers/provider/install/deployment.go index b6c94cb..957832c 100644 --- a/internal/controllers/provider/install/deployment.go +++ b/internal/controllers/provider/install/deployment.go @@ -16,6 +16,7 @@ import ( "github.com/openmcp-project/controller-utils/pkg/resources" "github.com/openmcp-project/openmcp-operator/api/install" + libutils "github.com/openmcp-project/openmcp-operator/lib/utils" ) type deploymentMutator struct { @@ -57,6 +58,28 @@ func (m *deploymentMutator) Mutate(d *appsv1.Deployment) error { return err } + volumes := m.values.deploymentSpec.ExtraVolumes + volumeMounts := m.values.deploymentSpec.ExtraVolumeMounts + if m.values.deploymentSpec.Webhook != nil && m.values.deploymentSpec.Webhook.Enabled { + whSecretName, err := libutils.WebhookSecretName(m.values.provider.GetName()) + if err != nil { + return err + } + volumes = append(volumes, corev1.Volume{ + Name: "webhook-tls", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: whSecretName, + }, + }, + }) + volumeMounts = append(volumeMounts, corev1.VolumeMount{ + Name: "webhook-tls", + MountPath: "/tmp/k8s-webhook-server/serving-certs", + ReadOnly: true, + }) + } + runCmd := slices.Clone(m.values.deploymentSpec.RunCommand) if len(runCmd) == 0 { runCmd = []string{"run"} @@ -86,12 +109,12 @@ func (m *deploymentMutator) Mutate(d *appsv1.Deployment) error { ImagePullPolicy: corev1.PullIfNotPresent, Args: runCmd, Env: env, - VolumeMounts: m.values.deploymentSpec.ExtraVolumeMounts, + VolumeMounts: volumeMounts, }, }, ImagePullSecrets: m.values.ImagePullSecrets(), ServiceAccountName: m.values.NamespacedDefaultResourceName(), - Volumes: m.values.deploymentSpec.ExtraVolumes, + Volumes: volumes, TopologySpreadConstraints: m.values.deploymentSpec.TopologySpreadConstraints, }, }, diff --git a/lib/utils/utils.go b/lib/utils/utils.go index 8449ebc..49f4fea 100644 --- a/lib/utils/utils.go +++ b/lib/utils/utils.go @@ -70,3 +70,13 @@ func StableMCPIdentifier(onboardingName, onboardingNamespace string) (string, er } return res, nil } + +// WebhookSecretName computes the name the secret containing the webhook TLS certificate is expected to have, based on the provider's name. +func WebhookSecretName(providerName string) (string, error) { + suffix := "-webhook-tls" + base, err := controller.ShortenToXCharacters(providerName, controller.K8sMaxNameLength-len(suffix)) + if err != nil { + return "", fmt.Errorf("error computing webhook secret name: %w", err) + } + return base + suffix, nil +} From 54b325922f90da862ce7bb202c7fe14f1ea1865d Mon Sep 17 00:00:00 2001 From: Johannes Aubart Date: Mon, 27 Oct 2025 15:04:06 +0100 Subject: [PATCH 2/3] grant provider init jobs cluster-admin privileges --- .../controllers/provider/install/installer.go | 8 ----- .../controllers/provider/install/rbac_init.go | 32 +------------------ 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/internal/controllers/provider/install/installer.go b/internal/controllers/provider/install/installer.go index 27b5158..696c4e8 100644 --- a/internal/controllers/provider/install/installer.go +++ b/internal/controllers/provider/install/installer.go @@ -48,10 +48,6 @@ func (a *Installer) InstallInitJob(ctx context.Context) (completed bool, err err return false, err } - if err = resources.CreateOrUpdateResource(ctx, a.PlatformClient, newInitClusterRoleMutator(values)); err != nil { - return false, err - } - if err = resources.CreateOrUpdateResource(ctx, a.PlatformClient, newInitClusterRoleBindingMutator(values)); err != nil { return false, err } @@ -159,10 +155,6 @@ func (a *Installer) UninstallProvider(ctx context.Context) (deleted bool, err er return false, err } - if err := resources.DeleteResource(ctx, a.PlatformClient, newInitClusterRoleMutator(values)); err != nil { - return false, err - } - if err := resources.DeleteResource(ctx, a.PlatformClient, newInitServiceAccountMutator(values)); err != nil { return false, err } diff --git a/internal/controllers/provider/install/rbac_init.go b/internal/controllers/provider/install/rbac_init.go index 8df769c..345faf5 100644 --- a/internal/controllers/provider/install/rbac_init.go +++ b/internal/controllers/provider/install/rbac_init.go @@ -23,37 +23,7 @@ func newInitClusterRoleBindingMutator(values *Values) resources.Mutator[*rbac.Cl Namespace: values.Namespace(), }, }, - resources.NewClusterRoleRef(clusterRoleName), - ) - res.MetadataMutator().WithLabels(values.LabelsInitJob()) - return res -} - -func newInitClusterRoleMutator(values *Values) resources.Mutator[*rbac.ClusterRole] { - res := resources.NewClusterRoleMutator( - values.ClusterScopedResourceName(initPrefix), - []rbac.PolicyRule{ - { - APIGroups: []string{"apiextensions.k8s.io"}, - Resources: []string{"customresourcedefinitions"}, - Verbs: []string{"get", "list", "watch", "create", "update", "patch", "delete"}, - }, - { - APIGroups: []string{""}, - Resources: []string{"secrets"}, - Verbs: []string{"get", "list", "watch"}, - }, - { - APIGroups: []string{""}, - Resources: []string{"configmaps"}, - Verbs: []string{"get", "list", "watch"}, - }, - { - APIGroups: []string{"clusters.openmcp.cloud"}, - Resources: []string{"accessrequests", "clusterrequests", "clusterprofiles"}, - Verbs: []string{"get", "list", "watch", "create", "update", "patch", "delete"}, - }, - }, + resources.NewClusterRoleRef("cluster-admin"), ) res.MetadataMutator().WithLabels(values.LabelsInitJob()) return res From a0ea7e2bb208e7dea355ac812d2492192fab0a58 Mon Sep 17 00:00:00 2001 From: Johannes Aubart Date: Wed, 29 Oct 2025 13:41:52 +0100 Subject: [PATCH 3/3] remove webhook from provider config and check for TLS secret instead --- .../manifests/openmcp.cloud_clusterproviders.yaml | 11 ----------- .../manifests/openmcp.cloud_platformservices.yaml | 11 ----------- .../manifests/openmcp.cloud_serviceproviders.yaml | 11 ----------- api/provider/v1alpha1/deployment_types.go | 4 ---- api/provider/v1alpha1/zz_generated.deepcopy.go | 5 ----- internal/controllers/provider/install/deployment.go | 9 ++------- internal/controllers/provider/install/installer.go | 12 ++++++++++++ internal/controllers/provider/install/values.go | 11 ++++++----- 8 files changed, 20 insertions(+), 54 deletions(-) diff --git a/api/crds/manifests/openmcp.cloud_clusterproviders.yaml b/api/crds/manifests/openmcp.cloud_clusterproviders.yaml index 8336b09..6a84d34 100644 --- a/api/crds/manifests/openmcp.cloud_clusterproviders.yaml +++ b/api/crds/manifests/openmcp.cloud_clusterproviders.yaml @@ -2265,17 +2265,6 @@ spec: - info - error type: string - webhook: - description: Webhook contains the webhook configuration for the provider, - if any. - properties: - enabled: - default: false - description: Enabled indicates whether the webhook is enabled. - type: boolean - required: - - enabled - type: object required: - image type: object diff --git a/api/crds/manifests/openmcp.cloud_platformservices.yaml b/api/crds/manifests/openmcp.cloud_platformservices.yaml index f25ea3f..9b5b857 100644 --- a/api/crds/manifests/openmcp.cloud_platformservices.yaml +++ b/api/crds/manifests/openmcp.cloud_platformservices.yaml @@ -2265,17 +2265,6 @@ spec: - info - error type: string - webhook: - description: Webhook contains the webhook configuration for the provider, - if any. - properties: - enabled: - default: false - description: Enabled indicates whether the webhook is enabled. - type: boolean - required: - - enabled - type: object required: - image type: object diff --git a/api/crds/manifests/openmcp.cloud_serviceproviders.yaml b/api/crds/manifests/openmcp.cloud_serviceproviders.yaml index e21b3bc..f870c74 100644 --- a/api/crds/manifests/openmcp.cloud_serviceproviders.yaml +++ b/api/crds/manifests/openmcp.cloud_serviceproviders.yaml @@ -2265,17 +2265,6 @@ spec: - info - error type: string - webhook: - description: Webhook contains the webhook configuration for the provider, - if any. - properties: - enabled: - default: false - description: Enabled indicates whether the webhook is enabled. - type: boolean - required: - - enabled - type: object required: - image type: object diff --git a/api/provider/v1alpha1/deployment_types.go b/api/provider/v1alpha1/deployment_types.go index 396d2be..3346bcc 100644 --- a/api/provider/v1alpha1/deployment_types.go +++ b/api/provider/v1alpha1/deployment_types.go @@ -94,10 +94,6 @@ type DeploymentSpec struct { // +listType=map // +listMapKey=topologyKey TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty" patchStrategy:"merge" patchMergeKey:"topologyKey"` - - // Webhook contains the webhook configuration for the provider, if any. - // +optional - Webhook *WebhookConfiguration `json:"webhook,omitempty"` } type WebhookConfiguration struct { diff --git a/api/provider/v1alpha1/zz_generated.deepcopy.go b/api/provider/v1alpha1/zz_generated.deepcopy.go index 8eca713..186ffb1 100644 --- a/api/provider/v1alpha1/zz_generated.deepcopy.go +++ b/api/provider/v1alpha1/zz_generated.deepcopy.go @@ -147,11 +147,6 @@ func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.Webhook != nil { - in, out := &in.Webhook, &out.Webhook - *out = new(WebhookConfiguration) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentSpec. diff --git a/internal/controllers/provider/install/deployment.go b/internal/controllers/provider/install/deployment.go index 957832c..6f033d5 100644 --- a/internal/controllers/provider/install/deployment.go +++ b/internal/controllers/provider/install/deployment.go @@ -16,7 +16,6 @@ import ( "github.com/openmcp-project/controller-utils/pkg/resources" "github.com/openmcp-project/openmcp-operator/api/install" - libutils "github.com/openmcp-project/openmcp-operator/lib/utils" ) type deploymentMutator struct { @@ -60,16 +59,12 @@ func (m *deploymentMutator) Mutate(d *appsv1.Deployment) error { volumes := m.values.deploymentSpec.ExtraVolumes volumeMounts := m.values.deploymentSpec.ExtraVolumeMounts - if m.values.deploymentSpec.Webhook != nil && m.values.deploymentSpec.Webhook.Enabled { - whSecretName, err := libutils.WebhookSecretName(m.values.provider.GetName()) - if err != nil { - return err - } + if m.values.webhookTLSSecretName != "" { volumes = append(volumes, corev1.Volume{ Name: "webhook-tls", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: whSecretName, + SecretName: m.values.webhookTLSSecretName, }, }, }) diff --git a/internal/controllers/provider/install/installer.go b/internal/controllers/provider/install/installer.go index 696c4e8..dcc8c9e 100644 --- a/internal/controllers/provider/install/installer.go +++ b/internal/controllers/provider/install/installer.go @@ -16,6 +16,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/openmcp-project/openmcp-operator/api/provider/v1alpha1" + libutils "github.com/openmcp-project/openmcp-operator/lib/utils" ) const ( @@ -112,6 +113,17 @@ func (a *Installer) InstallProvider(ctx context.Context) error { return err } + // check if webhook TLS secret exists + whSecretName, err := libutils.WebhookSecretName(values.provider.GetName()) + if err != nil { + return err + } + if err := a.PlatformClient.Get(ctx, client.ObjectKey{Name: whSecretName, Namespace: values.Namespace()}, &core.Secret{}); err == nil { + values.webhookTLSSecretName = whSecretName + } else if !apierrors.IsNotFound(err) { + return fmt.Errorf("unable to check for webhook TLS secret existence: %w", err) + } + if err := resources.CreateOrUpdateResource(ctx, a.PlatformClient, NewDeploymentMutator(values)); err != nil { return err } diff --git a/internal/controllers/provider/install/values.go b/internal/controllers/provider/install/values.go index 2056603..0975467 100644 --- a/internal/controllers/provider/install/values.go +++ b/internal/controllers/provider/install/values.go @@ -27,11 +27,12 @@ func NewValues(provider *unstructured.Unstructured, deploymentSpec *v1alpha1.Dep } type Values struct { - provider *unstructured.Unstructured - deploymentSpec *v1alpha1.DeploymentSpec - environment string - namespace string - providerPrefix string + provider *unstructured.Unstructured + deploymentSpec *v1alpha1.DeploymentSpec + environment string + namespace string + providerPrefix string + webhookTLSSecretName string } func (v *Values) Environment() string {