From 45d0869b910a4fecb0a0a8d2318271fa294bdf52 Mon Sep 17 00:00:00 2001 From: Dario Tranchitella Date: Fri, 31 May 2024 12:05:09 +0200 Subject: [PATCH] feat(webhook): validating DNS service IPs on Service CIDR Signed-off-by: Dario Tranchitella --- cmd/manager/cmd.go | 1 + internal/webhook/handlers/tcp_service_cidr.go | 71 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 internal/webhook/handlers/tcp_service_cidr.go diff --git a/cmd/manager/cmd.go b/cmd/manager/cmd.go index 3fdbb4a..37d54a7 100644 --- a/cmd/manager/cmd.go +++ b/cmd/manager/cmd.go @@ -194,6 +194,7 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command { Scheme: *mgr.GetScheme(), }, }, + handlers.TenantControlPlaneServiceCIDR{}, }, routes.DataStoreValidate{}: { handlers.DataStoreValidation{Client: mgr.GetClient()}, diff --git a/internal/webhook/handlers/tcp_service_cidr.go b/internal/webhook/handlers/tcp_service_cidr.go new file mode 100644 index 0000000..e6daee3 --- /dev/null +++ b/internal/webhook/handlers/tcp_service_cidr.go @@ -0,0 +1,71 @@ +// Copyright 2022 Clastix Labs +// SPDX-License-Identifier: Apache-2.0 + +package handlers + +import ( + "context" + "fmt" + "net" + + "gomodules.xyz/jsonpatch/v2" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1" + "github.com/clastix/kamaji/internal/webhook/utils" +) + +type TenantControlPlaneServiceCIDR struct{} + +func (t TenantControlPlaneServiceCIDR) handle(tcp *kamajiv1alpha1.TenantControlPlane) error { + if tcp.Spec.Addons.CoreDNS == nil { + return nil + } + + _, cidr, err := net.ParseCIDR(tcp.Spec.NetworkProfile.ServiceCIDR) + if err != nil { + return fmt.Errorf("unable to parse Service CIDR, %s", err.Error()) + } + + for _, serviceIP := range tcp.Spec.NetworkProfile.DNSServiceIPs { + ip := net.ParseIP(serviceIP) + if ip == nil { + return fmt.Errorf("unable to parse IP address %s", serviceIP) + } + + if !cidr.Contains(ip) { + return fmt.Errorf("the Service CIDR does not contain the DNS Service IP %s", serviceIP) + } + } + + return nil +} + +func (t TenantControlPlaneServiceCIDR) OnCreate(object runtime.Object) AdmissionResponse { + return func(context.Context, admission.Request) ([]jsonpatch.JsonPatchOperation, error) { + tcp := object.(*kamajiv1alpha1.TenantControlPlane) //nolint:forcetypeassert + + if err := t.handle(tcp); err != nil { + return nil, err + } + + return nil, nil + } +} + +func (t TenantControlPlaneServiceCIDR) OnDelete(runtime.Object) AdmissionResponse { + return utils.NilOp() +} + +func (t TenantControlPlaneServiceCIDR) OnUpdate(object runtime.Object, _ runtime.Object) AdmissionResponse { + return func(ctx context.Context, req admission.Request) ([]jsonpatch.JsonPatchOperation, error) { + tcp := object.(*kamajiv1alpha1.TenantControlPlane) //nolint:forcetypeassert + + if err := t.handle(tcp); err != nil { + return nil, err + } + + return nil, nil + } +}