Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support SSH private key with password #338

Merged
merged 2 commits into from
Apr 12, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pkg/git/gogit/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,14 @@ func (s *PublicKeyAuth) Method(secret corev1.Secret) (*git.Auth, error) {
return nil, fmt.Errorf("invalid '%s' secret data: required fields 'identity' and 'known_hosts'", secret.Name)
}

password := secret.Data["password"]

user := s.user
if user == "" {
user = git.DefaultPublicKeyAuthUser
}

pk, err := ssh.NewPublicKeys(user, identity, "")
pk, err := ssh.NewPublicKeys(user, identity, string(password))
if err != nil {
return nil, err
}
Expand Down
25 changes: 25 additions & 0 deletions pkg/git/gogit/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ v2MYnxRjc9INpi/Dyzz2MMvOnOW+aDuOh/If2AtVCmeJUx1pf4CFk3viQwJBAKyC
t824+evjv+NQBlme3AOF6PgxtV4D4wWoJ5Uk/dTejER0j/Hbl6sqPxuiILRRV9qJ
Ngkgu4mLjc3RfenEhJECQAx8zjWUE6kHHPGAd9DfiAIQ4bChqnyS0Nwb9+Gd4hSE
P0Ah10mHiK/M0o3T8Eanwum0gbQHPnOwqZgsPkwXRqQ=
-----END RSA PRIVATE KEY-----`

// secretKeyFixture is a randomly generated
// 512bit RSA private key with password foobar.
secretPassphraseFixture = `-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,0B016973B2A761D31E6B388D0F327C35

X9GET/qAyZkAJBl/RK+1XX75NxONgdUfZDw7PIYi/g+Efh3Z5zH5kh/dx9lxH5ZG
HGCqPAeMO/ofGDGtDULWW6iqDUFRu5gPgEVSCnnbqoHNU325WHhXdhejVAItwObC
IpL/zYfs2+gDHXct/n9FJ/9D/EGXZihwPqYaK8GQSfZAxz0QjLuh0wU1qpbm3y3N
q+o9FLv3b2Ys/tCJOUsYVQOYLSrZEI77y1ii3nWgQ8lXiTJbBUKzuq4f1YWeO8Ah
RZbdhTa57AF5lUaRtL7Nrm3HJUrK1alBbU7HHyjeW4Q4n/D3fiRDC1Mh2Bi4EOOn
wGctSx4kHsZGhJv5qwKqqPEFPhUzph8D2tm2TABk8HJa5KJFDbGrcfvk2uODAoZr
MbcpIxCfl8oB09bWfY6tDQjyvwSYYo2Phdwm7kT92xc=
-----END RSA PRIVATE KEY-----`

// knownHostsFixture is known_hosts fixture in the expected
Expand All @@ -63,6 +78,13 @@ var (
"known_hosts": []byte(knownHostsFixture),
},
}
privateKeySecretWithPassphraseFixture = corev1.Secret{
Data: map[string][]byte{
"identity": []byte(secretPassphraseFixture),
"known_hosts": []byte(knownHostsFixture),
"password": []byte("foobar"),
},
}
)

func TestAuthSecretStrategyForURL(t *testing.T) {
Expand Down Expand Up @@ -131,10 +153,13 @@ func TestPublicKeyStrategy_Method(t *testing.T) {
wantErr bool
}{
{"private key and known_hosts", privateKeySecretFixture, nil, false},
{"private key with passphrase and known_hosts", privateKeySecretWithPassphraseFixture, nil, false},
{"missing private key", privateKeySecretFixture, func(s *corev1.Secret) { delete(s.Data, "identity") }, true},
{"invalid private key", privateKeySecretFixture, func(s *corev1.Secret) { s.Data["identity"] = []byte(`-----BEGIN RSA PRIVATE KEY-----`) }, true},
{"missing known_hosts", privateKeySecretFixture, func(s *corev1.Secret) { delete(s.Data, "known_hosts") }, true},
{"invalid known_hosts", privateKeySecretFixture, func(s *corev1.Secret) { s.Data["known_hosts"] = []byte(`invalid`) }, true},
{"missing password", privateKeySecretWithPassphraseFixture, func(s *corev1.Secret) { delete(s.Data, "password") }, true},
{"wrong password", privateKeySecretWithPassphraseFixture, func(s *corev1.Secret) { s.Data["password"] = []byte("pass") }, true},
{"empty", corev1.Secret{}, nil, true},
}
for _, tt := range tests {
Expand Down
10 changes: 8 additions & 2 deletions pkg/git/libgit2/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,15 @@ func (s *PublicKeyAuth) Method(secret corev1.Secret) (*git.Auth, error) {
return nil, err
}

password := secret.Data["password"]
// Need to validate private key as it is not
// done by git2go when loading the key
_, err = ssh.ParsePrivateKey(identity)
if len(password) == 0 {
_, err = ssh.ParsePrivateKey(identity)
} else {
_, err = ssh.ParsePrivateKeyWithPassphrase(identity, password)
}

if err != nil {
return nil, err
}
Expand All @@ -132,7 +138,7 @@ func (s *PublicKeyAuth) Method(secret corev1.Secret) (*git.Auth, error) {
}

credCallback := func(url string, usernameFromURL string, allowedTypes git2go.CredType) (*git2go.Cred, error) {
cred, err := git2go.NewCredSshKeyFromMemory(user, "", string(identity), "")
cred, err := git2go.NewCredSshKeyFromMemory(user, "", string(identity), string(password))
if err != nil {
return nil, err
}
Expand Down