Eric Bower
·
2026-02-24
ssh.go
1package git
2
3import (
4 "context"
5 "fmt"
6 "os"
7 "path/filepath"
8
9 "github.com/picosh/pico/pkg/pssh"
10 "golang.org/x/crypto/ssh"
11)
12
13func authHandler(pr *PrCmd) func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
14 return func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
15 pubkey := pr.Backend.Pubkey(key)
16 userName := conn.User()
17 perms := &ssh.Permissions{
18 Extensions: map[string]string{
19 "pubkey": pubkey,
20 },
21 }
22 err := pr.IsBanned(pubkey, userName)
23 if err != nil {
24 pr.Backend.Logger.Info(
25 "user denied access",
26 "err", err,
27 "username", userName,
28 "pubkey", pubkey,
29 )
30 return perms, err
31 }
32 return perms, nil
33 }
34}
35
36func GitSshServer(ctx context.Context, cfg *GitCfg) *pssh.SSHServer {
37 dbpath := filepath.Join(cfg.DataDir, "pr.db?_fk=on")
38 dbh, err := SqliteOpen("file:"+dbpath, cfg.Logger)
39 if err != nil {
40 panic(fmt.Sprintf("cannot find database file, check folder and perms: %s: %s", dbpath, err))
41 }
42
43 be := &Backend{
44 DB: dbh,
45 Logger: cfg.Logger,
46 Cfg: cfg,
47 }
48
49 prCmd := &PrCmd{
50 Backend: be,
51 }
52
53 server, err := pssh.NewSSHServerWithConfig(
54 ctx,
55 cfg.Logger,
56 "git-pr",
57 cfg.Host,
58 cfg.SshPort,
59 cfg.PromPort,
60 filepath.Join(cfg.DataDir, "term_info_ed25519"),
61 authHandler(prCmd),
62 []pssh.SSHServerMiddleware{
63 GitPatchRequestMiddleware(be, prCmd),
64 },
65 []pssh.SSHServerMiddleware{},
66 nil,
67 )
68
69 if err != nil {
70 cfg.Logger.Error("failed to create ssh server", "err", err)
71 os.Exit(1)
72 }
73
74 return server
75}