diff --git a/integration/integration_test.go b/integration/integration_test.go index cf708fa97c038..9aba03e648c83 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -149,7 +149,7 @@ func TestIntegrations(t *testing.T) { t.Run("ClientIdleConnection", suite.bind(testClientIdleConnection)) t.Run("CmdLabels", suite.bind(testCmdLabels)) t.Run("ControlMaster", suite.bind(testControlMaster)) - t.Run("X11Forwarding", suite.bind(testX11Forwarding)) + t.Run("CreateAndUpdateTrustedClusters", suite.bind(testCreateAndUpdateTrustedClusters)) t.Run("CustomReverseTunnel", suite.bind(testCustomReverseTunnel)) t.Run("DataTransfer", suite.bind(testDataTransfer)) t.Run("DifferentPinnedIP", suite.bind(testDifferentPinnedIP)) @@ -181,6 +181,7 @@ func TestIntegrations(t *testing.T) { t.Run("PAM", suite.bind(testPAM)) t.Run("PortForwarding", suite.bind(testPortForwarding)) t.Run("ProxyHostKeyCheck", suite.bind(testProxyHostKeyCheck)) + t.Run("RecordingModesSessionTrackers", suite.bind(testRecordingModesSessionTrackers)) t.Run("ReverseTunnelCollapse", suite.bind(testReverseTunnelCollapse)) t.Run("RotateRollback", suite.bind(testRotateRollback)) t.Run("RotateSuccess", suite.bind(testRotateSuccess)) @@ -197,12 +198,12 @@ func TestIntegrations(t *testing.T) { t.Run("TrustedClustersRoleMapChanges", suite.bind(testTrustedClustersRoleMapChanges)) t.Run("TrustedClustersWithLabels", suite.bind(testTrustedClustersWithLabels)) t.Run("TrustedClustersSkipNameValidation", suite.bind(testTrustedClustersSkipNameValidation)) - t.Run("CreateAndUpdateTrustedClusters", suite.bind(testCreateAndUpdateTrustedClusters)) t.Run("TrustedTunnelNode", suite.bind(testTrustedTunnelNode)) t.Run("TwoClustersProxy", suite.bind(testTwoClustersProxy)) t.Run("TwoClustersTunnel", suite.bind(testTwoClustersTunnel)) t.Run("UUIDBasedProxy", suite.bind(testUUIDBasedProxy)) t.Run("WindowChange", suite.bind(testWindowChange)) + t.Run("X11Forwarding", suite.bind(testX11Forwarding)) } // testDifferentPinnedIP tests connection is rejected when source IP doesn't match the pinned one @@ -1036,6 +1037,81 @@ func testSessionRecordingModes(t *testing.T, suite *integrationTestSuite) { } } +func testRecordingModesSessionTrackers(t *testing.T, suite *integrationTestSuite) { + ctx := context.Background() + + cfg := suite.defaultServiceConfig() + cfg.Auth.Enabled = true + cfg.Proxy.DisableWebService = true + cfg.Proxy.DisableWebInterface = true + cfg.Proxy.Enabled = true + cfg.SSH.Enabled = true + + teleport := suite.NewTeleportWithConfig(t, nil, nil, cfg) + defer teleport.StopAll() + + // startSession starts an interactive session, users must terminate the + // session by typing "exit" in the terminal. + startSession := func(username string) (*Terminal, chan error) { + term := NewTerminal(250) + errCh := make(chan error) + + go func() { + cl, err := teleport.NewClient(helpers.ClientConfig{ + Login: username, + Cluster: helpers.Site, + Host: Host, + }) + if err != nil { + errCh <- trace.Wrap(err) + return + } + cl.Stdout = term + cl.Stdin = term + + ctx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() + errCh <- cl.SSH(ctx, nil) + }() + + return term, errCh + } + + auth := teleport.Process.GetAuthServer() + for _, mode := range []string{types.RecordAtNode, types.RecordAtProxy} { + t.Run(mode, func(t *testing.T) { + rc := types.DefaultSessionRecordingConfig() + rc.SetMode(mode) + + _, err := auth.UpsertSessionRecordingConfig(ctx, rc) + require.NoError(t, err) + + // Start session. + term, errCh := startSession(suite.Me.Username) + + // Validate that the session tracker exists and contains + // the correct target address. + var sessionID string + require.EventuallyWithT(t, func(t *assert.CollectT) { + trackers, err := auth.GetActiveSessionTrackers(ctx) + assert.NoError(t, err) + if !assert.Len(t, trackers, 1) { + return + } + assert.Equal(t, helpers.HostID, trackers[0].GetAddress()) + sessionID = trackers[0].GetSessionID() + }, 30*time.Second, 100*time.Millisecond) + + // Wait for the session to terminate without error. + term.Type("exit\n\r") + require.NoError(t, waitForError(errCh, 30*time.Second)) + + // Manually clean up the tracker for the session to prevent + // it leaking into the next test case. + require.NoError(t, auth.RemoveSessionTracker(ctx, sessionID)) + }) + } +} func testLeafProxySessionRecording(t *testing.T, suite *integrationTestSuite) { tests := []struct { rootRecordingMode string diff --git a/lib/proxy/router.go b/lib/proxy/router.go index 635b26574cc32..b01124b3c4394 100644 --- a/lib/proxy/router.go +++ b/lib/proxy/router.go @@ -22,7 +22,6 @@ import ( "bytes" "context" "errors" - "fmt" "math/rand/v2" "net" "os" @@ -229,61 +228,45 @@ func (r *Router) DialHost(ctx context.Context, clientSrcAddr, clientDstAddr net. } span.AddEvent("retrieved target server") + serverID := target.GetName() + "." + clusterName principals := []string{ host, - // Add in principal for when nodes are on leaf clusters. + // Required when nodes are in leaf clusters. host + "." + clusterName, } + proxyIDs := target.GetProxyIDs() - var ( - isAgentlessNode bool - serverID string - serverAddr string - proxyIDs []string - sshSigner ssh.Signer - ) - - if target != nil { - proxyIDs = target.GetProxyIDs() - serverID = fmt.Sprintf("%v.%v", target.GetName(), clusterName) + // add ip if it exists to the principals + serverAddr := target.GetAddr() + switch { + case serverAddr != "": + h, _, err := net.SplitHostPort(serverAddr) + if err != nil { + return nil, trace.Wrap(err) + } - // add hostUUID.cluster to the principals - principals = append(principals, serverID) + principals = append(principals, h) + case serverAddr == "" && target.GetUseTunnel(): + serverAddr = reversetunnelclient.LocalNode + } - // add ip if it exists to the principals - serverAddr = target.GetAddr() + // If the node is a registered openssh node don't set agentGetter + // so a SSH user agent will not be created when connecting to the remote node. + var sshSigner ssh.Signer + if target.IsOpenSSHNode() { + agentGetter = nil - switch { - case serverAddr != "": - h, _, err := net.SplitHostPort(serverAddr) + if target.GetSubKind() == types.SubKindOpenSSHNode { + // If the node is of SubKindOpenSSHNode, create the signer. + client, err := r.GetSiteClient(ctx, clusterName) if err != nil { return nil, trace.Wrap(err) } - - principals = append(principals, h) - case serverAddr == "" && target.GetUseTunnel(): - serverAddr = reversetunnelclient.LocalNode - } - // If the node is a registered openssh node don't set agentGetter - // so a SSH user agent will not be created when connecting to the remote node. - if target.IsOpenSSHNode() { - agentGetter = nil - isAgentlessNode = true - - if target.GetSubKind() == types.SubKindOpenSSHNode { - // If the node is of SubKindOpenSSHNode, create the signer. - client, err := r.GetSiteClient(ctx, clusterName) - if err != nil { - return nil, trace.Wrap(err) - } - sshSigner, err = signer(ctx, r.localAccessPoint, client) - if err != nil { - return nil, trace.Wrap(err) - } + sshSigner, err = signer(ctx, r.localAccessPoint, client) + if err != nil { + return nil, trace.Wrap(err) } } - } else { - return nil, trace.ConnectionProblem(errors.New("connection problem"), "direct dialing to nodes not found in inventory is not supported") } conn, err := site.Dial(reversetunnelclient.DialParams{ @@ -291,7 +274,6 @@ func (r *Router) DialHost(ctx context.Context, clientSrcAddr, clientDstAddr net. To: &utils.NetAddr{AddrNetwork: "tcp", Addr: serverAddr}, OriginalClientDstAddr: clientDstAddr, GetUserAgent: agentGetter, - IsAgentlessNode: isAgentlessNode, AgentlessSigner: sshSigner, Address: host, Principals: apiutils.Deduplicate(principals), @@ -519,7 +501,11 @@ func getServerWithResolver(ctx context.Context, host, port string, site site, re server = matches[0] } - if routeMatcher.MatchesServerIDs() && server == nil { + if server != nil { + return server, nil + } + + if routeMatcher.MatchesServerIDs() { idType := "UUID" if aws.IsEC2NodeID(host) { idType = "EC2" @@ -528,7 +514,7 @@ func getServerWithResolver(ctx context.Context, host, port string, site site, re return nil, trace.NotFound("unable to locate node matching %s-like target %s", idType, host) } - return server, nil + return nil, trace.ConnectionProblem(errors.New("connection problem"), "direct dialing to nodes not found in inventory is not supported") } // DialSite establishes a connection to the auth server in the provided diff --git a/lib/proxy/router_test.go b/lib/proxy/router_test.go index d637244bb32fd..e76b4f8aae49c 100644 --- a/lib/proxy/router_test.go +++ b/lib/proxy/router_test.go @@ -385,7 +385,7 @@ func TestGetServers(t *testing.T) { name: "no matches for hostname", site: testSite{cfg: &unambiguousCfg}, host: "test", - errAssertion: require.NoError, + errAssertion: require.Error, serverAssertion: func(t *testing.T, srv types.Server) { require.Empty(t, srv) }, @@ -799,7 +799,6 @@ func TestRouter_DialHost(t *testing.T) { require.Equal(t, agentlessSrv, params.TargetServer) require.Nil(t, params.GetUserAgent) require.NotNil(t, params.AgentlessSigner) - require.True(t, params.IsAgentlessNode) require.NotNil(t, conn) require.Contains(t, params.Principals, "host") require.Contains(t, params.Principals, "host.test") @@ -819,7 +818,6 @@ func TestRouter_DialHost(t *testing.T) { require.Equal(t, agentlessEC2ICESrv, params.TargetServer) require.Nil(t, params.GetUserAgent) require.Nil(t, params.AgentlessSigner) - require.True(t, params.IsAgentlessNode) require.NotNil(t, conn) }, }, diff --git a/lib/reversetunnel/localsite.go b/lib/reversetunnel/localsite.go index 1fc58df2a0c0b..bc7751222d32a 100644 --- a/lib/reversetunnel/localsite.go +++ b/lib/reversetunnel/localsite.go @@ -254,6 +254,10 @@ func shouldDialAndForward(params reversetunnelclient.DialParams, recConfig types } func (s *localSite) Dial(params reversetunnelclient.DialParams) (net.Conn, error) { + if params.TargetServer == nil && params.ConnType == types.NodeTunnel { + return nil, trace.BadParameter("target server is required for teleport nodes") + } + if params.TargetServer != nil && params.TargetServer.GetKind() == types.KindGitServer { return s.dialAndForwardGit(params) } @@ -282,7 +286,8 @@ func shouldSendSignedPROXYHeader(signer multiplexer.PROXYHeaderSigner, useTunnel } func (s *localSite) maybeSendSignedPROXYHeader(params reversetunnelclient.DialParams, conn net.Conn, useTunnel bool) error { - if !shouldSendSignedPROXYHeader(s.srv.proxySigner, useTunnel, params.IsAgentlessNode, params.From, params.OriginalClientDstAddr) { + isAgentless := params.ConnType == types.NodeTunnel && params.TargetServer != nil && params.TargetServer.IsOpenSSHNode() + if !shouldSendSignedPROXYHeader(s.srv.proxySigner, useTunnel, isAgentless, params.From, params.OriginalClientDstAddr) { return nil } @@ -404,7 +409,7 @@ func (s *localSite) dialAndForwardGit(params reversetunnelclient.DialParams) (_ func (s *localSite) dialAndForward(params reversetunnelclient.DialParams) (_ net.Conn, retErr error) { ctx := s.srv.ctx - if params.GetUserAgent == nil && !params.IsAgentlessNode { + if params.GetUserAgent == nil && !params.TargetServer.IsOpenSSHNode() { return nil, trace.BadParameter("agentless node require an agent getter") } s.logger.DebugContext(ctx, "Initiating dial and forwarding request", @@ -451,7 +456,6 @@ func (s *localSite) dialAndForward(params reversetunnelclient.DialParams) (_ net LocalAuthClient: s.client, TargetClusterAccessPoint: s.accessPoint, UserAgent: userAgent, - IsAgentlessNode: params.IsAgentlessNode, AgentlessSigner: params.AgentlessSigner, TargetConn: targetConn, SrcAddr: params.From, @@ -467,16 +471,10 @@ func (s *localSite) dialAndForward(params reversetunnelclient.DialParams) (_ net Emitter: s.srv.Config.Emitter, ParentContext: s.srv.Context, LockWatcher: s.srv.LockWatcher, - TargetID: params.ServerID, TargetAddr: params.To.String(), - TargetHostname: params.Address, TargetServer: params.TargetServer, Clock: s.clock, } - // Ensure the hostname is set correctly if we have details of the target - if params.TargetServer != nil { - serverConfig.TargetHostname = params.TargetServer.GetHostname() - } remoteServer, err := forward.New(serverConfig) if err != nil { return nil, trace.Wrap(err) diff --git a/lib/reversetunnel/remotesite.go b/lib/reversetunnel/remotesite.go index 46fbe8f06a204..825816fce93b7 100644 --- a/lib/reversetunnel/remotesite.go +++ b/lib/reversetunnel/remotesite.go @@ -798,6 +798,10 @@ func (s *remoteSite) DialAuthServer(params reversetunnelclient.DialParams) (net. // located in a remote connected site, the connection goes through the // reverse proxy tunnel. func (s *remoteSite) Dial(params reversetunnelclient.DialParams) (net.Conn, error) { + if params.TargetServer == nil && params.ConnType == types.NodeTunnel { + return nil, trace.BadParameter("target server is required for teleport nodes") + } + localRecCfg, err := s.localAccessPoint.GetSessionRecordingConfig(s.ctx) if err != nil { return nil, trace.Wrap(err) @@ -831,13 +835,15 @@ func (s *remoteSite) DialTCP(params reversetunnelclient.DialParams) (net.Conn, e "target_addr", logutils.StringerAttr(params.To), ) + isAgentless := params.ConnType == types.NodeTunnel && params.TargetServer != nil && params.TargetServer.IsOpenSSHNode() + conn, err := s.connThroughTunnel(&sshutils.DialReq{ Address: params.To.String(), ServerID: params.ServerID, ConnType: params.ConnType, ClientSrcAddr: stringOrEmpty(params.From), ClientDstAddr: stringOrEmpty(params.OriginalClientDstAddr), - IsAgentlessNode: params.IsAgentlessNode, + IsAgentlessNode: isAgentless, }) if err != nil { return nil, trace.Wrap(err) @@ -847,7 +853,7 @@ func (s *remoteSite) DialTCP(params reversetunnelclient.DialParams) (net.Conn, e } func (s *remoteSite) dialAndForward(params reversetunnelclient.DialParams) (_ net.Conn, retErr error) { - if params.GetUserAgent == nil && !params.IsAgentlessNode { + if params.GetUserAgent == nil && !params.TargetServer.IsOpenSSHNode() { return nil, trace.BadParameter("user agent getter is required for teleport nodes") } s.logger.DebugContext(s.ctx, "Initiating dial and forward request", @@ -882,7 +888,7 @@ func (s *remoteSite) dialAndForward(params reversetunnelclient.DialParams) (_ ne ConnType: params.ConnType, ClientSrcAddr: stringOrEmpty(params.From), ClientDstAddr: stringOrEmpty(params.OriginalClientDstAddr), - IsAgentlessNode: params.IsAgentlessNode, + IsAgentlessNode: params.TargetServer.IsOpenSSHNode(), }) if err != nil { return nil, trace.Wrap(err) @@ -895,7 +901,6 @@ func (s *remoteSite) dialAndForward(params reversetunnelclient.DialParams) (_ ne LocalAuthClient: s.localClient, TargetClusterAccessPoint: s.remoteAccessPoint, UserAgent: userAgent, - IsAgentlessNode: params.IsAgentlessNode, AgentlessSigner: params.AgentlessSigner, TargetConn: targetConn, SrcAddr: params.From, @@ -912,16 +917,10 @@ func (s *remoteSite) dialAndForward(params reversetunnelclient.DialParams) (_ ne Emitter: s.srv.Config.Emitter, ParentContext: s.srv.Context, LockWatcher: s.srv.LockWatcher, - TargetID: params.ServerID, TargetAddr: params.To.String(), - TargetHostname: params.Address, TargetServer: params.TargetServer, Clock: s.clock, } - // Ensure the hostname is set correctly if we have details of the target - if params.TargetServer != nil { - serverConfig.TargetHostname = params.TargetServer.GetHostname() - } remoteServer, err := forward.New(serverConfig) if err != nil { return nil, trace.Wrap(err) diff --git a/lib/reversetunnelclient/api.go b/lib/reversetunnelclient/api.go index 1be0980c03e2d..8ab865359ccd7 100644 --- a/lib/reversetunnelclient/api.go +++ b/lib/reversetunnelclient/api.go @@ -47,10 +47,6 @@ type DialParams struct { // forwarding proxy. GetUserAgent teleagent.Getter - // IsAgentlessNode indicates whether the Node is an OpenSSH Node. - // This includes Nodes whose sub kind is OpenSSH and OpenSSHEICE. - IsAgentlessNode bool - // AgentlessSigner is used for authenticating to the remote host when it is an // agentless node. AgentlessSigner ssh.Signer diff --git a/lib/srv/ctx.go b/lib/srv/ctx.go index 53c1df223c10f..1e440af626279 100644 --- a/lib/srv/ctx.go +++ b/lib/srv/ctx.go @@ -120,11 +120,14 @@ type Server interface { // event streams for recording sessions events.StreamEmitter - // ID is the unique ID of the server. + // ID is the unique ID of the server. For the forwarding server + // this is the UUID of the forwarding proxy, NOT the UUID of + // the target host. ID() string // HostUUID is the UUID of the underlying host. For the forwarding - // server this is the proxy the forwarding server is running in. + // server this is the UUID of the target host, NOT the UUID of + // the forwarding proxy. HostUUID() string // GetNamespace returns the namespace the server was created in. diff --git a/lib/srv/forward/sshserver.go b/lib/srv/forward/sshserver.go index b57f333b4f5b0..7262d50cf1bc0 100644 --- a/lib/srv/forward/sshserver.go +++ b/lib/srv/forward/sshserver.go @@ -30,7 +30,6 @@ import ( "strings" "time" - "github.com/google/uuid" "github.com/gravitational/trace" "github.com/jonboulle/clockwork" semconv "go.opentelemetry.io/otel/semconv/v1.10.0" @@ -83,8 +82,6 @@ import ( type Server struct { logger *slog.Logger - id string - // targetConn is the TCP connection to the remote host. targetConn net.Conn @@ -174,11 +171,9 @@ type Server struct { // of starting spans. tracerProvider oteltrace.TracerProvider - targetID, targetAddr, targetHostname string + targetAddr string // targetServer is the host that the connection is being established for. - // It **MUST** only be populated when the target is a teleport ssh server - // or an agentless server. targetServer types.Server } @@ -248,16 +243,10 @@ type ServerConfig struct { // of starting spans. TracerProvider oteltrace.TracerProvider - TargetID, TargetAddr, TargetHostname string + TargetAddr string // TargetServer is the host that the connection is being established for. - // It **MUST** only be populated when the target is a teleport ssh server - // or an agentless server. TargetServer types.Server - - // IsAgentlessNode indicates whether the targetServer is a Node with an OpenSSH server (no teleport agent). - // This includes Nodes whose sub kind is OpenSSH and OpenSSHEphemeralKey. - IsAgentlessNode bool } // CheckDefaults makes sure all required parameters are passed in. @@ -271,19 +260,20 @@ func (s *ServerConfig) CheckDefaults() error { if s.DataDir == "" { return trace.BadParameter("missing parameter DataDir") } - if s.IsAgentlessNode { - if s.TargetServer == nil { - return trace.BadParameter("target server is required for agentless nodes") - } + if s.TargetServer == nil { + return trace.BadParameter("target server is required") + } - if s.TargetServer.GetSubKind() == types.SubKindOpenSSHNode && s.AgentlessSigner == nil { + if s.TargetServer.IsOpenSSHNode() { + if s.AgentlessSigner == nil { return trace.BadParameter("agentless signer is required for OpenSSH Nodes") } + } else { + if s.UserAgent == nil { + return trace.BadParameter("user agent required for teleport nodes") + } } - if s.UserAgent == nil && !s.IsAgentlessNode { - return trace.BadParameter("user agent required for teleport nodes (agentless)") - } if s.TargetConn == nil { return trace.BadParameter("connection to target connection required") } @@ -335,7 +325,6 @@ func New(c ServerConfig) (*Server, error) { "src_addr", c.SrcAddr.String(), "dst_addr", c.DstAddr.String(), ), - id: uuid.New().String(), targetConn: c.TargetConn, serverConn: utils.NewTrackingConn(serverConn), clientConn: clientConn, @@ -353,9 +342,7 @@ func New(c ServerConfig) (*Server, error) { parentContext: c.ParentContext, lockWatcher: c.LockWatcher, tracerProvider: c.TracerProvider, - targetID: c.TargetID, targetAddr: c.TargetAddr, - targetHostname: c.TargetHostname, targetServer: c.TargetServer, } @@ -403,19 +390,14 @@ func New(c ServerConfig) (*Server, error) { // TargetMetadata returns metadata about the forwarding target. func (s *Server) TargetMetadata() apievents.ServerMetadata { - var subKind string - if s.targetServer != nil { - subKind = s.targetServer.GetSubKind() - } - return apievents.ServerMetadata{ ServerVersion: teleport.Version, ServerNamespace: s.GetNamespace(), - ServerID: s.targetID, - ServerAddr: s.targetAddr, - ServerHostname: s.targetHostname, + ServerID: s.targetServer.GetName(), + ServerAddr: s.targetServer.GetName(), + ServerHostname: s.targetServer.GetHostname(), ForwardedBy: s.hostUUID, - ServerSubKind: subKind, + ServerSubKind: s.targetServer.GetSubKind(), } } @@ -432,13 +414,13 @@ func (s *Server) GetDataDir() string { // ID returns the ID of the proxy that creates the in-memory forwarding server. func (s *Server) ID() string { - return s.id + return s.hostUUID } // HostUUID is the UUID of the underlying proxy that the forwarding server // is running in. func (s *Server) HostUUID() string { - return s.hostUUID + return s.targetServer.GetName() } // GetNamespace returns the namespace the forwarding server resides in. @@ -603,7 +585,7 @@ func (s *Server) Serve() { return } - if s.targetServer != nil && s.targetServer.IsOpenSSHNode() { + if s.targetServer.IsOpenSSHNode() { // OpenSSH nodes don't support moderated sessions, send an error to // the user and gracefully fail if the user is attempting to create one. policySets := s.identityContext.AccessChecker.SessionPolicySets() @@ -1019,7 +1001,7 @@ func (s *Server) checkTCPIPForwardRequest(ctx context.Context, r *ssh.Request) e } // RBAC checks are only necessary when connecting to an agentless node - if s.targetServer != nil && s.targetServer.IsOpenSSHNode() { + if s.targetServer.IsOpenSSHNode() { scx, err := srv.NewServerContext(s.Context(), s.connectionContext, s, s.identityContext) if err != nil { return err @@ -1102,7 +1084,7 @@ func (s *Server) handleDirectTCPIPRequest(ctx context.Context, ch ssh.Channel, r ch = scx.TrackActivity(ch) // RBAC checks are only necessary when connecting to an agentless node - if s.targetServer != nil && s.targetServer.IsOpenSSHNode() { + if s.targetServer.IsOpenSSHNode() { err = s.authHandlers.CheckPortForward(scx.DstAddr, scx, decisionpb.SSHPortForwardMode_SSH_PORT_FORWARD_MODE_LOCAL) if err != nil { s.stderrWrite(ctx, ch, err.Error()) diff --git a/lib/srv/forward/sshserver_test.go b/lib/srv/forward/sshserver_test.go index 3dd1b250de40e..2275e5f02cf71 100644 --- a/lib/srv/forward/sshserver_test.go +++ b/lib/srv/forward/sshserver_test.go @@ -31,6 +31,7 @@ import ( "golang.org/x/crypto/ssh" "github.com/gravitational/teleport" + "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils/keys" apisshutils "github.com/gravitational/teleport/api/utils/sshutils" "github.com/gravitational/teleport/lib/fixtures" @@ -259,6 +260,7 @@ func TestCheckTCPIPForward(t *testing.T) { s := Server{ logger: utils.NewSlogLoggerForTests(), identityContext: srv.IdentityContext{Login: tt.login}, + targetServer: &types.ServerV2{}, } err := s.checkTCPIPForwardRequest(context.Background(), &ssh.Request{ diff --git a/lib/srv/sess.go b/lib/srv/sess.go index 3251926b6fec0..2f284832dd664 100644 --- a/lib/srv/sess.go +++ b/lib/srv/sess.go @@ -2297,7 +2297,7 @@ func (s *session) trackSession(ctx context.Context, teleportUser string, policyS Kind: string(types.SSHSessionKind), State: types.SessionState_SessionStatePending, Hostname: s.serverMeta.ServerHostname, - Address: s.serverMeta.ServerID, + Address: s.scx.srv.HostUUID(), ClusterName: s.scx.ClusterName, Login: s.login, HostUser: teleportUser,