mirror of
https://github.com/ovh/the-bastion.git
synced 2025-09-13 00:14:18 +08:00
new account option: --pubkey-auth-optional, to allow ingress login with or without pubkey when pam is required
This commit is contained in:
parent
4d3ee1b99d
commit
d85298f229
18 changed files with 120 additions and 97 deletions
|
@ -872,7 +872,7 @@ if [ "$nothing" = 0 ]; then
|
||||||
at_least_one_error=0
|
at_least_one_error=0
|
||||||
for group in bastion-users \
|
for group in bastion-users \
|
||||||
mfa-password-reqd mfa-password-bypass mfa-password-configd \
|
mfa-password-reqd mfa-password-bypass mfa-password-configd \
|
||||||
mfa-totp-reqd mfa-totp-bypass mfa-totp-configd bastion-nopam mfa-any
|
mfa-totp-reqd mfa-totp-bypass mfa-totp-configd bastion-nopam osh-pubkey-auth-optional
|
||||||
do
|
do
|
||||||
if getent group "$group" >/dev/null 2>&1; then
|
if getent group "$group" >/dev/null 2>&1; then
|
||||||
:
|
:
|
||||||
|
|
|
@ -280,45 +280,45 @@ foreach my $tuple (@modify) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif ($key eq 'mfa-any') {
|
elsif ($key eq 'pubkey-auth-optional') {
|
||||||
$fnret = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_ANY_GROUP);
|
$fnret = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::OSH_PUBKEY_AUTH_OPTIONAL_GROUP);
|
||||||
if ($value eq 'yes') {
|
if ($value eq 'yes') {
|
||||||
{
|
{
|
||||||
osh_info "Setting authentication requirements to pubkey OR pam (if a password/TOTP is set) for this account...";
|
osh_info "Making public key authentication optional for this account...";
|
||||||
if ($fnret) {
|
if ($fnret) {
|
||||||
osh_info "... no change was required";
|
osh_info "... no change was required";
|
||||||
$result{$jsonkey} = R('OK_NO_CHANGE');
|
$result{$jsonkey} = R('OK_NO_CHANGE');
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
|
|
||||||
$fnret = OVH::Bastion::sys_addmembertogroup(user => $account, group => OVH::Bastion::MFA_ANY_GROUP, noisy_stderr => 1);
|
$fnret = OVH::Bastion::sys_addmembertogroup(user => $account, group => OVH::Bastion::OSH_PUBKEY_AUTH_OPTIONAL_GROUP, noisy_stderr => 1);
|
||||||
if (!$fnret) {
|
if (!$fnret) {
|
||||||
osh_warn "... error while setting the alternative authentication option";
|
osh_warn "... error while setting the optional pubkey option";
|
||||||
$result{$jsonkey} = R('ERR_ADDING_TO_GROUP');
|
$result{$jsonkey} = R('ERR_ADDING_TO_GROUP');
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
|
|
||||||
osh_info "... done, this account can now authenticate with either pubkey or pam (if a password/TOTP is set)";
|
osh_info "... done, this account can now authenticate with or without a pubkey if a password/TOTP is set";
|
||||||
$result{$jsonkey} = R('OK');
|
$result{$jsonkey} = R('OK');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif ($value eq 'no') {
|
elsif ($value eq 'no') {
|
||||||
{
|
{
|
||||||
osh_info "Setting authentication to pubkey AND pam (if a password/TOTP is set) for this account...";
|
osh_info "Making pubkey authentication mandatory for this account...";
|
||||||
if (!$fnret) {
|
if (!$fnret) {
|
||||||
osh_info "... no change was required";
|
osh_info "... no change was required";
|
||||||
$result{$jsonkey} = R('OK_NO_CHANGE');
|
$result{$jsonkey} = R('OK_NO_CHANGE');
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
|
|
||||||
$fnret = OVH::Bastion::sys_delmemberfromgroup(user => $account, group => OVH::Bastion::MFA_ANY_GROUP, noisy_stderr => 1);
|
$fnret = OVH::Bastion::sys_delmemberfromgroup(user => $account, group => OVH::Bastion::OSH_PUBKEY_AUTH_OPTIONAL_GROUP, noisy_stderr => 1);
|
||||||
if (!$fnret) {
|
if (!$fnret) {
|
||||||
osh_warn "... error while removing the alternative authentication option";
|
osh_warn "... error while removing the optional pubkey option";
|
||||||
$result{$jsonkey} = R('ERR_REMOVING_FROM_GROUP');
|
$result{$jsonkey} = R('ERR_REMOVING_FROM_GROUP');
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
|
|
||||||
osh_info "... done, this account now requires to authenticate with pubkey AND pam (if a password/TOTP is set)";
|
osh_info "... done, this account now requires a pubkey to authenticate";
|
||||||
$result{$jsonkey} = R('OK');
|
$result{$jsonkey} = R('OK');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,8 +267,8 @@ if (OVH::Bastion::is_auditor(account => $self)) {
|
||||||
$ret{'pam_auth_bypass'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::PAM_AUTH_BYPASS_GROUP) ? 1 : 0;
|
$ret{'pam_auth_bypass'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::PAM_AUTH_BYPASS_GROUP) ? 1 : 0;
|
||||||
osh_info "- PAM authentication bypass is " . ($ret{'pam_auth_bypass'} ? colored('enabled', 'green') : colored('disabled', 'blue'));
|
osh_info "- PAM authentication bypass is " . ($ret{'pam_auth_bypass'} ? colored('enabled', 'green') : colored('disabled', 'blue'));
|
||||||
|
|
||||||
$ret{'mfa_any'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_ANY_GROUP) ? 1 : 0;
|
$ret{'pubkey_auth_optional'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::OSH_PUBKEY_AUTH_OPTIONAL_GROUP) ? 1 : 0;
|
||||||
osh_info "- Alternative authentication logic (allow both pubkey alone and PAM alone) is " . ($ret{'mfa_any'} ? colored('enabled', 'green') : colored('disabled', 'blue'));
|
osh_info "- Optional public key authentication is " . ($ret{'pubkey_auth_optional'} ? colored('enabled', 'green') : colored('disabled', 'blue'));
|
||||||
|
|
||||||
$ret{'personal_egress_mfa_required'} = OVH::Bastion::account_config(account => $account, key => "personal_egress_mfa_required")->value;
|
$ret{'personal_egress_mfa_required'} = OVH::Bastion::account_config(account => $account, key => "personal_egress_mfa_required")->value;
|
||||||
$ret{'personal_egress_mfa_required'} ||= 'none'; # no config means no mfa
|
$ret{'personal_egress_mfa_required'} ||= 'none'; # no config means no mfa
|
||||||
|
|
|
@ -131,14 +131,14 @@ foreach my $account (sort keys %$accounts) {
|
||||||
|
|
||||||
$states{'can_connect'} = ($states{'is_active'} && !$states{'is_expired'}) ? 1 : 0;
|
$states{'can_connect'} = ($states{'is_active'} && !$states{'is_expired'}) ? 1 : 0;
|
||||||
|
|
||||||
$states{'mfa_password_required'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_PASSWORD_REQUIRED_GROUP) ? 1 : 0;
|
$states{'mfa_password_required'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_PASSWORD_REQUIRED_GROUP) ? 1 : 0;
|
||||||
$states{'mfa_password_configured'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_PASSWORD_CONFIGURED_GROUP) ? 1 : 0;
|
$states{'mfa_password_configured'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_PASSWORD_CONFIGURED_GROUP) ? 1 : 0;
|
||||||
$states{'mfa_password_bypass'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_PASSWORD_BYPASS_GROUP) ? 1 : 0;
|
$states{'mfa_password_bypass'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_PASSWORD_BYPASS_GROUP) ? 1 : 0;
|
||||||
$states{'mfa_totp_required'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_TOTP_REQUIRED_GROUP) ? 1 : 0;
|
$states{'mfa_totp_required'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_TOTP_REQUIRED_GROUP) ? 1 : 0;
|
||||||
$states{'mfa_totp_configured'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_TOTP_CONFIGURED_GROUP) ? 1 : 0;
|
$states{'mfa_totp_configured'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_TOTP_CONFIGURED_GROUP) ? 1 : 0;
|
||||||
$states{'mfa_totp_bypass'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_TOTP_BYPASS_GROUP) ? 1 : 0;
|
$states{'mfa_totp_bypass'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_TOTP_BYPASS_GROUP) ? 1 : 0;
|
||||||
$states{'pam_auth_bypass'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::PAM_AUTH_BYPASS_GROUP) ? 1 : 0;
|
$states{'pam_auth_bypass'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::PAM_AUTH_BYPASS_GROUP) ? 1 : 0;
|
||||||
$states{'mfa_any'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::MFA_ANY_GROUP) ? 1 : 0;
|
$states{'pubkey_auth_optional'} = OVH::Bastion::is_user_in_group(user => $account, group => OVH::Bastion::OSH_PUBKEY_AUTH_OPTIONAL_GROUP) ? 1 : 0;
|
||||||
|
|
||||||
if ($fnretPassword) {
|
if ($fnretPassword) {
|
||||||
$states{"password_$_"} = $fnretPassword->value->{$account}{$_} for (keys %{$fnretPassword->value->{$account}});
|
$states{"password_$_"} = $fnretPassword->value->{$account}{$_} for (keys %{$fnretPassword->value->{$account}});
|
||||||
|
@ -160,7 +160,7 @@ foreach my $account (sort keys %$accounts) {
|
||||||
push @mfaTOTP, 'bypass' if $states{'mfa_totp_bypass'};
|
push @mfaTOTP, 'bypass' if $states{'mfa_totp_bypass'};
|
||||||
|
|
||||||
osh_info sprintf(
|
osh_info sprintf(
|
||||||
"%-18s %6d active:%-12s expired:%-12s can_connect:%-12s already_seen:%-12s mfa_password:%-25s mfa_totp:%-25s pam_bypass:%-12s mfa_any:%-12s pass_status:%-15s pass_changed:%-10s pass_min_days:%-3d pass_max_days:%-3d pass_warn_days:%-3d %s\n",
|
"%-18s %6d active:%-12s expired:%-12s can_connect:%-12s already_seen:%-12s mfa_password:%-25s mfa_totp:%-25s pam_bypass:%-12s pubkey_auth_optional:%-12s pass_status:%-15s pass_changed:%-10s pass_min_days:%-3d pass_max_days:%-3d pass_warn_days:%-3d %s\n",
|
||||||
$account,
|
$account,
|
||||||
$accounts->{$account}{'uid'},
|
$accounts->{$account}{'uid'},
|
||||||
tristate2str($states{'is_active'}),
|
tristate2str($states{'is_active'}),
|
||||||
|
@ -169,8 +169,8 @@ foreach my $account (sort keys %$accounts) {
|
||||||
tristate2str($states{'already_seen_before'}),
|
tristate2str($states{'already_seen_before'}),
|
||||||
@mfaPassword ? colored(join(',', @mfaPassword), 'green') : colored('-', 'blue'),
|
@mfaPassword ? colored(join(',', @mfaPassword), 'green') : colored('-', 'blue'),
|
||||||
@mfaTOTP ? colored(join(',', @mfaTOTP), 'green') : colored('-', 'blue'),
|
@mfaTOTP ? colored(join(',', @mfaTOTP), 'green') : colored('-', 'blue'),
|
||||||
tristate2str($states{'pam_auth_bypass'}, 1),
|
tristate2str($states{'pam_auth_bypass'}, 1),
|
||||||
tristate2str($states{'mfa_any'}, 1),
|
tristate2str($states{'pubkey_auth_optional'}, 1),
|
||||||
(
|
(
|
||||||
$states{'password_password'} eq 'locked'
|
$states{'password_password'} eq 'locked'
|
||||||
? colored('locked', 'blue')
|
? colored('locked', 'blue')
|
||||||
|
|
|
@ -23,7 +23,7 @@ my $remainingOptions = OVH::Bastion::Plugin::begin(
|
||||||
"idle-ignore=s" => \$modify{'idle-ignore'},
|
"idle-ignore=s" => \$modify{'idle-ignore'},
|
||||||
"max-inactive-days=i" => \$modify{'max-inactive-days'},
|
"max-inactive-days=i" => \$modify{'max-inactive-days'},
|
||||||
"osh-only=s" => \$modify{'osh-only'},
|
"osh-only=s" => \$modify{'osh-only'},
|
||||||
"mfa-any=s" => \$modify{'mfa-any'},
|
"pubkey-auth-optional=s" => \$modify{'pubkey-auth-optional'},
|
||||||
},
|
},
|
||||||
helptext => <<'EOF',
|
helptext => <<'EOF',
|
||||||
Modify an account configuration
|
Modify an account configuration
|
||||||
|
@ -55,10 +55,12 @@ Usage: --osh SCRIPT_NAME --account ACCOUNT [--option value [--option value [...]
|
||||||
Setting this option to zero disables account expiration. Setting this option to -1 removes this account
|
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.
|
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
|
||||||
--mfa-any yes|no Control the ingress login requirements for pubkey and pam (when a password and/or TOTP is set).
|
--pubkey-auth-optional yes|no Make the public key optional on ingress for the account (default is 'no').
|
||||||
When disabled, the user needs pubkey AND pam, this is the default.
|
When enabled the public key part of the authentication becomes optional when a password and/or TOTP is defined,
|
||||||
When enabled, the user can authenticate with either pubkey OR pam.
|
allowing to login with just the password/TOTP. If no password/TOTP is defined then the public key is the only way to authenticate,
|
||||||
If the account has no password/TOTP, this option has no effect, i.e: pubkey is used. Egress is not affected.
|
because some form of authentication is always required.
|
||||||
|
When disabled, the public key is always required.
|
||||||
|
Egress is not affected.
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
@ -86,7 +88,7 @@ foreach my $key (qw{ mfa-password-required mfa-totp-required }) {
|
||||||
osh_exit 'ERR_INVALID_PARAMETER', "Expected '--$key yes' or '--$key no' or '--$key bypass' instead of '--$key $modify{$key}'";
|
osh_exit 'ERR_INVALID_PARAMETER', "Expected '--$key yes' or '--$key no' or '--$key bypass' instead of '--$key $modify{$key}'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach my $key (qw{ always-active pam-auth-bypass idle-ignore osh-only mfa-any }) {
|
foreach my $key (qw{ always-active pam-auth-bypass idle-ignore osh-only pubkey-auth-optional }) {
|
||||||
next unless $modify{$key};
|
next unless $modify{$key};
|
||||||
if (not grep { $modify{$key} eq $_ } qw{ yes no }) {
|
if (not grep { $modify{$key} eq $_ } qw{ yes no }) {
|
||||||
help();
|
help();
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"master_only": true,
|
"master_only": true,
|
||||||
"interactive": [
|
"interactive": [
|
||||||
"accountModify" , {"ac": ["--account"]},
|
"accountModify" , {"ac": ["--account"]},
|
||||||
"accountModify --account" , {"ac": ["<ACCOUNT>"]},
|
"accountModify --account" , {"ac": ["<ACCOUNT>"]},
|
||||||
"accountModify --account \\S+" , {"ac": ["--mfa-password-required","--mfa-totp-required","--pam-auth-bypass","--always-active","--egress-strict-host-key-checking","--personal-egress-mfa-required","--idle-ignore","--mfa-any"]},
|
"accountModify --account \\S+" , {"ac": ["--mfa-password-required","--mfa-totp-required","--pam-auth-bypass","--always-active","--egress-strict-host-key-checking","--personal-egress-mfa-required","--idle-ignore","--pubkey-auth-optional"]},
|
||||||
"accountModify --account \\S+ .*(--mfa-password-required|--mfa-totp-required)" , {"ac": ["yes","no","bypass"]},
|
"accountModify --account \\S+ .*(--mfa-password-required|--mfa-totp-required)" , {"ac": ["yes","no","bypass"]},
|
||||||
"accountModify --account \\S+ .*(--pam-auth-bypass|--mfa-auth-bypass|--always-active|idle-ignore|--mfa-any)", {"ac": ["yes","no"]},
|
"accountModify --account \\S+ .*(--pam-auth-bypass|--mfa-auth-bypass|--always-active|idle-ignore|--pubkey-auth-optional)", {"ac": ["yes","no"]},
|
||||||
"accountModify --account \\S+ .*(--egress-strict-host-key-checking)" , {"ac": ["yes","accept-new","no","ask","default","bypass"]},
|
"accountModify --account \\S+ .*(--egress-strict-host-key-checking)" , {"ac": ["yes","accept-new","no","ask","default","bypass"]},
|
||||||
"accountModify --account \\S+ .*(--personal-egress-mfa-required)" , {"ac": ["password","totp","any","none"]},
|
"accountModify --account \\S+ .*(--personal-egress-mfa-required)" , {"ac": ["password","totp","any","none"]},
|
||||||
"accountModify --account \\S+ .*(yes|accept-new|no|bypass|ask|default|totp|password|none)" , {"ac": ["--mfa-password-required","--mfa-totp-required","--pam-auth-bypass","--always-active","--egress-strict-host-key-checking","--personal-egress-mfa-required","--idle-ignore","-mfa-any","<enter>"]}
|
"accountModify --account \\S+ .*(yes|accept-new|no|bypass|ask|default|totp|password|none)" , {"ac": ["--mfa-password-required","--mfa-totp-required","--pam-auth-bypass","--always-active","--egress-strict-host-key-checking","--personal-egress-mfa-required","--idle-ignore","--pubkey-auth-optional","<enter>"]}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ Output example
|
||||||
~ - Additional TOTP authentication bypass is disabled for this account
|
~ - Additional TOTP authentication bypass is disabled for this account
|
||||||
~ - Additional TOTP authentication is disabled
|
~ - Additional TOTP authentication is disabled
|
||||||
~ - PAM authentication bypass is disabled
|
~ - PAM authentication bypass is disabled
|
||||||
~ - Alternative authentication logic (allow both pubkey alone and PAM alone) is disabled
|
~ - Optional public key authentication is disabled
|
||||||
~ - MFA policy on personal accesses (using personal keys) on egress side is: password
|
~ - MFA policy on personal accesses (using personal keys) on egress side is: password
|
||||||
|
|
||||||
~ Account PAM UNIX password information (used for password MFA):
|
~ Account PAM UNIX password information (used for password MFA):
|
||||||
|
|
|
@ -60,7 +60,7 @@ Output example
|
||||||
~ - Additional TOTP authentication bypass is disabled for this account
|
~ - Additional TOTP authentication bypass is disabled for this account
|
||||||
~ - Additional TOTP authentication is disabled
|
~ - Additional TOTP authentication is disabled
|
||||||
~ - PAM authentication bypass is disabled
|
~ - PAM authentication bypass is disabled
|
||||||
~ - Alternative authentication logic (allow both pubkey alone and PAM alone) is disabled
|
~ - Optional public key authentication is disabled
|
||||||
~ - MFA policy on personal accesses (using personal keys) on egress side is: password
|
~ - MFA policy on personal accesses (using personal keys) on egress side is: password
|
||||||
|
|
||||||
~ Account PAM UNIX password information (used for password MFA):
|
~ Account PAM UNIX password information (used for password MFA):
|
||||||
|
|
|
@ -69,10 +69,12 @@ Modify an account configuration
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
.. option:: --mfa-any yes|no
|
.. option:: --pubkey-auth-optional yes|no
|
||||||
|
|
||||||
Control the ingress login requirements for pubkey and pam (when a password and/or TOTP is set).
|
Make the public key optional on ingress for the account (default is 'no').
|
||||||
|
|
||||||
When disabled, the user needs pubkey AND pam, this is the default.
|
When enabled the public key part of the authentication becomes optional when a password and/or TOTP is defined,
|
||||||
When enabled, the user can authenticate with either pubkey OR pam.
|
allowing to login with just the password/TOTP. If no password/TOTP is defined then the public key is the only way to authenticate,
|
||||||
If the account has no password/TOTP, this option has no effect, i.e: pubkey is used. Egress is not affected.
|
because some form of authentication is always required.
|
||||||
|
When disabled, the public key is always required.
|
||||||
|
Egress is not affected.
|
||||||
|
|
|
@ -129,9 +129,9 @@ UsePAM yes
|
||||||
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
||||||
Match Group bastion-nopam
|
Match Group bastion-nopam
|
||||||
AuthenticationMethods publickey
|
AuthenticationMethods publickey
|
||||||
# if in one of the mfa groups AND the mfa-any group, use publickey OR pam
|
# if in one of the mfa groups AND the osh-pubkey-auth-optional group, use publickey+pam OR pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd Group mfa-any
|
Match Group mfa-totp-configd,mfa-password-configd Group osh-pubkey-auth-optional
|
||||||
AuthenticationMethods publickey keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam keyboard-interactive:pam
|
||||||
# if in one of the mfa groups, use publickey AND pam
|
# if in one of the mfa groups, use publickey AND pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd
|
Match Group mfa-totp-configd,mfa-password-configd
|
||||||
AuthenticationMethods publickey,keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam
|
||||||
|
|
|
@ -129,9 +129,9 @@ UsePAM yes
|
||||||
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
||||||
Match Group bastion-nopam
|
Match Group bastion-nopam
|
||||||
AuthenticationMethods publickey
|
AuthenticationMethods publickey
|
||||||
# if in one of the mfa groups AND the mfa-any group, use publickey OR pam
|
# if in one of the mfa groups AND the osh-pubkey-auth-optional group, use publickey+pam OR pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd Group mfa-any
|
Match Group mfa-totp-configd,mfa-password-configd Group osh-pubkey-auth-optional
|
||||||
AuthenticationMethods publickey keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam keyboard-interactive:pam
|
||||||
# if in one of the mfa groups, use publickey AND pam
|
# if in one of the mfa groups, use publickey AND pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd
|
Match Group mfa-totp-configd,mfa-password-configd
|
||||||
AuthenticationMethods publickey,keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam
|
||||||
|
|
|
@ -133,9 +133,9 @@ UsePAM yes
|
||||||
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
||||||
Match Group bastion-nopam
|
Match Group bastion-nopam
|
||||||
AuthenticationMethods publickey
|
AuthenticationMethods publickey
|
||||||
# if in one of the mfa groups AND the mfa-any group, use publickey OR pam
|
# if in one of the mfa groups AND the osh-pubkey-auth-optional group, use publickey+pam OR pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd Group mfa-any
|
Match Group mfa-totp-configd,mfa-password-configd Group osh-pubkey-auth-optional
|
||||||
AuthenticationMethods publickey keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam keyboard-interactive:pam
|
||||||
# if in one of the mfa groups, use publickey AND pam
|
# if in one of the mfa groups, use publickey AND pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd
|
Match Group mfa-totp-configd,mfa-password-configd
|
||||||
AuthenticationMethods publickey,keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam
|
||||||
|
|
|
@ -133,9 +133,9 @@ UsePAM yes
|
||||||
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
||||||
Match Group bastion-nopam
|
Match Group bastion-nopam
|
||||||
AuthenticationMethods publickey
|
AuthenticationMethods publickey
|
||||||
# if in one of the mfa groups AND the mfa-any group, use publickey OR pam
|
# if in one of the mfa groups AND the osh-pubkey-auth-optional group, use publickey+pam OR pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd Group mfa-any
|
Match Group mfa-totp-configd,mfa-password-configd Group osh-pubkey-auth-optional
|
||||||
AuthenticationMethods publickey keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam keyboard-interactive:pam
|
||||||
# if in one of the mfa groups, use publickey AND pam
|
# if in one of the mfa groups, use publickey AND pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd
|
Match Group mfa-totp-configd,mfa-password-configd
|
||||||
AuthenticationMethods publickey,keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam
|
||||||
|
|
|
@ -136,9 +136,9 @@ UsePAM yes
|
||||||
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
||||||
Match Group bastion-nopam
|
Match Group bastion-nopam
|
||||||
AuthenticationMethods publickey
|
AuthenticationMethods publickey
|
||||||
# if in one of the mfa groups AND the mfa-any group, use publickey OR pam
|
# if in one of the mfa groups AND the osh-pubkey-auth-optional group, use publickey+pam OR pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd Group mfa-any
|
Match Group mfa-totp-configd,mfa-password-configd Group osh-pubkey-auth-optional
|
||||||
AuthenticationMethods publickey keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam keyboard-interactive:pam
|
||||||
# if in one of the mfa groups, use publickey AND pam
|
# if in one of the mfa groups, use publickey AND pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd
|
Match Group mfa-totp-configd,mfa-password-configd
|
||||||
AuthenticationMethods publickey,keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam
|
||||||
|
|
|
@ -136,9 +136,9 @@ UsePAM yes
|
||||||
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
||||||
Match Group bastion-nopam
|
Match Group bastion-nopam
|
||||||
AuthenticationMethods publickey
|
AuthenticationMethods publickey
|
||||||
# if in one of the mfa groups AND the mfa-any group, use publickey OR pam
|
# if in one of the mfa groups AND the osh-pubkey-auth-optional group, use publickey+pam OR pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd Group mfa-any
|
Match Group mfa-totp-configd,mfa-password-configd Group osh-pubkey-auth-optional
|
||||||
AuthenticationMethods publickey keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam keyboard-interactive:pam
|
||||||
# if in one of the mfa groups, use publickey AND pam
|
# if in one of the mfa groups, use publickey AND pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd
|
Match Group mfa-totp-configd,mfa-password-configd
|
||||||
AuthenticationMethods publickey,keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam
|
||||||
|
|
|
@ -126,9 +126,9 @@ UsePAM yes
|
||||||
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
# Unconditionally skip PAM auth for members of the bastion-nopam group
|
||||||
Match Group bastion-nopam
|
Match Group bastion-nopam
|
||||||
AuthenticationMethods publickey
|
AuthenticationMethods publickey
|
||||||
# if in one of the mfa groups AND the mfa-any group, use publickey OR pam
|
# if in one of the mfa groups AND the osh-pubkey-auth-optional group, use publickey+pam OR pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd Group mfa-any
|
Match Group mfa-totp-configd,mfa-password-configd Group osh-pubkey-auth-optional
|
||||||
AuthenticationMethods publickey keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam keyboard-interactive:pam
|
||||||
# if in one of the mfa groups, use publickey AND pam
|
# if in one of the mfa groups, use publickey AND pam
|
||||||
Match Group mfa-totp-configd,mfa-password-configd
|
Match Group mfa-totp-configd,mfa-password-configd
|
||||||
AuthenticationMethods publickey,keyboard-interactive:pam
|
AuthenticationMethods publickey,keyboard-interactive:pam
|
||||||
|
|
|
@ -96,14 +96,14 @@ use constant {
|
||||||
};
|
};
|
||||||
|
|
||||||
use constant {
|
use constant {
|
||||||
MFA_PASSWORD_REQUIRED_GROUP => 'mfa-password-reqd',
|
MFA_PASSWORD_REQUIRED_GROUP => 'mfa-password-reqd',
|
||||||
MFA_PASSWORD_CONFIGURED_GROUP => 'mfa-password-configd',
|
MFA_PASSWORD_CONFIGURED_GROUP => 'mfa-password-configd',
|
||||||
MFA_PASSWORD_BYPASS_GROUP => 'mfa-password-bypass',
|
MFA_PASSWORD_BYPASS_GROUP => 'mfa-password-bypass',
|
||||||
MFA_TOTP_REQUIRED_GROUP => 'mfa-totp-reqd',
|
MFA_TOTP_REQUIRED_GROUP => 'mfa-totp-reqd',
|
||||||
MFA_TOTP_CONFIGURED_GROUP => 'mfa-totp-configd',
|
MFA_TOTP_CONFIGURED_GROUP => 'mfa-totp-configd',
|
||||||
MFA_TOTP_BYPASS_GROUP => 'mfa-totp-bypass',
|
MFA_TOTP_BYPASS_GROUP => 'mfa-totp-bypass',
|
||||||
PAM_AUTH_BYPASS_GROUP => 'bastion-nopam',
|
PAM_AUTH_BYPASS_GROUP => 'bastion-nopam',
|
||||||
MFA_ANY_GROUP => 'mfa-any',
|
OSH_PUBKEY_AUTH_OPTIONAL_GROUP => 'osh-pubkey-auth-optional',
|
||||||
|
|
||||||
TOTP_FILENAME => '.otp',
|
TOTP_FILENAME => '.otp',
|
||||||
TOTP_BASEDIR => '/var/otp',
|
TOTP_BASEDIR => '/var/otp',
|
||||||
|
|
|
@ -381,16 +381,18 @@ testsuite_mfa()
|
||||||
success a0_remove_mfa_req_a4_dupe $a0 --osh accountModify --account $account4 --pam-auth-bypass no --mfa-totp-required no --mfa-password-required no
|
success a0_remove_mfa_req_a4_dupe $a0 --osh accountModify --account $account4 --pam-auth-bypass no --mfa-totp-required no --mfa-password-required no
|
||||||
json .error_code OK .command accountModify .value.pam_auth_bypass.error_code OK_NO_CHANGE .value.mfa_totp_required.error_code OK_NO_CHANGE .value.mfa_password_required.error_code OK_NO_CHANGE
|
json .error_code OK .command accountModify .value.pam_auth_bypass.error_code OK_NO_CHANGE .value.mfa_totp_required.error_code OK_NO_CHANGE .value.mfa_password_required.error_code OK_NO_CHANGE
|
||||||
|
|
||||||
# remove totp from account4 to simplify the following mfa-any tests
|
# pubkey-auth-optional
|
||||||
|
|
||||||
|
# remove totp from account4 to simplify the following tests
|
||||||
grant accountMFAResetTOTP
|
grant accountMFAResetTOTP
|
||||||
|
|
||||||
success mfa a0_nototp_a4 $a0 --osh accountMFAResetTOTP --account $account4
|
success a0_nototp_a4 $a0 --osh accountMFAResetTOTP --account $account4
|
||||||
json .command accountMFAResetTOTP .error_code OK
|
json .command accountMFAResetTOTP .error_code OK
|
||||||
|
|
||||||
revoke accountMFAResetTOTP
|
revoke accountMFAResetTOTP
|
||||||
|
|
||||||
# no mfa-any, success with pubkey and password
|
# pubkey-auth-optional disabled: success with pubkey and password
|
||||||
script mfa a4_no_mfaany_login_pubkey_pam "echo 'set timeout 30; \
|
script a4_no_pubkeyauthoptional_login_pubkey_pam "echo 'set timeout 30; \
|
||||||
spawn $a4 --osh groupList; \
|
spawn $a4 --osh groupList; \
|
||||||
expect \"word:\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
expect \"word:\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
||||||
expect eof; \
|
expect eof; \
|
||||||
|
@ -401,8 +403,8 @@ testsuite_mfa()
|
||||||
contain REGEX 'Password:|Password for'
|
contain REGEX 'Password:|Password for'
|
||||||
json .command groupList .error_code OK_EMPTY
|
json .command groupList .error_code OK_EMPTY
|
||||||
|
|
||||||
# no mfa-any, fail with pubkey but no password (timeout)
|
# pubkey-auth-optional disabled: fail with pubkey but no password (timeout)
|
||||||
script mfa a4_no_mfaany_login_pubkey_nopam $a4 --osh groupList
|
script a4_no_pubkeyauthoptional_login_pubkey_nopam $a4 --osh groupList
|
||||||
retvalshouldbe 124
|
retvalshouldbe 124
|
||||||
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
|
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
|
||||||
contain 'Your password expires on'
|
contain 'Your password expires on'
|
||||||
|
@ -410,27 +412,35 @@ testsuite_mfa()
|
||||||
contain REGEX 'Password:|Password for'
|
contain REGEX 'Password:|Password for'
|
||||||
nocontain 'JSON_OUTPUT'
|
nocontain 'JSON_OUTPUT'
|
||||||
|
|
||||||
# no mfa-any, fail with no pubkey (never gets to ask for the password)
|
# pubkey-auth-optional disabled: fail with no pubkey (never gets to ask for the password)
|
||||||
script mfa a4_no_mfaany_login_nopubkey_pam $a4np --osh groupList
|
script a4_no_pubkeyauthoptional_login_nopubkey_pam $a4np --osh groupList
|
||||||
retvalshouldbe 255
|
retvalshouldbe 255
|
||||||
contain 'Permission denied (publickey).'
|
contain 'Permission denied (publickey).'
|
||||||
nocontain 'password'
|
nocontain 'password'
|
||||||
nocontain 'JSON_OUTPUT'
|
nocontain 'JSON_OUTPUT'
|
||||||
|
|
||||||
# set mfa-any on account4
|
# set pubkey-auth-optional on account4
|
||||||
success mfa a0_set_mfaany_a4 $a0 --osh accountModify --account $account4 --mfa-any yes
|
success a0_set_pubkeyauthoptional_a4 $a0 --osh accountModify --account $account4 --pubkey-auth-optional yes
|
||||||
json .error_code OK .command accountModify .value.mfa_any.error_code OK
|
json .error_code OK .command accountModify .value.pubkey_auth_optional.error_code OK
|
||||||
|
|
||||||
# set mfa-any on account4 (dupe)
|
# set pubkey-auth-optional on account4 (dupe)
|
||||||
success mfa a0_set_mfaany_a4_dupe $a0 --osh accountModify --account $account4 --mfa-any yes
|
success a0_set_pubkeyauthoptional_a4_dupe $a0 --osh accountModify --account $account4 --pubkey-auth-optional yes
|
||||||
json .error_code OK .command accountModify .value.mfa_any.error_code OK_NO_CHANGE
|
json .error_code OK .command accountModify .value.pubkey_auth_optional.error_code OK_NO_CHANGE
|
||||||
|
|
||||||
# success with pubkey but no password
|
# pubkey-auth-optional enabled: success with pubkey and password
|
||||||
success mfa a4_mfaany_login_pubkey_nopam $a4 --osh groupList
|
script a4_pubkeyauthoptional_login_pubkey_pam "echo 'set timeout 30; \
|
||||||
|
spawn $a4 --osh groupList; \
|
||||||
|
expect \"word:\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
||||||
|
expect eof; \
|
||||||
|
lassign [wait] pid spawnid value value; \
|
||||||
|
exit \$value' | expect -f -"
|
||||||
|
retvalshouldbe 0
|
||||||
|
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
|
||||||
|
contain REGEX 'Password:|Password for'
|
||||||
json .command groupList .error_code OK_EMPTY
|
json .command groupList .error_code OK_EMPTY
|
||||||
|
|
||||||
# success with password but no pubkey
|
# pubkey-auth-optional enabled: success with password only
|
||||||
script mfa a4_mfaany_login_nopubkey_pam "echo 'set timeout 30; \
|
script a4_pubkeyauthoptional_login_nopubkey_pam "echo 'set timeout 30; \
|
||||||
spawn $a4np --osh groupList; \
|
spawn $a4np --osh groupList; \
|
||||||
expect \"word:\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
expect \"word:\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
||||||
expect eof; \
|
expect eof; \
|
||||||
|
@ -441,13 +451,22 @@ testsuite_mfa()
|
||||||
contain REGEX 'Password:|Password for'
|
contain REGEX 'Password:|Password for'
|
||||||
json .command groupList .error_code OK_EMPTY
|
json .command groupList .error_code OK_EMPTY
|
||||||
|
|
||||||
# unset mfa-any on account4
|
# pubkey-auth-optional enabled: fail with pubkey only
|
||||||
success mfa a0_unset_mfaany_a4 $a0 --osh accountModify --account $account4 --mfa-any no
|
script a4_pubkeyauthoptional_login_pubkey_nopam $a4 --osh groupList
|
||||||
json .error_code OK .command accountModify .value.mfa_any.error_code OK
|
retvalshouldbe 124
|
||||||
|
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
|
||||||
|
contain 'Your password expires on'
|
||||||
|
contain 'in 89 days'
|
||||||
|
contain REGEX 'Password:|Password for'
|
||||||
|
nocontain 'JSON_OUTPUT'
|
||||||
|
|
||||||
|
# unset pubkey-auth-optional on account4
|
||||||
|
success a0_unset_pubkeyauthoptional_a4 $a0 --osh accountModify --account $account4 --pubkey-auth-optional no
|
||||||
|
json .error_code OK .command accountModify .value.pubkey_auth_optional.error_code OK
|
||||||
|
|
||||||
# unset mfa-any on account4 (dupe)
|
# unset mfa-any on account4 (dupe)
|
||||||
success mfa a0_unset_mfaany_a4_dupe $a0 --osh accountModify --account $account4 --mfa-any no
|
success a0_unset_pubkeyauthoptional_a4_dupe $a0 --osh accountModify --account $account4 --pubkey-auth-optional no
|
||||||
json .error_code OK .command accountModify .value.mfa_any.error_code OK_NO_CHANGE
|
json .error_code OK .command accountModify .value.pubkey_auth_optional.error_code OK_NO_CHANGE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue