Skip to content

Commit

Permalink
Merge pull request #655 from aryan9600/preferred-kex
Browse files Browse the repository at this point in the history
  • Loading branch information
hiddeco authored Apr 7, 2022
2 parents 362bc56 + 5c84ea7 commit 62604a2
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 12 deletions.
9 changes: 9 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import (
"github.com/fluxcd/source-controller/controllers"
"github.com/fluxcd/source-controller/internal/cache"
"github.com/fluxcd/source-controller/internal/helm"
"github.com/fluxcd/source-controller/pkg/git"
"github.com/fluxcd/source-controller/pkg/git/libgit2/managed"
// +kubebuilder:scaffold:imports
)
Expand Down Expand Up @@ -90,6 +91,7 @@ func main() {
helmCacheMaxSize int
helmCacheTTL string
helmCachePurgeInterval string
kexAlgos []string
)

flag.StringVar(&metricsAddr, "metrics-addr", envOrDefault("METRICS_ADDR", ":8080"),
Expand Down Expand Up @@ -120,6 +122,8 @@ func main() {
"The TTL of an index in the cache. Valid time units are ns, us (or µs), ms, s, m, h.")
flag.StringVar(&helmCachePurgeInterval, "helm-cache-purge-interval", "1m",
"The interval at which the cache is purged. Valid time units are ns, us (or µs), ms, s, m, h.")
flag.StringSliceVar(&kexAlgos, "ssh-kex-algos", []string{},
"The list of key exchange algorithms to use for ssh connections, arranged from most preferred to the least.")

clientOptions.BindFlags(flag.CommandLine)
logOptions.BindFlags(flag.CommandLine)
Expand Down Expand Up @@ -174,6 +178,7 @@ func main() {
storageAdvAddr = determineAdvStorageAddr(storageAddr, setupLog)
}
storage := mustInitStorage(storagePath, storageAdvAddr, setupLog)
setPreferredKexAlgos(kexAlgos)

if err = (&controllers.GitRepositoryReconciler{
Client: mgr.GetClient(),
Expand Down Expand Up @@ -333,3 +338,7 @@ func envOrDefault(envName, defaultValue string) string {

return defaultValue
}

func setPreferredKexAlgos(algos []string) {
git.KexAlgos = algos
}
32 changes: 31 additions & 1 deletion pkg/git/gogit/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
"github.com/fluxcd/pkg/ssh/knownhosts"

"github.com/fluxcd/source-controller/pkg/git"

gossh "golang.org/x/crypto/ssh"
)

// transportAuth constructs the transport.AuthMethod for the git.Transport of
Expand Down Expand Up @@ -58,7 +60,10 @@ func transportAuth(opts *git.AuthOptions) (transport.AuthMethod, error) {
}
pk.HostKeyCallback = callback
}
return pk, nil
customPK := &CustomPublicKeys{
pk: pk,
}
return customPK, nil
}
case "":
return nil, fmt.Errorf("no transport type set")
Expand All @@ -75,3 +80,28 @@ func caBundle(opts *git.AuthOptions) []byte {
}
return opts.CAFile
}

// CustomPublicKeys is a wrapper around ssh.PublicKeys to help us
// customize the ssh config. It implements ssh.AuthMethod.
type CustomPublicKeys struct {
pk *ssh.PublicKeys
}

func (a *CustomPublicKeys) Name() string {
return a.pk.Name()
}

func (a *CustomPublicKeys) String() string {
return a.pk.String()
}

func (a *CustomPublicKeys) ClientConfig() (*gossh.ClientConfig, error) {
config, err := a.pk.ClientConfig()
if err != nil {
return nil, err
}
if len(git.KexAlgos) > 0 {
config.Config.KeyExchanges = git.KexAlgos
}
return config, nil
}
47 changes: 36 additions & 11 deletions pkg/git/gogit/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (

"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
. "github.com/onsi/gomega"

"github.com/fluxcd/source-controller/pkg/git"
Expand Down Expand Up @@ -72,6 +71,7 @@ func Test_transportAuth(t *testing.T) {
name string
opts *git.AuthOptions
wantFunc func(g *WithT, t transport.AuthMethod, opts *git.AuthOptions)
kexAlgos []string
wantErr error
}{
{
Expand Down Expand Up @@ -128,10 +128,10 @@ func Test_transportAuth(t *testing.T) {
Identity: []byte(privateKeyFixture),
},
wantFunc: func(g *WithT, t transport.AuthMethod, opts *git.AuthOptions) {
tt, ok := t.(*ssh.PublicKeys)
tt, ok := t.(*CustomPublicKeys)
g.Expect(ok).To(BeTrue())
g.Expect(tt.User).To(Equal(opts.Username))
g.Expect(tt.Signer.PublicKey().Type()).To(Equal("ssh-rsa"))
g.Expect(tt.pk.User).To(Equal(opts.Username))
g.Expect(tt.pk.Signer.PublicKey().Type()).To(Equal("ssh-rsa"))
},
},
{
Expand All @@ -143,10 +143,31 @@ func Test_transportAuth(t *testing.T) {
Identity: []byte(privateKeyPassphraseFixture),
},
wantFunc: func(g *WithT, t transport.AuthMethod, opts *git.AuthOptions) {
tt, ok := t.(*ssh.PublicKeys)
tt, ok := t.(*CustomPublicKeys)
g.Expect(ok).To(BeTrue())
g.Expect(tt.User).To(Equal(opts.Username))
g.Expect(tt.Signer.PublicKey().Type()).To(Equal("ssh-rsa"))
g.Expect(tt.pk.User).To(Equal(opts.Username))
g.Expect(tt.pk.Signer.PublicKey().Type()).To(Equal("ssh-rsa"))
},
},
{
name: "SSH with custom key exchanges",
opts: &git.AuthOptions{
Transport: git.SSH,
Username: "example",
Identity: []byte(privateKeyFixture),
KnownHosts: []byte(knownHostsFixture),
},
kexAlgos: []string{"curve25519-sha256", "diffie-hellman-group-exchange-sha256"},
wantFunc: func(g *WithT, t transport.AuthMethod, opts *git.AuthOptions) {
tt, ok := t.(*CustomPublicKeys)
g.Expect(ok).To(BeTrue())
g.Expect(tt.pk.User).To(Equal(opts.Username))
g.Expect(tt.pk.Signer.PublicKey().Type()).To(Equal("ssh-rsa"))
config, err := tt.ClientConfig()
g.Expect(err).ToNot(HaveOccurred())
g.Expect(config.Config.KeyExchanges).To(Equal(
[]string{"curve25519-sha256", "diffie-hellman-group-exchange-sha256"}),
)
},
},
{
Expand All @@ -168,11 +189,11 @@ func Test_transportAuth(t *testing.T) {
KnownHosts: []byte(knownHostsFixture),
},
wantFunc: func(g *WithT, t transport.AuthMethod, opts *git.AuthOptions) {
tt, ok := t.(*ssh.PublicKeys)
tt, ok := t.(*CustomPublicKeys)
g.Expect(ok).To(BeTrue())
g.Expect(tt.User).To(Equal(opts.Username))
g.Expect(tt.Signer.PublicKey().Type()).To(Equal("ssh-rsa"))
g.Expect(tt.HostKeyCallback).ToNot(BeNil())
g.Expect(tt.pk.User).To(Equal(opts.Username))
g.Expect(tt.pk.Signer.PublicKey().Type()).To(Equal("ssh-rsa"))
g.Expect(tt.pk.HostKeyCallback).ToNot(BeNil())
},
},
{
Expand Down Expand Up @@ -202,6 +223,10 @@ func Test_transportAuth(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)

if len(tt.kexAlgos) > 0 {
git.KexAlgos = tt.kexAlgos
}

got, err := transportAuth(tt.opts)
if tt.wantErr != nil {
g.Expect(err).To(Equal(tt.wantErr))
Expand Down
4 changes: 4 additions & 0 deletions pkg/git/libgit2/managed/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import (

"golang.org/x/crypto/ssh"

"github.com/fluxcd/source-controller/pkg/git"
git2go "github.com/libgit2/git2go/v33"
)

Expand Down Expand Up @@ -344,6 +345,9 @@ func cacheKeyAndConfig(remoteAddress string, cred *git2go.Credential) (string, *
Auth: []ssh.AuthMethod{ssh.PublicKeys(key)},
Timeout: sshConnectionTimeOut,
}
if len(git.KexAlgos) > 0 {
cfg.Config.KeyExchanges = git.KexAlgos
}

return ck, cfg, nil
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/git/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ type AuthOptions struct {
CAFile []byte
}

// List of custom key exchange algorithms to be used for ssh connections.
var KexAlgos []string

// Validate the AuthOptions against the defined Transport.
func (o AuthOptions) Validate() error {
switch o.Transport {
Expand Down

0 comments on commit 62604a2

Please sign in to comment.