@@ -19,6 +19,7 @@ import (
19
19
"time"
20
20
21
21
"github.com/gliderlabs/ssh"
22
+ "github.com/google/uuid"
22
23
"github.com/kballard/go-shellquote"
23
24
"github.com/pkg/sftp"
24
25
"github.com/prometheus/client_golang/prometheus"
@@ -192,9 +193,16 @@ func (s *Server) ConnStats() ConnStats {
192
193
}
193
194
194
195
func (s * Server ) sessionHandler (session ssh.Session ) {
195
- logger := s .logger .With (slog .F ("remote_addr" , session .RemoteAddr ()), slog .F ("local_addr" , session .LocalAddr ()))
196
- logger .Info (session .Context (), "handling ssh session" )
197
196
ctx := session .Context ()
197
+ logger := s .logger .With (
198
+ slog .F ("remote_addr" , session .RemoteAddr ()),
199
+ slog .F ("local_addr" , session .LocalAddr ()),
200
+ // Assigning a random uuid for each session is useful for tracking
201
+ // logs for the same ssh session.
202
+ slog .F ("id" , uuid .NewString ()),
203
+ )
204
+ logger .Info (ctx , "handling ssh session" )
205
+
198
206
if ! s .trackSession (session , true ) {
199
207
// See (*Server).Close() for why we call Close instead of Exit.
200
208
_ = session .Close ()
@@ -218,15 +226,15 @@ func (s *Server) sessionHandler(session ssh.Session) {
218
226
switch ss := session .Subsystem (); ss {
219
227
case "" :
220
228
case "sftp" :
221
- s .sftpHandler (session )
229
+ s .sftpHandler (logger , session )
222
230
return
223
231
default :
224
232
logger .Warn (ctx , "unsupported subsystem" , slog .F ("subsystem" , ss ))
225
233
_ = session .Exit (1 )
226
234
return
227
235
}
228
236
229
- err := s .sessionStart (session , extraEnv )
237
+ err := s .sessionStart (logger , session , extraEnv )
230
238
var exitError * exec.ExitError
231
239
if xerrors .As (err , & exitError ) {
232
240
logger .Info (ctx , "ssh session returned" , slog .Error (exitError ))
@@ -244,7 +252,7 @@ func (s *Server) sessionHandler(session ssh.Session) {
244
252
_ = session .Exit (0 )
245
253
}
246
254
247
- func (s * Server ) sessionStart (session ssh.Session , extraEnv []string ) (retErr error ) {
255
+ func (s * Server ) sessionStart (logger slog. Logger , session ssh.Session , extraEnv []string ) (retErr error ) {
248
256
ctx := session .Context ()
249
257
env := append (session .Environ (), extraEnv ... )
250
258
var magicType string
@@ -268,7 +276,7 @@ func (s *Server) sessionStart(session ssh.Session, extraEnv []string) (retErr er
268
276
s .connCountSSHSession .Add (1 )
269
277
defer s .connCountSSHSession .Add (- 1 )
270
278
default :
271
- s . logger .Warn (ctx , "invalid magic ssh session type specified" , slog .F ("type" , magicType ))
279
+ logger .Warn (ctx , "invalid magic ssh session type specified" , slog .F ("type" , magicType ))
272
280
}
273
281
274
282
magicTypeLabel := magicTypeMetricLabel (magicType )
@@ -301,7 +309,7 @@ func (s *Server) sessionStart(session ssh.Session, extraEnv []string) (retErr er
301
309
}
302
310
303
311
if isPty {
304
- return s .startPTYSession (session , magicTypeLabel , cmd , sshPty , windowSize )
312
+ return s .startPTYSession (logger , session , magicTypeLabel , cmd , sshPty , windowSize )
305
313
}
306
314
return s .startNonPTYSession (session , magicTypeLabel , cmd .AsExec ())
307
315
}
@@ -342,7 +350,7 @@ type ptySession interface {
342
350
RawCommand () string
343
351
}
344
352
345
- func (s * Server ) startPTYSession (session ptySession , magicTypeLabel string , cmd * pty.Cmd , sshPty ssh.Pty , windowSize <- chan ssh.Window ) (retErr error ) {
353
+ func (s * Server ) startPTYSession (logger slog. Logger , session ptySession , magicTypeLabel string , cmd * pty.Cmd , sshPty ssh.Pty , windowSize <- chan ssh.Window ) (retErr error ) {
346
354
s .metrics .sessionsTotal .WithLabelValues (magicTypeLabel , "yes" ).Add (1 )
347
355
348
356
ctx := session .Context ()
@@ -355,7 +363,7 @@ func (s *Server) startPTYSession(session ptySession, magicTypeLabel string, cmd
355
363
if serviceBanner != nil {
356
364
err := showServiceBanner (session , serviceBanner )
357
365
if err != nil {
358
- s . logger .Error (ctx , "agent failed to show service banner" , slog .Error (err ))
366
+ logger .Error (ctx , "agent failed to show service banner" , slog .Error (err ))
359
367
s .metrics .sessionErrors .WithLabelValues (magicTypeLabel , "yes" , "service_banner" ).Add (1 )
360
368
}
361
369
}
@@ -366,11 +374,11 @@ func (s *Server) startPTYSession(session ptySession, magicTypeLabel string, cmd
366
374
if manifest != nil {
367
375
err := showMOTD (s .fs , session , manifest .MOTDFile )
368
376
if err != nil {
369
- s . logger .Error (ctx , "agent failed to show MOTD" , slog .Error (err ))
377
+ logger .Error (ctx , "agent failed to show MOTD" , slog .Error (err ))
370
378
s .metrics .sessionErrors .WithLabelValues (magicTypeLabel , "yes" , "motd" ).Add (1 )
371
379
}
372
380
} else {
373
- s . logger .Warn (ctx , "metadata lookup failed, unable to show MOTD" )
381
+ logger .Warn (ctx , "metadata lookup failed, unable to show MOTD" )
374
382
}
375
383
}
376
384
@@ -379,7 +387,7 @@ func (s *Server) startPTYSession(session ptySession, magicTypeLabel string, cmd
379
387
// The pty package sets `SSH_TTY` on supported platforms.
380
388
ptty , process , err := pty .Start (cmd , pty .WithPTYOption (
381
389
pty .WithSSHRequest (sshPty ),
382
- pty .WithLogger (slog .Stdlib (ctx , s . logger , slog .LevelInfo )),
390
+ pty .WithLogger (slog .Stdlib (ctx , logger , slog .LevelInfo )),
383
391
))
384
392
if err != nil {
385
393
s .metrics .sessionErrors .WithLabelValues (magicTypeLabel , "yes" , "start_command" ).Add (1 )
@@ -388,7 +396,7 @@ func (s *Server) startPTYSession(session ptySession, magicTypeLabel string, cmd
388
396
defer func () {
389
397
closeErr := ptty .Close ()
390
398
if closeErr != nil {
391
- s . logger .Warn (ctx , "failed to close tty" , slog .Error (closeErr ))
399
+ logger .Warn (ctx , "failed to close tty" , slog .Error (closeErr ))
392
400
s .metrics .sessionErrors .WithLabelValues (magicTypeLabel , "yes" , "close" ).Add (1 )
393
401
if retErr == nil {
394
402
retErr = closeErr
@@ -400,7 +408,7 @@ func (s *Server) startPTYSession(session ptySession, magicTypeLabel string, cmd
400
408
resizeErr := ptty .Resize (uint16 (win .Height ), uint16 (win .Width ))
401
409
// If the pty is closed, then command has exited, no need to log.
402
410
if resizeErr != nil && ! errors .Is (resizeErr , pty .ErrClosed ) {
403
- s . logger .Warn (ctx , "failed to resize tty" , slog .Error (resizeErr ))
411
+ logger .Warn (ctx , "failed to resize tty" , slog .Error (resizeErr ))
404
412
s .metrics .sessionErrors .WithLabelValues (magicTypeLabel , "yes" , "resize" ).Add (1 )
405
413
}
406
414
}
@@ -422,7 +430,7 @@ func (s *Server) startPTYSession(session ptySession, magicTypeLabel string, cmd
422
430
// 2. The client hangs up, which cancels the command's Context, and go will
423
431
// kill the command's process. This then has the same effect as (1).
424
432
n , err := io .Copy (session , ptty .OutputReader ())
425
- s . logger .Debug (ctx , "copy output done" , slog .F ("bytes" , n ), slog .Error (err ))
433
+ logger .Debug (ctx , "copy output done" , slog .F ("bytes" , n ), slog .Error (err ))
426
434
if err != nil {
427
435
s .metrics .sessionErrors .WithLabelValues (magicTypeLabel , "yes" , "output_io_copy" ).Add (1 )
428
436
return xerrors .Errorf ("copy error: %w" , err )
@@ -435,7 +443,7 @@ func (s *Server) startPTYSession(session ptySession, magicTypeLabel string, cmd
435
443
// ExitErrors just mean the command we run returned a non-zero exit code, which is normal
436
444
// and not something to be concerned about. But, if it's something else, we should log it.
437
445
if err != nil && ! xerrors .As (err , & exitErr ) {
438
- s . logger .Warn (ctx , "process wait exited with error" , slog .Error (err ))
446
+ logger .Warn (ctx , "process wait exited with error" , slog .Error (err ))
439
447
s .metrics .sessionErrors .WithLabelValues (magicTypeLabel , "yes" , "wait" ).Add (1 )
440
448
}
441
449
if err != nil {
@@ -444,7 +452,7 @@ func (s *Server) startPTYSession(session ptySession, magicTypeLabel string, cmd
444
452
return nil
445
453
}
446
454
447
- func (s * Server ) sftpHandler (session ssh.Session ) {
455
+ func (s * Server ) sftpHandler (logger slog. Logger , session ssh.Session ) {
448
456
s .metrics .sftpConnectionsTotal .Add (1 )
449
457
450
458
ctx := session .Context ()
@@ -460,14 +468,14 @@ func (s *Server) sftpHandler(session ssh.Session) {
460
468
// directory so that SFTP connections land there.
461
469
homedir , err := userHomeDir ()
462
470
if err != nil {
463
- s . logger .Warn (ctx , "get sftp working directory failed, unable to get home dir" , slog .Error (err ))
471
+ logger .Warn (ctx , "get sftp working directory failed, unable to get home dir" , slog .Error (err ))
464
472
} else {
465
473
opts = append (opts , sftp .WithServerWorkingDirectory (homedir ))
466
474
}
467
475
468
476
server , err := sftp .NewServer (session , opts ... )
469
477
if err != nil {
470
- s . logger .Debug (ctx , "initialize sftp server" , slog .Error (err ))
478
+ logger .Debug (ctx , "initialize sftp server" , slog .Error (err ))
471
479
return
472
480
}
473
481
defer server .Close ()
@@ -485,7 +493,7 @@ func (s *Server) sftpHandler(session ssh.Session) {
485
493
_ = session .Exit (0 )
486
494
return
487
495
}
488
- s . logger .Warn (ctx , "sftp server closed with error" , slog .Error (err ))
496
+ logger .Warn (ctx , "sftp server closed with error" , slog .Error (err ))
489
497
s .metrics .sftpServerErrors .Add (1 )
490
498
_ = session .Exit (1 )
491
499
}
0 commit comments