From 45d441ac323c8f5cbae99000253049328d32527c Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Mon, 6 Apr 2020 21:03:39 -0700 Subject: [PATCH] Check permissions when performing websocket actions --- router/tokens/websocket.go | 3 ++- router/websocket/listeners.go | 1 + router/websocket/websocket.go | 45 ++++++++++++++++++++++++----------- server/events.go | 11 +++++---- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/router/tokens/websocket.go b/router/tokens/websocket.go index 897abec..cc03306 100644 --- a/router/tokens/websocket.go +++ b/router/tokens/websocket.go @@ -3,6 +3,7 @@ package tokens import ( "encoding/json" "github.com/gbrlsnchs/jwt/v3" + "strings" ) type WebsocketPayload struct { @@ -20,7 +21,7 @@ func (p *WebsocketPayload) GetPayload() *jwt.Payload { // Checks if the given token payload has a permission string. func (p *WebsocketPayload) HasPermission(permission string) bool { for _, k := range p.Permissions { - if k == permission { + if k == permission || (!strings.HasPrefix(permission, "admin") && k == "*") { return true } } diff --git a/router/websocket/listeners.go b/router/websocket/listeners.go index 9b79fbb..6d99b51 100644 --- a/router/websocket/listeners.go +++ b/router/websocket/listeners.go @@ -50,6 +50,7 @@ func (h *Handler) ListenForServerEvents(ctx context.Context) { server.ConsoleOutputEvent, server.InstallOutputEvent, server.DaemonMessageEvent, + server.BackupCompletedEvent, } eventChannel := make(chan server.Event) diff --git a/router/websocket/websocket.go b/router/websocket/websocket.go index 435c33d..2380b3c 100644 --- a/router/websocket/websocket.go +++ b/router/websocket/websocket.go @@ -20,11 +20,14 @@ import ( var alg *jwt.HMACSHA const ( - PermissionConnect = "connect" - PermissionSendCommand = "send-command" - PermissionSendPower = "send-power" - PermissionReceiveErrors = "receive-errors" - PermissionReceiveInstall = "receive-install" + PermissionConnect = "websocket.*" + PermissionSendCommand = "control.console" + PermissionSendPowerStart = "control.start" + PermissionSendPowerStop = "control.stop" + PermissionSendPowerRestart = "control.restart" + PermissionReceiveErrors = "admin.errors" + PermissionReceiveInstall = "admin.install" + PermissionReceiveBackups = "backup.read" ) type Handler struct { @@ -88,6 +91,14 @@ func (h *Handler) SendJson(v *Message) error { } } + // If the user does not have permission to see backup events, do not emit + // them over the socket. + if v.Event == server.BackupCompletedEvent { + if h.JWT != nil && !h.JWT.HasPermission(PermissionReceiveBackups) { + return nil + } + } + return h.unsafeSendJson(v) } @@ -203,25 +214,31 @@ func (h *Handler) HandleInbound(m Message) error { } case SetStateEvent: { - if !h.JWT.HasPermission(PermissionSendPower) { - return nil - } - switch strings.Join(m.Args, "") { case "start": - return h.server.Environment.Start() + if h.JWT.HasPermission(PermissionSendPowerStart) { + return h.server.Environment.Start() + } + break case "stop": - return h.server.Environment.Stop() + if h.JWT.HasPermission(PermissionSendPowerStop) { + return h.server.Environment.Stop() + } + break case "restart": - { + if h.JWT.HasPermission(PermissionSendPowerRestart) { if err := h.server.Environment.WaitForStop(60, false); err != nil { return err } return h.server.Environment.Start() } + break case "kill": - return h.server.Environment.Terminate(os.Kill) + if h.JWT.HasPermission(PermissionSendPowerStop) { + return h.server.Environment.Terminate(os.Kill) + } + break } return nil @@ -261,4 +278,4 @@ func (h *Handler) HandleInbound(m Message) error { } return nil -} \ No newline at end of file +} diff --git a/server/events.go b/server/events.go index f3e19b0..22413a1 100644 --- a/server/events.go +++ b/server/events.go @@ -7,11 +7,12 @@ import ( // Defines all of the possible output events for a server. // noinspection GoNameStartsWithPackageName const ( - DaemonMessageEvent = "daemon message" - InstallOutputEvent = "install output" - ConsoleOutputEvent = "console output" - StatusEvent = "status" - StatsEvent = "stats" + DaemonMessageEvent = "daemon message" + InstallOutputEvent = "install output" + ConsoleOutputEvent = "console output" + StatusEvent = "status" + StatsEvent = "stats" + BackupCompletedEvent = "backup completed" ) type Event struct {