V8.00.000.2025.06.17
All checks were successful
🛡️ Shell Script Linting / 🛡️ Shell Script Linting (push) Successful in 1m1s

Signed-off-by: Marc S. Weidner <msw@coresecret.dev>
This commit is contained in:
2025-09-11 15:42:15 +02:00
parent 001c501683
commit 227b74d124

View File

@@ -175,7 +175,7 @@ EOF
[[ "${user_root_authentication_2fa_tty}" == "true" ]] && pam_access_totp_enable "root" "login" [[ "${user_root_authentication_2fa_tty}" == "true" ]] && pam_access_totp_enable "root" "login"
### 7) Final status logging. ### 7) Final status logging.
do_log "info" "file_only" "User: 'root' updated." do_log "info" "file_only" "4520() User: 'root' updated."
### Iterate through all remaining 'user' accounts and install them. ### Iterate through all remaining 'user' accounts and install them.
@@ -333,12 +333,17 @@ EOF
### 7) Check sudo membership for user. ### 7) Check sudo membership for user.
if [[ "${var_sudo}" == "true" ]]; then if [[ "${var_sudo}" == "true" ]]; then
chroot_exec "${TARGET}" usermod -aG sudo "${var_username}" chroot_exec "${TARGET}" usermod -aG sudo "${var_username}"
### Hardening sudo users (idempotent) and ensure WinSCP SFTP-as-root.
hardening_sudo "${var_username}" hardening_sudo "${var_username}"
### Enable per-user TOTP in a given PAM service (login, sshd, su, sudo).
pam_access_totp_enable "${var_username}" "sudo"
fi fi
### 8) Final status logging. ### 8) Final status logging.
do_log "info" "file_only" "Created user: [${var_username}] UID: [${var_uid}] GID: [${var_gid}]" do_log "info" "file_only" "4520() Created user: [${var_username}] UID: [${var_uid}] GID: [${var_gid}]"
done done
@@ -351,6 +356,9 @@ EOF
printf "# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf \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"
printf "# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf \n" >> "${TARGET}/etc/ssh/sshd_conf" printf "# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf \n" >> "${TARGET}/etc/ssh/sshd_conf"
### Hardening of '/bin/su': only members of the group 'sudo' can su to root.
hardening_su
guard_dir && return 0 guard_dir && return 0
} }
@@ -392,7 +400,49 @@ generate_totp_secret() {
} }
####################################### #######################################
# Hardening sudo users. # Hardening of '/bin/su': only members of the group 'sudo' can su to root.
# Globals:
# None
# Arguments:
# None
# Returns:
# 0: on success
#######################################
hardening_su() {
### Declare Arrays, HashMaps, and Variables.
declare -r pam_su="/etc/pam.d/su"
[[ -f "${pam_su}" ]] || return 0
### If the pam_wheel line already exists with the group=sudo and use_uid, then do nothing.
if grep -Eq '^[[:space:]]*auth[[:space:]]+required[[:space:]]+pam_wheel\.so([[:space:]].*)?\bgroup=sudo\b([[:space:]].*)?\buse_uid\b' "${pam_su}"; then
return 0
fi
### Insert 'auth required pam_wheel.so use_uid group=sudo' before pam_unix/rootok (fail early).
awk '
BEGIN{ins=0}
{
### Insert just before the first pam_unix or pam_rootok auth line.
if (!ins && $0 ~ /^[[:space:]]*auth[[:space:]]+.*pam_(unix|rootok)\.so/) {
print "auth required pam_wheel.so use_uid group=sudo"
ins=1
}
print
}
END{
if (!ins) {
### Fallback: append if no anchor found
print "auth required pam_wheel.so use_uid group=sudo"
}
}
' "${pam_su}" > "${pam_su}.new" && mv -f "${pam_su}.new" "${pam_su}"
return 0
}
#######################################
# Hardening sudo users (idempotent) and ensure WinSCP SFTP-as-root.
# Globals: # Globals:
# TARGET # TARGET
# Arguments: # Arguments:
@@ -406,44 +456,92 @@ hardening_sudo() {
### Declare Arrays, HashMaps, and Variables. ### Declare Arrays, HashMaps, and Variables.
declare var_user="$1" declare var_user="$1"
declare -r var_logfile="/root/.ciss/cdi/log/4520_accounts_setup.log" declare -r var_logfile="/root/.ciss/cdi/log/4520_accounts_setup.log"
declare -r var_sudo_iolog_dir="${TARGET}/var/log/sudo-io"
declare -r var_sudoers_main="${TARGET}/etc/sudoers"
declare -r var_sudoers_dir="${TARGET}/etc/sudoers.d"
declare -r var_lr_conf="${TARGET}/etc/logrotate.d/sudo"
declare -r var_sudoers_winscp_global="${TARGET}/etc/sudoers.d/90-ciss-winscp-sftp"
declare -r var_sudoers_winscp_user="${TARGET}/etc/sudoers.d/91-ciss-winscp-${var_user}"
declare -r var_sftp_bin="/usr/lib/openssh/sftp-server"
### Create sudo log directory. ### Create sudo I/O log directory (idempotent).
mkdir -p "${TARGET}/var/log/sudo-io" if [[ ! -d "${var_sudo_iolog_dir}" ]]; then
find "${TARGET}/var/log/sudo-io" -type d -exec chmod 0700 {} \; mkdir -p "${var_sudo_iolog_dir}"
chmod 0700 "${var_sudo_iolog_dir}"
else
### Enforce restrictive perms on an existing tree.
chmod 0700 "${var_sudo_iolog_dir}"
fi
### Create sudoers logfile directive. ### Ensure sudoers Defaults are present only once. We key on 'iolog_dir' to avoid duplicate blocks.
cat << EOF >> "${TARGET}/etc/sudoers" if ! grep -qF 'iolog_dir="/var/log/sudo-io"' "${var_sudoers_main}" 2>/dev/null; then
cat << 'EOF' >> "${var_sudoers_main}"
##### Added by CISS.debian.installer ##### Added by CISS.debian.installer
Defaults log_host, log_year, log_input, log_exit_status, log_subcmds, logfile="/var/log/sudo.log", iolog_dir="/var/log/sudo-io" Defaults log_host, log_year, log_input, log_exit_status, log_subcmds, logfile="/var/log/sudo.log", iolog_dir="/var/log/sudo-io"
EOF EOF
fi
### Create sudoers user directive. ### Install global WinSCP SFTP-as-root command alias (idempotent).
touch "${TARGET}/etc/sudoers.d/user_${var_user}" if [[ -x "${TARGET}${var_sftp_bin}" ]]; then
cat << EOF >> "${TARGET}/etc/sudoers.d/user_${var_user}"
${var_user} ALL=NOPASSWD: ALL if [[ ! -f "${var_sudoers_winscp_global}" ]]; then
cat << EOF > "${var_sudoers_winscp_global}"
### Added by CISS.debian.installer. WinSCP SFTP-as-root (least privilege).
### Allow exactly the sftp-server binary, optionally with -e (stderr logging).
Cmnd_Alias CISS_SFTPROOT = ${var_sftp_bin}, ${var_sftp_bin} -e
# Harden per-command defaults: noexec to block execve(), and forbid env changes.
Defaults!CISS_SFTPROOT noexec, !setenv
EOF EOF
chmod 0440 "${var_sudoers_winscp_global}"
### Set '/etc/sudoers.d' file permissions to 0440. fi
find "${TARGET}/etc/sudoers.d" -type f -exec chmod 0440 {} \;
### Verify written '/etc/sudoers.d' configuration. else
if ! chroot_script "${TARGET}" "export EDITOR=/usr/bin/nano /usr/sbin/visudo -q -c >> ${var_logfile}"; then
do_log "warn" "file_only" "Command: [chroot_script ${TARGET} export EDITOR=/usr/bin/nano /usr/sbin/visudo -q -c] failed." do_log "warn" "file_only" "4520() sftp-server not found at [${var_sftp_bin}] in TARGET; skipping global alias for now."
fi
### Grant this user access to the alias (idempotent). Only add if not already present; keep the file permissive correctness.
if [[ -f "${var_sudoers_winscp_user}" ]]; then
if ! grep -qE "^${var_user}\s+ALL=\(root\)\s+NOPASSWD:\s+CISS_SFTPROOT\b" "${var_sudoers_winscp_user}" 2>/dev/null; then
echo "${var_user} ALL=(root) NOPASSWD: CISS_SFTPROOT" >> "${var_sudoers_winscp_user}"
fi
else
echo "${var_user} ALL=(root) NOPASSWD: CISS_SFTPROOT" >| "${var_sudoers_winscp_user}"
fi
chmod 0440 "${var_sudoers_winscp_user}"
### Tighten perms on sudoers.d (idempotent).
find "${var_sudoers_dir}" -type f -exec chmod 0440 {} \;
### Verify sudoers syntax in chroot
if ! chroot_script "${TARGET}" "EDITOR=/usr/bin/nano /usr/sbin/visudo -q -c >> ${var_logfile}"; then
do_log "warn" "file_only" "4520() Command: [chroot_script ${TARGET} EDITOR=/usr/bin/nano /usr/sbin/visudo -q -c] failed."
return "${ERR_VERIFY_VISUDO}" return "${ERR_VERIFY_VISUDO}"
else else
do_log "info" "file_only" "Command: [chroot_script ${TARGET} export EDITOR=/usr/bin/nano /usr/sbin/visudo -q -c] successful." do_log "info" "file_only" "4520() Command: [chroot_script ${TARGET} EDITOR=/usr/bin/nano /usr/sbin/visudo -q -c] successful."
fi fi
### Create sudo log rotation directive. #### Ensure logrotate for /var/log/sudo.log exists once.
insert_header "${TARGET}/etc/logrotate.d/sudo" if ! grep -qF "/var/log/sudo.log {" "${var_lr_conf}" 2>/dev/null; then
insert_comments "${TARGET}/etc/logrotate.d/sudo"
cat << EOF >> "${TARGET}/etc/logrotate.d/sudo" insert_header "${var_lr_conf}"
insert_comments "${var_lr_conf}"
cat << EOF >> "${var_lr_conf}"
/var/log/sudo.log { /var/log/sudo.log {
daily daily
rotate 90 rotate 90
@@ -458,16 +556,17 @@ EOF
} }
EOF EOF
### Verify written sudo log rotation configuration. ### Verify logrotate config in chroot.
if ! chroot_script "${TARGET}" "logrotate -d /etc/logrotate.conf >> ${var_logfile}"; then if ! chroot_script "${TARGET}" "logrotate -d /etc/logrotate.conf >> ${var_logfile}"; then
do_log "warn" "file_only" "Command: [chroot_script ${TARGET} logrotate -d /etc/logrotate.conf] failed." do_log "warn" "file_only" "4520() Command: [chroot_script ${TARGET} logrotate -d /etc/logrotate.conf] failed."
return "${ERR_VERIFY_LOGROTATE}" return "${ERR_VERIFY_LOGROTATE}"
else else
do_log "info" "file_only" "Command: [chroot_script ${TARGET} logrotate -d /etc/logrotate.conf] successful." do_log "info" "file_only" "4520() Command: [chroot_script ${TARGET} logrotate -d /etc/logrotate.conf] successful."
fi
fi fi
@@ -484,6 +583,7 @@ EOF
# 0: on success # 0: on success
####################################### #######################################
pam_access_sync_login_sshd() { pam_access_sync_login_sshd() {
### Declare Arrays, HashMaps, and Variables.
declare var_file_login="/etc/pam.d/login" declare var_file_login="/etc/pam.d/login"
declare var_file_sshd="/etc/pam.d/sshd" declare var_file_sshd="/etc/pam.d/sshd"
@@ -538,6 +638,7 @@ pam_access_sync_login_sshd() {
# 0: on success # 0: on success
####################################### #######################################
pam_access_totp_enable() { pam_access_totp_enable() {
### Declare Arrays, HashMaps, and Variables.
declare var_user="$1" declare var_user="$1"
declare var_module="$2" declare var_module="$2"
declare var_pam_file="/etc/pam.d/${var_module}" declare var_pam_file="/etc/pam.d/${var_module}"