• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nixpig / syringe.sh / 13870686685

15 Mar 2025 07:17AM UTC coverage: 11.936% (-5.5%) from 17.445%
13870686685

push

github

nixpig
chore: start wiring up cli

0 of 461 new or added lines in 7 files covered. (0.0%)

4 existing lines in 2 files now uncovered.

127 of 1064 relevant lines covered (11.94%)

0.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pkg/ssh/ssh.go
1
package ssh
2

3
import (
4
        "crypto/rand"
5
        "crypto/rsa"
6
        "crypto/sha256"
7
        "encoding/base64"
8
        "errors"
9
        "fmt"
10
        "io"
11
        "os"
12
        "slices"
13

14
        gossh "golang.org/x/crypto/ssh"
15
        "golang.org/x/crypto/ssh/agent"
16
        "golang.org/x/term"
17
)
18

19
type PasswordReader func(int) ([]byte, error)
20

21
type Cryptor func(string) (string, error)
22

NEW
23
func NewEncryptor(publicKey gossh.PublicKey) Cryptor {
×
NEW
24
        return func(s string) (string, error) {
×
NEW
25
                authorisedKey, _, _, _, err := gossh.ParseAuthorizedKey([]byte(
×
NEW
26
                        gossh.MarshalAuthorizedKey(publicKey),
×
NEW
27
                ))
×
NEW
28
                if err != nil {
×
NEW
29
                        return "", fmt.Errorf("parse authorised key: %w", err)
×
NEW
30
                }
×
31

NEW
32
                cryptoKey, ok := authorisedKey.(gossh.CryptoPublicKey)
×
NEW
33
                if !ok {
×
NEW
34
                        return "", fmt.Errorf("failed to cast authorised key to crypto key")
×
NEW
35
                }
×
36

NEW
37
                rsaPublicKey, ok := cryptoKey.CryptoPublicKey().(*rsa.PublicKey)
×
NEW
38
                if !ok {
×
NEW
39
                        return "", fmt.Errorf("failed to cast crypto key to rsa public key")
×
NEW
40
                }
×
41

NEW
42
                encryptedValue, err := rsa.EncryptOAEP(
×
NEW
43
                        sha256.New(),
×
NEW
44
                        rand.Reader,
×
NEW
45
                        rsaPublicKey,
×
NEW
46
                        []byte(s),
×
NEW
47
                        nil,
×
NEW
48
                )
×
NEW
49
                if err != nil {
×
NEW
50
                        return "", fmt.Errorf("encrypt provided value: %w", err)
×
NEW
51
                }
×
52

NEW
53
                return base64.StdEncoding.EncodeToString(encryptedValue), nil
×
54
        }
55
}
56

NEW
57
func NewDecryptor(privateKey *rsa.PrivateKey) Cryptor {
×
NEW
58
        return func(s string) (string, error) {
×
NEW
59
                data, err := base64.StdEncoding.DecodeString(s)
×
NEW
60
                if err != nil {
×
NEW
61
                        return "", fmt.Errorf("decode cypher text: %w", err)
×
NEW
62
                }
×
63

NEW
64
                decryptedValue, err := rsa.DecryptOAEP(
×
NEW
65
                        sha256.New(),
×
NEW
66
                        rand.Reader,
×
NEW
67
                        privateKey,
×
NEW
68
                        data,
×
NEW
69
                        nil,
×
NEW
70
                )
×
NEW
71
                if err != nil {
×
NEW
72
                        return "", fmt.Errorf("decrypt cypher text: %w", err)
×
NEW
73
                }
×
74

NEW
75
                return string(decryptedValue), nil
×
76
        }
77
}
78

79
func GetPublicKey(path string) (gossh.PublicKey, error) {
×
NEW
80
        fc, err := os.ReadFile(path)
×
81
        if err != nil {
×
NEW
82
                return nil, err
×
83
        }
×
84

NEW
85
        publicKey, _, _, _, err := gossh.ParseAuthorizedKey(fc)
×
86
        if err != nil {
×
NEW
87
                return nil, err
×
88
        }
×
89

90
        return publicKey, nil
×
91
}
92

NEW
93
func GetPrivateKey(path string, out io.Writer, pr PasswordReader) (*rsa.PrivateKey, error) {
×
94
        var err error
×
95

×
NEW
96
        fc, err := os.ReadFile(path)
×
97
        if err != nil {
×
NEW
98
                return nil, err
×
99
        }
×
100

101
        var key interface{}
×
102

×
NEW
103
        key, err = gossh.ParseRawPrivateKey(fc)
×
104
        if err != nil {
×
105
                if _, ok := err.(*gossh.PassphraseMissingError); !ok {
×
NEW
106
                        return nil, err
×
107
                }
×
108

NEW
109
                out.Write([]byte(fmt.Sprintf("Enter passphrase for %s: ", path)))
×
110

×
NEW
111
                passphrase, err := pr(int(os.Stdin.Fd()))
×
112
                if err != nil {
×
NEW
113
                        return nil, fmt.Errorf("failed to read password: %w", err)
×
114
                }
×
115

NEW
116
                out.Write([]byte("\n"))
×
117

×
NEW
118
                key, err = gossh.ParseRawPrivateKeyWithPassphrase(fc, []byte(passphrase))
×
119
                if err != nil {
×
NEW
120
                        return nil, err
×
121
                }
×
122
        }
123

124
        rsaPrivateKey, ok := key.(*rsa.PrivateKey)
×
125
        if !ok {
×
NEW
126
                return nil, errors.New("failed to cast to rsa private key")
×
127
        }
×
128

129
        return rsaPrivateKey, nil
×
130
}
131

NEW
132
func GetSigner(path string, out io.Writer, pr PasswordReader) (gossh.Signer, error) {
×
NEW
133
        var err error
×
NEW
134

×
NEW
135
        fc, err := os.ReadFile(path)
×
NEW
136
        if err != nil {
×
NEW
137
                return nil, err
×
NEW
138
        }
×
139

NEW
140
        var signer gossh.Signer
×
NEW
141

×
NEW
142
        signer, err = gossh.ParsePrivateKey(fc)
×
NEW
143
        if err != nil {
×
NEW
144
                if _, ok := err.(*gossh.PassphraseMissingError); !ok {
×
NEW
145
                        return nil, err
×
NEW
146
                }
×
147

NEW
148
                out.Write([]byte(fmt.Sprintf("Enter passphrase for %s: ", path)))
×
NEW
149

×
NEW
150
                passphrase, err := pr(int(os.Stdin.Fd()))
×
151
                if err != nil {
×
NEW
152
                        return nil, fmt.Errorf("failed to read password: %w", err)
×
153
                }
×
154

NEW
155
                signer, err = gossh.ParsePrivateKeyWithPassphrase(fc, passphrase)
×
NEW
156
                if err != nil {
×
NEW
157
                        return nil, err
×
UNCOV
158
                }
×
159
        }
160

NEW
161
        return signer, nil
×
162
}
163

NEW
164
func NewSignersFunc(publicKey gossh.PublicKey, agentSigners []gossh.Signer) func() ([]gossh.Signer, error) {
×
NEW
165
        return func() ([]gossh.Signer, error) {
×
NEW
166
                var signers []gossh.Signer
×
NEW
167

×
NEW
168
                for _, signer := range agentSigners {
×
NEW
169
                        if string(publicKey.Marshal()) == string(signer.PublicKey().Marshal()) {
×
NEW
170
                                signers = append(signers, signer)
×
NEW
171
                        }
×
172
                }
173

NEW
174
                if len(signers) == 0 {
×
NEW
175
                        return nil, errors.New("no valid signers in agent")
×
UNCOV
176
                }
×
177

NEW
178
                return signers, nil
×
179
        }
180
}
181

NEW
182
func AuthMethod(identity string, out io.Writer) (gossh.AuthMethod, error) {
×
NEW
183
        var authMethod gossh.AuthMethod
×
NEW
184

×
NEW
185
        publicKey, err := GetPublicKey(fmt.Sprintf("%s.pub", identity))
×
NEW
186
        if err != nil {
×
NEW
187
                return nil, fmt.Errorf("failed to get public key: %w", err)
×
NEW
188
        }
×
189

NEW
190
        sshAuthSock := os.Getenv("SSH_AUTH_SOCK")
×
NEW
191
        sshAgentClient, err := NewSSHAgentClient(sshAuthSock)
×
NEW
192
        if err != nil {
×
NEW
193
                fmt.Println("unable to connect to agent, falling back to identity")
×
NEW
194

×
NEW
195
                signer, err := GetSigner(identity, out, term.ReadPassword)
×
196
                if err != nil {
×
NEW
197
                        return nil, err
×
198
                }
×
199

NEW
200
                authMethod = gossh.PublicKeys(signer)
×
201

NEW
202
        } else {
×
NEW
203
                agentKeys, err := sshAgentClient.List()
×
204
                if err != nil {
×
NEW
205
                        return nil, fmt.Errorf("failed to get identities from ssh agent: %w", err)
×
206
                }
×
207

208
                // if the agent doesn't already contain the identity, then add it
NEW
209
                if i := slices.IndexFunc(agentKeys, func(agentKey *agent.Key) bool {
×
NEW
210
                        return string(agentKey.Marshal()) == string(publicKey.Marshal())
×
NEW
211
                }); i == -1 {
×
NEW
212
                        privateKey, err := GetPrivateKey(identity, out, term.ReadPassword)
×
NEW
213
                        if err != nil {
×
NEW
214
                                return nil, fmt.Errorf("failed to read private key: %w", err)
×
NEW
215
                        }
×
216

NEW
217
                        if err := sshAgentClient.Add(agent.AddedKey{PrivateKey: privateKey}); err != nil {
×
NEW
218
                                return nil, fmt.Errorf("failed to add key to agent: %w", err)
×
NEW
219
                        }
×
220
                }
221

NEW
222
                sshAgentClientSigners, err := sshAgentClient.Signers()
×
NEW
223
                if err != nil {
×
NEW
224
                        return nil, fmt.Errorf("failed to get signers from ssh client: %w", err)
×
NEW
225
                }
×
226

NEW
227
                authMethod = gossh.PublicKeysCallback(
×
NEW
228
                        // use only signer for the specified identity key
×
NEW
229
                        NewSignersFunc(publicKey, sshAgentClientSigners),
×
NEW
230
                )
×
231
        }
232

NEW
233
        return authMethod, nil
×
234
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc