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 (
"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
}
}

View File

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

View File

@ -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
}
}

View File

@ -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 {