Skip to content

Commit

Permalink
fix: metrics should be protected behind authZ
Browse files Browse the repository at this point in the history
Signed-off-by: Alexei Dodon <[email protected]>
  • Loading branch information
adodon2go committed Oct 16, 2023
1 parent 12227b4 commit 7e4f8cb
Show file tree
Hide file tree
Showing 22 changed files with 758 additions and 383 deletions.
7 changes: 6 additions & 1 deletion examples/config-metrics.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
},
"http": {
"address": "127.0.0.1",
"port": "8080"
"port": "8080",
"auth": {
"htpasswd": {
"path": "test/data/htpasswd"
}
}
},
"log": {
"level": "debug"
Expand Down
4 changes: 2 additions & 2 deletions pkg/api/authn.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func AuthHandler(ctlr *Controller) mux.MiddlewareFunc {
return bearerAuthHandler(ctlr)
}

return authnMiddleware.TryAuthnHandlers(ctlr)
return authnMiddleware.tryAuthnHandlers(ctlr)
}

func (amw *AuthnMiddleware) sessionAuthn(ctlr *Controller, userAc *reqCtx.UserAccessControl,
Expand Down Expand Up @@ -250,7 +250,7 @@ func (amw *AuthnMiddleware) basicAuthn(ctlr *Controller, userAc *reqCtx.UserAcce
return false, nil
}

func (amw *AuthnMiddleware) TryAuthnHandlers(ctlr *Controller) mux.MiddlewareFunc { //nolint: gocyclo
func (amw *AuthnMiddleware) tryAuthnHandlers(ctlr *Controller) mux.MiddlewareFunc { //nolint: gocyclo
// no password based authN, if neither LDAP nor HTTP BASIC is enabled
if !ctlr.Config.IsBasicAuthnEnabled() {
return noPasswdAuth(ctlr)
Expand Down
61 changes: 44 additions & 17 deletions pkg/api/authz.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,10 @@ func (ac *AccessController) getAuthnMiddlewareContext(authnType string, request
func (ac *AccessController) isPermitted(userGroups []string, username, action string,
policyGroup config.PolicyGroup,
) bool {
var result bool

// check repo/system based policies
for _, p := range policyGroup.Policies {
if common.Contains(p.Users, username) && common.Contains(p.Actions, action) {
result = true

return result
return true
}
}

Expand All @@ -207,30 +203,24 @@ func (ac *AccessController) isPermitted(userGroups []string, username, action st
if common.Contains(p.Actions, action) {
for _, group := range p.Groups {
if common.Contains(userGroups, group) {
result = true

return result
return true
}
}
}
}
}

// check defaultPolicy
if !result {
if common.Contains(policyGroup.DefaultPolicy, action) && username != "" {
result = true
}
if common.Contains(policyGroup.DefaultPolicy, action) && username != "" {
return true
}

// check anonymousPolicy
if !result {
if common.Contains(policyGroup.AnonymousPolicy, action) && username == "" {
result = true
}
if common.Contains(policyGroup.AnonymousPolicy, action) && username == "" {
return true
}

return result
return false
}

func BaseAuthzHandler(ctlr *Controller) mux.MiddlewareFunc {
Expand Down Expand Up @@ -343,3 +333,40 @@ func DistSpecAuthzHandler(ctlr *Controller) mux.MiddlewareFunc {
})
}
}

func MetricsAuthzHandler(ctlr *Controller) mux.MiddlewareFunc {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
if ctlr.Config.HTTP.AccessControl == nil {
// allow access to authenticated user as anonymous policy does not exist
next.ServeHTTP(response, request)

return
}
if len(ctlr.Config.HTTP.AccessControl.Metrics.Users) == 0 {
log := ctlr.Log
log.Warn().Msg("auth is enabled but no metrics users in accessControl: /metrics is unaccesible")
common.AuthzFail(response, request, "", ctlr.Config.HTTP.Realm, ctlr.Config.HTTP.Auth.FailDelay)

return
}

// get access control context made in authn.go
userAc, err := reqCtx.UserAcFromContext(request.Context())
if err != nil { // should never happen
common.AuthzFail(response, request, "", ctlr.Config.HTTP.Realm, ctlr.Config.HTTP.Auth.FailDelay)

return
}

Check warning on line 360 in pkg/api/authz.go

View check run for this annotation

Codecov / codecov/patch

pkg/api/authz.go#L357-L360

Added lines #L357 - L360 were not covered by tests

username := userAc.GetUsername()
if !common.Contains(ctlr.Config.HTTP.AccessControl.Metrics.Users, username) {
common.AuthzFail(response, request, username, ctlr.Config.HTTP.Realm, ctlr.Config.HTTP.Auth.FailDelay)

return
}

next.ServeHTTP(response, request) //nolint:contextcheck
})
}
}
5 changes: 5 additions & 0 deletions pkg/api/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ type AccessControlConfig struct {
Repositories Repositories `json:"repositories" mapstructure:"repositories"`
AdminPolicy Policy
Groups Groups
Metrics Metrics
}

func (config *AccessControlConfig) AnonymousPolicyExists() bool {
Expand Down Expand Up @@ -168,6 +169,10 @@ type Policy struct {
Groups []string
}

type Metrics struct {
Users []string
}

type Config struct {
DistSpecVersion string `json:"distSpecVersion" mapstructure:"distSpecVersion"`
GoVersion string
Expand Down
Loading

0 comments on commit 7e4f8cb

Please sign in to comment.