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:
parent
7a5d8b116d
commit
99428f593e
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
|
Loading…
Reference in New Issue