Compare commits
2 Commits
b8bf9730c4
...
93fe56e837
| Author | SHA256 | Date | |
|---|---|---|---|
|
93fe56e837
|
|||
|
257187bf41
|
@@ -17,8 +17,13 @@ guard_sourcing
|
||||
# Globals:
|
||||
# TARGET
|
||||
# VAR_SETUP_PATH
|
||||
# VAR_TEMP_PLAIN_MFA_SEED
|
||||
# VAR_USER_MAX
|
||||
# user_root_authentication_2fa_ssh
|
||||
# user_root_authentication_2fa_tty
|
||||
# user_root_authentication_access_ssh
|
||||
# user_root_authentication_access_tty
|
||||
# user_root_authentication_password
|
||||
# user_root_password
|
||||
# user_root_shell
|
||||
# user_root_sshpubkey
|
||||
@@ -32,10 +37,10 @@ accounts_setup() {
|
||||
declare -r var_logfile="/root/.ciss/cdi/log/4520_accounts_setup.log"
|
||||
declare -i i=0
|
||||
declare tmp_username="" tmp_fullname="" tmp_uid="" tmp_gid="" tmp_shell="" tmp_password="" tmp_sshpubkey="" \
|
||||
tmp_access_ssh="" tmp_access_tty="" tmp_auth_pwd="" tmp_2fa_ssh="" tmp_2fa_tty="" tmp_sudo="" tmp_restricted=""
|
||||
tmp_access_tty="" tmp_auth_pwd="" tmp_2fa_ssh="" tmp_2fa_tty="" tmp_sudo="" tmp_restricted=""
|
||||
declare var_username="" var_fullname="" var_uid="" var_gid="" var_shell="" var_password="" var_sshpubkey="" \
|
||||
var_access_ssh="" var_access_tty="" var_auth_pwd="" var_2fa_ssh="" var_2fa_tty="" var_sudo="" var_restricted=""
|
||||
declare var_chpasswd="" var_sshdir="" var_pam_login="/etc/pam.d/login"
|
||||
var_access_tty="" var_auth_pwd="" var_2fa_ssh="" var_2fa_tty="" var_sudo="" var_restricted=""
|
||||
declare var_chpasswd="" var_pam_login="/etc/pam.d/login"
|
||||
|
||||
chroot_logger "${TARGET}${var_logfile}"
|
||||
|
||||
@@ -91,10 +96,10 @@ accounts_setup() {
|
||||
### 3) Check tty access capabilities.
|
||||
case "${user_root_authentication_access_tty}" in
|
||||
false)
|
||||
### 1) Ensure the 'pam_access' line is not activated in '/etc/pam.d/login' and '/etc/pam.d/sshd' in parallel.
|
||||
### 3) A) 1) Ensure the 'pam_access' line is not activated in '/etc/pam.d/login' and '/etc/pam.d/sshd' in parallel.
|
||||
pam_access_sync_login_sshd
|
||||
|
||||
### 2) Ensure 'pam_securetty' in the auth phase; requisite causes immediate fail for disallowed ttys.
|
||||
### 3) A) 2) Ensure 'pam_securetty' in the auth phase; requisite causes immediate fail for disallowed ttys.
|
||||
if ! grep -qE '^\s*auth\s+requisite\s+pam_securetty\.so' "${var_pam_login}"; then
|
||||
### Insert pam_securetty before pam_unix to fail early.
|
||||
awk '
|
||||
@@ -110,10 +115,10 @@ accounts_setup() {
|
||||
' "${var_pam_login}" >| "${var_pam_login}.new" && mv -f "${var_pam_login}.new" "${var_pam_login}"
|
||||
fi
|
||||
|
||||
### 3) Disallow all local access for root in '/etc/security/access.conf'.
|
||||
### 3) A) 3) Disallow all local access for root in '/etc/security/access.conf'.
|
||||
printf "-: root:ALL \n" >> "${TARGET}/etc/security/access.conf"
|
||||
|
||||
### 4) Empty "/etc/securetty".
|
||||
### 3) A) 4) Empty "/etc/securetty".
|
||||
cat << 'EOF' >| "${TARGET}/etc/securetty"
|
||||
EOF
|
||||
|
||||
@@ -121,10 +126,10 @@ EOF
|
||||
;;
|
||||
|
||||
true)
|
||||
### 1) Allow local access for 'root' only on 'tty1' in '/etc/security/access.conf'.
|
||||
### 3) B) 1) Allow local access for 'root' only on 'tty1' in '/etc/security/access.conf'.
|
||||
printf "+: root:tty1 \n" >> "${TARGET}/etc/security/access.conf"
|
||||
|
||||
### 2) Allow local access for 'root' only on 'tty1' in '/etc/securetty'.
|
||||
### 3) B) 2) Allow local access for 'root' only on 'tty1' in '/etc/securetty'.
|
||||
cat << 'EOF' >| "${TARGET}/etc/securetty"
|
||||
tty1
|
||||
EOF
|
||||
@@ -132,7 +137,7 @@ EOF
|
||||
;;
|
||||
esac
|
||||
|
||||
### Check the password policy for the 'root' account.
|
||||
### 4) Check the password policy for the 'root' account.
|
||||
case "${user_root_authentication_password}" in
|
||||
false)
|
||||
chroot_script "${TARGET}" "passwd -l root"
|
||||
@@ -146,13 +151,13 @@ EOF
|
||||
;;
|
||||
esac
|
||||
|
||||
### Update the 'root' SSH pubkey, if provided via 'preseed.yaml'.
|
||||
### 5) Update the 'root' SSH pubkey, if provided via 'preseed.yaml'.
|
||||
if [[ -n "${user_root_sshpubkey:-}" ]]; then
|
||||
printf "%s\n" "${user_root_sshpubkey}" >| "${TARGET}/root/.ssh/authorized_keys"
|
||||
do_log "info" "file_only" "4520() User: 'root' SSH public key: inserted."
|
||||
fi
|
||||
|
||||
### Update the 'root' 'totp'-policy and write the '.google_authenticator'-file.
|
||||
### 6) Update the 'root' 'totp'-policy and write the '.google_authenticator'-file.
|
||||
[[ "${user_root_authentication_2fa_ssh}" == "true" || "${user_root_authentication_2fa_tty}" == "true" ]] && \
|
||||
write_google_authenticator_file "root"
|
||||
|
||||
@@ -160,7 +165,7 @@ EOF
|
||||
|
||||
[[ "${user_root_authentication_2fa_tty}" == "true" ]] && pam_access_totp_enable "root" "login"
|
||||
|
||||
|
||||
### 7) Final status logging.
|
||||
do_log "info" "file_only" "User: 'root' updated."
|
||||
|
||||
|
||||
@@ -174,8 +179,7 @@ EOF
|
||||
tmp_shell="user_user${i}_shell"
|
||||
tmp_password="user_user${i}_password"
|
||||
tmp_sshpubkey="user_user${i}_sshpubkey"
|
||||
tmp_access_ssh="user_user${i}authentication_access_ssh"
|
||||
tmp_access_tty="user_user${i}authentication_access_ssh"
|
||||
tmp_access_tty="user_user${i}authentication_access_tty"
|
||||
tmp_auth_pwd="user_user${i}authentication_password"
|
||||
tmp_2fa_ssh="user_user${i}authentication_2fa_ssh"
|
||||
tmp_2fa_tty="user_user${i}authentication_2fa_tty"
|
||||
@@ -189,7 +193,6 @@ EOF
|
||||
var_shell="${!tmp_shell}"
|
||||
var_password="${!tmp_password}"
|
||||
var_sshpubkey="${!tmp_sshpubkey}"
|
||||
var_access_ssh"${!tmp_access_ssh}"
|
||||
var_access_tty"${!tmp_access_tty}"
|
||||
var_auth_pwd"${!tmp_auth_pwd}"
|
||||
var_2fa_ssh"${!tmp_2fa_ssh}"
|
||||
@@ -254,124 +257,79 @@ EOF
|
||||
do_log "info" "file_only" "4520() Skeleton: '${var_username}' successfully generated."
|
||||
|
||||
### 2) Check SSH access capabilities.
|
||||
# Nothing to do here as per user SSH capabilities are already handled in '4330_installation_ssh.sh'
|
||||
### Nothing to do here as per-user SSH capabilities are already handled in '4330_installation_ssh.sh'.
|
||||
|
||||
### 3) Check tty access capabilities.
|
||||
case "${var_access_tty}" in
|
||||
false)
|
||||
### 1) Ensure the 'pam_access' line is not activated in '/etc/pam.d/login' and '/etc/pam.d/sshd' in parallel.
|
||||
### 3) A) 1) Ensure the 'pam_access' line is not activated in '/etc/pam.d/login' and '/etc/pam.d/sshd' in parallel.
|
||||
pam_access_sync_login_sshd
|
||||
|
||||
### 2) This step is not required for user accounts.
|
||||
### 3) A) 2) This step is not required for user accounts.
|
||||
|
||||
### 3) Disallow all local access for user in '/etc/security/access.conf'.
|
||||
### 3) A) 3) Disallow all local access for user in '/etc/security/access.conf'.
|
||||
printf "-: %s:ALL \n" "${var_username}" >> "${TARGET}/etc/security/access.conf"
|
||||
|
||||
### 4) This step is not required for user accounts.
|
||||
|
||||
### 3) A) 4) This step is not required for user accounts.
|
||||
|
||||
do_log "info" "file_only" "4520() User: '${var_username}' tty access: [false]"
|
||||
;;
|
||||
|
||||
true)
|
||||
### 1) Allow local access for 'user' only on 'tty1' in '/etc/security/access.conf'.
|
||||
### 3) B) 1) Allow local access for 'user' only on 'tty1' in '/etc/security/access.conf'.
|
||||
printf "+: %s:tty1 \n" "${var_username}" >> "${TARGET}/etc/security/access.conf"
|
||||
|
||||
### 2) Allow local access for 'root' only on 'tty1' in '/etc/securetty'.
|
||||
cat << 'EOF' >| "${TARGET}/etc/securetty"
|
||||
tty1
|
||||
EOF
|
||||
do_log "info" "file_only" "4520() User: 'root' tty access: [true]"
|
||||
### 3) B) 2) This step is not required for user accounts.
|
||||
|
||||
do_log "info" "file_only" "4520() User: '${var_username}' tty access: [true]"
|
||||
;;
|
||||
esac
|
||||
|
||||
### 4) Check the password policy for the 'user' account.
|
||||
case "${var_auth_pwd}" in
|
||||
false)
|
||||
chroot_script "${TARGET}" "passwd -l ${var_username}"
|
||||
do_log "info" "file_only" "4520() User: '${var_username}' password access: [false]"
|
||||
;;
|
||||
true)
|
||||
var_chpasswd="${var_username}:${var_password}"
|
||||
chroot_script "${TARGET}" "echo \"${var_chpasswd}\" | chpasswd -e"
|
||||
var_chpasswd=""
|
||||
do_log "info" "file_only" "4520() User: '${var_username}' password access: [true]"
|
||||
;;
|
||||
esac
|
||||
|
||||
### 5) Update the 'user' SSH pubkey, if provided via 'preseed.yaml'.
|
||||
if [[ -n "${var_sshpubkey:-}" ]]; then
|
||||
printf "%s\n" "${var_sshpubkey}" >| "${TARGET}/home/${var_username}/.ssh/authorized_keys"
|
||||
do_log "info" "file_only" "4520() User: '${var_username}' SSH public key: inserted."
|
||||
fi
|
||||
|
||||
### 6) Update the 'root' 'totp'-policy and write the '.google_authenticator'-file.
|
||||
[[ "${var_2fa_ssh}" == "true" || "${var_2fa_tty}" == "true" ]] && \
|
||||
write_google_authenticator_file "${var_username}"
|
||||
|
||||
[[ "${var_2fa_ssh}" == "true" ]] && pam_access_totp_enable "${var_username}" "sshd"
|
||||
|
||||
[[ "${var_2fa_tty}" == "true" ]] && pam_access_totp_enable "${var_username}" "login"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var_chpasswd="${var_username}:${var_password}"
|
||||
chroot_script "${TARGET}" "echo \"${var_chpasswd}\" | chpasswd -e"
|
||||
var_chpasswd=""
|
||||
|
||||
### 7) Check sudo membership for user.
|
||||
if [[ "${var_sudo}" == "true" ]]; then
|
||||
chroot_exec "${TARGET}" usermod -aG sudo "${var_username}"
|
||||
fi
|
||||
|
||||
if [[ -n "${var_sshpubkey}" ]]; then
|
||||
var_sshdir="${TARGET}/home/${var_username}/.ssh"
|
||||
install -d -m 0700 -o "${var_username}" -g "${var_username}" "${var_sshdir}"
|
||||
install -m 0600 -o "${var_username}" -g "${var_username}" /dev/null "${var_sshdir}/authorized_keys"
|
||||
grep -qxF "${var_sshpubkey}" "${var_sshdir}/authorized_keys" || \
|
||||
printf "%s\n" "${var_sshpubkey}" >> "${var_sshdir}/authorized_keys"
|
||||
fi
|
||||
|
||||
do_log "info" "file_only" "Created user: [${var_username}] UID: [${var_uid}], GID: [${var_gid}]"
|
||||
### 8) Final status logging.
|
||||
do_log "info" "file_only" "Created user: [${var_username}] UID: [${var_uid}] GID: [${var_gid}]"
|
||||
|
||||
done
|
||||
|
||||
|
||||
|
||||
|
||||
unset VAR_TEMP_PLAIN_MFA_SEED
|
||||
printf "-: ALL:ALL \n" >> "${TARGET}/etc/security/access.conf"
|
||||
printf "# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf \n" >> "${TARGET}/etc/security/access.conf"
|
||||
|
||||
guard_dir && return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Writes '.google_authenticator'-file for the respective user.
|
||||
# Globals:
|
||||
# RANDOM
|
||||
# TARGET
|
||||
# Arguments:
|
||||
# 1: Username
|
||||
# Returns:
|
||||
# 0: on success
|
||||
#######################################
|
||||
write_google_authenticator_file() {
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare var_user="${1}" var_secret=""
|
||||
case "${1}" in
|
||||
root) declare var_base="${TARGET}/root" ;;
|
||||
*) declare var_base="${TARGET}/home/${var_user}" ;;
|
||||
esac
|
||||
declare -i i=0
|
||||
|
||||
guard_trace on
|
||||
|
||||
var_secret="$(generate_totp_secret "${var_user}")"
|
||||
|
||||
umask 0077
|
||||
{
|
||||
printf '%s\n' "${var_secret}"
|
||||
printf '"RATE_LIMIT 3 30"\n'
|
||||
printf '"WINDOW 10"\n'
|
||||
printf '"DISALLOW_REUSE"\n'
|
||||
printf '"TOTP_AUTH"\n'
|
||||
### Emergency Codes:
|
||||
for i in {0..7}; do printf '%08d\n' "$(( RANDOM % 100000000 ))"; done
|
||||
} >| "${var_base}/.google_authenticator"
|
||||
chown "${var_user}:${var_user}" "${var_base}/.google_authenticator"
|
||||
chmod 0600 "${var_base}/.google_authenticator"
|
||||
|
||||
{
|
||||
printf '%s\n' "${var_user}"
|
||||
printf '%s\n' "${var_secret}"
|
||||
} >| "${DIR_TMP}/TOTP_${var_user}.secret"
|
||||
chmod 0400 "${DIR_TMP}/TOTP_${var_user}.secret"
|
||||
|
||||
umask 0022
|
||||
unset var_secret
|
||||
|
||||
guard_trace off
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Generates a deterministic TOTP secret based on:
|
||||
# Username, FQDN, MFA salt, MFA master seed
|
||||
@@ -404,40 +362,6 @@ generate_totp_secret() {
|
||||
|
||||
printf '%s\n' "${var_secret}"
|
||||
|
||||
unset var_secret
|
||||
|
||||
guard_trace off
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Reads a 256-bit seed from '${DIR_CNF}/mfa_master.txt' (64 hex chars) into VAR_TEMP_PLAIN_MFA_SEED.
|
||||
# Globals:
|
||||
# DIR_CNF
|
||||
# VAR_TEMP_PLAIN_MFA_SEED
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# 0: on success
|
||||
# ERR_READ_SEED_FILE
|
||||
#######################################
|
||||
read_totp_seed(){
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare -r var_mfa_seed_file="${DIR_CNF}/mfa_master.txt"
|
||||
declare -g VAR_TEMP_PLAIN_MFA_SEED=""
|
||||
|
||||
guard_trace on
|
||||
|
||||
if ! read_password_file "${var_mfa_seed_file}" VAR_TEMP_PLAIN_MFA_SEED; then
|
||||
|
||||
return "${ERR_READ_SEED_FILE}"
|
||||
|
||||
fi
|
||||
|
||||
### Validate: exactly 64 hex.
|
||||
[[ "${VAR_TEMP_PLAIN_MFA_SEED}" =~ ^[0-9a-fA-F]{64}$ ]] || return "${ERR_READ_SEED_FILE}"
|
||||
|
||||
guard_trace off
|
||||
|
||||
return 0
|
||||
@@ -445,6 +369,8 @@ read_totp_seed(){
|
||||
|
||||
#######################################
|
||||
# Ensure the 'pam_access' line is not activated in '/etc/pam.d/login' and '/etc/pam.d/sshd' in parallel.
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
@@ -496,6 +422,8 @@ pam_access_sync_login_sshd() {
|
||||
|
||||
#######################################
|
||||
# Enable per-user TOTP in a given PAM service (login, sshd, su, sudo).
|
||||
# Globals:
|
||||
# TARGET
|
||||
# Arguments:
|
||||
# 1: <username>
|
||||
# 2: <pam_module>
|
||||
@@ -563,4 +491,85 @@ pam_access_totp_enable() {
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Reads a 256-bit seed from '${DIR_CNF}/mfa_master.txt' (64 hex chars) into VAR_TEMP_PLAIN_MFA_SEED.
|
||||
# Globals:
|
||||
# DIR_CNF
|
||||
# VAR_TEMP_PLAIN_MFA_SEED
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# 0: on success
|
||||
# ERR_READ_SEED_FILE
|
||||
#######################################
|
||||
read_totp_seed(){
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare -r var_mfa_seed_file="${DIR_CNF}/mfa_master.txt"
|
||||
declare -g VAR_TEMP_PLAIN_MFA_SEED=""
|
||||
|
||||
guard_trace on
|
||||
|
||||
if ! read_password_file "${var_mfa_seed_file}" VAR_TEMP_PLAIN_MFA_SEED; then
|
||||
|
||||
return "${ERR_READ_SEED_FILE}"
|
||||
|
||||
fi
|
||||
|
||||
### Validate: exactly 64 hex.
|
||||
[[ "${VAR_TEMP_PLAIN_MFA_SEED}" =~ ^[0-9a-fA-F]{64}$ ]] || return "${ERR_READ_SEED_FILE}"
|
||||
|
||||
guard_trace off
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Writes '.google_authenticator'-file for the respective user.
|
||||
# Globals:
|
||||
# DIR_TMP
|
||||
# RANDOM
|
||||
# TARGET
|
||||
# Arguments:
|
||||
# 1: Username
|
||||
# Returns:
|
||||
# 0: on success
|
||||
#######################################
|
||||
write_google_authenticator_file() {
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare var_user="${1}" var_secret=""
|
||||
case "${1}" in
|
||||
root) declare var_base="${TARGET}/root" ;;
|
||||
*) declare var_base="${TARGET}/home/${var_user}" ;;
|
||||
esac
|
||||
declare -i i=0
|
||||
|
||||
guard_trace on
|
||||
|
||||
var_secret="$(generate_totp_secret "${var_user}")"
|
||||
|
||||
umask 0077
|
||||
{
|
||||
printf '%s\n' "${var_secret}"
|
||||
printf '"RATE_LIMIT 3 30"\n'
|
||||
printf '"WINDOW 10"\n'
|
||||
printf '"DISALLOW_REUSE"\n'
|
||||
printf '"TOTP_AUTH"\n'
|
||||
### Emergency Codes:
|
||||
for i in {0..7}; do printf '%08d\n' "$(( RANDOM % 100000000 ))"; done
|
||||
} >| "${var_base}/.google_authenticator"
|
||||
chown "${var_user}:${var_user}" "${var_base}/.google_authenticator"
|
||||
chmod 0600 "${var_base}/.google_authenticator"
|
||||
|
||||
{
|
||||
printf '%s\n' "${var_user}"
|
||||
printf '%s\n' "${var_secret}"
|
||||
} >| "${DIR_TMP}/TOTP_${var_user}.secret"
|
||||
chmod 0400 "${DIR_TMP}/TOTP_${var_user}.secret"
|
||||
|
||||
umask 0022
|
||||
|
||||
guard_trace off
|
||||
|
||||
return 0
|
||||
}
|
||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||
|
||||
Reference in New Issue
Block a user