From 77f531d3173f2e503c77044c1cfdd45105745033 Mon Sep 17 00:00:00 2001 From: Nic Klaassen Date: Wed, 16 Oct 2024 17:22:22 -0700 Subject: [PATCH] eliminate hardcoded from lib/cloud/gcp (#47606) --- lib/cloud/gcp/vm.go | 28 +++++++++++++--------------- lib/cloud/gcp/vm_test.go | 6 ++++-- lib/srv/discovery/discovery.go | 6 ++++++ lib/srv/server/gcp_installer.go | 3 +++ 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/lib/cloud/gcp/vm.go b/lib/cloud/gcp/vm.go index 09c1d3aee4a5..514d0d346598 100644 --- a/lib/cloud/gcp/vm.go +++ b/lib/cloud/gcp/vm.go @@ -46,8 +46,8 @@ import ( "github.com/gravitational/teleport/api/internalutils/stream" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils/sshutils" - "github.com/gravitational/teleport/lib/auth/native" gcpimds "github.com/gravitational/teleport/lib/cloud/imds/gcp" + "github.com/gravitational/teleport/lib/cryptosuites" ) // sshUser is the user to log in as on GCP VMs. @@ -473,6 +473,8 @@ type RunCommandRequest struct { Script string // SSHPort is the ssh server port to connect to. Defaults to 22. SSHPort string + // SSHKeyAlgo is the algorithm to use for generated SSH keys. + SSHKeyAlgo cryptosuites.Algorithm dialContext func(ctx context.Context, network, addr string) (net.Conn, error) } @@ -487,6 +489,9 @@ func (req *RunCommandRequest) CheckAndSetDefaults() error { if req.SSHPort == "" { req.SSHPort = "22" } + if req.SSHKeyAlgo == cryptosuites.Algorithm(0) { + return trace.BadParameter("ssh key algorithm must be set") + } if req.dialContext == nil { dialer := net.Dialer{ Timeout: sshDefaultTimeout, @@ -496,20 +501,13 @@ func (req *RunCommandRequest) CheckAndSetDefaults() error { return nil } -func generateKeyPair() (ssh.Signer, ssh.PublicKey, error) { - rawPriv, rawPub, err := native.GenerateKeyPair() - if err != nil { - return nil, nil, trace.Wrap(err) - } - signer, err := ssh.ParsePrivateKey(rawPriv) +func generateKeyPair(keyAlgo cryptosuites.Algorithm) (ssh.Signer, error) { + signer, err := cryptosuites.GenerateKeyWithAlgorithm(keyAlgo) if err != nil { - return nil, nil, trace.Wrap(err) - } - publicKey, _, _, _, err := ssh.ParseAuthorizedKey(rawPub) - if err != nil { - return nil, nil, trace.Wrap(err) + return nil, trace.Wrap(err) } - return signer, publicKey, nil + sshSigner, err := ssh.NewSignerFromSigner(signer) + return sshSigner, trace.Wrap(err) } // RunCommand runs a command on an instance. @@ -519,7 +517,7 @@ func RunCommand(ctx context.Context, req *RunCommandRequest) error { } // Generate keys and add them to the instance. - signer, publicKey, err := generateKeyPair() + signer, err := generateKeyPair(req.SSHKeyAlgo) if err != nil { return trace.Wrap(err) } @@ -543,7 +541,7 @@ https://cloud.google.com/solutions/connecting-securely#storing_host_keys_by_enab } keyReq := &SSHKeyRequest{ Instance: instance, - PublicKey: publicKey, + PublicKey: signer.PublicKey(), } if err := req.Client.AddSSHKey(ctx, keyReq); err != nil { return trace.Wrap(err) diff --git a/lib/cloud/gcp/vm_test.go b/lib/cloud/gcp/vm_test.go index 2d3a9198bb40..acaaf8819ed7 100644 --- a/lib/cloud/gcp/vm_test.go +++ b/lib/cloud/gcp/vm_test.go @@ -43,6 +43,7 @@ import ( "github.com/gravitational/teleport/api/internalutils/stream" gcpimds "github.com/gravitational/teleport/lib/cloud/imds/gcp" + "github.com/gravitational/teleport/lib/cryptosuites" "github.com/gravitational/teleport/lib/sshutils" "github.com/gravitational/teleport/lib/utils" ) @@ -224,7 +225,7 @@ func TestRunCommand(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) t.Cleanup(cancel) - signer, publicKey, err := generateKeyPair() + signer, err := generateKeyPair(cryptosuites.ECDSAP256) require.NoError(t, err) clientConn, serverConn, err := utils.DualPipeNetConn( &utils.NetAddr{Addr: "server", AddrNetwork: "tcp"}, @@ -234,7 +235,7 @@ func TestRunCommand(t *testing.T) { mock := newMockInstance(t, signer, &mockListener{Conn: serverConn, ctx: ctx}) require.NoError(t, mock.Start()) t.Cleanup(mock.Stop) - mock.hostKeys = []ssh.PublicKey{publicKey} + mock.hostKeys = []ssh.PublicKey{signer.PublicKey()} inst := &gcpimds.Instance{ Name: "my-instance", @@ -257,6 +258,7 @@ func TestRunCommand(t *testing.T) { dialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { return clientConn, nil }, + SSHKeyAlgo: cryptosuites.ECDSAP256, })) require.Equal(t, 1, mock.execCount) } diff --git a/lib/srv/discovery/discovery.go b/lib/srv/discovery/discovery.go index adb2c6727de8..375fedf436ac 100644 --- a/lib/srv/discovery/discovery.go +++ b/lib/srv/discovery/discovery.go @@ -52,6 +52,7 @@ import ( "github.com/gravitational/teleport/lib/auth/authclient" "github.com/gravitational/teleport/lib/cloud" gcpimds "github.com/gravitational/teleport/lib/cloud/imds/gcp" + "github.com/gravitational/teleport/lib/cryptosuites" "github.com/gravitational/teleport/lib/integrations/awsoidc" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/srv/discovery/common" @@ -1242,6 +1243,10 @@ func (s *Server) handleGCPInstances(instances *server.GCPInstances) error { s.Log.Debugf("Running Teleport installation on these virtual machines: ProjectID: %s, VMs: %s", instances.ProjectID, genGCPInstancesLogStr(instances.Instances), ) + sshKeyAlgo, err := cryptosuites.AlgorithmForKey(s.ctx, cryptosuites.GetCurrentSuiteFromPing(s.AccessPoint), cryptosuites.UserSSH) + if err != nil { + return trace.Wrap(err, "finding algorithm for SSH key from ping response") + } req := server.GCPRunRequest{ Client: client, Instances: instances.Instances, @@ -1250,6 +1255,7 @@ func (s *Server) handleGCPInstances(instances *server.GCPInstances) error { Params: instances.Parameters, ScriptName: instances.ScriptName, PublicProxyAddr: instances.PublicProxyAddr, + SSHKeyAlgo: sshKeyAlgo, } if err := s.gcpInstaller.Run(s.ctx, req); err != nil { return trace.Wrap(err) diff --git a/lib/srv/server/gcp_installer.go b/lib/srv/server/gcp_installer.go index cd7542cb6d0b..54c0935c6f3e 100644 --- a/lib/srv/server/gcp_installer.go +++ b/lib/srv/server/gcp_installer.go @@ -29,6 +29,7 @@ import ( apievents "github.com/gravitational/teleport/api/types/events" "github.com/gravitational/teleport/lib/cloud/gcp" gcpimds "github.com/gravitational/teleport/lib/cloud/imds/gcp" + "github.com/gravitational/teleport/lib/cryptosuites" ) // GCPInstaller handles running commands that install Teleport on GCP @@ -47,6 +48,7 @@ type GCPRunRequest struct { ProjectID string ScriptName string PublicProxyAddr string + SSHKeyAlgo cryptosuites.Algorithm } // Run runs a command on a set of virtual machines and then blocks until the @@ -72,6 +74,7 @@ func (gi *GCPInstaller) Run(ctx context.Context, req GCPRunRequest) error { req.PublicProxyAddr, req.Params, ), + SSHKeyAlgo: req.SSHKeyAlgo, } return trace.Wrap(gcp.RunCommand(ctx, &runRequest)) })