enh: use ttyrec instead of sqlite to record plugin output

pull/405/head
Stéphane Lesimple 3 years ago committed by Stéphane Lesimple
parent 7821c9ff75
commit a65c53b76e

@ -525,13 +525,11 @@ if ($interactive and not $ENV{'OSH_IN_INTERACTIVE_SESSION'}) {
if (defined $log_insert_id and defined $log_db_name) {
$logret = OVH::Bastion::log_access_update(
account => $self,
insert_id => $log_insert_id,
db_name => $log_db_name,
uniq_id => $log_uniq_id,
returnvalue => undef,
plugin_stdout => undef,
plugin_stderr => undef
account => $self,
insert_id => $log_insert_id,
db_name => $log_db_name,
uniq_id => $log_uniq_id,
returnvalue => undef,
);
$logret or osh_warn($logret->msg);
}
@ -1053,6 +1051,25 @@ if ($osh_command) {
$is_binary = 1 if $fnret->value eq 'binary';
}
$ENV{'OSH_IP_FROM'} = $ipfrom; # used in some plugins for is_access_granted()
# build ttyrec command that'll prefix the real command
$fnret = OVH::Bastion::build_ttyrec_cmdline(
ip => $osh_command,
port => 0,
user => 0,
account => $self,
uniqid => $log_uniq_id,
home => $home,
realm => $realm,
remoteaccount => $remoteself,
debug => $osh_debug,
tty => $tty,
notty => $notty
);
main_exit(OVH::Bastion::EXIT_TTYREC_CMDLINE_FAILED, "ttyrec_failed", $fnret->msg) if !$fnret;
@cmd = (@{$fnret->value->{'cmd'}}, '--', @cmd);
$fnret = OVH::Bastion::execute(
cmd => \@cmd,
noisy_stdout => 1,
@ -1065,13 +1082,11 @@ if ($osh_command) {
if (defined $log_insert_id and defined $log_db_name) {
$logret = OVH::Bastion::log_access_update(
account => $self,
insert_id => $log_insert_id,
db_name => $log_db_name,
uniq_id => $log_uniq_id,
returnvalue => $fnret->value ? $fnret->value->{'sysret_raw'} : undef,
plugin_stdout => $fnret->value ? $fnret->value->{'stdout'} : undef,
plugin_stderr => $fnret->value ? $fnret->value->{'stderr'} : undef
account => $self,
insert_id => $log_insert_id,
db_name => $log_db_name,
uniq_id => $log_uniq_id,
returnvalue => $fnret->value ? $fnret->value->{'sysret_raw'} : undef,
);
$logret or osh_warn($logret->msg);
}

@ -27,6 +27,13 @@ See the ``--help`` for a more fine-grained upgrade path if needed.
Version-specific upgrade instructions
=====================================
v3.xx.xx - 2023/xx/xx
*********************
Plugins output is now recorded using ttyrec, as the connections are, instead of being stored in sqlite format
within the home folder of the account. This helps avoiding the sqlite databases growing too much in size when
accounts are using osh commands very intensively.
v3.12.00 - 2023/06/27
*********************

@ -1088,8 +1088,8 @@ sub build_ttyrec_cmdline_part1of2 {
$ttyrecFilenameFormat =~ s/&bastionname/$bastionName/g;
$ttyrecFilenameFormat =~ s/&uniqid/$params{'uniqid'}/g if $params{'uniqid'};
$ttyrecFilenameFormat =~ s/&ip/$params{'ip'}/g if $params{'ip'};
$ttyrecFilenameFormat =~ s/&port/$params{'port'}/g if $params{'port'};
$ttyrecFilenameFormat =~ s/&user/$params{'user'}/g if $params{'user'};
$ttyrecFilenameFormat =~ s/&port/$params{'port'}/g if defined $params{'port'};
$ttyrecFilenameFormat =~ s/&user/$params{'user'}/g if defined $params{'user'};
$ttyrecFilenameFormat =~ s/&account/$params{'account'}/g if $params{'account'};
if ($ttyrecFilenameFormat =~ /&(bastionname|uniqid|ip|port|user|account)/) {

@ -514,9 +514,6 @@ sub _sql_log_update_file {
my $timestampend = $params{'timestampend'};
my $timestampendusec = $params{'timestampendusec'};
my $plugin_stdout = $params{'plugin_stdout'};
my $plugin_stderr = $params{'plugin_stderr'};
if (not $file or not defined $id) {
return R('ERR_MISSING_PARAMETER', msg => "Missing required parameter file or id");
}
@ -580,71 +577,6 @@ sub _sql_log_update_file {
return R('ERR_SQL_EXECUTE', msg => "SQL error [updating] err $DBI::err while doing [$doing]: $DBI::errstr");
}
# if we have plugin stdout or stderr, log it too
if (defined $plugin_stdout or defined $plugin_stderr) {
# retry block
foreach my $retry (0 .. 19) {
# if we're retrying, sleep a bit before, to ease concurrency
sleep($retry / 50 + rand() / 10) if $retry;
# on each retry, clean those vars (undef $dbh disconnects if connected)
undef $dbh;
undef $sth;
undef $result;
undef $doing;
# connect to db
$dbh = DBI->connect("dbi:SQLite:dbname=$file", "", "", {PrintError => 0, RaiseError => 0});
if (!$dbh) {
$doing = "opening database";
next; # retry
}
$sth = $dbh->prepare(
<<'EOS'
CREATE TABLE IF NOT EXISTS plugincalls(
id INTEGER PRIMARY KEY,
connection_id INTEGER UNIQUE,
stdout TEXT,
stderr TEXT)
EOS
);
if (!$sth) {
$doing = "creating plugins table (prepare)";
next; # retry
}
$result = $sth->execute();
if (!$result) {
$doing = "creating plugins table (execute)";
next; # retry
}
$sth = $dbh->prepare("INSERT INTO plugincalls (connection_id, stdout, stderr) VALUES (?,?,?)");
if (!$sth) {
$doing = "inserting plugincall data (prepare)";
next; # retry
}
$result = $sth->execute($id, join("\n", @{$plugin_stdout || []}), join("\n", @{$plugin_stderr || []}));
if (!$result) {
$doing = "inserting plugincall data (execute)";
next; # retry
}
# if we're here, it worked, stop retrying
last;
}
# if this is set, we probably reached max retry in previous loop without succeeding
if ($DBI::err) {
warn_syslog(
"Failed after multiple retries [plugins] err $DBI::err while doing [$doing]: $DBI::errstr ($file)");
return R('ERR_SQL_EXECUTE', msg => "SQL error [plugins] err $DBI::err while doing [$doing]: $DBI::errstr");
}
}
return R('OK');
}

Loading…
Cancel
Save