You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
the-bastion/bin/plugin/open/selfPlaySession

142 lines
4.6 KiB

#! /usr/bin/env perl
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
use common::sense;
use File::Basename;
use lib dirname(__FILE__) . '/../../../lib/perl';
use OVH::Result;
use OVH::Bastion;
use OVH::Bastion::Plugin qw( :DEFAULT help );
my $remainingOptions = OVH::Bastion::Plugin::begin(
argv => \@ARGV,
header => "replay a past session",
options => {
"id=s" => \my $id,
},
helptext => <<'EOF',
Replay the ttyrec of a past session
Usage: --osh SCRIPT_NAME --id ID
--id ID ID of the session to replay, use ``selfListSessions`` to find it.
EOF
);
#
# code
#
my $fnret;
if (not $id) {
help();
osh_exit R('ERR_MISSING_PARAMETER', msg => "Missing mandatory parameter ID");
}
$fnret = OVH::Bastion::log_access_get(account => $self, uniqid => $id);
$fnret or osh_exit $fnret;
my $hashkey = (keys %{$fnret->value})[0];
my $r = $fnret->value->{$hashkey};
if (not defined $r) {
osh_exit R('ERR_NOT_FOUND', msg => "Found no session under this ID");
}
my $diff =
($r->{timestampend} + $r->{timestampendusec} / 1_000_000) - ($r->{timestamp} + $r->{timestampusec} / 1_000_000);
$diff = 0 if not $r->{timestampend};
my $delay = $diff;
if (not $r->{timestampend}) {
$delay = 'n/a';
}
else {
my $d = int($delay / 86400);
$delay -= $d * 86400;
my $h = int($delay / 3600);
$delay -= $h * 3600;
my $m = int($delay / 60);
$delay -= $m * 60;
my $s = int($delay);
$delay -= $s;
my $ds = int($delay * 1_000_000);
$delay = sprintf('%dd+%02d:%02d:%02d.%06d', $d, $h, $m, $s, $ds);
}
$r->{params} = undef if ($r->{cmdtype} ne 'osh');
$r->{returnvalue} = $r->{comment} if $r->{returnvalue} < 0;
osh_info sprintf "%8s: %s\n", "ID", $r->{uniqid};
osh_info sprintf "%8s: %s\n", "Started", POSIX::strftime("%Y/%m/%d %H:%M:%S", localtime($r->{timestamp}));
osh_info sprintf "%8s: %s\n", "Ended",
$r->{timestampend} ? POSIX::strftime("%Y/%m/%d %H:%M:%S", localtime($r->{timestampend})) : 'n/a';
osh_info sprintf "%8s: %s\n", "Duration", $delay;
osh_info sprintf "%8s: %s\n", "Type",
$r->{'cmdtype'} . ($r->{'plugin'} ? '-' . $r->{'plugin'} : '') . ($r->{allowed} ? '' : '/DENIED');
osh_info sprintf "%8s: %s:%s (%s)\n", "From", $r->{'ipfrom'}, $r->{'portfrom'}, $r->{'hostfrom'};
osh_info sprintf "%8s: %s@%s:%s\n", "Via", $r->{'account'}, $r->{'bastionip'}, $r->{'bastionport'};
if ($r->{user} || $r->{ipto} || $r->{portto} || $r->{hostto}) {
osh_info sprintf "%8s: %s@%s:%s (%s)\n", "To", $r->{'user'}, $r->{'ipto'}, $r->{'portto'}, $r->{'hostto'};
}
osh_info sprintf "%8s: %s\n", "RetCode", $r->{returnvalue} // 'n/a';
osh_info sprintf "%8s: %s\n", "Params", $r->{params} // "''";
osh_info "\n";
my $ttyrecfile = $r->{'ttyrecfile'};
# if we used on-the-fly compression, maybe the file ends in ".zst"
if ($ttyrecfile && !-r $ttyrecfile) {
$ttyrecfile .= ".zst";
}
# if the column is not present in db
if (!$ttyrecfile) {
# find it ourselves: this can only work if &uniqid is referenced somewhere in the
# "ttyrecFilenameFormat" global config parameter
if (OVH::Bastion::config('ttyrecFilenameFormat')->value !~ /&uniqid/) {
osh_exit R('ERR_NOT_FOUND',
msg =>
"Can't look for the recorded session of ID $id, as the ttyrec files naming pattern doesn't contain the uniqid"
);
}
my $dirname = "$HOME/ttyrec/";
if ($r->{ipto}) {
$dirname .= $r->{ipto};
}
elsif ($r->{plugin}) {
$dirname .= $r->{plugin};
}
else {
osh_info "There were no terminal recording for this session";
osh_ok {};
}
# look for *.ttyrec and *.ttyrec.zst, we use readdir so that we can stop on the first match
my $uniqid = $r->{uniqid};
if (opendir(my $dh, $dirname)) {
while (my $filename = readdir $dh) {
next if ($filename !~ m{\Q$uniqid\E.+\.ttyrec(?:\.zst)?$});
$ttyrecfile = "$dirname/$filename";
last;
}
closedir($dh);
}
else {
syslog_warn("Couldn't open ttyrec directory $dirname: $!");
osh_exit R('ERR_NOT_FOUND', msg => "Couldn't open the directory containing the ttyrec files");
}
}
if (!$ttyrecfile || !-r $ttyrecfile) {
osh_exit R('ERR_NOT_FOUND', msg => "Recorded session for ID $id couldn't be found, it might have been archived");
}
osh_info "Press '+' to play faster";
osh_info "Press '-' to play slower";
osh_info "Press '1' to restore normal playing speed";
osh_info "\nWhen you're ready to replay session $id, press ENTER.";
osh_info "Starting from the next line, the Total Recall begins. Press CTRL+C to jolt awake.";
<STDIN>;
my $sysret = system('ttyplay', $ttyrecfile);
osh_ok {};