Skip to content

Commit

Permalink
tsh play --format=text
Browse files Browse the repository at this point in the history
For sessions with print events, this command will strip ANSI
control sequences from the recording and write the text directly
to standard out. This makes it easier to grep for a particular
pattern or just dump a session recording to a file for manual
analysis.

Closes #11694
  • Loading branch information
zmb3 committed Sep 22, 2024
1 parent ed26cb1 commit a95b5f9
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 3 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ require (
github.com/opensearch-project/opensearch-go/v2 v2.3.0
github.com/parquet-go/parquet-go v0.23.0
github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0
github.com/pborman/ansi v1.0.0
github.com/pelletier/go-toml v1.9.5
github.com/pkg/sftp v1.13.6
github.com/pquerna/otp v1.4.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1995,6 +1995,8 @@ github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/En
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 h1:2nosf3P75OZv2/ZO/9Px5ZgZ5gbKrzA3joN1QMfOGMQ=
github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ=
github.com/pborman/ansi v1.0.0 h1:OqjHMhvlSuCCV5JT07yqPuJPQzQl+WXsiZ14gZsqOrQ=
github.com/pborman/ansi v1.0.0/go.mod h1:SgWzwMAx1X/Ez7i90VqF8LRiQtx52pWDiQP+x3iGnzw=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
Expand Down
30 changes: 29 additions & 1 deletion tool/tsh/common/play.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (

"github.com/ghodss/yaml"
"github.com/gravitational/trace"
"github.com/pborman/ansi"

"github.com/gravitational/teleport"
apievents "github.com/gravitational/teleport/api/types/events"
Expand Down Expand Up @@ -115,7 +116,7 @@ func exportSession(cf *CLIConf) error {
}

switch format {
case teleport.JSON, teleport.YAML:
case teleport.JSON, teleport.YAML, teleport.Text:
default:
return trace.Errorf("Invalid format %s, only json and yaml are supported", format)
}
Expand Down Expand Up @@ -144,6 +145,8 @@ func exportSession(cf *CLIConf) error {
exporter = jsonSessionExporter{}
case teleport.YAML:
exporter = yamlSessionExporter{}
case teleport.Text:
exporter = textSessionExporter{}
}

exporter.WriteStart()
Expand Down Expand Up @@ -233,6 +236,31 @@ func (yamlSessionExporter) WriteEvent(evt apievents.AuditEvent) error {
return err
}

type textSessionExporter struct{}

func (textSessionExporter) WriteStart() error { return nil }
func (textSessionExporter) WriteEnd() error { return nil }
func (textSessionExporter) WriteSeparator() error { return nil }

func (textSessionExporter) WriteEvent(evt apievents.AuditEvent) error {
printEvent, ok := evt.(*apievents.SessionPrint)
if !ok {
return nil
}

var writeErr error

// strip ANSI control characters
if stripped, err := ansi.Strip(printEvent.Data); err != nil {
// best we can do is just write the original data
_, writeErr = os.Stdout.Write(printEvent.Data)
} else {
_, writeErr = os.Stdout.Write(stripped)
}

return writeErr
}

// exportFile converts the binary protobuf events from the file
// identified by path to text (JSON/YAML) and writes the converted
// events to standard out.
Expand Down
4 changes: 2 additions & 2 deletions tool/tsh/common/tsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -983,8 +983,8 @@ func Run(ctx context.Context, args []string, opts ...CliOption) error {
play.Flag("speed", "Playback speed, applicable when streaming SSH or Kubernetes sessions.").Default("1x").EnumVar(&cf.PlaySpeed, "0.5x", "1x", "2x", "4x", "8x")
play.Flag("skip-idle-time", "Quickly skip over idle time, applicable when streaming SSH or Kubernetes sessions.").BoolVar(&cf.NoWait)
play.Flag("format", defaults.FormatFlagDescription(
teleport.PTY, teleport.JSON, teleport.YAML,
)).Short('f').Default(teleport.PTY).EnumVar(&cf.Format, teleport.PTY, teleport.JSON, teleport.YAML)
teleport.PTY, teleport.JSON, teleport.YAML, teleport.Text,
)).Short('f').Default(teleport.PTY).EnumVar(&cf.Format, teleport.PTY, teleport.JSON, teleport.YAML, teleport.Text)
play.Arg("session-id", "ID or path to session file to play").Required().StringVar(&cf.SessionID)

// scp
Expand Down

0 comments on commit a95b5f9

Please sign in to comment.