Check permissions when performing websocket actions

This commit is contained in:
Dane Everitt 2020-04-06 21:03:39 -07:00
parent 3edcd5f9c3
commit 45d441ac32
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
4 changed files with 40 additions and 20 deletions

View File

@ -3,6 +3,7 @@ package tokens
import ( import (
"encoding/json" "encoding/json"
"github.com/gbrlsnchs/jwt/v3" "github.com/gbrlsnchs/jwt/v3"
"strings"
) )
type WebsocketPayload struct { type WebsocketPayload struct {
@ -20,7 +21,7 @@ func (p *WebsocketPayload) GetPayload() *jwt.Payload {
// Checks if the given token payload has a permission string. // Checks if the given token payload has a permission string.
func (p *WebsocketPayload) HasPermission(permission string) bool { func (p *WebsocketPayload) HasPermission(permission string) bool {
for _, k := range p.Permissions { for _, k := range p.Permissions {
if k == permission { if k == permission || (!strings.HasPrefix(permission, "admin") && k == "*") {
return true return true
} }
} }

View File

@ -50,6 +50,7 @@ func (h *Handler) ListenForServerEvents(ctx context.Context) {
server.ConsoleOutputEvent, server.ConsoleOutputEvent,
server.InstallOutputEvent, server.InstallOutputEvent,
server.DaemonMessageEvent, server.DaemonMessageEvent,
server.BackupCompletedEvent,
} }
eventChannel := make(chan server.Event) eventChannel := make(chan server.Event)

View File

@ -20,11 +20,14 @@ import (
var alg *jwt.HMACSHA var alg *jwt.HMACSHA
const ( const (
PermissionConnect = "connect" PermissionConnect = "websocket.*"
PermissionSendCommand = "send-command" PermissionSendCommand = "control.console"
PermissionSendPower = "send-power" PermissionSendPowerStart = "control.start"
PermissionReceiveErrors = "receive-errors" PermissionSendPowerStop = "control.stop"
PermissionReceiveInstall = "receive-install" PermissionSendPowerRestart = "control.restart"
PermissionReceiveErrors = "admin.errors"
PermissionReceiveInstall = "admin.install"
PermissionReceiveBackups = "backup.read"
) )
type Handler struct { 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) return h.unsafeSendJson(v)
} }
@ -203,25 +214,31 @@ func (h *Handler) HandleInbound(m Message) error {
} }
case SetStateEvent: case SetStateEvent:
{ {
if !h.JWT.HasPermission(PermissionSendPower) {
return nil
}
switch strings.Join(m.Args, "") { switch strings.Join(m.Args, "") {
case "start": case "start":
return h.server.Environment.Start() if h.JWT.HasPermission(PermissionSendPowerStart) {
return h.server.Environment.Start()
}
break
case "stop": case "stop":
return h.server.Environment.Stop() if h.JWT.HasPermission(PermissionSendPowerStop) {
return h.server.Environment.Stop()
}
break
case "restart": case "restart":
{ if h.JWT.HasPermission(PermissionSendPowerRestart) {
if err := h.server.Environment.WaitForStop(60, false); err != nil { if err := h.server.Environment.WaitForStop(60, false); err != nil {
return err return err
} }
return h.server.Environment.Start() return h.server.Environment.Start()
} }
break
case "kill": case "kill":
return h.server.Environment.Terminate(os.Kill) if h.JWT.HasPermission(PermissionSendPowerStop) {
return h.server.Environment.Terminate(os.Kill)
}
break
} }
return nil return nil
@ -261,4 +278,4 @@ func (h *Handler) HandleInbound(m Message) error {
} }
return nil return nil
} }

View File

@ -7,11 +7,12 @@ import (
// Defines all of the possible output events for a server. // Defines all of the possible output events for a server.
// noinspection GoNameStartsWithPackageName // noinspection GoNameStartsWithPackageName
const ( const (
DaemonMessageEvent = "daemon message" DaemonMessageEvent = "daemon message"
InstallOutputEvent = "install output" InstallOutputEvent = "install output"
ConsoleOutputEvent = "console output" ConsoleOutputEvent = "console output"
StatusEvent = "status" StatusEvent = "status"
StatsEvent = "stats" StatsEvent = "stats"
BackupCompletedEvent = "backup completed"
) )
type Event struct { type Event struct {