Skip to content

Commit 9527e83

Browse files
Kamil PrzybylKamil Przybyl
authored andcommitted
feat: add validating addmission webhook for ALB Ingress annotations
1 parent 7af9e33 commit 9527e83

11 files changed

Lines changed: 364 additions & 1 deletion

File tree

cmd/application-load-balancer-controller-manager/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import (
1919
"sigs.k8s.io/controller-runtime/pkg/healthz"
2020
"sigs.k8s.io/controller-runtime/pkg/log/zap"
2121
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
22+
"sigs.k8s.io/controller-runtime/pkg/webhook"
23+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
2224
)
2325

2426
var (
@@ -133,6 +135,13 @@ func main() {
133135
os.Exit(1)
134136
}
135137

138+
mgr.GetWebhookServer().Register("/validate-ingress", &webhook.Admission{
139+
Handler: &ingress.IngressValidator{
140+
Client: mgr.GetClient(),
141+
Decoder: admission.NewDecoder(mgr.GetScheme()),
142+
},
143+
})
144+
136145
setupLog.Info("starting manager")
137146
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
138147
setupLog.Error(err, "problem running manager")

deploy/application-load-balancer-controller-manager/deployment.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ spec:
4343
hostPort: 8081
4444
name: probe
4545
protocol: TCP
46+
- containerPort: 9443
47+
name: validating-webhook
48+
protocol: TCP
4649
resources:
4750
limits:
4851
cpu: "0.5"
@@ -53,7 +56,14 @@ spec:
5356
volumeMounts:
5457
- mountPath: /etc/serviceaccount
5558
name: cloud-secret
59+
- mountPath: /tmp/k8s-webhook-server/serving-certs
60+
name: validating-webhook-cert
61+
readOnly: true
5662
volumes:
5763
- name: cloud-secret
5864
secret:
5965
secretName: stackit-cloud-secret
66+
- name: validating-webhook-cert
67+
secret:
68+
secretName: stackit-application-load-balancer-contoller-manager-webhook-cert
69+

deploy/application-load-balancer-controller-manager/kustomization.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ kind: Kustomization
44
resources:
55
- deployment.yaml
66
- rbac.yaml
7-
7+
- validating-webhook.yaml
8+
- validating-webhook-issuer.yaml

deploy/application-load-balancer-controller-manager/service.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,8 @@ spec:
1717
port: 8080
1818
targetPort: metrics
1919
protocol: TCP
20+
- name: webhook
21+
port: 443
22+
targetPort: 9443
23+
protocol: TCP
2024
type: ClusterIP
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: cert-manager.io/v1
2+
kind: Issuer
3+
metadata:
4+
name: stackit-application-load-balancer-contoller-manager
5+
namespace: kube-system
6+
spec:
7+
selfSigned: {}
8+
---
9+
apiVersion: cert-manager.io/v1
10+
kind: Certificate
11+
metadata:
12+
name: stackit-application-load-balancer-contoller-manager-webhook-cert
13+
namespace: kube-system
14+
spec:
15+
dnsNames:
16+
- stackit-application-load-balancer-contoller-manager.kube-system.svc
17+
- stackit-application-load-balancer-contoller-manager.kube-system.svc.cluster.local
18+
issuerRef:
19+
kind: Issuer
20+
name: stackit-application-load-balancer-contoller-manager
21+
secretName: stackit-application-load-balancer-contoller-manager-webhook-cert # cert-manager will create this secret
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
apiVersion: admissionregistration.k8s.io/v1
2+
kind: ValidatingWebhookConfiguration
3+
metadata:
4+
name: stackit-application-load-balancer-contoller-manager
5+
annotations:
6+
cert-manager.io/inject-ca-from: kube-system/stackit-application-load-balancer-contoller-manager-webhook-cert
7+
webhooks:
8+
- name: validate-ingress.stackit.cloud
9+
rules:
10+
- apiGroups: ["networking.k8s.io"]
11+
apiVersions: ["v1"]
12+
operations: ["CREATE", "UPDATE"]
13+
resources: ["ingresses"]
14+
scope: "Namespaced"
15+
clientConfig:
16+
service:
17+
namespace: kube-system
18+
name: stackit-application-load-balancer-contoller-manager
19+
path: "/validate-ingress"
20+
admissionReviewVersions: ["v1"]
21+
sideEffects: None
22+
timeoutSeconds: 5

go.mod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ require (
1414
github.com/spf13/cobra v1.10.2
1515
github.com/spf13/pflag v1.0.10
1616
github.com/stackitcloud/stackit-sdk-go/core v0.26.0
17+
github.com/stackitcloud/stackit-sdk-go/services/alb v0.14.2
18+
github.com/stackitcloud/stackit-sdk-go/services/certificates v1.6.2
1719
github.com/stackitcloud/stackit-sdk-go/services/iaas v1.11.1
1820
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.12.2
1921
go.uber.org/mock v0.6.0
@@ -30,6 +32,7 @@ require (
3032
k8s.io/klog/v2 v2.140.0
3133
k8s.io/mount-utils v0.36.0
3234
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2
35+
sigs.k8s.io/controller-runtime v0.24.1
3336
)
3437

3538
replace k8s.io/cloud-provider => github.com/stackitcloud/cloud-provider v0.36.0-ske-1
@@ -48,11 +51,13 @@ require (
4851
github.com/coreos/go-systemd/v22 v22.7.0 // indirect
4952
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
5053
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
54+
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
5155
github.com/felixge/httpsnoop v1.0.4 // indirect
5256
github.com/fsnotify/fsnotify v1.9.0 // indirect
5357
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
5458
github.com/go-logr/logr v1.4.3 // indirect
5559
github.com/go-logr/stdr v1.2.2 // indirect
60+
github.com/go-logr/zapr v1.3.0 // indirect
5661
github.com/go-openapi/jsonpointer v0.22.1 // indirect
5762
github.com/go-openapi/jsonreference v0.21.2 // indirect
5863
github.com/go-openapi/swag v0.25.1 // indirect
@@ -121,12 +126,14 @@ require (
121126
golang.org/x/text v0.36.0 // indirect
122127
golang.org/x/time v0.14.0 // indirect
123128
golang.org/x/tools v0.44.0 // indirect
129+
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
124130
google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 // indirect
125131
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
126132
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
127133
gopkg.in/inf.v0 v0.9.1 // indirect
128134
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
129135
gopkg.in/yaml.v2 v2.4.0 // indirect
136+
k8s.io/apiextensions-apiserver v0.36.0 // indirect
130137
k8s.io/apiserver v0.36.0 // indirect
131138
k8s.io/component-helpers v0.36.0 // indirect
132139
k8s.io/controller-manager v0.36.0 // indirect

go.sum

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
3333
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
3434
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
3535
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
36+
github.com/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k=
37+
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
38+
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
39+
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
3640
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
3741
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
3842
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
@@ -105,6 +109,8 @@ github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7O
105109
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
106110
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
107111
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
112+
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
113+
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
108114
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 h1:EwtI+Al+DeppwYX2oXJCETMO23COyaKGP6fHVpkpWpg=
109115
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
110116
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -159,6 +165,8 @@ github.com/onsi/ginkgo/v2 v2.28.3 h1:4JvMdwtFU0imd8fHx25OJXoDMRexnf8v5NHKYSTTji4
159165
github.com/onsi/ginkgo/v2 v2.28.3/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44=
160166
github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc=
161167
github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A=
168+
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
169+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
162170
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
163171
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
164172
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -186,6 +194,10 @@ github.com/stackitcloud/cloud-provider v0.36.0-ske-1 h1:CZaL+8FH1rOjPnlPkhmvfKUk
186194
github.com/stackitcloud/cloud-provider v0.36.0-ske-1/go.mod h1:y/3sksoC0taJZR0PcAAYUqVyD6Jzu2X0lD4yCEPXPuI=
187195
github.com/stackitcloud/stackit-sdk-go/core v0.26.0 h1:jQEb9gkehfp6VCP6TcYk7BI10cz4l0KM2L6hqYBH2QA=
188196
github.com/stackitcloud/stackit-sdk-go/core v0.26.0/go.mod h1:WU1hhxnjXw2EV7CYa1nlEvNpMiRY6CvmIOaHuL3pOaA=
197+
github.com/stackitcloud/stackit-sdk-go/services/alb v0.14.2 h1:hGzfOJjlCRoFpri5eYIiwhE27qu02pKZLprKvbsTC/w=
198+
github.com/stackitcloud/stackit-sdk-go/services/alb v0.14.2/go.mod h1:eK6oRB5Tmpt6KbXQ4UYBGg2LgW5bPtVoncL9E8JSRww=
199+
github.com/stackitcloud/stackit-sdk-go/services/certificates v1.6.2 h1:ERtEiDYvT1BYCHzqMk2RUdD7o/9dkpa/60s1QVol3yI=
200+
github.com/stackitcloud/stackit-sdk-go/services/certificates v1.6.2/go.mod h1:eJpB3/pukz+KzVPVHQ4g3DVtQkxGga18VbFBhq9ugdY=
189201
github.com/stackitcloud/stackit-sdk-go/services/iaas v1.11.1 h1:HcKqjwIjv4OAW1aWI0U/JWjnzTwzSvdr6DLasH940EU=
190202
github.com/stackitcloud/stackit-sdk-go/services/iaas v1.11.1/go.mod h1:Ts06id0KejUlQWbpR+/rm+tKng6QkTuFV1VQTPJ4dA4=
191203
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.12.2 h1:3Xnt5lnMmqVWChvH8lYJwpRoRatoqXfHlZ12wgNwUD4=
@@ -326,6 +338,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
326338
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
327339
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
328340
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
341+
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
342+
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
329343
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
330344
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
331345
google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 h1:tu/dtnW1o3wfaxCOjSLn5IRX4YDcJrtlpzYkhHhGaC4=
@@ -352,6 +366,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
352366
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
353367
k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80=
354368
k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34=
369+
k8s.io/apiextensions-apiserver v0.36.0 h1:Wt7E8J+VBCbj4FjiBfDTK/neXDDjyJVJc7xfuOHImZ0=
370+
k8s.io/apiextensions-apiserver v0.36.0/go.mod h1:kGDjH0msuiIB3tgsYRV0kS9GqpMYMUsQ3GHv7TApyug=
355371
k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ=
356372
k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc=
357373
k8s.io/apiserver v0.36.0 h1:Jg5OFAENUACByUCg15CmhZAYrr5ZyJ+jodyA1mHl3YE=
@@ -378,6 +394,8 @@ k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 h1:wU4tMEhLGgIbLvXQb1cfN+EcM0wf7
378394
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
379395
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec=
380396
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
397+
sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4=
398+
sigs.k8s.io/controller-runtime v0.24.1/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw=
381399
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
382400
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
383401
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=

pkg/alb/ingress/annotations.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ const (
2020
// AnnotationPlanID sets the plan for the ALB.
2121
// Can be set on IngressClass.
2222
AnnotationPlanID = "alb.stackit.cloud/plan-id"
23+
// AnnotationNetworkMode specifies the network routing mode.
24+
// It currently validates the presence of "NodePort" to ensure backward compatibility for future direct-to-pod routing.
25+
// Can be set on Ingress.
26+
AnnotationNetworkMode = "alb.stackit.cloud/network-mode"
2327

2428
// AnnotationTargetPoolTLSEnabled If true, the application load balancer enables TLS bridging.
2529
// It uses the trusted CAs from the operating system for validation.

0 commit comments

Comments
 (0)