Eric Bower
·
2025-08-22
util.go
1package util
2
3import (
4 "crypto/ed25519"
5 "crypto/rand"
6 "fmt"
7 "io"
8 "os"
9 "path/filepath"
10 "strings"
11
12 "golang.org/x/crypto/ssh"
13)
14
15func CreateTmpDir() string {
16 tmp, err := os.MkdirTemp(os.TempDir(), "git-pr*")
17 if err != nil {
18 panic(err)
19 }
20 return tmp
21}
22
23func CreateCfgFile(dataDir, cfgTmpl string, adminKey UserSSH) string {
24 cfgPath := filepath.Join(dataDir, "git-pr.toml")
25 cfgFi, err := os.Create(cfgPath)
26 if err != nil {
27 panic(err)
28 }
29 _, _ = fmt.Fprintf(cfgFi, cfgTmpl, dataDir, adminKey.Public())
30 _ = cfgFi.Close()
31 return cfgPath
32}
33
34type UserSSH struct {
35 username string
36 signer ssh.Signer
37}
38
39func NewUserSSH(username string, signer ssh.Signer) *UserSSH {
40 return &UserSSH{
41 username: username,
42 signer: signer,
43 }
44}
45
46func (s UserSSH) Public() string {
47 pubkey := s.signer.PublicKey()
48 return string(ssh.MarshalAuthorizedKey(pubkey))
49}
50
51func (s UserSSH) MustCmd(patch []byte, cmd string) string {
52 res, err := s.Cmd(patch, cmd)
53 if err != nil {
54 panic(err)
55 }
56 return res
57}
58
59func (s UserSSH) Cmd(patch []byte, cmd string) (string, error) {
60 host := "localhost:2222"
61
62 config := &ssh.ClientConfig{
63 User: s.username,
64 Auth: []ssh.AuthMethod{
65 ssh.PublicKeys(s.signer),
66 },
67 HostKeyCallback: ssh.InsecureIgnoreHostKey(),
68 }
69
70 client, err := ssh.Dial("tcp", host, config)
71 if err != nil {
72 return "", err
73 }
74 defer func() {
75 _ = client.Close()
76 }()
77
78 session, err := client.NewSession()
79 if err != nil {
80 return "", err
81 }
82 defer func() {
83 _ = session.Close()
84 }()
85
86 stdinPipe, err := session.StdinPipe()
87 if err != nil {
88 return "", err
89 }
90
91 stdoutPipe, err := session.StdoutPipe()
92 if err != nil {
93 return "", err
94 }
95
96 if err := session.Start(cmd); err != nil {
97 return "", err
98 }
99
100 if patch != nil {
101 _, err = stdinPipe.Write(patch)
102 if err != nil {
103 return "", err
104 }
105 }
106
107 _ = stdinPipe.Close()
108
109 if err := session.Wait(); err != nil {
110 return "", err
111 }
112
113 buf := new(strings.Builder)
114 _, err = io.Copy(buf, stdoutPipe)
115 if err != nil {
116 return "", err
117 }
118
119 return buf.String(), nil
120}
121
122func GenerateKeys() (UserSSH, UserSSH) {
123 _, adminKey, err := ed25519.GenerateKey(rand.Reader)
124 if err != nil {
125 panic(err)
126 }
127
128 adminSigner, err := ssh.NewSignerFromKey(adminKey)
129 if err != nil {
130 panic(err)
131 }
132
133 _, userKey, err := ed25519.GenerateKey(rand.Reader)
134 if err != nil {
135 panic(err)
136 }
137
138 userSigner, err := ssh.NewSignerFromKey(userKey)
139 if err != nil {
140 panic(err)
141 }
142
143 return UserSSH{
144 username: "admin",
145 signer: adminSigner,
146 }, UserSSH{
147 username: "contributor",
148 signer: userSigner,
149 }
150}