1package server
 2
 3import (
 4	"fmt"
 5	"net"
 6	"path/filepath"
 7	"strings"
 8	"testing"
 9
10	"github.com/charmbracelet/keygen"
11	"github.com/charmbracelet/soft-serve/server/backend/noop"
12	"github.com/charmbracelet/soft-serve/server/config"
13	"github.com/charmbracelet/ssh"
14	"github.com/matryer/is"
15	gossh "golang.org/x/crypto/ssh"
16)
17
18func randomPort() int {
19	addr, _ := net.Listen("tcp", ":0") //nolint:gosec
20	_ = addr.Close()
21	return addr.Addr().(*net.TCPAddr).Port
22}
23
24func setupServer(tb testing.TB) (*Server, *config.Config, string) {
25	tb.Helper()
26	tb.Log("creating keypair")
27	pub, pkPath := createKeyPair(tb)
28	dp := tb.TempDir()
29	sshPort := fmt.Sprintf(":%d", randomPort())
30	tb.Setenv("SOFT_SERVE_DATA_PATH", dp)
31	tb.Setenv("SOFT_SERVE_INITIAL_ADMIN_KEY", authorizedKey(pub))
32	tb.Setenv("SOFT_SERVE_SSH_LISTEN_ADDR", sshPort)
33	tb.Setenv("SOFT_SERVE_GIT_LISTEN_ADDR", fmt.Sprintf(":%d", randomPort()))
34	cfg := config.DefaultConfig()
35	nop := &noop.Noop{Port: sshPort[1:]}
36	tb.Log("configuring server")
37	cfg = cfg.WithBackend(nop).WithAccessMethod(nop)
38	s, err := NewServer(cfg)
39	if err != nil {
40		tb.Fatal(err)
41	}
42	go func() {
43		tb.Log("starting server")
44		s.Start()
45	}()
46	tb.Cleanup(func() {
47		s.Close()
48	})
49	return s, cfg, pkPath
50}
51
52func createKeyPair(tb testing.TB) (ssh.PublicKey, string) {
53	tb.Helper()
54	is := is.New(tb)
55	keyDir := tb.TempDir()
56	kp, err := keygen.NewWithWrite(filepath.Join(keyDir, "id"), nil, keygen.Ed25519)
57	is.NoErr(err)
58	pubkey, _, _, _, err := ssh.ParseAuthorizedKey(kp.PublicKey())
59	is.NoErr(err)
60	return pubkey, filepath.Join(keyDir, "id_ed25519")
61}
62
63func authorizedKey(pk ssh.PublicKey) string {
64	return strings.TrimSpace(string(gossh.MarshalAuthorizedKey(pk)))
65}