Skip to content

Commit

Permalink
plumbing: transport/ssh, Optional configuration of ssh.ClientConfig f…
Browse files Browse the repository at this point in the history
…rom environment variables. Fixes go-git#411
  • Loading branch information
smveloso committed Apr 13, 2022
1 parent 4f91622 commit c4e371f
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 22 deletions.
42 changes: 20 additions & 22 deletions plumbing/transport/ssh/auth_method.go
Expand Up @@ -56,12 +56,10 @@ func (a *KeyboardInteractive) String() string {
}

func (a *KeyboardInteractive) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{
a.Challenge,
},
})
clientConfig := DefaultSSHClientConfig
clientConfig.User = a.User
clientConfig.Auth = []ssh.AuthMethod{a.Challenge}
return a.SetHostKeyCallback(clientConfig)
}

// Password implements AuthMethod by using the given password.
Expand All @@ -80,10 +78,10 @@ func (a *Password) String() string {
}

func (a *Password) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.Password(a.Password)},
})
clientConfig := DefaultSSHClientConfig
clientConfig.User = a.User
clientConfig.Auth = []ssh.AuthMethod{ssh.Password(a.Password)}
return a.SetHostKeyCallback(clientConfig)
}

// PasswordCallback implements AuthMethod by using a callback
Expand All @@ -103,10 +101,10 @@ func (a *PasswordCallback) String() string {
}

func (a *PasswordCallback) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PasswordCallback(a.Callback)},
})
clientConfig := DefaultSSHClientConfig
clientConfig.User = a.User
clientConfig.Auth = []ssh.AuthMethod{ssh.PasswordCallback(a.Callback)}
return a.SetHostKeyCallback(clientConfig)
}

// PublicKeys implements AuthMethod by using the given key pairs.
Expand Down Expand Up @@ -152,10 +150,10 @@ func (a *PublicKeys) String() string {
}

func (a *PublicKeys) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PublicKeys(a.Signer)},
})
clientConfig := DefaultSSHClientConfig
clientConfig.User = a.User
clientConfig.Auth = []ssh.AuthMethod{ssh.PublicKeys(a.Signer)}
return a.SetHostKeyCallback(clientConfig)
}

func username() (string, error) {
Expand Down Expand Up @@ -213,10 +211,10 @@ func (a *PublicKeysCallback) String() string {
}

func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PublicKeysCallback(a.Callback)},
})
clientConfig := DefaultSSHClientConfig
clientConfig.User = a.User
clientConfig.Auth = []ssh.AuthMethod{ssh.PublicKeysCallback(a.Callback)}
return a.SetHostKeyCallback(clientConfig)
}

// NewKnownHostsCallback returns ssh.HostKeyCallback based on a file based on a
Expand Down
84 changes: 84 additions & 0 deletions plumbing/transport/ssh/common.go
Expand Up @@ -4,6 +4,7 @@ package ssh
import (
"context"
"fmt"
"os"
"reflect"
"strconv"
"strings"
Expand All @@ -27,6 +28,89 @@ type sshConfig interface {
Get(alias, key string) string
}

// ENV_SSH_HOSTKEY_ALGORITHMS
//
// ssh.ClientConfig.HostKeyAlgorithms
//
// Use comma as separator if multiple values.
//
// Example:
// export GO_GIT_SSH_HOSTKEY_ALGORITHMS="ssh-ed25519,ecdsa-sha2-nistp256"
//
// See golang.org/x/crypto/ssh for valid values.
//
//
//
const ENV_SSH_HOSTKEY_ALGORITHMS = "GO_GIT_SSH_HOSTKEY_ALGORITHMS"

// ENV_SSH_CONFIG_KEY_EXCHANGES
//
// ssh.ClientConfig.Config.KeyExchanges
//
// Use comma as separator if multiple values.
//
// Example:
// export GO_GIT_SSH_CONFIG_KEY_EXCHANGES="diffie-hellman-group14-sha1,ecdh-sha2-nistp256"
//
// See golang.org/x/crypto/ssh for valid values.
const ENV_SSH_CONFIG_KEY_EXCHANGES = "GO_GIT_SSH_CONFIG_KEY_EXCHANGES"

// ENV_SSH_CONFIG_CIPHERS
//
// ssh.ClientConfig.Config.Ciphers
//
// Use comma as separator if multiple values.
//
// Example:
// export GO_GIT_SSH_CONFIG_CIPHERS="aes128-ctr,aes192-ctr"
//
// See golang.org/x/crypto/ssh for valid values.
const ENV_SSH_CONFIG_CIPHERS = "GO_GIT_SSH_CONFIG_CIPHERS"

// ENV_SSH_CONFIG_MACS
//
// ssh.ClientConfig.Config.MACs
//
// Use comma as separator if multiple values.
//
// Example:
// export GO_GIT_SSH_CONFIG_MACS="hmac-sha2-256,hmac-sha1"
//
// See golang.org/x/crypto/ssh for valid values.
const ENV_SSH_CONFIG_MACS = "GO_GIT_SSH_CONFIG_MACS"

// DefaultSSHClientConfig
//
// The following environment variables will be used if defined
//
// GO_GIT_SSH_HOSTKEY_ALGORITHMS
// GO_GIT_SSH_CONFIG_KEY_EXCHANGES
// GO_GIT_SSH_CONFIG_CIPHERS
// GO_GIT_SSH_CONFIG_MACS
//
var DefaultSSHClientConfig *ssh.ClientConfig = func() *ssh.ClientConfig {
sshClientConfig := &ssh.ClientConfig{}

if hostKeyAlgorithms, isSet := os.LookupEnv(ENV_SSH_HOSTKEY_ALGORITHMS); isSet {
// TODO validation
sshClientConfig.HostKeyAlgorithms = strings.Split(hostKeyAlgorithms, ",")
}
if keyExchanges, isSet := os.LookupEnv(ENV_SSH_CONFIG_KEY_EXCHANGES); isSet {
// TODO validation
sshClientConfig.Config.KeyExchanges = strings.Split(keyExchanges, ",")
}
if ciphers, isSet := os.LookupEnv(ENV_SSH_CONFIG_CIPHERS); isSet {
// TODO validation
sshClientConfig.Config.Ciphers = strings.Split(ciphers, ",")
}
if MACs, isSet := os.LookupEnv(ENV_SSH_CONFIG_MACS); isSet {
// TODO validation
sshClientConfig.Config.MACs = strings.Split(MACs, ",")
}

return sshClientConfig
}()

// NewClient creates a new SSH client with an optional *ssh.ClientConfig.
func NewClient(config *ssh.ClientConfig) transport.Transport {
return common.NewClient(&runner{config: config})
Expand Down

0 comments on commit c4e371f

Please sign in to comment.