mirror of
https://github.com/amir20/dozzle.git
synced 2025-12-21 13:23:07 +01:00
136 lines
3.5 KiB
Go
136 lines
3.5 KiB
Go
package web
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/amir20/dozzle/internal/auth"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/gorilla/websocket"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
var upgrader = websocket.Upgrader{
|
|
ReadBufferSize: 1024,
|
|
WriteBufferSize: 1024,
|
|
CheckOrigin: func(r *http.Request) bool {
|
|
return true
|
|
},
|
|
}
|
|
|
|
func (h *handler) attach(w http.ResponseWriter, r *http.Request) {
|
|
conn, err := upgrader.Upgrade(w, r, nil)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error while trying to upgrade connection")
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
|
|
id := chi.URLParam(r, "id")
|
|
userLabels := h.config.Labels
|
|
permit := true
|
|
if h.config.Authorization.Provider != NONE {
|
|
user := auth.UserFromContext(r.Context())
|
|
if user.ContainerLabels.Exists() {
|
|
userLabels = user.ContainerLabels
|
|
}
|
|
permit = user.Roles.Has(auth.Shell)
|
|
}
|
|
|
|
if !permit {
|
|
log.Warn().Msg("user is not permitted to attach to container")
|
|
conn.WriteMessage(websocket.TextMessage, []byte("⛔ Access denied: attaching to this container is forbidden\r\n"))
|
|
return
|
|
}
|
|
|
|
containerService, err := h.hostService.FindContainer(hostKey(r), id, userLabels)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error while trying to find container")
|
|
return
|
|
}
|
|
|
|
wsReader := &webSocketReader{conn: conn}
|
|
wsWriter := &webSocketWriter{conn: conn}
|
|
if err = containerService.Attach(r.Context(), wsReader, wsWriter); err != nil {
|
|
log.Error().Err(err).Msg("error while trying to attach to container")
|
|
conn.WriteMessage(websocket.TextMessage, []byte("🚨 Error while trying to attach to container\r\n"))
|
|
return
|
|
}
|
|
}
|
|
|
|
func (h *handler) exec(w http.ResponseWriter, r *http.Request) {
|
|
conn, err := upgrader.Upgrade(w, r, nil)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error while trying to upgrade connection")
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
|
|
id := chi.URLParam(r, "id")
|
|
userLabels := h.config.Labels
|
|
permit := true
|
|
if h.config.Authorization.Provider != NONE {
|
|
user := auth.UserFromContext(r.Context())
|
|
if user.ContainerLabels.Exists() {
|
|
userLabels = user.ContainerLabels
|
|
}
|
|
permit = user.Roles.Has(auth.Shell)
|
|
}
|
|
|
|
if !permit {
|
|
log.Warn().Msg("user is not permitted to exec into container")
|
|
conn.WriteMessage(websocket.TextMessage, []byte("⛔ Access denied: attaching to this container is forbidden\r\n"))
|
|
return
|
|
}
|
|
|
|
containerService, err := h.hostService.FindContainer(hostKey(r), id, userLabels)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("error while trying to find container")
|
|
return
|
|
}
|
|
|
|
wsReader := &webSocketReader{conn: conn}
|
|
wsWriter := &webSocketWriter{conn: conn}
|
|
if err = containerService.Exec(r.Context(), []string{"sh", "-c", "command -v bash >/dev/null 2>&1 && exec bash || exec sh"}, wsReader, wsWriter); err != nil {
|
|
log.Error().Err(err).Msg("error while trying to attach to container")
|
|
conn.WriteMessage(websocket.TextMessage, []byte("🚨 Error while trying to attach to container\r\n"))
|
|
return
|
|
}
|
|
}
|
|
|
|
type webSocketWriter struct {
|
|
conn *websocket.Conn
|
|
}
|
|
|
|
func (w *webSocketWriter) Write(p []byte) (int, error) {
|
|
err := w.conn.WriteMessage(websocket.TextMessage, p)
|
|
return len(p), err
|
|
}
|
|
|
|
type webSocketReader struct {
|
|
conn *websocket.Conn
|
|
buffer []byte
|
|
}
|
|
|
|
func (r *webSocketReader) Read(p []byte) (n int, err error) {
|
|
if len(r.buffer) > 0 {
|
|
n = copy(p, r.buffer)
|
|
r.buffer = r.buffer[n:]
|
|
return n, nil
|
|
}
|
|
|
|
// Otherwise, read a new message
|
|
_, message, err := r.conn.ReadMessage()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
n = copy(p, message)
|
|
|
|
// If we couldn't copy the entire message, store the rest in our buffer
|
|
if n < len(message) {
|
|
r.buffer = message[n:]
|
|
}
|
|
|
|
return n, nil
|
|
}
|