pomerium/pkg/ssh/manager.go
Kenneth Jenkins 177677f239
ssh: continuous authorization (#5687)
Re-evaluate ssh authorization decision on a fixed interval, or whenever 
the config changes. If access is no longer allowed, log a new 'authorize
check' message and disconnect. 

Refactor the ssh.StreamManager initialization so that its lifecycle 
matches the Authorize lifecycle.
2025-07-02 12:01:25 -07:00

91 lines
1.9 KiB
Go

package ssh
import (
"context"
"sync"
extensions_ssh "github.com/pomerium/envoy-custom/api/extensions/filters/network/ssh"
"github.com/pomerium/pomerium/config"
)
type StreamManager struct {
auth AuthInterface
reauthC chan struct{}
mu sync.Mutex
cfg *config.Config
activeStreams map[uint64]*StreamHandler
}
func NewStreamManager(ctx context.Context, auth AuthInterface, cfg *config.Config) *StreamManager {
sm := &StreamManager{
auth: auth,
reauthC: make(chan struct{}, 1),
cfg: cfg,
activeStreams: map[uint64]*StreamHandler{},
}
go sm.reauthLoop(ctx)
return sm
}
func (sm *StreamManager) OnConfigChange(cfg *config.Config) {
sm.mu.Lock()
sm.cfg = cfg
sm.mu.Unlock()
select {
case sm.reauthC <- struct{}{}:
default:
}
}
func (sm *StreamManager) LookupStream(streamID uint64) *StreamHandler {
sm.mu.Lock()
defer sm.mu.Unlock()
return sm.activeStreams[streamID]
}
func (sm *StreamManager) NewStreamHandler(
downstream *extensions_ssh.DownstreamConnectEvent,
) *StreamHandler {
sm.mu.Lock()
defer sm.mu.Unlock()
streamID := downstream.StreamId
writeC := make(chan *extensions_ssh.ServerMessage, 32)
sh := &StreamHandler{
auth: sm.auth,
config: sm.cfg,
downstream: downstream,
readC: make(chan *extensions_ssh.ClientMessage, 32),
writeC: writeC,
reauthC: make(chan struct{}),
close: func() {
sm.mu.Lock()
defer sm.mu.Unlock()
delete(sm.activeStreams, streamID)
close(writeC)
},
}
sm.activeStreams[streamID] = sh
return sh
}
func (sm *StreamManager) reauthLoop(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
case <-sm.reauthC:
sm.mu.Lock()
snapshot := make([]*StreamHandler, 0, len(sm.activeStreams))
for _, s := range sm.activeStreams {
snapshot = append(snapshot, s)
}
sm.mu.Unlock()
for _, s := range snapshot {
s.Reauth()
}
}
}
}