-
Notifications
You must be signed in to change notification settings - Fork 72
/
Copy pathssh.go
71 lines (63 loc) · 2.29 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
package ssh_ca_util
import (
"crypto"
"fmt"
"github.com/cloudtools/ssh-cert-authority/signer"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
"io"
"net/url"
"regexp"
)
var md5Fingerprint = regexp.MustCompile("([0-9a-fA-F]{2}:){15}[0-9a-fA-F]{2}")
//This interface provides a way to reach the exported, but not accessible SignWithOpts() method
//in x/crypto/ssh/agent. Access to this is needed to sign with more secure signing algorithms
type agentKeyringSigner interface {
SignWithOpts(rand io.Reader, data []byte, opts crypto.SignerOpts) (*ssh.Signature, error)
}
//A struct to wrap an SSH Signer with one that will switch to SHA256 Signatures.
//Replaces the call to Sign() with a call to SignWithOpts using HashFunc() algorithm.
type Sha256Signer struct {
ssh.Signer
}
func (s Sha256Signer) HashFunc() crypto.Hash {
return crypto.SHA256
}
func (s Sha256Signer) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) {
if aks, ok := s.Signer.(agentKeyringSigner); !ok {
return nil, fmt.Errorf("ssh: can't wrap a non ssh agentKeyringSigner")
} else {
return aks.SignWithOpts(rand, data, s)
}
}
func GetSignerForFingerprintOrUrl(fingerprint string, conn io.ReadWriter) (ssh.Signer, error) {
isFingerprint := md5Fingerprint.MatchString(fingerprint)
if isFingerprint {
return GetSignerForFingerprint(fingerprint, conn)
}
keyUrl, err := url.Parse(fingerprint)
if err != nil {
return nil, fmt.Errorf("Ignoring invalid private key url: '%s'. Error parsing: %s", fingerprint, err)
}
if keyUrl.Scheme != "gcpkms" {
return nil, fmt.Errorf("gcpkms:// is the only supported url scheme")
}
return getSignerForGcpKms(keyUrl.Path)
}
func getSignerForGcpKms(keyUrl string) (ssh.Signer, error) {
return signer.NewSshGcpKmsSigner(keyUrl)
}
func GetSignerForFingerprint(fingerprint string, conn io.ReadWriter) (ssh.Signer, error) {
sshAgent := agent.NewClient(conn)
signers, err := sshAgent.Signers()
if err != nil {
return nil, fmt.Errorf("Unable to find your SSH key (%s) in agent. Consider ssh-add", fingerprint)
}
for i := range signers {
signerFingerprint := MakeFingerprint(signers[i].PublicKey().Marshal())
if signerFingerprint == fingerprint {
return Sha256Signer{signers[i]}, nil
}
}
return nil, fmt.Errorf("Unable to find your SSH key (%s) in agent. Consider ssh-add", fingerprint)
}