fix(authz): metrics: deny authenticated users not in ACL even with anonymous read (#4131)

* fix(authz): metrics: reject users not in list even with anonymous read

Even when anonymous reads are enabled for metrics, users not in the
allowed list should not be allowed.

This change also refactors the MetricsAuthzHandler to align better
with this logic.

Signed-off-by: Vishwas Rajashekar <dev@vrajashkr.com>

* fix(authz): address review comments

Address comments to pass username when present
to AuthzFail if user is not allowed for metrics.
This changes the response to Forbidden instead of
Unauthorized.

Use isAnonymous() check instead of only checking for
empty username.

Signed-off-by: Vishwas Rajashekar <dev@vrajashkr.com>

* fix(authz): fix additional review comments

Fix a few more review comments

Signed-off-by: Vishwas Rajashekar <dev@vrajashkr.com>

---------

Signed-off-by: Vishwas Rajashekar <dev@vrajashkr.com>
This commit is contained in:
Vishwas Rajashekar
2026-06-14 19:59:22 +05:30
committed by GitHub
parent 6a143cadfa
commit c18a4a975d
2 changed files with 88 additions and 25 deletions
+24 -19
View File
@@ -741,21 +741,6 @@ func MetricsAuthzHandler(ctlr *Controller) mux.MiddlewareFunc {
return
}
metricsConfig := accessControlConfig.GetMetrics()
if slices.Contains(metricsConfig.AnonymousPolicy, constants.ReadPermission) {
next.ServeHTTP(response, request)
return
}
if len(metricsConfig.Users) == 0 {
log := ctlr.Log
log.Warn().Msg("auth is enabled but no metrics users in accessControl: /metrics is unaccesible")
common.AuthzFail(response, request, "", realm, failDelay)
return
}
// get access control context made in authn.go
userAc, err := reqCtx.UserAcFromContext(request.Context())
if err != nil { // should never happen
@@ -764,11 +749,31 @@ func MetricsAuthzHandler(ctlr *Controller) mux.MiddlewareFunc {
return
}
username := userAc.GetUsername()
if !slices.Contains(metricsConfig.Users, username) {
common.AuthzFail(response, request, username, realm, failDelay)
metricsAccessConfig := accessControlConfig.GetMetrics()
return
if userAc.IsAnonymous() {
// If anonymous read is not specified in access control, deny.
if !slices.Contains(metricsAccessConfig.AnonymousPolicy, constants.ReadPermission) {
common.AuthzFail(response, request, "", realm, failDelay)
return
}
} else {
username := userAc.GetUsername()
if len(metricsAccessConfig.Users) == 0 {
log := ctlr.Log
log.Warn().Msg("no users configured in metrics user list; " +
"metrics are not accessible to any authenticated user.")
common.AuthzFail(response, request, username, realm, failDelay)
return
}
if !slices.Contains(metricsAccessConfig.Users, username) {
common.AuthzFail(response, request, username, realm, failDelay)
return
}
}
next.ServeHTTP(response, request) //nolint:contextcheck