Skip to content

Commit 7fba82c

Browse files
authored
Merge pull request #3734 from everettraven/cve/rapid-reset-remediation
✨ : (go/v3,go/v4) Disable HTTP2 for webhook server and metrics in order to address CVE-2023-39325 HTTP/2 rapid reset can cause excessive work in net/http
2 parents c856aee + 2375fa3 commit 7fba82c

File tree

9 files changed

+294
-15
lines changed
  • docs/book/src/cronjob-tutorial/testdata/project/cmd
  • pkg/plugins/golang
    • v3/scaffolds/internal/templates
    • v4/scaffolds/internal/templates
  • testdata

9 files changed

+294
-15
lines changed

docs/book/src/cronjob-tutorial/testdata/project/cmd/main.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ limitations under the License.
1818
package main
1919

2020
import (
21+
"crypto/tls"
2122
"flag"
2223
"os"
2324

@@ -32,6 +33,7 @@ import (
3233
"sigs.k8s.io/controller-runtime/pkg/healthz"
3334
"sigs.k8s.io/controller-runtime/pkg/log/zap"
3435
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
36+
"sigs.k8s.io/controller-runtime/pkg/webhook"
3537

3638
batchv1 "tutorial.kubebuilder.io/project/api/v1"
3739
"tutorial.kubebuilder.io/project/internal/controller"
@@ -72,11 +74,17 @@ func main() {
7274
var metricsAddr string
7375
var enableLeaderElection bool
7476
var probeAddr string
77+
var secureMetrics bool
78+
var enableHTTP2 bool
7579
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
7680
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
7781
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
7882
"Enable leader election for controller manager. "+
7983
"Enabling this will ensure there is only one active controller manager.")
84+
flag.BoolVar(&secureMetrics, "metrics-secure", false,
85+
"If set the metrics endpoint is served securely")
86+
flag.BoolVar(&enableHTTP2, "enable-http2", false,
87+
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
8088
opts := zap.Options{
8189
Development: true,
8290
}
@@ -85,9 +93,34 @@ func main() {
8593

8694
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
8795

96+
// if the enable-http2 flag is false (the default), http/2 should be disabled
97+
// due to its vulnerabilities. More specifically, disabling http/2 will
98+
// prevent from being vulnerable to the HTTP/2 Stream Cancelation and
99+
// Rapid Reset CVEs. For more information see:
100+
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
101+
// - https://github.com/advisories/GHSA-4374-p667-p6c8
102+
disableHTTP2 := func(c *tls.Config) {
103+
setupLog.Info("disabling http/2")
104+
c.NextProtos = []string{"http/1.1"}
105+
}
106+
107+
tlsOpts := []func(*tls.Config){}
108+
if !enableHTTP2 {
109+
tlsOpts = append(tlsOpts, disableHTTP2)
110+
}
111+
112+
webhookServer := webhook.NewServer(webhook.Options{
113+
TLSOpts: tlsOpts,
114+
})
115+
88116
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
89-
Scheme: scheme,
90-
Metrics: metricsserver.Options{BindAddress: metricsAddr},
117+
Scheme: scheme,
118+
Metrics: metricsserver.Options{
119+
BindAddress: metricsAddr,
120+
SecureServing: secureMetrics,
121+
TLSOpts: tlsOpts,
122+
},
123+
WebhookServer: webhookServer,
91124
HealthProbeBindAddress: probeAddr,
92125
LeaderElection: enableLeaderElection,
93126
LeaderElectionID: "80807133.tutorial.kubebuilder.io",

pkg/plugins/golang/v3/scaffolds/internal/templates/main.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ var mainTemplate = `{{ .Boilerplate }}
185185
package main
186186
187187
import (
188+
"crypto/tls"
188189
"flag"
189190
"os"
190191
@@ -198,6 +199,7 @@ import (
198199
ctrl "sigs.k8s.io/controller-runtime"
199200
"sigs.k8s.io/controller-runtime/pkg/log/zap"
200201
"sigs.k8s.io/controller-runtime/pkg/healthz"
202+
"sigs.k8s.io/controller-runtime/pkg/webhook"
201203
%s
202204
)
203205
@@ -217,11 +219,14 @@ func main() {
217219
var metricsAddr string
218220
var enableLeaderElection bool
219221
var probeAddr string
222+
var enableHTTP2 bool
220223
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
221224
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
222225
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
223226
"Enable leader election for controller manager. " +
224227
"Enabling this will ensure there is only one active controller manager.")
228+
flag.BoolVar(&enableHTTP2, "enable-http2", false,
229+
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
225230
{{- else }}
226231
var configFile string
227232
flag.StringVar(&configFile, "config", "",
@@ -238,9 +243,28 @@ func main() {
238243
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
239244
240245
{{ if not .ComponentConfig }}
246+
// if the enable-http2 flag is false (the default), http/2 should be disabled
247+
// due to its vulnerabilities. More specifically, disabling http/2 will
248+
// prevent from being vulnerable to the HTTP/2 Stream Cancelation and
249+
// Rapid Reset CVEs. For more information see:
250+
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
251+
// - https://github.com/advisories/GHSA-4374-p667-p6c8
252+
disableHTTP2 := func(c *tls.Config) {
253+
setupLog.Info("disabling http/2")
254+
c.NextProtos = []string{"http/1.1"}
255+
}
256+
257+
tlsOpts := []func(*tls.Config){}
258+
if !enableHTTP2 {
259+
tlsOpts = append(tlsOpts, disableHTTP2)
260+
}
261+
241262
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
242263
Scheme: scheme,
243264
MetricsBindAddress: metricsAddr,
265+
WebhookServer: &webhook.Server{
266+
TLSOpts: tlsOpts,
267+
},
244268
Port: 9443,
245269
HealthProbeBindAddress: probeAddr,
246270
LeaderElection: enableLeaderElection,

pkg/plugins/golang/v4/scaffolds/internal/templates/main.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ var mainTemplate = `{{ .Boilerplate }}
187187
package main
188188
189189
import (
190+
"crypto/tls"
190191
"flag"
191192
"os"
192193
@@ -200,6 +201,7 @@ import (
200201
ctrl "sigs.k8s.io/controller-runtime"
201202
"sigs.k8s.io/controller-runtime/pkg/log/zap"
202203
"sigs.k8s.io/controller-runtime/pkg/healthz"
204+
"sigs.k8s.io/controller-runtime/pkg/webhook"
203205
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
204206
%s
205207
)
@@ -220,11 +222,17 @@ func main() {
220222
var metricsAddr string
221223
var enableLeaderElection bool
222224
var probeAddr string
225+
var secureMetrics bool
226+
var enableHTTP2 bool
223227
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
224228
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
225229
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
226230
"Enable leader election for controller manager. " +
227231
"Enabling this will ensure there is only one active controller manager.")
232+
flag.BoolVar(&secureMetrics, "metrics-secure", false,
233+
"If set the metrics endpoint is served securely")
234+
flag.BoolVar(&enableHTTP2, "enable-http2", false,
235+
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
228236
{{- else }}
229237
var configFile string
230238
flag.StringVar(&configFile, "config", "",
@@ -241,9 +249,34 @@ func main() {
241249
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
242250
243251
{{ if not .ComponentConfig }}
252+
// if the enable-http2 flag is false (the default), http/2 should be disabled
253+
// due to its vulnerabilities. More specifically, disabling http/2 will
254+
// prevent from being vulnerable to the HTTP/2 Stream Cancelation and
255+
// Rapid Reset CVEs. For more information see:
256+
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
257+
// - https://github.com/advisories/GHSA-4374-p667-p6c8
258+
disableHTTP2 := func(c *tls.Config) {
259+
setupLog.Info("disabling http/2")
260+
c.NextProtos = []string{"http/1.1"}
261+
}
262+
263+
tlsOpts := []func(*tls.Config){}
264+
if !enableHTTP2 {
265+
tlsOpts = append(tlsOpts, disableHTTP2)
266+
}
267+
268+
webhookServer := webhook.NewServer(webhook.Options{
269+
TLSOpts: tlsOpts,
270+
})
271+
244272
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
245273
Scheme: scheme,
246-
Metrics: metricsserver.Options{BindAddress: metricsAddr},
274+
Metrics: metricsserver.Options{
275+
BindAddress: metricsAddr,
276+
SecureServing: secureMetrics,
277+
TLSOpts: tlsOpts,
278+
},
279+
WebhookServer: webhookServer,
247280
HealthProbeBindAddress: probeAddr,
248281
LeaderElection: enableLeaderElection,
249282
LeaderElectionID: "{{ hashFNV .Repo }}.{{ .Domain }}",

testdata/project-v3/main.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package main
1818

1919
import (
20+
"crypto/tls"
2021
"flag"
2122
"os"
2223

@@ -30,6 +31,7 @@ import (
3031
ctrl "sigs.k8s.io/controller-runtime"
3132
"sigs.k8s.io/controller-runtime/pkg/healthz"
3233
"sigs.k8s.io/controller-runtime/pkg/log/zap"
34+
"sigs.k8s.io/controller-runtime/pkg/webhook"
3335

3436
crewv1 "sigs.k8s.io/kubebuilder/testdata/project-v3/api/v1"
3537
"sigs.k8s.io/kubebuilder/testdata/project-v3/controllers"
@@ -52,11 +54,14 @@ func main() {
5254
var metricsAddr string
5355
var enableLeaderElection bool
5456
var probeAddr string
57+
var enableHTTP2 bool
5558
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
5659
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
5760
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
5861
"Enable leader election for controller manager. "+
5962
"Enabling this will ensure there is only one active controller manager.")
63+
flag.BoolVar(&enableHTTP2, "enable-http2", false,
64+
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
6065
opts := zap.Options{
6166
Development: true,
6267
}
@@ -65,9 +70,28 @@ func main() {
6570

6671
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
6772

73+
// if the enable-http2 flag is false (the default), http/2 should be disabled
74+
// due to its vulnerabilities. More specifically, disabling http/2 will
75+
// prevent from being vulnerable to the HTTP/2 Stream Cancelation and
76+
// Rapid Reset CVEs. For more information see:
77+
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
78+
// - https://github.com/advisories/GHSA-4374-p667-p6c8
79+
disableHTTP2 := func(c *tls.Config) {
80+
setupLog.Info("disabling http/2")
81+
c.NextProtos = []string{"http/1.1"}
82+
}
83+
84+
tlsOpts := []func(*tls.Config){}
85+
if !enableHTTP2 {
86+
tlsOpts = append(tlsOpts, disableHTTP2)
87+
}
88+
6889
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
69-
Scheme: scheme,
70-
MetricsBindAddress: metricsAddr,
90+
Scheme: scheme,
91+
MetricsBindAddress: metricsAddr,
92+
WebhookServer: &webhook.Server{
93+
TLSOpts: tlsOpts,
94+
},
7195
Port: 9443,
7296
HealthProbeBindAddress: probeAddr,
7397
LeaderElection: enableLeaderElection,

testdata/project-v4-multigroup-with-deploy-image/cmd/main.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package main
1818

1919
import (
20+
"crypto/tls"
2021
"flag"
2122
"os"
2223

@@ -31,6 +32,7 @@ import (
3132
"sigs.k8s.io/controller-runtime/pkg/healthz"
3233
"sigs.k8s.io/controller-runtime/pkg/log/zap"
3334
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
35+
"sigs.k8s.io/controller-runtime/pkg/webhook"
3436

3537
crewv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup-with-deploy-image/api/crew/v1"
3638
fizv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup-with-deploy-image/api/fiz/v1"
@@ -78,11 +80,17 @@ func main() {
7880
var metricsAddr string
7981
var enableLeaderElection bool
8082
var probeAddr string
83+
var secureMetrics bool
84+
var enableHTTP2 bool
8185
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
8286
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
8387
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
8488
"Enable leader election for controller manager. "+
8589
"Enabling this will ensure there is only one active controller manager.")
90+
flag.BoolVar(&secureMetrics, "metrics-secure", false,
91+
"If set the metrics endpoint is served securely")
92+
flag.BoolVar(&enableHTTP2, "enable-http2", false,
93+
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
8694
opts := zap.Options{
8795
Development: true,
8896
}
@@ -91,9 +99,34 @@ func main() {
9199

92100
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
93101

102+
// if the enable-http2 flag is false (the default), http/2 should be disabled
103+
// due to its vulnerabilities. More specifically, disabling http/2 will
104+
// prevent from being vulnerable to the HTTP/2 Stream Cancelation and
105+
// Rapid Reset CVEs. For more information see:
106+
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
107+
// - https://github.com/advisories/GHSA-4374-p667-p6c8
108+
disableHTTP2 := func(c *tls.Config) {
109+
setupLog.Info("disabling http/2")
110+
c.NextProtos = []string{"http/1.1"}
111+
}
112+
113+
tlsOpts := []func(*tls.Config){}
114+
if !enableHTTP2 {
115+
tlsOpts = append(tlsOpts, disableHTTP2)
116+
}
117+
118+
webhookServer := webhook.NewServer(webhook.Options{
119+
TLSOpts: tlsOpts,
120+
})
121+
94122
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
95-
Scheme: scheme,
96-
Metrics: metricsserver.Options{BindAddress: metricsAddr},
123+
Scheme: scheme,
124+
Metrics: metricsserver.Options{
125+
BindAddress: metricsAddr,
126+
SecureServing: secureMetrics,
127+
TLSOpts: tlsOpts,
128+
},
129+
WebhookServer: webhookServer,
97130
HealthProbeBindAddress: probeAddr,
98131
LeaderElection: enableLeaderElection,
99132
LeaderElectionID: "65c8a5ec.testproject.org",

0 commit comments

Comments
 (0)