From 8751dab9dfd8457f08ccf90c25c78366d2b3258d Mon Sep 17 00:00:00 2001 From: Damiano Donati Date: Sat, 7 Feb 2026 11:46:53 +0100 Subject: [PATCH 1/2] k8s.io/cloud-provider: fix webhook flags description previously the webhook flags descriptions were still referencing the old flag names. --- staging/src/k8s.io/cloud-provider/options/webhook.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/staging/src/k8s.io/cloud-provider/options/webhook.go b/staging/src/k8s.io/cloud-provider/options/webhook.go index 5174ae80f12..f5353b8e79d 100644 --- a/staging/src/k8s.io/cloud-provider/options/webhook.go +++ b/staging/src/k8s.io/cloud-provider/options/webhook.go @@ -126,16 +126,16 @@ func (o *WebhookServingOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&o.ServerCert.CertDirectory, "webhook-cert-dir", o.ServerCert.CertDirectory, ""+ "The directory where the TLS certs are located. "+ - "If --tls-cert-file and --tls-private-key-file are provided, this flag will be ignored.") + "If --webhook-tls-cert-file and --webhook-tls-private-key-file are provided, this flag will be ignored.") fs.StringVar(&o.ServerCert.CertKey.CertFile, "webhook-tls-cert-file", o.ServerCert.CertKey.CertFile, ""+ "File containing the default x509 Certificate for HTTPS. (CA cert, if any, concatenated "+ - "after server cert). If HTTPS serving is enabled, and --tls-cert-file and "+ - "--tls-private-key-file are not provided, a self-signed certificate and key "+ - "are generated for the public address and saved to the directory specified by --cert-dir.") + "after server cert). If HTTPS serving is enabled, and --webhook-tls-cert-file and "+ + "--webhook-tls-private-key-file are not provided, a self-signed certificate and key "+ + "are generated for the public address and saved to the directory specified by --webhook-cert-dir.") fs.StringVar(&o.ServerCert.CertKey.KeyFile, "webhook-tls-private-key-file", o.ServerCert.CertKey.KeyFile, - "File containing the default x509 private key matching --tls-cert-file.") + "File containing the default x509 private key matching --webhook-tls-cert-file.") } func (o *WebhookServingOptions) Validate() []error { From 5e9056fe3507d1f4ec28c431c64b0cf5db67122a Mon Sep 17 00:00:00 2001 From: Damiano Donati Date: Sat, 7 Feb 2026 12:00:51 +0100 Subject: [PATCH 2/2] k8s.io/cloud-provider: add missing --webhook-tls-* --webhook-disable-http2-serving options The webhook server was missing several TLS configuration flags that the main secure serving endpoint exposes. Add the following flags and wire them through ApplyTo: --webhook-disable-http2-serving --webhook-tls-cipher-suites --webhook-tls-min-version --webhook-tls-sni-cert-key These flags mirror the behavior of their non-prefixed equivalents (--disable-http2-serving, --tls-cipher-suites, --tls-min-version, --tls-sni-cert-key) and allow operators to fully configure TLS for the webhook endpoint independently of the main serving endpoint. --- .../cloud-provider/options/options_test.go | 17 ++++- .../k8s.io/cloud-provider/options/webhook.go | 62 +++++++++++++++++-- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/staging/src/k8s.io/cloud-provider/options/options_test.go b/staging/src/k8s.io/cloud-provider/options/options_test.go index 8cafb4518ab..9f888241b48 100644 --- a/staging/src/k8s.io/cloud-provider/options/options_test.go +++ b/staging/src/k8s.io/cloud-provider/options/options_test.go @@ -33,6 +33,7 @@ import ( cpconfig "k8s.io/cloud-provider/config" nodeconfig "k8s.io/cloud-provider/controllers/node/config" serviceconfig "k8s.io/cloud-provider/controllers/service/config" + cliflag "k8s.io/component-base/cli/flag" componentbaseconfig "k8s.io/component-base/config" cmconfig "k8s.io/controller-manager/config" cmoptions "k8s.io/controller-manager/options" @@ -202,6 +203,10 @@ func TestAddFlags(t *testing.T) { "--use-service-account-credentials=false", "--concurrent-node-syncs=5", "--webhooks=foo,bar,-baz", + "--webhook-disable-http2-serving=true", + "--webhook-tls-cipher-suites=TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA", + "--webhook-tls-min-version=VersionTLS13", + "--webhook-tls-sni-cert-key=example.crt,example.key:example.com", } err = fs.Parse(args) if err != nil { @@ -275,8 +280,16 @@ func TestAddFlags(t *testing.T) { CertDirectory: "", PairName: "cloud-controller-manager-webhook", }, - BindPort: 10260, - BindAddress: netutils.ParseIPSloppy("0.0.0.0"), + BindPort: 10260, + BindAddress: netutils.ParseIPSloppy("0.0.0.0"), + DisableHTTP2Serving: true, + CipherSuites: []string{"TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA"}, + MinTLSVersion: "VersionTLS13", + SNICertKeys: []cliflag.NamedCertKey{{ + CertFile: "example.crt", + KeyFile: "example.key", + Names: []string{"example.com"}, + }}, }, }, SecureServing: (&apiserveroptions.SecureServingOptions{ diff --git a/staging/src/k8s.io/cloud-provider/options/webhook.go b/staging/src/k8s.io/cloud-provider/options/webhook.go index f5353b8e79d..10a1f8a4c63 100644 --- a/staging/src/k8s.io/cloud-provider/options/webhook.go +++ b/staging/src/k8s.io/cloud-provider/options/webhook.go @@ -29,6 +29,7 @@ import ( "k8s.io/apiserver/pkg/server/dynamiccertificates" apiserveroptions "k8s.io/apiserver/pkg/server/options" "k8s.io/cloud-provider/config" + cliflag "k8s.io/component-base/cli/flag" netutils "k8s.io/utils/net" ) @@ -124,6 +125,9 @@ func (o *WebhookServingOptions) AddFlags(fs *pflag.FlagSet) { fs.IntVar(&o.BindPort, "webhook-secure-port", o.BindPort, "Secure port to serve cloud provider webhooks. If 0, don't serve webhooks at all.") + fs.BoolVar(&o.DisableHTTP2Serving, "webhook-disable-http2-serving", o.DisableHTTP2Serving, + "If true, HTTP2 serving will be disabled for the webhook server [default=false]") + fs.StringVar(&o.ServerCert.CertDirectory, "webhook-cert-dir", o.ServerCert.CertDirectory, ""+ "The directory where the TLS certs are located. "+ "If --webhook-tls-cert-file and --webhook-tls-private-key-file are provided, this flag will be ignored.") @@ -136,6 +140,30 @@ func (o *WebhookServingOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&o.ServerCert.CertKey.KeyFile, "webhook-tls-private-key-file", o.ServerCert.CertKey.KeyFile, "File containing the default x509 private key matching --webhook-tls-cert-file.") + + tlsCipherPreferredValues := cliflag.PreferredTLSCipherNames() + tlsCipherInsecureValues := cliflag.InsecureTLSCipherNames() + fs.StringSliceVar(&o.CipherSuites, "webhook-tls-cipher-suites", o.CipherSuites, + "Comma-separated list of cipher suites for the webhook server. "+ + "If omitted, the default Go cipher suites will be used. \n"+ + "Preferred values: "+strings.Join(tlsCipherPreferredValues, ", ")+". \n"+ + "Insecure values: "+strings.Join(tlsCipherInsecureValues, ", ")+".") + + tlsPossibleVersions := cliflag.TLSPossibleVersions() + fs.StringVar(&o.MinTLSVersion, "webhook-tls-min-version", o.MinTLSVersion, + "Minimum TLS version supported for the webhook server. "+ + "Possible values: "+strings.Join(tlsPossibleVersions, ", ")) + + fs.Var(cliflag.NewNamedCertKeyArray(&o.SNICertKeys), "webhook-tls-sni-cert-key", ""+ + "A pair of x509 certificate and private key file paths, optionally suffixed with a list of "+ + "domain patterns which are fully qualified domain names, possibly with prefixed wildcard "+ + "segments. The domain patterns also allow IP addresses, but IPs should only be used if "+ + "the webhook server has visibility to the IP address requested by a client. "+ + "If no domain patterns are provided, the names of the certificate are "+ + "extracted. Non-wildcard matches trump over wildcard matches, explicit domain patterns "+ + "trump over extracted names. For multiple key/certificate pairs, use the "+ + "--webhook-tls-sni-cert-key multiple times. "+ + "Examples: \"example.crt,example.key\" or \"foo.crt,foo.key:*.foo.com,foo.com\".") } func (o *WebhookServingOptions) Validate() []error { @@ -176,20 +204,46 @@ func (o *WebhookServingOptions) ApplyTo(cfg **server.SecureServingInfo, webhookC } *cfg = &server.SecureServingInfo{ - Listener: listener, + Listener: listener, + DisableHTTP2: o.DisableHTTP2Serving, } + c := *cfg serverCertFile, serverKeyFile := o.ServerCert.CertKey.CertFile, o.ServerCert.CertKey.KeyFile if len(serverCertFile) != 0 || len(serverKeyFile) != 0 { var err error - (*cfg).Cert, err = dynamiccertificates.NewDynamicServingContentFromFiles("serving-cert", serverCertFile, serverKeyFile) + c.Cert, err = dynamiccertificates.NewDynamicServingContentFromFiles("serving-cert", serverCertFile, serverKeyFile) if err != nil { - return err + return fmt.Errorf("failed to load serving cert: %w", err) } } else if o.ServerCert.GeneratedCert != nil { - (*cfg).Cert = o.ServerCert.GeneratedCert + c.Cert = o.ServerCert.GeneratedCert } + if len(o.CipherSuites) != 0 { + cipherSuites, err := cliflag.TLSCipherSuites(o.CipherSuites) + if err != nil { + return fmt.Errorf("failed to parse cipher suites: %w", err) + } + c.CipherSuites = cipherSuites + } + + c.MinTLSVersion, err = cliflag.TLSVersion(o.MinTLSVersion) + if err != nil { + return fmt.Errorf("failed to parse TLS version: %w", err) + } + + // load SNI certs + namedTLSCerts := make([]dynamiccertificates.SNICertKeyContentProvider, 0, len(o.SNICertKeys)) + for _, nck := range o.SNICertKeys { + tlsCert, err := dynamiccertificates.NewDynamicSNIContentFromFiles("sni-serving-cert", nck.CertFile, nck.KeyFile, nck.Names...) + if err != nil { + return fmt.Errorf("failed to load SNI cert and key: %w", err) + } + namedTLSCerts = append(namedTLSCerts, tlsCert) + } + c.SNICerts = namedTLSCerts + return nil }