Skip to content

Commit

Permalink
Terminate the console session if the machine changed (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
majst01 authored Sep 9, 2021
1 parent e97be42 commit 73dd107
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 13 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ require (
github.com/metal-stack/metal-go v0.15.7
github.com/metal-stack/v v1.0.3
github.com/stretchr/testify v1.7.0
go.uber.org/zap v1.19.0
go.uber.org/zap v1.19.1
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
)
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,8 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
Expand All @@ -955,6 +957,8 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
Expand Down Expand Up @@ -1273,6 +1277,7 @@ golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
83 changes: 71 additions & 12 deletions internal/console/consoleServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import (
"fmt"
"io"
"os"
"reflect"
"runtime"
"strings"
"sync"
"time"

metalgo "github.com/metal-stack/metal-go"
"github.com/metal-stack/metal-go/api/models"
Expand All @@ -20,10 +22,11 @@ import (
)

type consoleServer struct {
log *zap.SugaredLogger
client *metalgo.Driver
spec *Specification
ips *sync.Map
log *zap.SugaredLogger
client *metalgo.Driver
spec *Specification
ips *sync.Map
pubKeys *sync.Map
}

func NewServer(log *zap.SugaredLogger, spec *Specification) (*consoleServer, error) {
Expand All @@ -32,10 +35,11 @@ func NewServer(log *zap.SugaredLogger, spec *Specification) (*consoleServer, err
return nil, err
}
return &consoleServer{
log: log,
client: client,
spec: spec,
ips: new(sync.Map),
log: log,
client: client,
spec: spec,
ips: new(sync.Map),
pubKeys: new(sync.Map),
}, nil
}

Expand Down Expand Up @@ -126,10 +130,6 @@ func (cs *consoleServer) sessionHandler(s ssh.Session) {
}
}

defer func() {
cs.exitSession(s)
}()

mgmtServiceAddress := m.Partition.Mgmtserviceaddress

if cs.spec.DevMode() {
Expand Down Expand Up @@ -162,6 +162,9 @@ func (cs *consoleServer) sessionHandler(s ssh.Session) {

cs.redirectIO(s, sshSession, done)

// check periodically if the session is still allowed.
go cs.terminateIfPublicKeysChanged(s)

err = sshSession.Start("bash")
if err != nil {
cs.log.Errorw("failed to start bash via SSH session", "error", err)
Expand All @@ -172,6 +175,57 @@ func (cs *consoleServer) sessionHandler(s ssh.Session) {
<-done
}

func (cs *consoleServer) terminateIfPublicKeysChanged(s ssh.Session) {
machineID := s.User()
ticker := time.NewTicker(20 * time.Second)
defer ticker.Stop()
done := make(chan bool)
for {
select {
case <-done:
return
case <-s.Context().Done():
cs.log.Infow("connection closed", "machine", machineID)
done <- true
continue
case <-ticker.C:
cs.log.Infow("checking if machine is still owned by the same user", "machine", machineID)

m, err := cs.client.MachineGet(machineID)
if err != nil {
cs.log.Warnw("unable to load machine", "machineID", machineID, "error", err)
}
if m.Machine == nil {
cs.log.Warnw("unable to load machine is nil", "machineID", machineID)
}
if m.Machine.Allocation == nil {
_, _ = io.WriteString(s, "machine is not allocated anymore, terminating console session\n")
cs.log.Infow("machine is not allocated anymore, terminating ssh session", "machineID", machineID)
cs.pubKeys.Delete(machineID)
cs.exitSession(s)
done <- true
continue
}
keys, ok := cs.pubKeys.Load(machineID)
if !ok {
_, _ = io.WriteString(s, "public key of machine removed, terminating console session\n")
cs.log.Infow("no ssh public key stored anymore, terminating ssh session", "machineID", machineID)
cs.exitSession(s)
done <- true
continue
}
sshKeys := keys.([]string)
if !reflect.DeepEqual(sshKeys, m.Machine.Allocation.SSHPubKeys) {
_, _ = io.WriteString(s, "public key of machine changed, terminating console session\n")
cs.log.Infow("ssh public keys changed, terminating ssh session", "machineID", machineID)
cs.exitSession(s)
done <- true
continue
}
}
}
}

func (cs *consoleServer) exitSession(session ssh.Session) {
err := session.Exit(1)
if err != nil {
Expand Down Expand Up @@ -374,8 +428,13 @@ func (cs *consoleServer) getAuthorizedKeysForMachine(machineID string) ([]ssh.Pu
if privateIP == "" {
return nil, fmt.Errorf("failed to detect private IP of machine:%s", machineID)
}

cs.ips.Store(machineID, privateIP)

_, ok := cs.pubKeys.Load(machineID)
if !ok {
cs.pubKeys.Store(machineID, resp.Allocation.SSHPubKeys)
}
var pubKeys []ssh.PublicKey
for _, key := range resp.Allocation.SSHPubKeys {
pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(key))
Expand Down

0 comments on commit 73dd107

Please sign in to comment.