the-bastion/tests/unit/run.pl
2023-01-31 12:03:13 +01:00

423 lines
12 KiB
Perl
Executable file

#! /usr/bin/env perl
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
use common::sense;
use Test::More;
use Test::Deep;
use File::Basename;
use lib dirname(__FILE__) . '/../../lib/perl';
use OVH::Bastion;
use OVH::Result;
use JSON;
OVH::Bastion::enable_mocking();
OVH::Bastion::set_mock_data(
{
"accounts" => {
"me" => {
"uid" => 99982,
"gid" => 99982,
"personal_accesses" => [qw{ me@1.2.3.4 }],
"legacy_accesses" => [qw{ me@1.2.3.5 }],
"guest_accesses" => {
"group2" => [qw{ group1@9.9.9.9 }],
}
},
"wildcard" => {
"uid" => 99981,
"gid" => 99981,
"personal_accesses" => [qw{ 0.0.0.0/0 }],
},
},
"groups" => {
"group1" => {
"members" => [qw{ me }],
"accesses" => [qw{ group1@0.0.0.0/0 }],
},
"group2" => {}
},
}
);
OVH::Bastion::load_configuration(
mock_data => {
ingressToEgressRules => [
[["10.19.0.0/16", "10.15.15.0/24"], ["10.20.0.0/16"], "ALLOW-EXCLUSIVE"],
[["192.168.42.0/24"], ["192.168.42.0/24"], "ALLOW"],
[["192.168.0.0/16"], ["192.168.0.0/16"], "DENY"]
],
bastionName => "mock",
idleLockTimeout => 17,
idleKillTimeout => 29,
# all options below are bool, we'll test for their normalization
enableSyslog => 1,
enableGlobalAccessLog => JSON::true,
enableAccountAccessLog => "yes",
enableGlobalSqlLog => 0,
enableAccountSqlLog => JSON::false,
displayLastLogin => "",
debug => JSON::null,
passwordAllowed => "no",
telnetAllowed => "false",
}
);
# TESTS
my $fnret;
$fnret = OVH::Bastion::build_ttyrec_cmdline(
ip => "127.0.0.1",
port => 7979,
user => "randomuser",
account => "bastionuser",
uniqid => 'cafed00dcafe',
home => "/home/randomuser",
);
cmp_deeply(
$fnret->value->{'saveFile'},
re(
qr{^\Q/home/randomuser/ttyrec/127.0.0.1/20\E\d\d-\d\d-\d\d.\d\d\-\d\d\-\d\d\.\d{6}\Q.cafed00dcafe.bastionuser.randomuser.127.0.0.1.7979.ttyrec\E$}
),
"build_ttyrec_cmdline saveFile"
);
cmp_deeply(
$fnret->value->{'cmd'},
[
'ttyrec',
'-f',
$fnret->value->{'saveFile'},
'-F',
'/home/randomuser/ttyrec/127.0.0.1/%Y-%m-%d.%H-%M-%S.#usec#.cafed00dcafe.bastionuser.randomuser.127.0.0.1.7979.ttyrec',
'-t',
17,
'-s',
"To unlock, use '--osh unlock' from another console",
'-k',
29,
],
"build_ttyrec_cmdline cmd"
);
$fnret = OVH::Bastion::build_ttyrec_cmdline_part1of2(
ip => "127.0.0.1",
port => 7979,
user => "randomuser",
account => "bastionuser",
uniqid => 'cafed00dcafe',
home => "/home/randomuser",
);
cmp_deeply(
$fnret->value->{'saveFile'},
re(
qr{^\Q/home/randomuser/ttyrec/127.0.0.1/20\E\d\d-\d\d-\d\d.\d\d\-\d\d\-\d\d\.\d{6}\Q.cafed00dcafe.bastionuser.randomuser.127.0.0.1.7979.ttyrec\E$}
),
"build_ttyrec_cmdline_part1of2 saveFile"
);
cmp_deeply(
$fnret->value->{'cmd'},
[
'ttyrec',
'-f',
$fnret->value->{'saveFile'},
'-F',
'/home/randomuser/ttyrec/127.0.0.1/%Y-%m-%d.%H-%M-%S.#usec#.cafed00dcafe.bastionuser.randomuser.127.0.0.1.7979.ttyrec'
],
"build_ttyrec_cmdline_part1of2 cmd"
);
$fnret = OVH::Bastion::build_ttyrec_cmdline_part2of2(
input => $fnret->value,
idleKillTimeout => 88,
idleLockTimeout => 99,
);
cmp_deeply(
$fnret->value->{'saveFile'},
re(
qr{^\Q/home/randomuser/ttyrec/127.0.0.1/20\E\d\d-\d\d-\d\d.\d\d\-\d\d\-\d\d\.\d{6}\Q.cafed00dcafe.bastionuser.randomuser.127.0.0.1.7979.ttyrec\E$}
),
"build_ttyrec_cmdline_part2of2 saveFile"
);
cmp_deeply(
$fnret->value->{'cmd'},
[
'ttyrec',
'-f',
$fnret->value->{'saveFile'},
'-F',
'/home/randomuser/ttyrec/127.0.0.1/%Y-%m-%d.%H-%M-%S.#usec#.cafed00dcafe.bastionuser.randomuser.127.0.0.1.7979.ttyrec',
'-t',
99,
'-s',
"To unlock, use '--osh unlock' from another console",
'-k',
88,
],
"build_ttyrec_cmdline_part2of2 cmd"
);
is(OVH::Bastion::config("bastionName")->value, "mock", "bastion name is mocked");
ok(OVH::Bastion::is_account_valid(account => "azerty")->is_ok, "is_account_valid('azerty')");
is(OVH::Bastion::is_account_valid(account => "in valid")->err, "KO_FORBIDDEN_CHARS", "is_account_valid('in valid')");
for my $suffix (qw{ tty aclkeeper gatekeeper owner }) {
is(OVH::Bastion::is_account_valid(account => "account-$suffix")->err,
"KO_FORBIDDEN_SUFFIX", "is_account_valid('account-$suffix')");
}
is(OVH::Bastion::is_account_valid(account => "root")->err, "KO_FORBIDDEN_NAME", "is_account_valid('root')");
ok(OVH::Bastion::is_bastion_account_valid_and_existing(account => "me")->is_ok,
"is_bastion_account_valid_and_existing('me')");
is_deeply(
OVH::Bastion::is_access_granted(
account => "me",
user => "remote",
ipfrom => "1.2.3.4",
ip => "5.6.7.8",
port => "9876"
),
R('KO_ACCESS_DENIED', msg => 'Access denied for me to remote@5.6.7.8:9876'),
"is_access_granted(me) on denied machine"
);
ok(
OVH::Bastion::is_access_granted(
account => "me",
user => "me",
ipfrom => "1.1.1.1",
ip => "1.2.3.4",
port => "9876"
)->is_ok,
"is_access_granted(me) on allowed machine"
);
is(
OVH::Bastion::is_access_granted(
account => "wildcard",
user => "root",
ipfrom => "10.15.15.15",
ip => "1.2.3.4",
port => "9876"
)->err,
"KO_ACCESS_DENIED",
"is_access_granted(wildcard) on disallowed machine due to ingressToEgressRules #1"
);
is(
OVH::Bastion::is_access_granted(
account => "wildcard",
user => "root",
ipfrom => "10.19.1.2",
ip => "1.2.3.4",
port => "9876"
)->err,
"KO_ACCESS_DENIED",
"is_access_granted(wildcard) on disallowed machine due to ingressToEgressRules #1"
);
ok(
OVH::Bastion::is_access_granted(
account => "wildcard",
user => "root",
ipfrom => "10.19.1.2",
ip => "10.20.1.2",
port => "9876"
)->is_ok,
"is_access_granted(wildcard) on allowed machine due to ingressToEgressRules #1"
);
ok(
OVH::Bastion::is_access_granted(
account => "wildcard",
user => "root",
ipfrom => "192.168.42.1",
ip => "192.168.42.4",
port => "9876"
)->is_ok,
"is_access_granted(wildcard) on allowed machine due to ingressToEgressRules #2"
);
ok(
OVH::Bastion::is_access_granted(
account => "wildcard",
user => "root",
ipfrom => "192.168.42.1",
ip => "5.6.7.8",
port => "9876"
)->is_ok,
"is_access_granted(wildcard) on allowed machine due to ingressToEgressRules #2"
);
is(
OVH::Bastion::is_access_granted(
account => "wildcard",
user => "root",
ipfrom => "192.168.43.1",
ip => "192.168.42.4",
port => "9876"
)->err,
"KO_ACCESS_DENIED",
"is_access_granted(wildcard) on disallowed machine due to ingressToEgressRules #3"
);
ok(
OVH::Bastion::is_access_granted(
account => "wildcard",
user => "root",
ipfrom => "192.168.43.1",
ip => "5.6.7.8",
port => "9876"
)->is_ok,
"is_access_granted(wildcard) on allowed machine due to ingressToEgressRules catch-all"
);
# check that "bool" type options are correctly normalized
is(OVH::Bastion::config("enableSyslog")->value, 1, "config bool(1)");
is(OVH::Bastion::config("enableGlobalAccessLog")->value, 1, "config bool(true)");
is(OVH::Bastion::config("enableAccountAccessLog")->value, 1, "config bool(\"yes\")");
is(OVH::Bastion::config("enableGlobalSqlLog")->value, 0, "config bool(0)");
is(OVH::Bastion::config("enableAccountSqlLog")->value, 0, "config bool(false)");
is(OVH::Bastion::config("displayLastLogin")->value, 0, "config bool(\"\")");
is(OVH::Bastion::config("interactiveModeByDefault")->value, 1, "config bool(missing, default true)");
is(OVH::Bastion::config("interactiveModeAllowed")->value, 0, "config bool(missing, default false)");
is(OVH::Bastion::config("debug")->value, 0, "config bool(null)");
is(OVH::Bastion::config("passwordAllowed")->value, 0, "config bool(\"no\")");
is(OVH::Bastion::config("telnetAllowed")->value, 0, "config bool(\"false\")");
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => JSON::true}
)->value ? 1 : 0,
1,
"is_plugin_disabled(disabled=true)"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => JSON::false}
)->value ? 1 : 0,
0,
"is_plugin_disabled(disabled=false)"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => JSON::null}
)->value ? 1 : 0,
0,
"is_plugin_disabled(disabled=null)"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => "yes"}
)->value ? 1 : 0,
1,
"is_plugin_disabled(disabled=\"yes\")"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => "no"}
)->value ? 1 : 0,
0,
"is_plugin_disabled(disabled=\"no\")"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => "true"}
)->value ? 1 : 0,
1,
"is_plugin_disabled(disabled=\"true\")"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => "false"}
)->value ? 1 : 0,
0,
"is_plugin_disabled(disabled=\"false\")"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => ""}
)->value ? 1 : 0,
0,
"is_plugin_disabled(disabled=\"\")"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => "0"}
)->value ? 1 : 0,
0,
"is_plugin_disabled(disabled=\"0\")"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => "1"}
)->value ? 1 : 0,
1,
"is_plugin_disabled(disabled=\"1\")"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => 0}
)->value ? 1 : 0,
0,
"is_plugin_disabled(disabled=0)"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {disabled => 1}
)->value ? 1 : 0,
1,
"is_plugin_disabled(disabled=1)"
);
is(
OVH::Bastion::plugin_config(
plugin => "help",
key => "disabled",
mock_data => {}
)->value ? 1 : 0,
0,
"is_plugin_disabled()"
);
is(
OVH::Bastion::build_re_from_wildcards(wildcards => ["azerty", "st*ar", "que?stion", "c*ompl?i*cated*"])->value,
qr/^azerty$|^st.*ar$|^que.stion$|^c.*ompl.i.*cated.*$/,
"build_re_from_wildcards() 1"
);
is(
OVH::Bastion::build_re_from_wildcards(
wildcards => ["azerty", "st*ar", "que?stion", "c*ompl?i*cated*"],
implicit_contains => 1
)->value,
qr/^.*azerty.*$|^st.*ar$|^que.stion$|^c.*ompl.i.*cated.*$/,
"build_re_from_wildcards() 2"
);
done_testing();