mirror of
https://github.com/portainer/portainer.git
synced 2025-08-02 20:35:25 +02:00
fix(api): add an authenticated access policy to the websocket endpoint (#1979)
* fix(api): add an authenticated access policy to the websocket endpoint * refactor(api): centralize EndpointAccess validation * feat(api): validate id query parameter for the /websocket/exec endpoint
This commit is contained in:
parent
f3ce5c25de
commit
da5a430b8c
14 changed files with 100 additions and 124 deletions
|
@ -11,16 +11,16 @@ import (
|
|||
// Handler is the HTTP handler used to proxy requests to external APIs.
|
||||
type Handler struct {
|
||||
*mux.Router
|
||||
EndpointService portainer.EndpointService
|
||||
EndpointGroupService portainer.EndpointGroupService
|
||||
TeamMembershipService portainer.TeamMembershipService
|
||||
ProxyManager *proxy.Manager
|
||||
requestBouncer *security.RequestBouncer
|
||||
EndpointService portainer.EndpointService
|
||||
ProxyManager *proxy.Manager
|
||||
}
|
||||
|
||||
// NewHandler creates a handler to proxy requests to external APIs.
|
||||
func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
||||
h := &Handler{
|
||||
Router: mux.NewRouter(),
|
||||
Router: mux.NewRouter(),
|
||||
requestBouncer: bouncer,
|
||||
}
|
||||
h.PathPrefix("/{id}/azure").Handler(
|
||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.proxyRequestsToAzureAPI)))
|
||||
|
@ -30,21 +30,3 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
|||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.proxyRequestsToStoridgeAPI)))
|
||||
return h
|
||||
}
|
||||
|
||||
func (handler *Handler) checkEndpointAccess(endpoint *portainer.Endpoint, userID portainer.UserID) error {
|
||||
memberships, err := handler.TeamMembershipService.TeamMembershipsByUserID(userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
group, err := handler.EndpointGroupService.EndpointGroup(endpoint.GroupID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !security.AuthorizedEndpointAccess(endpoint, group, userID, memberships) {
|
||||
return portainer.ErrEndpointAccessDenied
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/portainer/portainer"
|
||||
httperror "github.com/portainer/portainer/http/error"
|
||||
"github.com/portainer/portainer/http/request"
|
||||
"github.com/portainer/portainer/http/security"
|
||||
|
||||
"net/http"
|
||||
)
|
||||
|
@ -24,18 +23,9 @@ func (handler *Handler) proxyRequestsToAzureAPI(w http.ResponseWriter, r *http.R
|
|||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
||||
}
|
||||
|
||||
tokenData, err := security.RetrieveTokenData(r)
|
||||
err = handler.requestBouncer.EndpointAccess(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve user authentication token", err}
|
||||
}
|
||||
|
||||
if tokenData.Role != portainer.AdministratorRole {
|
||||
err = handler.checkEndpointAccess(endpoint, tokenData.ID)
|
||||
if err != nil && err == portainer.ErrEndpointAccessDenied {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to verify permission to access endpoint", err}
|
||||
}
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
||||
}
|
||||
|
||||
var proxy http.Handler
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/portainer/portainer"
|
||||
httperror "github.com/portainer/portainer/http/error"
|
||||
"github.com/portainer/portainer/http/request"
|
||||
"github.com/portainer/portainer/http/security"
|
||||
|
||||
"net/http"
|
||||
)
|
||||
|
@ -24,18 +23,9 @@ func (handler *Handler) proxyRequestsToDockerAPI(w http.ResponseWriter, r *http.
|
|||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
||||
}
|
||||
|
||||
tokenData, err := security.RetrieveTokenData(r)
|
||||
err = handler.requestBouncer.EndpointAccess(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve user authentication token", err}
|
||||
}
|
||||
|
||||
if tokenData.Role != portainer.AdministratorRole {
|
||||
err = handler.checkEndpointAccess(endpoint, tokenData.ID)
|
||||
if err != nil && err == portainer.ErrEndpointAccessDenied {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to verify permission to access endpoint", err}
|
||||
}
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
||||
}
|
||||
|
||||
var proxy http.Handler
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/portainer/portainer"
|
||||
httperror "github.com/portainer/portainer/http/error"
|
||||
"github.com/portainer/portainer/http/request"
|
||||
"github.com/portainer/portainer/http/security"
|
||||
|
||||
"net/http"
|
||||
)
|
||||
|
@ -24,18 +23,9 @@ func (handler *Handler) proxyRequestsToStoridgeAPI(w http.ResponseWriter, r *htt
|
|||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
|
||||
}
|
||||
|
||||
tokenData, err := security.RetrieveTokenData(r)
|
||||
err = handler.requestBouncer.EndpointAccess(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve user authentication token", err}
|
||||
}
|
||||
|
||||
if tokenData.Role != portainer.AdministratorRole {
|
||||
err = handler.checkEndpointAccess(endpoint, tokenData.ID)
|
||||
if err != nil && err == portainer.ErrEndpointAccessDenied {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to verify permission to access endpoint", err}
|
||||
}
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
|
||||
}
|
||||
|
||||
var storidgeExtension *portainer.EndpointExtension
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue