the-bastion/lib/perl/OVH/Bastion/jail.inc
Stéphane Lesimple fde20136ef
Initial commit
2020-10-20 14:30:27 +00:00

115 lines
4.2 KiB
Perl

# vim: set filetype=perl ts=4 sw=4 sts=4 et:
package OVH::Bastion;
use common::sense;
use constant {MINIJAIL_PATH => "/bin/minijail0",};
sub jailify {
my %params = @_;
my $required = delete $params{'required'};
my $use_sudo = delete $params{'use_sudo'};
my $user = delete $params{'user'};
my $group = delete $params{'group'};
my $no_new_privs = delete $params{'no_new_privs'};
my $set_env = delete $params{'set_env'};
my $pid_ns = delete $params{'pid_ns'};
my $mount_mode = delete $params{'mount_mode'};
my $mount_ns = delete $params{'mount_ns'};
my $pivot_root = delete $params{'pivot_root'};
my $bind_mounts = delete $params{'bind_mounts'};
my $mounts = delete $params{'mounts'};
my $seccomp = delete $params{'seccomp'};
my $uts = delete $params{'uts'};
my $ld_preload = delete $params{'ld_preload'};
my $dev = delete $params{'dev'};
my $cmd = delete $params{'cmd'};
if (%params) {
# this is a coding error => warn(), this'll make any test passing through it automatically fail
warn("Spurious parameter passed to jailify(): " . join(", ", keys %params));
return R('ERR_INTERNAL', msg => "Spurious parameter passed to jailify()");
}
if (!$cmd || ref $cmd ne 'ARRAY') {
return R('ERR_INVALID_PARAMETER', msg => "Specified cmd is either missing or not an arrayref");
}
if (!-e -x OVH::Bastion::MINIJAIL_PATH) {
return R('ERR_INTERNAL', msg => "minijail not available, please warn your bastion administrator") if $required;
# not installed and not required? just return the @cmd untouched
return R('OK_NO_CHANGE', value => $cmd);
}
# we need to be root for several cases
if (($user || $group || $mount_ns || $pivot_root || $bind_mounts || $mounts) && ($> != 0) && !$use_sudo) {
# this is a coding error => warn(), this'll make any test passing through it automatically fail
warn(
'Jailify attempted with a feature needing root without being root ',
"\$user: ",
($user // "_undef_"),
"\$group: ",
($group // "_undef_"),
"\$mount_ns: ",
($mount_ns // "_undef_"),
"\$pivot_root: ",
($pivot_root // "_undef_"),
"\$bind_mounts: ",
($bind_mounts // "_undef_"),
"\$mounts: ",
($mounts // "_undef_"),
);
return R('ERR_INTERNAL', msg => "Bad use of jailify(), please warn your bastion administrator");
}
my @jailcmd;
if ($use_sudo) {
push @jailcmd, qw{ sudo -n -u root -- };
}
push @jailcmd, OVH::Bastion::MINIJAIL_PATH, "--logging=stderr";
push @jailcmd, "-u", $user if $user;
push @jailcmd, "-g", $group if $group;
push @jailcmd, "-n" if $no_new_privs;
push @jailcmd, "-v" if $mount_ns;
push @jailcmd, "-p" if $pid_ns;
push @jailcmd, "--uts" if $uts;
push @jailcmd, "-K$mount_mode" if $mount_mode;
push @jailcmd, "-d" if $dev;
push @jailcmd, "--child-ld-preload", $ld_preload if $ld_preload;
if ($pivot_root) {
return R('ERR_INVALID_PARAMETER', msg => "Specified pivot_root ($pivot_root) is not a directory") if !-d $pivot_root;
push @jailcmd, "-P", $pivot_root;
}
if ($seccomp) {
return R('ERR_INVALID_PARAMETER', msg => "Specified seccomp filter is not a file") if !-f -r $seccomp;
push @jailcmd, "-S", $seccomp;
}
if (defined $bind_mounts) {
return R('ERR_INVALID_PARAMETER', msg => "Specified bind_mounts is not an arrayref") if (ref $bind_mounts ne 'ARRAY');
push @jailcmd, "-b", $_ for (@$bind_mounts);
}
if (defined $mounts) {
return R('ERR_INVALID_PARAMETER', msg => "Specified mounts is not an arrayref") if (ref $mounts ne 'ARRAY');
push @jailcmd, "-k", $_ for (@$mounts);
}
if (defined $set_env) {
return R('ERR_INVALID_PARAMETER', msg => "Specified set_env is not an arrayref") if (ref $set_env ne 'ARRAY');
push @jailcmd, "--set-env", $_ for (@$set_env);
}
push @jailcmd, '--', @$cmd;
return R('OK', value => \@jailcmd);
}
1;