@@ -75,11 +75,13 @@ func NewServer(cfg *config.Config) *Server {
sh.IdleTimeout = time.Duration(cfg.SSH.IdleTimeout) * time.Second
}
s.SSHServer = sh
- d, err := daemon.NewDaemon(cfg)
- if err != nil {
- log.Fatalln(err)
+ if cfg.Git.Enabled {
+ d, err := daemon.NewDaemon(cfg)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ s.GitServer = d
}
- s.GitServer = d
return s
}
@@ -92,13 +94,15 @@ func (s *Server) Reload() error {
// Start starts the SSH server.
func (s *Server) Start() error {
var errg errgroup.Group
- errg.Go(func() error {
- log.Printf("Starting Git server on %s:%d", s.Config.Host, s.Config.Git.Port)
- if err := s.GitServer.Start(); err != daemon.ErrServerClosed {
- return err
- }
- return nil
- })
+ if s.Config.Git.Enabled {
+ errg.Go(func() error {
+ log.Printf("Starting Git server on %s:%d", s.Config.Host, s.Config.Git.Port)
+ if err := s.GitServer.Start(); err != daemon.ErrServerClosed {
+ return err
+ }
+ return nil
+ })
+ }
errg.Go(func() error {
log.Printf("Starting SSH server on %s:%d", s.Config.Host, s.Config.SSH.Port)
if err := s.SSHServer.ListenAndServe(); err != ssh.ErrServerClosed {
@@ -112,12 +116,14 @@ func (s *Server) Start() error {
// Shutdown lets the server gracefully shutdown.
func (s *Server) Shutdown(ctx context.Context) error {
var errg errgroup.Group
+ if s.Config.Git.Enabled {
+ errg.Go(func() error {
+ return s.GitServer.Shutdown(ctx)
+ })
+ }
errg.Go(func() error {
return s.SSHServer.Shutdown(ctx)
})
- errg.Go(func() error {
- return s.GitServer.Shutdown(ctx)
- })
return errg.Wait()
}
@@ -127,8 +133,10 @@ func (s *Server) Close() error {
errg.Go(func() error {
return s.SSHServer.Close()
})
- errg.Go(func() error {
- return s.GitServer.Close()
- })
+ if s.Config.Git.Enabled {
+ errg.Go(func() error {
+ return s.GitServer.Close()
+ })
+ }
return errg.Wait()
}
@@ -2,35 +2,29 @@ package server
import (
"fmt"
- "log"
"net"
"os"
"path/filepath"
+ "strconv"
+ "strings"
"testing"
"github.com/charmbracelet/keygen"
- ggit "github.com/charmbracelet/soft-serve/git"
"github.com/charmbracelet/soft-serve/server/config"
"github.com/gliderlabs/ssh"
+ "github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
gconfig "github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing/object"
gssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
+ "github.com/go-git/go-git/v5/storage/memory"
"github.com/matryer/is"
- cssh "golang.org/x/crypto/ssh"
-)
-
-var (
- cfg = &config.Config{
- Host: "",
- Git: config.GitConfig{Port: 9418},
- }
+ gossh "golang.org/x/crypto/ssh"
)
func TestPushRepo(t *testing.T) {
is := is.New(t)
- _, pkPath := createKeyPair(t)
- s := setupServer(t)
+ s, cfg, pkPath := setupServer(t)
err := s.Reload()
is.NoErr(err)
rp := t.TempDir()
@@ -59,8 +53,9 @@ func TestPushRepo(t *testing.T) {
auth, err := gssh.NewPublicKeysFromFile("git", pkPath, "")
is.NoErr(err)
auth.HostKeyCallbackHelper = gssh.HostKeyCallbackHelper{
- HostKeyCallback: cssh.InsecureIgnoreHostKey(),
+ HostKeyCallback: gossh.InsecureIgnoreHostKey(),
}
+ t.Logf("pushing to ssh://localhost:%d/%s", cfg.SSH.Port, "testrepo")
err = r.Push(&git.PushOptions{
RemoteName: "origin",
Auth: auth,
@@ -70,21 +65,23 @@ func TestPushRepo(t *testing.T) {
func TestCloneRepo(t *testing.T) {
is := is.New(t)
- _, pkPath := createKeyPair(t)
- s := setupServer(t)
- log.Print("starting server")
+ s, cfg, pkPath := setupServer(t)
+ t.Log("starting server")
err := s.Reload()
- log.Print("reloaded server")
+ t.Log("reloaded server")
is.NoErr(err)
dst := t.TempDir()
+ t.Cleanup(func() { is.NoErr(os.RemoveAll(dst)) })
url := fmt.Sprintf("ssh://localhost:%d/config", cfg.SSH.Port)
- log.Print("cloning repo")
- err = ggit.Clone(url, dst, ggit.CloneOptions{
- CommandOptions: ggit.CommandOptions{
- Envs: []string{
- fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i %s -F /dev/null`, pkPath),
- },
- },
+ t.Log("cloning repo")
+ pk, err := gssh.NewPublicKeysFromFile("git", pkPath, "")
+ is.NoErr(err)
+ pk.HostKeyCallbackHelper = gssh.HostKeyCallbackHelper{
+ HostKeyCallback: gossh.InsecureIgnoreHostKey(),
+ }
+ _, err = git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{
+ URL: url,
+ Auth: pk,
})
is.NoErr(err)
}
@@ -95,20 +92,34 @@ func randomPort() int {
return addr.Addr().(*net.TCPAddr).Port
}
-func setupServer(t *testing.T) *Server {
+func setupServer(t *testing.T) (*Server, *config.Config, string) {
t.Helper()
- cfg.DataPath = t.TempDir()
- cfg.SSH.Port = randomPort()
+ is := is.New(t)
+ pub, pkPath := createKeyPair(t)
+ dp := t.TempDir()
+ is.NoErr(os.Setenv("SOFT_SERVE_DATA_PATH", dp))
+ is.NoErr(os.Setenv("SOFT_SERVE_INITIAL_ADMIN_KEY", authorizedKey(pub)))
+ is.NoErr(os.Setenv("SOFT_SERVE_GIT_ENABLED", "false"))
+ is.NoErr(os.Setenv("SOFT_SERVE_SSH_PORT", strconv.Itoa(randomPort())))
+ // is.NoErr(os.Setenv("SOFT_SERVE_DB_DRIVER", "fake"))
+ t.Cleanup(func() {
+ is.NoErr(os.Unsetenv("SOFT_SERVE_DATA_PATH"))
+ is.NoErr(os.Unsetenv("SOFT_SERVE_SSH_PORT"))
+ is.NoErr(os.Unsetenv("SOFT_SERVE_INITIAL_ADMIN_KEY"))
+ is.NoErr(os.Unsetenv("SOFT_SERVE_GIT_ENABLED"))
+ // is.NoErr(os.Unsetenv("SOFT_SERVE_DB_DRIVER"))
+ is.NoErr(os.RemoveAll(dp))
+ })
+ cfg := config.DefaultConfig() //.WithDB(&fakedb.FakeDB{})
s := NewServer(cfg)
go func() {
- log.Print("starting server")
+ t.Log("starting server")
s.Start()
}()
t.Cleanup(func() {
s.Close()
- os.RemoveAll(cfg.DataPath)
})
- return s
+ return s, cfg, pkPath
}
func createKeyPair(t *testing.T) (ssh.PublicKey, string) {
@@ -121,3 +132,7 @@ func createKeyPair(t *testing.T) (ssh.PublicKey, string) {
is.NoErr(err)
return pubkey, filepath.Join(keyDir, "id_ed25519")
}
+
+func authorizedKey(pk ssh.PublicKey) string {
+ return strings.TrimSpace(string(gossh.MarshalAuthorizedKey(pk)))
+}
@@ -4,11 +4,11 @@ import (
"bytes"
"errors"
"os"
+ "strconv"
"strings"
"testing"
"time"
- "github.com/charmbracelet/soft-serve/proto"
cm "github.com/charmbracelet/soft-serve/server/cmd"
"github.com/charmbracelet/soft-serve/server/config"
bm "github.com/charmbracelet/wish/bubbletea"
@@ -28,6 +28,12 @@ func TestSession(t *testing.T) {
defer s.Close()
err := s.RequestPty("xterm", 80, 40, nil)
is.NoErr(err)
+ go func() {
+ time.Sleep(1 * time.Second)
+ s.Signal(gossh.SIGTERM)
+ // FIXME: exit with code 0 instead of forcibly closing the session
+ s.Close()
+ }()
err = s.Run("config")
// Session writes error and exits
is.True(strings.Contains(out.String(), cm.ErrUnauthorized.Error()))
@@ -54,16 +60,20 @@ func TestSession(t *testing.T) {
func setup(tb testing.TB) *gossh.Session {
tb.Helper()
- cfg := &config.Config{
- Host: "",
- SSH: config.SSHConfig{Port: randomPort()},
- Git: config.GitConfig{Port: 9418},
- DataPath: tb.TempDir(),
- InitialAdminKeys: []string{
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMJlb/qf2B2kMNdBxfpCQqI2ctPcsOkdZGVh5zTRhKtH",
- },
- AnonAccess: proto.ReadOnlyAccess,
- }
+ is := is.New(tb)
+ dp := tb.TempDir()
+ is.NoErr(os.Setenv("SOFT_SERVE_DATA_PATH", dp))
+ is.NoErr(os.Setenv("SOFT_SERVE_ANON_ACCESS", "read-only"))
+ is.NoErr(os.Setenv("SOFT_SERVE_GIT_PORT", "9418"))
+ is.NoErr(os.Setenv("SOFT_SERVE_SSH_PORT", strconv.Itoa(randomPort())))
+ tb.Cleanup(func() {
+ is.NoErr(os.Unsetenv("SOFT_SERVE_DATA_PATH"))
+ is.NoErr(os.Unsetenv("SOFT_SERVE_ANON_ACCESS"))
+ is.NoErr(os.Unsetenv("SOFT_SERVE_GIT_PORT"))
+ is.NoErr(os.Unsetenv("SOFT_SERVE_SSH_PORT"))
+ is.NoErr(os.RemoveAll(dp))
+ })
+ cfg := config.DefaultConfig()
return testsession.New(tb, &ssh.Server{
Handler: bm.MiddlewareWithProgramHandler(SessionHandler(cfg), termenv.ANSI256)(func(s ssh.Session) {
_, _, active := s.Pty()