internal.go

 1package internal
 2
 3import (
 4	"context"
 5	"fmt"
 6
 7	"github.com/charmbracelet/keygen"
 8	"github.com/charmbracelet/soft-serve/server/backend"
 9	"github.com/charmbracelet/soft-serve/server/config"
10	"github.com/charmbracelet/soft-serve/server/hooks"
11	"github.com/charmbracelet/ssh"
12	"github.com/charmbracelet/wish"
13)
14
15// InternalServer is a internal interface to communicate with the server.
16type InternalServer struct {
17	cfg *config.Config
18	s   *ssh.Server
19	kp  *keygen.SSHKeyPair
20	ckp *keygen.SSHKeyPair
21}
22
23// NewInternalServer returns a new internal server.
24func NewInternalServer(cfg *config.Config, hooks hooks.Hooks) (*InternalServer, error) {
25	i := &InternalServer{cfg: cfg}
26
27	// Create internal key.
28	ikp, err := keygen.New(
29		cfg.Internal.InternalKeyPath,
30		keygen.WithKeyType(keygen.Ed25519),
31		keygen.WithWrite(),
32	)
33	if err != nil {
34		return nil, fmt.Errorf("internal key: %w", err)
35	}
36
37	i.kp = ikp
38
39	// Create client key.
40	ckp, err := keygen.New(
41		cfg.Internal.ClientKeyPath,
42		keygen.WithKeyType(keygen.Ed25519),
43		keygen.WithWrite(),
44	)
45	if err != nil {
46		return nil, fmt.Errorf("client key: %w", err)
47	}
48
49	i.ckp = ckp
50
51	s, err := wish.NewServer(
52		wish.WithAddress(cfg.Internal.ListenAddr),
53		wish.WithHostKeyPath(cfg.Internal.KeyPath),
54		wish.WithPublicKeyAuth(i.PublicKeyHandler),
55		wish.WithMiddleware(
56			i.Middleware(hooks),
57		),
58	)
59	if err != nil {
60		return nil, fmt.Errorf("wish: %w", err)
61	}
62
63	i.s = s
64
65	return i, nil
66}
67
68// PublicKeyHandler handles public key authentication.
69func (i *InternalServer) PublicKeyHandler(ctx ssh.Context, pk ssh.PublicKey) bool {
70	return backend.KeysEqual(i.kp.PublicKey(), pk)
71}
72
73// Start starts the internal server.
74func (i *InternalServer) Start() error {
75	return i.s.ListenAndServe()
76}
77
78// Shutdown shuts down the internal server.
79func (i *InternalServer) Shutdown(ctx context.Context) error {
80	return i.s.Shutdown(ctx)
81}
82
83// Close closes the internal server.
84func (i *InternalServer) Close() error {
85	return i.s.Close()
86}