mirror of
https://github.com/ovh/the-bastion.git
synced 2025-01-06 07:22:14 +08:00
423 lines
12 KiB
Perl
Executable file
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();
|