Skip to content

Commit 8bda8b1

Browse files
authored
feat: replace kube rbac proxy with controller runtime authn (argoproj-labs#2119)
* chore: replace deprecated kube-rbac-proxy with controller-runtime authn/authz The gcr.io/kubebuilder/kube-rbac-proxy image is deprecated and no longer available. This commit replaces the kube-rbac-proxy sidecar approach with controller-runtime's built-in WithAuthenticationAndAuthorization filter for securing the /metrics endpoint. The existing RBAC roles for tokenreviews and subjectaccessreviews are retained as they are required by the controller-runtime authn/authz. Fixes: argoproj-labs#1613 Signed-off-by: Kerruba <2854782+Kerruba@users.noreply.github.com> Signed-off-by: Luca Cherubin <Kerruba@users.noreply.github.com> * fix: implemented single-toggle wiring combining deployment/service patch in manager_auth_proxy_patch Signed-off-by: Luca Cherubin <2854782+Kerruba@users.noreply.github.com> Signed-off-by: Luca Cherubin <Kerruba@users.noreply.github.com> * refactor(kustomize): split manager auth patches and restore default behavior with disabled patches Migrate metrics auth patching in config/default/kustomization.yaml to `patches` with separate deployment/service patch files. - split manager_auth_proxy_patch.yaml into: - manager_auth_proxy_patch.yaml (Deployment) - manager_auth_proxy_service_patch.yaml (Service) - keep both manager auth patch entries commented out by default - update cmd/main_test.go to validate split files and disabled-by-default toggle Signed-off-by: Luca Cherubin <2854782+Kerruba@users.noreply.github.com> Signed-off-by: Luca Cherubin <Kerruba@users.noreply.github.com> * chore: remove unnecessary changes Signed-off-by: Luca Cherubin <Kerruba@users.noreply.github.com> * docs: clean up formatting in development guide Signed-off-by: Luca Cherubin <Kerruba@users.noreply.github.com> * fix: address secure metrics review feedback Rename the auth_proxy patch and RBAC manifests to metrics-oriented names, remove the extra manifest tests from cmd/main_test.go, and align the secure metrics path to use 8443 across config, docs, and generated bundle/catalog manifests Signed-off-by: Luca Cherubin <Kerruba@users.noreply.github.com> --------- Signed-off-by: Kerruba <2854782+Kerruba@users.noreply.github.com> Signed-off-by: Luca Cherubin <Kerruba@users.noreply.github.com> Signed-off-by: Luca Cherubin <2854782+Kerruba@users.noreply.github.com> Co-authored-by: Luca Cherubin <Kerruba@users.noreply.github.com>
1 parent 954fe01 commit 8bda8b1

19 files changed

Lines changed: 208 additions & 86 deletions

bundle/manifests/argocd-operator-controller-manager-metrics-service_v1_service.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ spec:
99
ports:
1010
- name: https
1111
port: 8443
12-
targetPort: 8080
12+
targetPort: 8443
1313
selector:
1414
control-plane: controller-manager
1515
status:

bundle/manifests/argocd-operator.clusterserviceversion.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ metadata:
257257
capabilities: Deep Insights
258258
categories: Integration & Delivery
259259
certified: "false"
260-
createdAt: "2026-04-07T11:15:03Z"
260+
createdAt: "2026-04-08T14:38:12Z"
261261
description: Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.
262262
operators.operatorframework.io/builder: operator-sdk-v1.35.0
263263
operators.operatorframework.io/project_layout: go.kubebuilder.io/v4
@@ -1946,6 +1946,9 @@ spec:
19461946
spec:
19471947
containers:
19481948
- args:
1949+
- --health-probe-bind-address=:8081
1950+
- --metrics-bind-address=:8443
1951+
- --metrics-secure
19491952
- --leader-elect
19501953
command:
19511954
- /manager
@@ -1968,6 +1971,9 @@ spec:
19681971
- containerPort: 9443
19691972
name: webhook-server
19701973
protocol: TCP
1974+
- containerPort: 8443
1975+
name: https
1976+
protocol: TCP
19711977
readinessProbe:
19721978
httpGet:
19731979
path: /readyz

cmd/main.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import (
4040
"github.com/argoproj-labs/argocd-operator/controllers/argocdexport"
4141
"github.com/argoproj-labs/argocd-operator/controllers/argoutil"
4242

43+
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
4344
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
4445

4546
notificationsConfig "github.com/argoproj-labs/argocd-operator/controllers/notificationsconfiguration"
@@ -143,11 +144,7 @@ func main() {
143144
}
144145
webhookServer := webhook.NewServer(webhookServerOptions)
145146

146-
metricsServerOptions := metricsserver.Options{
147-
SecureServing: secureMetrics,
148-
BindAddress: metricsAddr,
149-
TLSOpts: []func(*tls.Config){disableHTTP2},
150-
}
147+
metricsServerOptions := buildMetricsServerOptions(metricsAddr, secureMetrics, []func(*tls.Config){disableHTTP2})
151148

152149
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
153150

@@ -370,3 +367,17 @@ func initK8sClient() (*kubernetes.Clientset, error) {
370367

371368
return k8sClient, nil
372369
}
370+
371+
func buildMetricsServerOptions(metricsAddr string, secureMetrics bool, tlsOpts []func(*tls.Config)) metricsserver.Options {
372+
opts := metricsserver.Options{
373+
SecureServing: secureMetrics,
374+
BindAddress: metricsAddr,
375+
TLSOpts: tlsOpts,
376+
}
377+
378+
if secureMetrics {
379+
opts.FilterProvider = filters.WithAuthenticationAndAuthorization
380+
}
381+
382+
return opts
383+
}

cmd/main_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package main
2+
3+
import (
4+
"crypto/tls"
5+
"testing"
6+
)
7+
8+
func TestBuildMetricsServerOptions_SecureDisabled(t *testing.T) {
9+
opts := buildMetricsServerOptions(":8080", false, nil)
10+
11+
if opts.SecureServing {
12+
t.Error("expected SecureServing to be false")
13+
}
14+
if opts.BindAddress != ":8080" {
15+
t.Errorf("expected BindAddress :8080, got %s", opts.BindAddress)
16+
}
17+
if opts.FilterProvider != nil {
18+
t.Error("expected FilterProvider to be nil when secureMetrics is false")
19+
}
20+
}
21+
22+
func TestBuildMetricsServerOptions_SecureEnabled(t *testing.T) {
23+
opts := buildMetricsServerOptions(":8443", true, nil)
24+
25+
if !opts.SecureServing {
26+
t.Error("expected SecureServing to be true")
27+
}
28+
if opts.BindAddress != ":8443" {
29+
t.Errorf("expected BindAddress :8443, got %s", opts.BindAddress)
30+
}
31+
if opts.FilterProvider == nil {
32+
t.Error("expected FilterProvider to be set when secureMetrics is true")
33+
}
34+
}
35+
36+
func TestBuildMetricsServerOptions_TLSOptsPassedThrough(t *testing.T) {
37+
called := false
38+
tlsOpt := func(c *tls.Config) { called = true }
39+
40+
opts := buildMetricsServerOptions(":8080", false, []func(*tls.Config){tlsOpt})
41+
42+
if len(opts.TLSOpts) != 1 {
43+
t.Fatalf("expected 1 TLS option, got %d", len(opts.TLSOpts))
44+
}
45+
opts.TLSOpts[0](&tls.Config{})
46+
if !called {
47+
t.Error("expected TLS option to be called")
48+
}
49+
}

config/default/kustomization.yaml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ resources:
2525
# - ../prometheus
2626

2727
patches:
28-
# Protect the /metrics endpoint by putting it behind auth.
29-
# If you want your controller-manager to expose the /metrics
30-
# endpoint w/o any authn/z, please comment the following line.
31-
#- path: manager_auth_proxy_patch.yaml
28+
# Protect the /metrics endpoint with controller-runtime authn/authz.
29+
# If you comment out manager_metrics_patch.yaml, also comment out metrics_service.yaml,
30+
# metrics_role.yaml, metrics_role_binding.yaml, and metrics_reader_clusterrole.yaml
31+
# in ../rbac/kustomization.yaml so the metrics Service is disabled as well.
32+
- path: manager_metrics_patch.yaml
3233

3334
# Mount the controller config file for loading manager configurations
3435
# through a ComponentConfig type

config/default/manager_auth_proxy_patch.yaml

Lines changed: 0 additions & 43 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# This patch configures the manager to serve metrics securely using
2+
# controller-runtime's built-in authn/authz (replacing the deprecated
3+
# kube-rbac-proxy sidecar).
4+
apiVersion: apps/v1
5+
kind: Deployment
6+
metadata:
7+
name: controller-manager
8+
namespace: system
9+
spec:
10+
template:
11+
spec:
12+
containers:
13+
- name: manager
14+
args:
15+
- "--health-probe-bind-address=:8081"
16+
- "--metrics-bind-address=:8443"
17+
- "--metrics-secure"
18+
- "--leader-elect"
19+
ports:
20+
- containerPort: 8443
21+
protocol: TCP
22+
name: https

config/rbac/kustomization.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ resources:
99
- role_binding.yaml
1010
- leader_election_role.yaml
1111
- leader_election_role_binding.yaml
12-
# Comment the following 4 lines if you want to disable
13-
# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
14-
# which protects your /metrics endpoint.
15-
- auth_proxy_service.yaml
16-
- auth_proxy_role.yaml
17-
- auth_proxy_role_binding.yaml
18-
- auth_proxy_client_clusterrole.yaml
12+
# These resources expose /metrics over HTTPS on port 8443 and grant the
13+
# controller-runtime authn/authz permissions required by manager_metrics_patch.yaml.
14+
# Comment these lines together with manager_metrics_patch.yaml if you want to
15+
# disable secure metrics for the controller-manager.
16+
- metrics_service.yaml
17+
- metrics_role.yaml
18+
- metrics_role_binding.yaml
19+
- metrics_reader_clusterrole.yaml
1920
# For each CRD, "Editor" and "Viewer" roles are scaffolded by
2021
# default, aiding admins in cluster management. Those roles are
2122
# not used by the Project itself. You can comment the following lines
2223
# if you do not want those helpers be installed with your Project.
2324
- namespacemanagement_editor_role.yaml
2425
- namespacemanagement_viewer_role.yaml
25-
File renamed without changes.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
apiVersion: rbac.authorization.k8s.io/v1
22
kind: ClusterRole
33
metadata:
4-
name: proxy-role
4+
name: metrics-role
55
rules:
66
- apiGroups:
77
- authentication.k8s.io

0 commit comments

Comments
 (0)