Skip to content

Commit 9c69814

Browse files
Camila Mcamilamacedo86
authored andcommitted
Replace kube-rbac-proxy with controller-runtime metrics authentication/authorization
This commit removes the use of the kube-rbac-proxy image and replaces it with metrics authentication/authorization provided by controller-runtime. The kube-rbac-proxy image is deprecated and will no longer be maintained, which introduces risks to production environments. For more details, see: kubernetes-sigs/kubebuilder#3907 Key changes: - Updated to configure metrics server options with secure authentication/authorization using controller-runtime filters. - Added support for disabling HTTP/2 by default to mitigate vulnerabilities (e.g., HTTP/2 Stream Cancellation CVE). - Changed the default metrics endpoint to HTTPS (port 8443) and removed the kube-rbac-proxy container from deployment configurations. This aligns with best practices for security and simplifies the metrics setup by leveraging built-in capabilities of controller-runtime.
1 parent a723f9a commit 9c69814

File tree

6 files changed

+84
-31
lines changed

6 files changed

+84
-31
lines changed

cmd/manager/main.go

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ package main
1818

1919
import (
2020
"context"
21+
"crypto/tls"
2122
"flag"
2223
"fmt"
24+
"log"
2325
"net/http"
2426
"os"
2527
"path/filepath"
@@ -41,9 +43,11 @@ import (
4143
"k8s.io/klog/v2/textlogger"
4244
ctrl "sigs.k8s.io/controller-runtime"
4345
crcache "sigs.k8s.io/controller-runtime/pkg/cache"
46+
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
4447
"sigs.k8s.io/controller-runtime/pkg/client"
4548
crfinalizer "sigs.k8s.io/controller-runtime/pkg/finalizer"
4649
"sigs.k8s.io/controller-runtime/pkg/healthz"
50+
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
4751
"sigs.k8s.io/controller-runtime/pkg/metrics/server"
4852

4953
catalogd "github.com/operator-framework/catalogd/api/v1"
@@ -89,17 +93,22 @@ func podNamespace() string {
8993
func main() {
9094
var (
9195
metricsAddr string
96+
tlsOpts []func(*tls.Config)
9297
enableLeaderElection bool
9398
probeAddr string
9499
cachePath string
95100
operatorControllerVersion bool
96101
systemNamespace string
97102
caCertDir string
103+
certFile string
104+
keyFile string
98105
globalPullSecret string
99106
)
100-
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
107+
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8443", "The address the metric endpoint binds to.")
101108
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
102109
flag.StringVar(&caCertDir, "ca-certs-dir", "", "The directory of TLS certificate to use for verifying HTTPS connections to the Catalogd and docker-registry web servers.")
110+
flag.StringVar(&certFile, "tls-cert", "", "The certificate file used for serving catalog contents over HTTPS. Requires tls-key.")
111+
flag.StringVar(&keyFile, "tls-key", "", "The key file used for serving catalog contents over HTTPS. Requires tls-cert.")
103112
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
104113
"Enable leader election for controller manager. "+
105114
"Enabling this will ensure there is only one active controller manager.")
@@ -119,6 +128,11 @@ func main() {
119128
os.Exit(0)
120129
}
121130

131+
if (certFile != "" && keyFile == "") || (certFile == "" && keyFile != "") {
132+
setupLog.Error(nil, "unable to configure TLS certificates: tls-cert and tls-key flags must be used together")
133+
os.Exit(1)
134+
}
135+
122136
ctrl.SetLogger(textlogger.NewLogger(textlogger.NewConfig()))
123137

124138
setupLog.Info("starting up the controller", "version info", version.String())
@@ -161,9 +175,48 @@ func main() {
161175
},
162176
}
163177
}
178+
179+
// http/2 should be disabled due to its vulnerabilities. More specifically,
180+
// disabling http/2 will prevent it from being vulnerable to the HTTP/2 Stream
181+
// Cancellation and Rapid Reset CVEs. For more information see:
182+
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
183+
// - https://github.com/advisories/GHSA-4374-p667-p6c8
184+
disableHTTP2 := func(c *tls.Config) {
185+
setupLog.Info("disabling http/2")
186+
c.NextProtos = []string{"http/1.1"}
187+
}
188+
189+
tlsOpts = append(tlsOpts, disableHTTP2)
190+
191+
// Create a new certificate watcher to watch for changes in the certificate files.
192+
// If the certificate files change, the certificate watcher will reload the certificate
193+
// and key files and update the TLS configuration.
194+
cw, err := certwatcher.New(certFile, keyFile)
195+
if err != nil {
196+
log.Fatalf("Failed to initialize certificate watcher: %v", err)
197+
}
198+
199+
// Ensure that metrics is protected with certs managed by cert-manager
200+
// If not informed, the metrics service provided by controller-runtime will generate
201+
// and use its own self-assigned certs which is not recommended for production envs.
202+
tlsOpts = append(tlsOpts, func(cfg *tls.Config) {
203+
cfg.GetCertificate = cw.GetCertificate
204+
})
205+
206+
metricsServerOptions := server.Options{
207+
BindAddress: metricsAddr,
208+
SecureServing: true,
209+
TLSOpts: tlsOpts,
210+
211+
// FilterProvider is used to protect the metrics endpoint with authn/authz.
212+
// These configurations ensure that only authorized users and service accounts
213+
// can access the metrics endpoint.
214+
FilterProvider: filters.WithAuthenticationAndAuthorization,
215+
}
216+
164217
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
165218
Scheme: scheme.Scheme,
166-
Metrics: server.Options{BindAddress: metricsAddr},
219+
Metrics: metricsServerOptions,
167220
HealthProbeBindAddress: probeAddr,
168221
LeaderElection: enableLeaderElection,
169222
LeaderElectionID: "9c4404e7.operatorframework.io",

config/base/manager/manager.yaml

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ spec:
5252
- /manager
5353
args:
5454
- "--health-probe-bind-address=:8081"
55-
- "--metrics-bind-address=127.0.0.1:8080"
55+
- "--metrics-bind-address=0.0.0.0:8443"
5656
- "--leader-elect"
5757
image: controller:latest
5858
imagePullPolicy: IfNotPresent
@@ -84,27 +84,6 @@ spec:
8484
cpu: 10m
8585
memory: 64Mi
8686
terminationMessagePolicy: FallbackToLogsOnError
87-
- name: kube-rbac-proxy
88-
securityContext:
89-
allowPrivilegeEscalation: false
90-
capabilities:
91-
drop:
92-
- "ALL"
93-
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.15.0
94-
args:
95-
- --secure-listen-address=0.0.0.0:8443
96-
- --http2-disable
97-
- --upstream=http://127.0.0.1:8080/
98-
- --logtostderr=true
99-
ports:
100-
- containerPort: 8443
101-
protocol: TCP
102-
name: https
103-
resources:
104-
requests:
105-
cpu: 5m
106-
memory: 64Mi
107-
terminationMessagePolicy: FallbackToLogsOnError
10887
serviceAccountName: operator-controller-controller-manager
10988
terminationGracePeriodSeconds: 10
11089
volumes:

config/base/rbac/kustomization.yaml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ resources:
1717
- extension_editor_role.yaml
1818
- extension_viewer_role.yaml
1919

20-
# Comment the following 4 lines if you want to disable
21-
# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
22-
# which protects your /metrics endpoint.
20+
# The following RBAC configurations are used to protect
21+
# the metrics endpoint with authn/authz. These configurations
22+
# ensure that only authorized users and service accounts
23+
# can access the metrics endpoint. Comment the following
24+
# permissions if you want to disable this protection.
25+
# More info: https://book.kubebuilder.io/reference/metrics.html
2326
- auth_proxy_service.yaml
2427
- auth_proxy_role.yaml
2528
- auth_proxy_role_binding.yaml

config/components/coverage/manager_e2e_coverage_patch.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ spec:
77
template:
88
spec:
99
containers:
10-
- name: kube-rbac-proxy
1110
- name: manager
1211
env:
1312
- name: GOCOVERDIR

config/components/registries-conf/manager_e2e_registries_conf_patch.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ spec:
77
template:
88
spec:
99
containers:
10-
- name: kube-rbac-proxy
1110
- name: manager
1211
volumeMounts:
1312
- name: e2e-registries-conf
Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,29 @@
11
- op: add
22
path: /spec/template/spec/volumes/-
3-
value: {"name":"olmv1-certificate", "secret":{"secretName":"olmv1-cert", "optional": false, "items": [{"key": "ca.crt", "path": "olm-ca.crt"}]}}
3+
value:
4+
name: "olmv1-certificate"
5+
secret:
6+
secretName: "olmv1-cert"
7+
optional: false
8+
items:
9+
- key: "ca.crt"
10+
path: "olm-ca.crt"
11+
- key: "tls.crt"
12+
path: "olm-tls.crt"
13+
- key: "tls.key"
14+
path: "olm-tls.key"
415
- op: add
516
path: /spec/template/spec/containers/0/volumeMounts/-
6-
value: {"name":"olmv1-certificate", "readOnly": true, "mountPath":"/var/certs/"}
17+
value:
18+
name: "olmv1-certificate"
19+
readOnly: true
20+
mountPath: "/var/certs/"
721
- op: add
822
path: /spec/template/spec/containers/0/args/-
923
value: "--ca-certs-dir=/var/certs"
24+
- op: add
25+
path: /spec/template/spec/containers/0/args/-
26+
value: "--tls-cert=/var/certs/olm-tls.crt"
27+
- op: add
28+
path: /spec/template/spec/containers/0/args/-
29+
value: "--tls-key=/var/certs/olm-tls.key"

0 commit comments

Comments
 (0)