-
Notifications
You must be signed in to change notification settings - Fork 0
/
ssh.go
98 lines (80 loc) · 1.88 KB
/
ssh.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package protocol
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/charmbracelet/ssh"
"github.com/charmbracelet/wish"
"github.com/charmbracelet/wish/git"
"github.com/charmbracelet/wish/logging"
)
type gitBackend struct {
access git.AccessLevel
}
func (b gitBackend) AuthRepo(repo string, pk ssh.PublicKey) git.AccessLevel {
return b.access
}
func (b gitBackend) Push(repo string, pk ssh.PublicKey) {
log.Printf("Pushed %s", repo)
}
func (b gitBackend) Fetch(repo string, pk ssh.PublicKey) {
log.Printf("Fetched %s", repo)
}
var _ git.Hooks = &gitBackend{}
type Waiter struct {
server *ssh.Server
done chan os.Signal
}
func (wh *Waiter) Wait() error {
<-wh.done
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer func() { cancel() }()
if err := wh.server.Shutdown(ctx); err != nil {
return err
}
return nil
}
func StartSSH(host string, port int, path, password string) (*Waiter, error) {
b := &gitBackend{git.ReadWriteAccess}
// Create the SSH server
s, err := wish.NewServer(
ssh.PublicKeyAuth(pkAuth),
ssh.PasswordAuth(passwordAuth(password != "", password)),
wish.WithAddress(fmt.Sprintf("%s:%d", host, port)),
wish.WithMiddleware(
git.Middleware(path, b),
logging.Middleware(),
),
)
if err != nil {
return nil, err
}
// Start the server
done := make(chan os.Signal, 1)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() {
if err := s.ListenAndServe(); err != nil {
fmt.Printf("%v\n", err)
os.Exit(1)
}
}()
// Return a wait handle
wh := &Waiter{s, done}
return wh, nil
}
func pkAuth(ctx ssh.Context, key ssh.PublicKey) bool {
return true
}
func passwordAuth(usePassword bool, password string) ssh.PasswordHandler {
return func(ctx ssh.Context, p string) bool {
// No authentication
if !usePassword {
return false
}
return password == p
}
}