Eric Bower
·
2024-10-23
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 _, _ = cfgFi.WriteString(fmt.Sprintf(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 client.Close()
75
76 session, err := client.NewSession()
77 if err != nil {
78 return "", err
79 }
80 defer session.Close()
81
82 stdinPipe, err := session.StdinPipe()
83 if err != nil {
84 return "", err
85 }
86
87 stdoutPipe, err := session.StdoutPipe()
88 if err != nil {
89 return "", err
90 }
91
92 if err := session.Start(cmd); err != nil {
93 return "", err
94 }
95
96 if patch != nil {
97 _, err = stdinPipe.Write(patch)
98 if err != nil {
99 return "", err
100 }
101 }
102
103 stdinPipe.Close()
104
105 if err := session.Wait(); err != nil {
106 return "", err
107 }
108
109 buf := new(strings.Builder)
110 _, err = io.Copy(buf, stdoutPipe)
111 if err != nil {
112 return "", err
113 }
114
115 return buf.String(), nil
116}
117
118func GenerateKeys() (UserSSH, UserSSH) {
119 _, adminKey, err := ed25519.GenerateKey(rand.Reader)
120 if err != nil {
121 panic(err)
122 }
123
124 adminSigner, err := ssh.NewSignerFromKey(adminKey)
125 if err != nil {
126 panic(err)
127 }
128
129 _, userKey, err := ed25519.GenerateKey(rand.Reader)
130 if err != nil {
131 panic(err)
132 }
133
134 userSigner, err := ssh.NewSignerFromKey(userKey)
135 if err != nil {
136 panic(err)
137 }
138
139 return UserSSH{
140 username: "admin",
141 signer: adminSigner,
142 }, UserSSH{
143 username: "contributor",
144 signer: userSigner,
145 }
146}