mirror of
https://github.com/ovh/the-bastion.git
synced 2025-01-10 01:15:15 +08:00
388 lines
18 KiB
Bash
388 lines
18 KiB
Bash
# vim: set filetype=sh ts=4 sw=4 sts=4 et:
|
|
# shellcheck shell=bash
|
|
# shellcheck disable=SC2086,SC2016,SC2046
|
|
# below: convoluted way that forces shellcheck to source our caller
|
|
# shellcheck source=tests/functional/launch_tests_on_instance.sh
|
|
. "$(dirname "${BASH_SOURCE[0]}")"/dummy
|
|
|
|
testsuite_mfa()
|
|
{
|
|
grant accountCreate
|
|
grant accountModify
|
|
|
|
# create account4
|
|
success mfa a0_create_a4 $a0 --osh accountCreate --always-active --account $account4 --uid $uid4 --public-key "\"$(cat $account4key1file.pub)\""
|
|
json .error_code OK .command accountCreate .value null
|
|
|
|
# set account4 as mfa password required
|
|
success mfa a0_accountModify_passreq_a4 $a0 --osh accountModify --account $account4 --mfa-password-required yes
|
|
json .error_code OK .command accountModify .value.mfa_password_required.error_code OK
|
|
|
|
# set account4 as mfa password required (dupe)
|
|
success mfa a0_accountModify_passreq_a4_dupe $a0 --osh accountModify --account $account4 --mfa-password-required yes
|
|
json .error_code OK .command accountModify .value.mfa_password_required.error_code OK_NO_CHANGE
|
|
|
|
# now try to connect with account4
|
|
run mfa a4_connect_with_passreq $a4 --osh groupList
|
|
retvalshouldbe 122
|
|
json .error_code KO_MFA_PASSWORD_SETUP_REQUIRED
|
|
|
|
# setup our password, step1
|
|
run mfa a4_setup_pass_step1of2 $a4f --osh selfMFASetupPassword --yes
|
|
retvalshouldbe 124
|
|
contain 'enter this:'
|
|
a4_password_tmp=$(get_stdout | grep -Eo 'enter this: [a-zA-Z0-9_-]+' | sed -e 's/enter this: //')
|
|
|
|
# setup our password, step2
|
|
a4_password=']BkL>3x#T)g~~B#rLv^!T2&N'
|
|
script mfa a4_setup_pass_step2of2 "echo 'set timeout 30; \
|
|
spawn $a4 --osh selfMFASetupPassword --yes; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password_tmp\\n\"; }; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect eof; \
|
|
lassign [wait] pid spawnid value value; \
|
|
exit \$value' | expect -f -"
|
|
retvalshouldbe 0
|
|
unset a4_password_tmp
|
|
nocontain 'enter this:'
|
|
nocontain 'unchanged'
|
|
nocontain 'sorry'
|
|
json .command selfMFASetupPassword .error_code OK
|
|
|
|
# now try to connect after we have a pass
|
|
run mfa a4_connect_after_pass $a4f --osh groupList
|
|
if [ "$HAS_MFA" = 1 ] || [ "$HAS_MFA_PASSWORD" = 1 ]; then
|
|
# now we need a password, we don't enter it so it'll timeout (124)
|
|
retvalshouldbe 124
|
|
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
|
|
contain REGEX 'Password:|Password for'
|
|
nocontain 'JSON_OUTPUT'
|
|
else
|
|
# our system doesn't support MFA so it still works without asking for a password
|
|
retvalshouldbe 0
|
|
nocontain 'Multi-Factor Authentication enabled'
|
|
nocontain REGEX 'Password:|Password for'
|
|
json .command groupList .error_code OK_EMPTY
|
|
fi
|
|
|
|
if [ "$HAS_PAMTESTER" = 1 ]; then
|
|
grant groupCreate
|
|
|
|
success mfa a0_create_g3 $a0 --osh groupCreate --group $group3 --algo rsa --size 4096 --owner $account4
|
|
|
|
revoke groupCreate
|
|
|
|
# setup group to force JIT egress MFA
|
|
script mfa a4_modify_g3_egress_mfa "echo 'set timeout 30; \
|
|
spawn $a4 --osh groupModify --group $group3 --mfa-required any; \
|
|
expect \":\" { 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 groupModify .error_code OK
|
|
|
|
# check that the MFA is set for the group
|
|
script mfa a4_verify_g3_egress_mfa "echo 'set timeout 30; \
|
|
spawn $a4 --osh groupInfo --group $group3; \
|
|
expect \":\" { 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 groupInfo .error_code OK
|
|
json .value.mfa_required any
|
|
|
|
# add 127.7.7.7 to this group
|
|
script mfa a4_add_g3_server "echo 'set timeout 30; \
|
|
spawn $a4 --osh groupAddServer --group $group3 --host 127.7.7.7 --user-any --port-any --force; \
|
|
expect \":\" { 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'
|
|
|
|
# connect to 127.7.7.7 with MFA JIT, bad password
|
|
script mfa a4_connect_g3_server_badpass "echo 'set timeout 45; \
|
|
spawn $a4 root@127.7.7.7; \
|
|
expect \"is required (password)\" { sleep 0.1; }; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect \"is required (password)\" { sleep 0.1; }; \
|
|
expect \":\" { sleep 0.2; send \"BADPASSWORD\\n\"; }; \
|
|
expect \"is required (password)\" { sleep 0.1; }; \
|
|
expect \":\" { sleep 0.2; send \"BADPASSWORD\\n\"; }; \
|
|
expect \"is required (password)\" { sleep 0.1; }; \
|
|
expect \":\" { sleep 0.2; send \"BADPASSWORD\\n\\n\"; }; \
|
|
expect eof; \
|
|
lassign [wait] pid spawnid value value; \
|
|
exit \$value' | expect -f -"
|
|
retvalshouldbe 125
|
|
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
|
|
contain REGEX 'Password:|Password for'
|
|
contain 'pamtester: '
|
|
nocontain 'Permission denied'
|
|
|
|
# connect to 127.7.7.7 with MFA JIT, good password
|
|
script mfa a4_connect_g3_server_goodpass "echo 'set timeout 30; \
|
|
spawn $a4 root@127.7.7.7; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect \"is required (password)\" { sleep 0.1; }; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect eof; \
|
|
lassign [wait] pid spawnid value value; \
|
|
exit \$value' | expect -f -"
|
|
retvalshouldbe 255
|
|
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
|
|
contain REGEX 'Password:|Password for'
|
|
contain 'pamtester: successfully authenticated'
|
|
contain 'Permission denied'
|
|
|
|
# create another account
|
|
success mfa a0_create_a3 $a0 --osh accountCreate --always-active --account $account3 --uid $uid3 --public-key "\"$(cat $account3key1file.pub)\""
|
|
json .error_code OK .command accountCreate .value null
|
|
|
|
# set the account as bypass
|
|
success mfa a0_set_a3_as_robot $a0 --osh accountModify --account $account3 --mfa-password-required bypass
|
|
json .command accountModify .error_code OK
|
|
|
|
# add to JIT MFA group
|
|
script mfa a0_add_a3_as_member "echo 'set timeout 30; \
|
|
spawn $a4 --osh groupAddMember --group $group3 --account $account3; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect eof; \
|
|
lassign [wait] pid spawnid value value; \
|
|
exit \$value' | expect -f -"
|
|
json .command groupAddMember .error_code OK
|
|
|
|
# connect to 127.7.7.7 with MFA JIT, no MFA needed
|
|
run mfa a3_connect_g3_server_mfa_bypass $a3 root@127.7.7.7
|
|
retvalshouldbe 255
|
|
nocontain 'pamtester: successfully authenticated'
|
|
contain 'Permission denied'
|
|
|
|
# remove the account bypass
|
|
success mfa a0_unset_a3_as_robot $a0 --osh accountModify --account $account3 --mfa-password-required no
|
|
json .command accountModify .error_code OK
|
|
|
|
# connect to 127.7.7.7 with MFA JIT, password setup needed
|
|
run mfa a3_connect_mfa_jit_need_pass_setup $a3 root@127.7.7.7
|
|
json .error_code KO_MFA_ANY_SETUP_REQUIRED
|
|
|
|
grant groupDelete
|
|
|
|
script mfa a0_delete_g3 "$a0 --osh groupDelete --group $group3 <<< \"$group3\""
|
|
|
|
revoke groupDelete
|
|
|
|
grant accountDelete
|
|
|
|
script mfa a0_delete_a3 $a0 --osh accountDelete --account $account3 "<<< \"Yes, do as I say and delete $account3, kthxbye\""
|
|
retvalshouldbe 0
|
|
json .command accountDelete .error_code OK
|
|
|
|
revoke accountDelete
|
|
fi
|
|
|
|
# change our password
|
|
a4_password_new="rkw=*Ffyqs23"
|
|
if [ "$HAS_MFA" = 1 ] || [ "$HAS_MFA_PASSWORD" = 1 ]; then
|
|
script mfa a4_change_pass "echo 'set timeout 30; \
|
|
spawn $a4 --osh selfMFASetupPassword --yes; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password_new\\n\"; }; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password_new\\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'
|
|
else
|
|
script mfa a4_change_pass "echo 'set timeout 30; \
|
|
spawn $a4 --osh selfMFASetupPassword --yes; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password_new\\n\"; }; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password_new\\n\"; }; \
|
|
expect eof; \
|
|
lassign [wait] pid spawnid value value; \
|
|
exit \$value' | expect -f -"
|
|
retvalshouldbe 0
|
|
nocontain 'Multi-Factor Authentication enabled'
|
|
fi
|
|
nocontain 'enter this:'
|
|
nocontain 'unchanged'
|
|
json .command selfMFASetupPassword .error_code OK
|
|
|
|
a4_password="$a4_password_new"
|
|
unset a4_password_new
|
|
|
|
if [ "$HAS_MFA" = 1 ] || [ "$HAS_MFA_PASSWORD" = 1 ]; then
|
|
script mfa a4_connect_with_pass "echo 'set timeout 30; \
|
|
spawn $a4 --osh groupList; \
|
|
expect \":\" { 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
|
|
fi
|
|
|
|
# set account4 as mfa totp required
|
|
success mfa a0_accountModify_totpreq_a4 $a0 --osh accountModify --account $account4 --mfa-totp-required yes
|
|
json .error_code OK .command accountModify .value.mfa_totp_required.error_code OK
|
|
|
|
# set account4 as mfa totp required (dupe)
|
|
success mfa a0_accountModify_totpreq_a4_dupe $a0 --osh accountModify --account $account4 --mfa-totp-required yes
|
|
json .error_code OK .command accountModify .value.mfa_totp_required.error_code OK_NO_CHANGE
|
|
|
|
# now try to connect with account4
|
|
if [ "$HAS_MFA" = 1 ] || [ "$HAS_MFA_PASSWORD" = 1 ]; then
|
|
script mfa a4_connect_with_totpreq "echo 'set timeout 30; \
|
|
spawn $a4 --osh groupList; \
|
|
expect \":\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect eof; \
|
|
lassign [wait] pid spawnid value value; \
|
|
exit \$value' | expect -f -"
|
|
else
|
|
run mfa a4_connect_with_totpreq $a4 --osh groupList
|
|
fi
|
|
retvalshouldbe 123
|
|
json .error_code KO_MFA_TOTP_SETUP_REQUIRED
|
|
|
|
if [ "$HAS_MFA" = 1 ]; then
|
|
# setup totp
|
|
script mfa a4_setup_totp "echo 'set timeout 30; \
|
|
spawn $a4 --osh selfMFASetupTOTP --no-confirm; \
|
|
expect \"word:\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
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'
|
|
|
|
a4_totp_code_1=$(get_stdout | grep -A1 'Your emergency scratch codes are:' | tail -n1 | tr -d '[:space:]')
|
|
#a4_totp_code_2=$(get_stdout | grep -A2 'Your emergency scratch codes are:' | tail -n1 | tr -d '[:space:]')
|
|
#a4_totp_code_3=$(get_stdout | grep -A3 'Your emergency scratch codes are:' | tail -n1 | tr -d '[:space:]')
|
|
#a4_totp_code_4=$(get_stdout | grep -A4 'Your emergency scratch codes are:' | tail -n1 | tr -d '[:space:]')
|
|
|
|
# login and fail without totp (timeout)
|
|
script mfa a4_connect_after_totp_fail "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 124
|
|
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
|
|
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (OTP).'
|
|
contain 'Your password expires on'
|
|
contain 'in 89 days'
|
|
contain REGEX 'Password:|Password for'
|
|
contain 'Verification code:'
|
|
nocontain 'JSON_OUTPUT'
|
|
|
|
# success with password + totp
|
|
script mfa a4_connect_after_totp_ok "echo 'set timeout 30; \
|
|
spawn $a4 --osh groupList; \
|
|
expect \"word:\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect \"code:\" { sleep 0.2; send \"$a4_totp_code_1\\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 'Multi-Factor Authentication enabled, an additional authentication factor is required (OTP).'
|
|
contain REGEX 'Password:|Password for'
|
|
contain 'Verification code:'
|
|
json .command groupList .error_code OK_EMPTY
|
|
|
|
# totp scratch codes don't work twice
|
|
script mfa a4_connect_after_totp_dupe "echo 'set timeout 30; \
|
|
spawn $a4 --osh groupList; \
|
|
expect \"word:\" { sleep 0.2; send \"$a4_password\\n\"; }; \
|
|
expect \"code:\" { sleep 0.2; send \"$a4_totp_code_1\\n\"; }; \
|
|
expect \"word:\" { exit 222; }; \
|
|
expect eof; \
|
|
lassign [wait] pid spawnid value value; \
|
|
exit \$value' | expect -f -"
|
|
retvalshouldbe 222
|
|
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
|
|
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (OTP).'
|
|
contain REGEX 'Password:|Password for'
|
|
contain 'Verification code:'
|
|
nocontain 'JSON_OUTPUT'
|
|
|
|
# set pam bypass on account4 (dupe)
|
|
success mfa a0_set_pambypass_a4 $a0 --osh accountModify --account $account4 --pam-auth-bypass yes
|
|
json .error_code OK .command accountModify .value.pam_auth_bypass.error_code OK
|
|
|
|
# set pam bypass on account4
|
|
success mfa a0_set_pambypass_a4_dupe $a0 --osh accountModify --account $account4 --pam-auth-bypass yes
|
|
json .error_code OK .command accountModify .value.pam_auth_bypass.error_code OK_NO_CHANGE
|
|
|
|
# we don't provide password or totp, it should work because bypass
|
|
success mfa a4_pam_auth_bypass $a4 --osh groupList
|
|
json .command groupList .error_code OK_EMPTY
|
|
|
|
# remove requirement of password and totp for account4, also remove bypass
|
|
success mfa a0_remove_mfa_req_a4 $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 .value.mfa_totp_required.error_code OK .value.mfa_password_required.error_code OK
|
|
|
|
# remove requirement of password and totp for account4, also remove bypass (dupe)
|
|
success mfa 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
|
|
|
|
# FIXME
|
|
# # reset totp
|
|
# script mfa a4_reset_totp "echo 'set timeout 30; \
|
|
# spawn $a4 --osh selfMFAResetTOTP; \
|
|
# expect \"word:\" { send_user \"premier password\\n\"; send \"$a4_password\\n\"; }; \
|
|
# expect \"code:\" { send_user \"premier code\\n\"; send \"$a4_totp_code_2\\n\"; }; \
|
|
# expect \"word:\" { send_user \"second password\\n\"; send \"$a4_password\\n\"; }; \
|
|
# expect \"code:\" { send_user \"second code\\n\"; send \"$a4_totp_code_3\\n\"; }; \
|
|
# expect eof; \
|
|
# lassign [wait] pid spawnid value value; \
|
|
# exit \$value' | expect -f -"
|
|
# retvalshouldbe 0
|
|
# json .error_code OK .command selfMFAResetTOTP
|
|
#
|
|
# # reset password
|
|
# script mfa a4_reset_password "echo 'set timeout 30; \
|
|
# spawn $a4 --osh selfMFAResetPassword; \
|
|
# expect \"word:\" { send \"$a4_password\\n\"; }; \
|
|
# expect eof; \
|
|
# lassign [wait] pid spawnid value value; \
|
|
# exit \$value' | expect -f -"
|
|
# retvalshouldbe 0
|
|
# json .error_code OK .command selfMFAResetPassword
|
|
|
|
# # now we no longer need MFA
|
|
# success mfa a4_mfa_deconfigured $a4 --osh groupList
|
|
# json .command groupList .error_code OK_EMPTY
|
|
fi
|
|
|
|
grant accountRevokeCommand
|
|
revoke accountModify
|
|
grant accountDelete
|
|
|
|
# remove account
|
|
script mfa a0_delete_a4 $a0 --osh accountDelete --account $account4 "<<< \"Yes, do as I say and delete $account4, kthxbye\""
|
|
retvalshouldbe 0
|
|
json .command accountDelete .error_code OK
|
|
|
|
revoke accountDelete
|
|
}
|
|
|
|
testsuite_mfa
|