mirror of
https://github.com/ovh/the-bastion.git
synced 2025-09-05 04:24:11 +08:00
enh: add max_inactive_days to account configuration (#230)
This commit is contained in:
parent
15cb2c2453
commit
ef10d509fd
6 changed files with 79 additions and 2 deletions
|
@ -223,7 +223,7 @@ sub _toggle_yes_no {
|
||||||
|
|
||||||
foreach my $tuple (@modify) {
|
foreach my $tuple (@modify) {
|
||||||
my ($key, $value) = $tuple =~ /^([a-zA-Z0-9-]+)=([a-zA-Z0-9-]+)$/;
|
my ($key, $value) = $tuple =~ /^([a-zA-Z0-9-]+)=([a-zA-Z0-9-]+)$/;
|
||||||
next if (!$key || !$value);
|
next if (!$key || !defined $value);
|
||||||
my $jsonkey = $key;
|
my $jsonkey = $key;
|
||||||
$jsonkey =~ s/-/_/g;
|
$jsonkey =~ s/-/_/g;
|
||||||
|
|
||||||
|
@ -336,6 +336,24 @@ foreach my $tuple (@modify) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elsif ($key eq 'max-inactive-days') {
|
||||||
|
osh_info "Changing the account expiration policy...";
|
||||||
|
if ($value !~ /^(?:\d+|-1)$/) {
|
||||||
|
osh_warn "Invalid parameter '$value', skipping";
|
||||||
|
$result{$jsonkey} = R('ERR_INVALID_PARAMETER');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
my %todo = ($value >= 0 ? (value => $value) : (delete => 1));
|
||||||
|
$fnret = OVH::Bastion::account_config(account => $account, %todo, %{OVH::Bastion::OPT_ACCOUNT_MAX_INACTIVE_DAYS()});
|
||||||
|
$result{$jsonkey} = $fnret;
|
||||||
|
if ($fnret) {
|
||||||
|
osh_info "... modification done";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
osh_warn "... error while setting the account expiration policy: " . $fnret->msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HEXIT('OK', value => \%result);
|
HEXIT('OK', value => \%result);
|
||||||
|
|
|
@ -274,6 +274,17 @@ if (OVH::Bastion::is_auditor(account => $self)) {
|
||||||
$ret{'idle_ignore'} = OVH::Bastion::account_config(account => $account, key => OVH::Bastion::OPT_ACCOUNT_IDLE_IGNORE, public => 1) ? 1 : 0;
|
$ret{'idle_ignore'} = OVH::Bastion::account_config(account => $account, key => OVH::Bastion::OPT_ACCOUNT_IDLE_IGNORE, public => 1) ? 1 : 0;
|
||||||
osh_info "\n- Account is immune to idle counter-measures: " . ($ret{'idle_ignore'} ? colored('yes', 'green') : colored('no', 'blue'));
|
osh_info "\n- Account is immune to idle counter-measures: " . ($ret{'idle_ignore'} ? colored('yes', 'green') : colored('no', 'blue'));
|
||||||
|
|
||||||
|
$ret{'max_inactive_days'} = OVH::Bastion::account_config(account => $account, %{OVH::Bastion::OPT_ACCOUNT_MAX_INACTIVE_DAYS()})->value;
|
||||||
|
if (!defined $ret{'max_inactive_days'}) {
|
||||||
|
osh_info "- Maximum number of days of inactivity before account is disabled: (default)";
|
||||||
|
}
|
||||||
|
elsif ($ret{'max_inactive_days'} == 0) {
|
||||||
|
osh_info "- Maximum number of days of inactivity before account is disabled: never";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
osh_info "- Maximum number of days of inactivity before account is disabled: " . $ret{'max_inactive_days'};
|
||||||
|
}
|
||||||
|
|
||||||
my @command = qw{ sudo -n -u root -- /usr/bin/env perl -T };
|
my @command = qw{ sudo -n -u root -- /usr/bin/env perl -T };
|
||||||
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-accountGetPasswordInfo';
|
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-accountGetPasswordInfo';
|
||||||
push @command, '--account', $account;
|
push @command, '--account', $account;
|
||||||
|
|
|
@ -21,6 +21,7 @@ my $remainingOptions = OVH::Bastion::Plugin::begin(
|
||||||
"egress-strict-host-key-checking=s" => \$modify{'egress-strict-host-key-checking'},
|
"egress-strict-host-key-checking=s" => \$modify{'egress-strict-host-key-checking'},
|
||||||
"personal-egress-mfa-required=s" => \$modify{'personal-egress-mfa-required'},
|
"personal-egress-mfa-required=s" => \$modify{'personal-egress-mfa-required'},
|
||||||
"idle-ignore=s" => \$modify{'idle-ignore'},
|
"idle-ignore=s" => \$modify{'idle-ignore'},
|
||||||
|
"max-inactive-days=i" => \$modify{'max-inactive-days'},
|
||||||
"osh-only=s" => \$modify{'osh-only'},
|
"osh-only=s" => \$modify{'osh-only'},
|
||||||
},
|
},
|
||||||
helptext => <<'EOF',
|
helptext => <<'EOF',
|
||||||
|
@ -49,6 +50,9 @@ Usage: --osh SCRIPT_NAME --account ACCOUNT [--option value [--option value [...]
|
||||||
using the personal keys of the account, POLICY can be 'password', 'totp', 'any' or 'none'
|
using the personal keys of the account, POLICY can be 'password', 'totp', 'any' or 'none'
|
||||||
--always-active yes|no Set or unset the account as always active (i.e. disable the check of the 'active' status on this account)
|
--always-active yes|no Set or unset the account as always active (i.e. disable the check of the 'active' status on this account)
|
||||||
--idle-ignore yes|no If enabled, this account is immune to the idleLockTimeout and idleKillTimeout bastion-wide policy
|
--idle-ignore yes|no If enabled, this account is immune to the idleLockTimeout and idleKillTimeout bastion-wide policy
|
||||||
|
--max-inactive-days DAYS Set account expiration policy, overriding the global bastion configuration 'accountMaxInactiveDays'.
|
||||||
|
Setting this option to zero disables account expiration. Setting this option to -1 removes this account
|
||||||
|
expiration policy, i.e. the global bastion setting will apply.
|
||||||
--osh-only yes|no If enabled, this account can only use ``--osh`` commands, and can't connect anywhere through the bastion
|
--osh-only yes|no If enabled, this account can only use ``--osh`` commands, and can't connect anywhere through the bastion
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
@ -91,12 +95,16 @@ if ($modify{'personal-egress-mfa-required'} && !grep { $modify{'personal-egress-
|
||||||
help();
|
help();
|
||||||
osh_exit 'ERR_INVALID_PARAMETER', "Expected option 'password', 'totp', 'any', 'none' to --personal-egress-mfa-required";
|
osh_exit 'ERR_INVALID_PARAMETER', "Expected option 'password', 'totp', 'any', 'none' to --personal-egress-mfa-required";
|
||||||
}
|
}
|
||||||
|
if ($modify{'max-inactive-days'} && $modify{'max-inactive-days'} !~ /^(?:\d+|-1)$/) {
|
||||||
|
help();
|
||||||
|
osh_exit "ERR_INVALID_PARAMETER", "Expected -1, 0, or a strictly positive number of days as parameter to --max-inactive-days";
|
||||||
|
}
|
||||||
|
|
||||||
my @command = qw{ sudo -n -u root -- /usr/bin/env perl -T };
|
my @command = qw{ sudo -n -u root -- /usr/bin/env perl -T };
|
||||||
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-accountModify';
|
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-accountModify';
|
||||||
push @command, '--account', $account;
|
push @command, '--account', $account;
|
||||||
foreach my $key (keys %modify) {
|
foreach my $key (keys %modify) {
|
||||||
push @command, '--modify', $key . '=' . $modify{$key} if $modify{$key};
|
push @command, '--modify', $key . '=' . $modify{$key} if defined $modify{$key};
|
||||||
}
|
}
|
||||||
|
|
||||||
osh_exit OVH::Bastion::helper(cmd => \@command);
|
osh_exit OVH::Bastion::helper(cmd => \@command);
|
||||||
|
|
|
@ -59,6 +59,12 @@ Modify an account configuration
|
||||||
|
|
||||||
If enabled, this account is immune to the idleLockTimeout and idleKillTimeout bastion-wide policy
|
If enabled, this account is immune to the idleLockTimeout and idleKillTimeout bastion-wide policy
|
||||||
|
|
||||||
|
.. option:: --max-inactive-days DAYS
|
||||||
|
|
||||||
|
Set account expiration policy, overriding the global bastion configuration 'accountMaxInactiveDays'.
|
||||||
|
|
||||||
|
Setting this option to zero disables account expiration. Setting this option to -1 removes this account
|
||||||
|
expiration policy, i.e. the global bastion setting will apply.
|
||||||
.. option:: --osh-only yes|no
|
.. option:: --osh-only yes|no
|
||||||
|
|
||||||
If enabled, this account can only use ``--osh`` commands, and can't connect anywhere through the bastion
|
If enabled, this account can only use ``--osh`` commands, and can't connect anywhere through the bastion
|
||||||
|
|
|
@ -116,6 +116,8 @@ use constant {
|
||||||
OPT_ACCOUNT_ALWAYS_ACTIVE => 'always_active',
|
OPT_ACCOUNT_ALWAYS_ACTIVE => 'always_active',
|
||||||
OPT_ACCOUNT_IDLE_IGNORE => 'idle_ignore',
|
OPT_ACCOUNT_IDLE_IGNORE => 'idle_ignore',
|
||||||
OPT_ACCOUNT_OSH_ONLY => 'osh_only',
|
OPT_ACCOUNT_OSH_ONLY => 'osh_only',
|
||||||
|
|
||||||
|
OPT_ACCOUNT_MAX_INACTIVE_DAYS => {key => 'max_inactive_days', public => 1},
|
||||||
};
|
};
|
||||||
|
|
||||||
###########
|
###########
|
||||||
|
@ -183,6 +185,12 @@ sub is_account_nonexpired {
|
||||||
$accountMaxInactiveDays = $fnret->value;
|
$accountMaxInactiveDays = $fnret->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# some accounts might have a specific configuration overriding the global one
|
||||||
|
$fnret = OVH::Bastion::account_config(account => $sysaccount, %{OVH::Bastion::OPT_ACCOUNT_MAX_INACTIVE_DAYS()});
|
||||||
|
if ($fnret) {
|
||||||
|
$accountMaxInactiveDays = $fnret->value;
|
||||||
|
}
|
||||||
|
|
||||||
my $isFirstLogin;
|
my $isFirstLogin;
|
||||||
my $lastlog;
|
my $lastlog;
|
||||||
my $filepath = "/home/$sysaccount/lastlog" . ($remoteaccount ? "_$remoteaccount" : "");
|
my $filepath = "/home/$sysaccount/lastlog" . ($remoteaccount ? "_$remoteaccount" : "");
|
||||||
|
|
|
@ -41,6 +41,7 @@ testsuite_accountinfo()
|
||||||
json .value.ingress_piv_enforced 0 .value.always_active 1 .value.creation_information.by "$account0"
|
json .value.ingress_piv_enforced 0 .value.always_active 1 .value.creation_information.by "$account0"
|
||||||
json .value.creation_information.comment "this is a comment"
|
json .value.creation_information.comment "this is a comment"
|
||||||
json .value.already_seen_before 0 .value.last_activity null
|
json .value.already_seen_before 0 .value.last_activity null
|
||||||
|
json .value.max_inactive_days null
|
||||||
|
|
||||||
# a2 connects, which will update already_seen_before
|
# a2 connects, which will update already_seen_before
|
||||||
success 325-accountinfo a2_connects $a2 --osh info
|
success 325-accountinfo a2_connects $a2 --osh info
|
||||||
|
@ -51,6 +52,31 @@ testsuite_accountinfo()
|
||||||
json .value.already_seen_before 1
|
json .value.already_seen_before 1
|
||||||
contain "Last seen on"
|
contain "Last seen on"
|
||||||
|
|
||||||
|
grant accountModify
|
||||||
|
|
||||||
|
# a0 changes a2 expiration policy
|
||||||
|
success 325-accountinfo a0_accountmodify_a2_expi_15 $a0 --osh accountModify --account $account2 --max-inactive-days 15
|
||||||
|
|
||||||
|
# a1 should see the updated field
|
||||||
|
success 325-accountinfo a1_accountinfo_a2_inactive_days $a1 --osh accountInfo --account $account2
|
||||||
|
json .value.max_inactive_days 15
|
||||||
|
|
||||||
|
# a0 changes a2 expiration policy
|
||||||
|
success 325-accountinfo a0_accountmodify_a2_expi_disabled $a0 --osh accountModify --account $account2 --max-inactive-days 0
|
||||||
|
|
||||||
|
# a1 should see the updated field
|
||||||
|
success 325-accountinfo a1_accountinfo_a2_inactive_days_disabled $a1 --osh accountInfo --account $account2
|
||||||
|
json .value.max_inactive_days 0
|
||||||
|
|
||||||
|
# a0 changes a2 expiration policy
|
||||||
|
success 325-accountinfo a0_accountmodify_a2_expi_default $a0 --osh accountModify --account $account2 --max-inactive-days -1
|
||||||
|
|
||||||
|
# a1 should see the updated field
|
||||||
|
success 325-accountinfo a1_accountinfo_a2_inactive_days_default $a1 --osh accountInfo --account $account2
|
||||||
|
json .value.max_inactive_days null
|
||||||
|
|
||||||
|
revoke accountModify
|
||||||
|
|
||||||
# delete account1 & account2
|
# delete account1 & account2
|
||||||
grant accountDelete
|
grant accountDelete
|
||||||
success 325-accountinfo a0_delete_a1 $a0 --osh accountDelete --account $account1 --no-confirm
|
success 325-accountinfo a0_delete_a1 $a0 --osh accountDelete --account $account1 --no-confirm
|
||||||
|
|
Loading…
Add table
Reference in a new issue