libgit2: change credentialsCallback logic

This changes the logic of `credentialsCallback` so that it takes the
`allowedTypes` passed on by `git2go` into account. Reason for this
change is because this prepares it to work with `v33`, but also
because it can provide better guidance when `libgit2` has been
compiled with a different configuration, which e.g. doesn't
allow for "in-memory SSH keys".

Because `AuthOptions#Identity` now gets validated by the callback
and go-git does its own validaiton, the check has been removed
from `Validate` (and now does a simple check if the fields are set).

Signed-off-by: Hidde Beydals <hello@hidde.co>
This commit is contained in:
Hidde Beydals 2021-10-25 21:46:15 +02:00 committed by Sunny
parent 7a5d8b116d
commit 99428f593e
3 changed files with 21 additions and 44 deletions

View File

@ -23,6 +23,7 @@ import (
"crypto/sha1"
"crypto/sha256"
"crypto/x509"
"fmt"
"hash"
"net"
"strings"
@ -52,30 +53,33 @@ func RemoteCallbacks(opts *git.AuthOptions) git2go.RemoteCallbacks {
}
// credentialsCallback constructs CredentialsCallbacks with the given options
// for git.Transport if the given opts is not nil, and returns the result.
// for git.Transport, and returns the result.
func credentialsCallback(opts *git.AuthOptions) git2go.CredentialsCallback {
switch opts.Transport {
case git.HTTP:
if opts.Username != "" {
return func(u string, user string, allowedTypes git2go.CredentialType) (*git2go.Credential, error) {
return git2go.NewCredentialUsername(opts.Username)
return func(url string, username string, allowedTypes git2go.CredentialType) (*git2go.Credential, error) {
if allowedTypes&(git2go.CredentialTypeSSHKey|git2go.CredentialTypeSSHCustom|git2go.CredentialTypeSSHMemory) != 0 {
var (
signer ssh.Signer
err error
)
if opts.Password != "" {
signer, err = ssh.ParsePrivateKeyWithPassphrase(opts.Identity, []byte(opts.Password))
} else {
signer, err = ssh.ParsePrivateKey(opts.Identity)
}
if err != nil {
return nil, err
}
case git.HTTPS:
if opts.Username != "" && opts.Password != "" {
return func(u string, user string, allowedTypes git2go.CredentialType) (*git2go.Credential, error) {
return git2go.NewCredentialSSHKeyFromSigner(opts.Username, signer)
}
if (allowedTypes & git2go.CredentialTypeUserpassPlaintext) != 0 {
return git2go.NewCredentialUserpassPlaintext(opts.Username, opts.Password)
}
if (allowedTypes & git2go.CredentialTypeUsername) != 0 {
return git2go.NewCredentialUsername(opts.Username)
}
case git.SSH:
if len(opts.Identity) > 0 {
return func(u string, user string, allowedTypes git2go.CredentialType) (*git2go.Credential, error) {
return git2go.NewCredentialSSHKeyFromMemory(opts.Username, "", string(opts.Identity), opts.Password)
return nil, fmt.Errorf("unknown credential type %+v", allowedTypes)
}
}
}
return nil
}
// certificateCallback constructs CertificateCallback with the given options
// for git.Transport if the given opts is not nil, and returns the result.

View File

@ -20,7 +20,6 @@ import (
"fmt"
"net/url"
"golang.org/x/crypto/ssh"
v1 "k8s.io/api/core/v1"
)
@ -82,15 +81,6 @@ func (o AuthOptions) Validate() error {
if len(o.Identity) == 0 {
return fmt.Errorf("invalid '%s' auth option: 'identity' is required", o.Transport)
}
var err error
if o.Password != "" {
_, err = ssh.ParsePrivateKeyWithPassphrase(o.Identity, []byte(o.Password))
} else {
_, err = ssh.ParsePrivateKey(o.Identity)
}
if err != nil {
return fmt.Errorf("invalid '%s' auth option 'identity': %w", o.Transport, err)
}
if len(o.KnownHosts) == 0 {
return fmt.Errorf("invalid '%s' auth option: 'known_hosts' is required", o.Transport)
}

View File

@ -113,23 +113,6 @@ func TestAuthOptions_Validate(t *testing.T) {
},
wantErr: "invalid 'ssh' auth option: 'identity' is required",
},
{
name: "SSH transport requires valid identity",
opts: AuthOptions{
Transport: SSH,
Identity: []byte("malformed"),
},
wantErr: "invalid 'ssh' auth option 'identity': ssh: no key found",
},
{
name: "SSH transport requires valid identity password",
opts: AuthOptions{
Transport: SSH,
Identity: []byte(privateKeyPassphraseFixture),
Password: "invalid",
},
wantErr: "invalid 'ssh' auth option 'identity': x509: decryption password incorrect",
},
{
name: "SSH transport requires known_hosts",
opts: AuthOptions{