1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-23 07:19:41 +02:00

feat(registries): Registry browser for non-admins [EE-2459] (#6549)

* feat(registries): allow non-admin users to see environment registries

* remove unused function

* fix error message

* fix test

* fix imports order

* feat(registry): check access first, add parameters name

* use registryID

* fix(sidebar): allow standard users to see endpoint registries view

Co-authored-by: LP B <xAt0mZ@users.noreply.github.com>
This commit is contained in:
Marcelo Rydel 2022-04-07 10:22:31 -03:00 committed by GitHub
parent 77e48bfb74
commit f9f937f844
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 226 additions and 202 deletions

View file

@ -5,6 +5,7 @@ import (
"github.com/gorilla/mux"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/http/proxy"
@ -45,27 +46,27 @@ func newHandler(bouncer *security.RequestBouncer) *Handler {
}
}
func (h *Handler) initRouter(bouncer accessGuard) {
h.Handle("/registries",
bouncer.AdminAccess(httperror.LoggerHandler(h.registryCreate))).Methods(http.MethodPost)
h.Handle("/registries",
bouncer.RestrictedAccess(httperror.LoggerHandler(h.registryList))).Methods(http.MethodGet)
h.Handle("/registries/{id}",
bouncer.RestrictedAccess(httperror.LoggerHandler(h.registryInspect))).Methods(http.MethodGet)
h.Handle("/registries/{id}",
bouncer.AdminAccess(httperror.LoggerHandler(h.registryUpdate))).Methods(http.MethodPut)
h.Handle("/registries/{id}/configure",
bouncer.AdminAccess(httperror.LoggerHandler(h.registryConfigure))).Methods(http.MethodPost)
h.Handle("/registries/{id}",
bouncer.AdminAccess(httperror.LoggerHandler(h.registryDelete))).Methods(http.MethodDelete)
h.PathPrefix("/registries/proxies/gitlab").Handler(
bouncer.AdminAccess(httperror.LoggerHandler(h.proxyRequestsToGitlabAPIWithoutRegistry)))
func (handler *Handler) initRouter(bouncer accessGuard) {
adminRouter := handler.NewRoute().Subrouter()
adminRouter.Use(bouncer.AdminAccess)
authenticatedRouter := handler.NewRoute().Subrouter()
authenticatedRouter.Use(bouncer.AuthenticatedAccess)
adminRouter.Handle("/registries", httperror.LoggerHandler(handler.registryList)).Methods(http.MethodGet)
adminRouter.Handle("/registries", httperror.LoggerHandler(handler.registryCreate)).Methods(http.MethodPost)
adminRouter.Handle("/registries/{id}", httperror.LoggerHandler(handler.registryUpdate)).Methods(http.MethodPut)
adminRouter.Handle("/registries/{id}/configure", httperror.LoggerHandler(handler.registryConfigure)).Methods(http.MethodPost)
adminRouter.Handle("/registries/{id}", httperror.LoggerHandler(handler.registryDelete)).Methods(http.MethodDelete)
authenticatedRouter.Handle("/registries/{id}", httperror.LoggerHandler(handler.registryInspect)).Methods(http.MethodGet)
authenticatedRouter.PathPrefix("/registries/proxies/gitlab").Handler(httperror.LoggerHandler(handler.proxyRequestsToGitlabAPIWithoutRegistry))
}
type accessGuard interface {
AdminAccess(h http.Handler) http.Handler
RestrictedAccess(h http.Handler) http.Handler
AuthenticatedAccess(h http.Handler) http.Handler
AuthorizedEndpointOperation(r *http.Request, endpoint *portainer.Endpoint) error
}
func (handler *Handler) registriesHaveSameURLAndCredentials(r1, r2 *portainer.Registry) bool {
@ -78,3 +79,30 @@ func (handler *Handler) registriesHaveSameURLAndCredentials(r1, r2 *portainer.Re
return hasSameUrl && hasSameCredentials && r1.Gitlab.ProjectPath == r2.Gitlab.ProjectPath
}
func (handler *Handler) userHasRegistryAccess(r *http.Request) (hasAccess bool, isAdmin bool, err error) {
securityContext, err := security.RetrieveRestrictedRequestContext(r)
if err != nil {
return false, false, err
}
if securityContext.IsAdmin {
return true, true, nil
}
endpointID, err := request.RetrieveNumericQueryParameter(r, "endpointId", false)
if err != nil {
return false, false, err
}
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if err != nil {
return false, false, err
}
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
if err != nil {
return false, false, err
}
return true, false, nil
}