V8.00.000.2025.06.17
All checks were successful
🛡️ Shell Script Linting / 🛡️ Shell Script Linting (push) Successful in 1m1s
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:
@@ -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}"
|
||||||
|
|||||||
Reference in New Issue
Block a user