From 426bb7cded93b84e57bef19fa1517306ac77f05e Mon Sep 17 00:00:00 2001 From: Richa Banker Date: Wed, 4 Mar 2026 14:47:05 -0800 Subject: [PATCH] Fix auth registration for statusz and flagz Co-authored-by: Jordan Liggitt --- pkg/kubelet/server/server.go | 24 ++++++++++--------- .../authorizer/rbac/bootstrappolicy/policy.go | 24 ++++++++++--------- .../testdata/cluster-roles-featuregates.yaml | 10 ++------ .../apiserver/pkg/server/genericapiserver.go | 8 +++---- 4 files changed, 32 insertions(+), 34 deletions(-) diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go index 114cda5b715..989d66fceca 100644 --- a/pkg/kubelet/server/server.go +++ b/pkg/kubelet/server/server.go @@ -312,18 +312,17 @@ func NewServer( server.InstallAuthNotRequiredHandlers(ctx) if kubeCfg != nil && kubeCfg.EnableDebuggingHandlers { logger.Info("Adding debug handlers to kubelet server") - server.InstallAuthRequiredHandlers(ctx) // To maintain backward compatibility serve logs and pprof only when enableDebuggingHandlers is also enabled // see https://github.com/kubernetes/kubernetes/pull/87273 server.InstallSystemLogHandler(kubeCfg.EnableSystemLogHandler, kubeCfg.EnableSystemLogQuery) server.InstallProfilingHandler(kubeCfg.EnableProfilingHandler, kubeCfg.EnableContentionProfiling) server.InstallDebugFlagsHandler(kubeCfg.EnableDebugFlagsHandler) + // must be done last so all paths are included in /statusz + server.InstallAuthRequiredHandlers(ctx) } else { server.InstallDebuggingDisabledHandlers() } - server.installStatusZ() - return server } @@ -387,7 +386,14 @@ func (s *Server) InstallTracingFilter(tp oteltrace.TracerProvider, opts ...otelr s.restfulCont.Filter(otelrestful.OTelFilter("kubelet", append(opts, otelrestful.WithTracerProvider(tp))...)) } -func (s *Server) installStatusZ() { +func (s *Server) InstallZPages() { + if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentFlagz) { + if s.flagz != nil { + s.addMetricsBucketMatcher("flagz") + flagz.Install(s.restfulCont, ComponentKubelet, s.flagz) + } + } + // must be done last so all paths are included in /statusz if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) { s.addMetricsBucketMatcher("statusz") statusz.Install(s.restfulCont, ComponentKubelet, statusz.NewRegistry(compatibility.DefaultBuildEffectiveVersion(), statusz.WithListedPaths(s.restfulCont.RegisteredHandlePaths()))) @@ -598,13 +604,6 @@ func (s *Server) InstallAuthRequiredHandlers(ctx context.Context) { s.addMetricsBucketMatcher("configz") configz.InstallHandler(s.restfulCont) - if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentFlagz) { - if s.flagz != nil { - s.addMetricsBucketMatcher("flagz") - flagz.Install(s.restfulCont, ComponentKubelet, s.flagz) - } - } - // The /runningpods endpoint is used for testing only. s.addMetricsBucketMatcher("runningpods") ws = new(restful.WebService) @@ -626,6 +625,9 @@ func (s *Server) InstallAuthRequiredHandlers(ctx context.Context) { Operation("checkpoint")) s.restfulCont.Add(ws) } + + // must be done last so all paths are included in /statusz + s.InstallZPages() } // InstallDebuggingDisabledHandlers registers the HTTP request patterns that provide better error message diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go index 1e3b75cd68b..e78183822c3 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go @@ -293,23 +293,25 @@ func NodeRules() []rbacv1.PolicyRule { // ClusterRoles returns the cluster roles to bootstrap an API server with func ClusterRoles() []rbacv1.ClusterRole { - monitoringRules := []rbacv1.PolicyRule{ - rbacv1helpers.NewRule("get").URLs( - "/metrics", "/metrics/slis", - "/livez", "/readyz", "/healthz", - "/livez/*", "/readyz/*", "/healthz/*", - ).RuleOrDie(), - - // Needed for kubelet metrics - rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("nodes/metrics").RuleOrDie(), + monitoringURLs := []string{ + "/metrics", "/metrics/slis", + "/livez", "/readyz", "/healthz", + "/livez/*", "/readyz/*", "/healthz/*", } if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentFlagz) { - monitoringRules = append(monitoringRules, rbacv1helpers.NewRule("get").URLs("/flagz").RuleOrDie()) + monitoringURLs = append(monitoringURLs, "/flagz") } if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) { - monitoringRules = append(monitoringRules, rbacv1helpers.NewRule("get").URLs("/statusz").RuleOrDie()) + monitoringURLs = append(monitoringURLs, "/statusz") + } + + monitoringRules := []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get").URLs(monitoringURLs...).RuleOrDie(), + + // Needed for kubelet metrics + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("nodes/metrics").RuleOrDie(), } roles := []rbacv1.ClusterRole{ diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles-featuregates.yaml b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles-featuregates.yaml index 31d6a31bc30..3ef7e645a15 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles-featuregates.yaml +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles-featuregates.yaml @@ -1052,6 +1052,7 @@ items: name: system:monitoring rules: - nonResourceURLs: + - /flagz - /healthz - /healthz/* - /livez @@ -1060,6 +1061,7 @@ items: - /metrics/slis - /readyz - /readyz/* + - /statusz verbs: - get - apiGroups: @@ -1068,14 +1070,6 @@ items: - nodes/metrics verbs: - get - - nonResourceURLs: - - /flagz - verbs: - - get - - nonResourceURLs: - - /statusz - verbs: - - get - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go index 840fff4c180..715501f67c8 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go +++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go @@ -468,15 +468,15 @@ func (s *GenericAPIServer) PrepareRun() preparedGenericAPIServer { s.installReadyz() componentName := "apiserver" - if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) { - statusz.Install(s.Handler.NonGoRestfulMux, componentName, statusz.NewRegistry(s.EffectiveVersion, statusz.WithListedPaths(s.ListedPaths()))) - } - if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentFlagz) { if s.Flagz != nil { flagz.Install(s.Handler.NonGoRestfulMux, componentName, s.Flagz) } } + // statusz is installed last so that it can list all the paths that have been registered + if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) { + statusz.Install(s.Handler.NonGoRestfulMux, componentName, statusz.NewRegistry(s.EffectiveVersion, statusz.WithListedPaths(s.ListedPaths()))) + } return preparedGenericAPIServer{s} }