diff --git a/http/handler/handler.go b/http/handler/handler.go index ba07f44b..18bcbcf5 100644 --- a/http/handler/handler.go +++ b/http/handler/handler.go @@ -19,6 +19,7 @@ import ( "github.com/portainer/agent/http/handler/kubernetesproxy" "github.com/portainer/agent/http/handler/nomadproxy" "github.com/portainer/agent/http/handler/ping" + "github.com/portainer/agent/http/handler/sosivio" "github.com/portainer/agent/http/handler/websocket" "github.com/portainer/agent/http/proxy" "github.com/portainer/agent/http/security" @@ -40,6 +41,7 @@ type Handler struct { webSocketHandler *websocket.Handler hostHandler *host.Handler pingHandler *ping.Handler + sosivioHandler *sosivio.Handler containerPlatform agent.ContainerPlatform } @@ -78,6 +80,7 @@ func NewHandler(config *Config) *Handler { webSocketHandler: websocket.NewHandler(config.ClusterService, config.RuntimeConfiguration, notaryService, config.KubeClient), hostHandler: host.NewHandler(config.SystemService, agentProxy, notaryService), pingHandler: ping.NewHandler(), + sosivioHandler: sosivio.NewHandler(notaryService), containerPlatform: config.ContainerPlatform, } } @@ -119,6 +122,8 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, request *http.Request) { h.kubernetesProxyHandler.ServeHTTP(rw, request) case strings.HasPrefix(request.URL.Path, "/nomad"): h.nomadProxyHandler.ServeHTTP(rw, request) + case strings.HasPrefix(request.URL.Path, "/sosivio"): + h.sosivioHandler.ServeHTTP(rw, request) case strings.HasPrefix(request.URL.Path, "/"): h.dockerProxyHandler.ServeHTTP(rw, request) } diff --git a/http/handler/sosivio/commandcenter.go b/http/handler/sosivio/commandcenter.go new file mode 100644 index 00000000..22647b5b --- /dev/null +++ b/http/handler/sosivio/commandcenter.go @@ -0,0 +1,28 @@ +package sosivio + +import ( + "io/ioutil" + "net/http" + + httperror "github.com/portainer/libhttp/error" +) + +// GET request on /sosivio/commandcenter +func (handler *Handler) commandCenter(rw http.ResponseWriter, r *http.Request) *httperror.HandlerError { + + // TODO: REVIEW-POC-SOSIVIO + // Make use of a proper HTTP client here to manage timeouts + // Alternatively, a proxy can probably be used to handle ALL Sosivio related requests. + resp, err := http.Get("http://poc-api.portainer.svc.cluster.local:8088/api/v1/commandcenter?" + r.URL.RawQuery) + if err != nil { + return &httperror.HandlerError{http.StatusInternalServerError, "Unable to query Sosivio API", err} + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return &httperror.HandlerError{http.StatusInternalServerError, "Unable to parse Sosivio API response", err} + } + + return Raw(rw, body) +} diff --git a/http/handler/sosivio/handler.go b/http/handler/sosivio/handler.go new file mode 100644 index 00000000..ec43bf57 --- /dev/null +++ b/http/handler/sosivio/handler.go @@ -0,0 +1,41 @@ +package sosivio + +import ( + "net/http" + + "github.com/gorilla/mux" + "github.com/portainer/agent/http/security" + httperror "github.com/portainer/libhttp/error" +) + +// Handler is the HTTP handler used to handle Sosivio operations. +type Handler struct { + *mux.Router +} + +// NewHandler returns a pointer to an Handler +// It sets the associated handle functions for all the Sosivio related HTTP endpoints. +func NewHandler(notaryService *security.NotaryService) *Handler { + h := &Handler{ + Router: mux.NewRouter(), + } + + h.Handle("/sosivio/namespaces", + notaryService.DigitalSignatureVerification(httperror.LoggerHandler(h.namespaces))).Methods(http.MethodGet) + h.Handle("/sosivio/pods", + notaryService.DigitalSignatureVerification(httperror.LoggerHandler(h.pods))).Methods(http.MethodGet) + h.Handle("/sosivio/nodes", + notaryService.DigitalSignatureVerification(httperror.LoggerHandler(h.nodes))).Methods(http.MethodGet) + h.Handle("/sosivio/commandcenter", + notaryService.DigitalSignatureVerification(httperror.LoggerHandler(h.commandCenter))).Methods(http.MethodGet) + return h +} + +// TODO: REVIEW-POC-SOSIVIO +// Port to libhttp. +// Raw returns raw data. Returns a pointer to a +// HandlerError if encoding fails. +func Raw(rw http.ResponseWriter, data []byte) *httperror.HandlerError { + rw.Write(data) + return nil +} diff --git a/http/handler/sosivio/namespaces.go b/http/handler/sosivio/namespaces.go new file mode 100644 index 00000000..55178667 --- /dev/null +++ b/http/handler/sosivio/namespaces.go @@ -0,0 +1,28 @@ +package sosivio + +import ( + "io/ioutil" + "net/http" + + httperror "github.com/portainer/libhttp/error" +) + +// GET request on /sosivio/namespaces +func (handler *Handler) namespaces(rw http.ResponseWriter, r *http.Request) *httperror.HandlerError { + + // TODO: REVIEW-POC-SOSIVIO + // Make use of a proper HTTP client here to manage timeouts + // Alternatively, a proxy can probably be used to handle ALL Sosivio related requests. + resp, err := http.Get("http://poc-api.portainer.svc.cluster.local:8088/api/v1/namespaces?" + r.URL.RawQuery) + if err != nil { + return &httperror.HandlerError{http.StatusInternalServerError, "Unable to query Sosivio API", err} + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return &httperror.HandlerError{http.StatusInternalServerError, "Unable to parse Sosivio API response", err} + } + + return Raw(rw, body) +} diff --git a/http/handler/sosivio/nodes.go b/http/handler/sosivio/nodes.go new file mode 100644 index 00000000..d46fd562 --- /dev/null +++ b/http/handler/sosivio/nodes.go @@ -0,0 +1,28 @@ +package sosivio + +import ( + "io/ioutil" + "net/http" + + httperror "github.com/portainer/libhttp/error" +) + +// GET request on /sosivio/nodes +func (handler *Handler) nodes(rw http.ResponseWriter, r *http.Request) *httperror.HandlerError { + + // TODO: REVIEW-POC-SOSIVIO + // Make use of a proper HTTP client here to manage timeouts + // Alternatively, a proxy can probably be used to handle ALL Sosivio related requests. + resp, err := http.Get("http://poc-api.portainer.svc.cluster.local:8088/api/v1/node?" + r.URL.RawQuery) + if err != nil { + return &httperror.HandlerError{http.StatusInternalServerError, "Unable to query Sosivio API", err} + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return &httperror.HandlerError{http.StatusInternalServerError, "Unable to parse Sosivio API response", err} + } + + return Raw(rw, body) +} diff --git a/http/handler/sosivio/pods.go b/http/handler/sosivio/pods.go new file mode 100644 index 00000000..7b861dfd --- /dev/null +++ b/http/handler/sosivio/pods.go @@ -0,0 +1,28 @@ +package sosivio + +import ( + "io/ioutil" + "net/http" + + httperror "github.com/portainer/libhttp/error" +) + +// GET request on /sosivio/pods +func (handler *Handler) pods(rw http.ResponseWriter, r *http.Request) *httperror.HandlerError { + + // TODO: REVIEW-POC-SOSIVIO + // Make use of a proper HTTP client here to manage timeouts + // Alternatively, a proxy can probably be used to handle ALL Sosivio related requests. + resp, err := http.Get("http://poc-api.portainer.svc.cluster.local:8088/api/v1/pod?" + r.URL.RawQuery) + if err != nil { + return &httperror.HandlerError{http.StatusInternalServerError, "Unable to query Sosivio API", err} + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return &httperror.HandlerError{http.StatusInternalServerError, "Unable to parse Sosivio API response", err} + } + + return Raw(rw, body) +}