V8.00.000.2025.06.17
All checks were successful
🛡️ Shell Script Linting / 🛡️ Shell Script Linting (push) Successful in 1m22s
All checks were successful
🛡️ Shell Script Linting / 🛡️ Shell Script Linting (push) Successful in 1m22s
Signed-off-by: Marc S. Weidner <msw@coresecret.dev>
This commit is contained in:
@@ -50,8 +50,12 @@ accounts_setup() {
|
||||
var_access_tty="" var_auth_pwd="" var_2fa_ssh="" var_2fa_tty="" var_sudo="" var_restricted="" var_system="" \
|
||||
var_specific=""
|
||||
declare var_ssh_totp_update="false"
|
||||
declare var_target="${TARGET}"
|
||||
|
||||
chroot_logger "${TARGET}${var_logfile}"
|
||||
### Check for TARGET / RECOVERY.
|
||||
[[ "${VAR_RUN_RECOVERY}" == "true" ]] && var_target="${RECOVERY}"
|
||||
|
||||
chroot_logger "${var_target}${var_logfile}"
|
||||
|
||||
### Prepare the '2fa'-seed variable.
|
||||
read_totp_seed
|
||||
@@ -60,21 +64,21 @@ accounts_setup() {
|
||||
### 0) The 'root' account is generated via debootstrap by default.
|
||||
|
||||
### 1) Prepare the 'root' account.
|
||||
install -d -m 0700 -o root -g root "${TARGET}/root/.ssh"
|
||||
install -m 0600 -o root -g root /dev/null "${TARGET}/root/.ssh/authorized_keys"
|
||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.bashrc" "${TARGET}/root/"
|
||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.ciss/theme_eza_ciss.yml" "${TARGET}/root/.ciss/"
|
||||
install -d -m 0700 -o root -g root "${var_target}/root/.ssh"
|
||||
install -m 0600 -o root -g root /dev/null "${var_target}/root/.ssh/authorized_keys"
|
||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.bashrc" "${var_target}/root/"
|
||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.ciss/theme_eza_ciss.yml" "${var_target}/root/.ciss/"
|
||||
|
||||
if [[ "${user_root_shell}" == "/bin/zsh" ]]; then
|
||||
|
||||
if [[ -x "${TARGET}${user_root_shell}" ]]; then
|
||||
if [[ -x "${var_target}${user_root_shell}" ]]; then
|
||||
|
||||
case "${user_root_specific,,}" in
|
||||
|
||||
"ciss")
|
||||
zsh_omz_installer "root"
|
||||
mv "${TARGET}/root/.zshrc" "${TARGET}/root/.zshrc.bak"
|
||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.zshrc" "${TARGET}/root/"
|
||||
zsh_omz_installer "root" "${var_target}"
|
||||
mv "${var_target}/root/.zshrc" "${var_target}/root/.zshrc.bak"
|
||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.zshrc" "${var_target}/root/"
|
||||
;;
|
||||
|
||||
"physnet")
|
||||
@@ -87,24 +91,24 @@ accounts_setup() {
|
||||
|
||||
esac
|
||||
|
||||
chroot_exec "${TARGET}" chsh -s "${user_root_shell}" root
|
||||
chroot_exec "${var_target}" chsh -s "${user_root_shell}" root
|
||||
do_log "info" "file_only" "4520() Shell: '${user_root_shell}' used for: 'root'."
|
||||
|
||||
else
|
||||
|
||||
chroot_exec "${TARGET}" chsh -s /bin/bash root
|
||||
chroot_exec "${var_target}" chsh -s /bin/bash root
|
||||
do_log "info" "file_only" "4520() Shell: '${user_root_shell}' not found for: 'root'. Using '/bin/bash' instead."
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/alias" "${TARGET}/root/.ciss/"
|
||||
install -m 0700 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/clean_logout.sh" "${TARGET}/root/.ciss/"
|
||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/shortcuts" "${TARGET}/root/.ciss/"
|
||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/alias" "${var_target}/root/.ciss/"
|
||||
install -m 0700 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/clean_logout.sh" "${var_target}/root/.ciss/"
|
||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/shortcuts" "${var_target}/root/.ciss/"
|
||||
|
||||
### To be able to copy/paste from vim, one needs to create a '.vimrc' with the following content:
|
||||
echo 'set clipboard=unnamed' >| "${TARGET}/root/.vimrc"
|
||||
chmod 0600 "${TARGET}/root/.vimrc"
|
||||
echo 'set clipboard=unnamed' >| "${var_target}/root/.vimrc"
|
||||
chmod 0600 "${var_target}/root/.vimrc"
|
||||
|
||||
do_log "info" "file_only" "4520() Skeleton: 'root' successfully generated."
|
||||
|
||||
@@ -112,12 +116,12 @@ accounts_setup() {
|
||||
case "${user_root_authentication_access_ssh,,}" in
|
||||
|
||||
false)
|
||||
sed -i -E "s|^[[:space:]]*PermitRootLogin[[:space:]]+.*$|$(printf '%-29s%s' 'PermitRootLogin' 'no')|" "${TARGET}/etc/ssh/sshd_config"
|
||||
sed -i -E "s|^[[:space:]]*PermitRootLogin[[:space:]]+.*$|$(printf '%-29s%s' 'PermitRootLogin' 'no')|" "${var_target}/etc/ssh/sshd_config"
|
||||
do_log "info" "file_only" "4520() User: 'root' SSH access: [PermitRootLogin no]"
|
||||
;;
|
||||
|
||||
true)
|
||||
sed -i -E "s|^[[:space:]]*PermitRootLogin[[:space:]]+.*$|$(printf '%-29s%s' 'PermitRootLogin' 'prohibit-password')|" "${TARGET}/etc/ssh/sshd_config"
|
||||
sed -i -E "s|^[[:space:]]*PermitRootLogin[[:space:]]+.*$|$(printf '%-29s%s' 'PermitRootLogin' 'prohibit-password')|" "${var_target}/etc/ssh/sshd_config"
|
||||
do_log "info" "file_only" "4520() User: 'root' SSH access: [PermitRootLogin prohibit-password]"
|
||||
;;
|
||||
|
||||
@@ -136,7 +140,7 @@ accounts_setup() {
|
||||
pam_access_sync_login_sshd
|
||||
|
||||
### 3) A) 2) Ensure 'pam_securetty' in the auth phase; requisite causes immediate fail for disallowed ttys.
|
||||
chroot_stdin "${TARGET}" "__payload__" <<'EOF'
|
||||
chroot_stdin "${var_target}" "__payload__" <<'EOF'
|
||||
export LC_ALL=C
|
||||
if ! grep -Eq '^[[:space:]]*auth[[:space:]]+requisite[[:space:]]+pam_securetty[.]so([[:space:]]|$)' /etc/pam.d/login; then
|
||||
tmp="$(mktemp /etc/pam.d/login.XXXXXX)"
|
||||
@@ -162,10 +166,10 @@ fi
|
||||
EOF
|
||||
|
||||
### 3) A) 3) Disallow all local access for root in '/etc/security/access.conf'.
|
||||
printf -- '-: root:ALL\n' >> "${TARGET}/etc/security/access.conf"
|
||||
printf -- '-: root:ALL\n' >> "${var_target}/etc/security/access.conf"
|
||||
|
||||
### 3) A) 4) Empty "/etc/securetty".
|
||||
cat << 'EOF' >| "${TARGET}/etc/securetty"
|
||||
cat << 'EOF' >| "${var_target}/etc/securetty"
|
||||
EOF
|
||||
|
||||
do_log "info" "file_only" "4520() User: 'root' tty access: [false]"
|
||||
@@ -173,10 +177,10 @@ EOF
|
||||
|
||||
true)
|
||||
### 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"
|
||||
printf -- "+: root:tty1 \n" >> "${var_target}/etc/security/access.conf"
|
||||
|
||||
### 3) B) 2) Allow local access for 'root' only on 'tty1' in '/etc/securetty'.
|
||||
cat << 'EOF' >| "${TARGET}/etc/securetty"
|
||||
cat << 'EOF' >| "${var_target}/etc/securetty"
|
||||
tty1
|
||||
EOF
|
||||
do_log "info" "file_only" "4520() User: 'root' tty access: [true]"
|
||||
@@ -193,13 +197,13 @@ EOF
|
||||
case "${user_root_authentication_password,,}" in
|
||||
|
||||
false)
|
||||
chroot_script "${TARGET}" "passwd -l root"
|
||||
chroot_script "${var_target}" "passwd -l root"
|
||||
do_log "info" "file_only" "4520() User: 'root' password access: [false]"
|
||||
;;
|
||||
|
||||
true)
|
||||
chroot_script "${TARGET}" "printf '%s:%s\n' root '${var_password}' | /usr/sbin/chpasswd -e"
|
||||
#chroot_script "${TARGET}" "/usr/sbin/usermod -p '${user_root_password}' root"
|
||||
chroot_script "${var_target}" "printf '%s:%s\n' root '${var_password}' | /usr/sbin/chpasswd -e"
|
||||
#chroot_script "${var_target}" "/usr/sbin/usermod -p '${user_root_password}' root"
|
||||
do_log "info" "file_only" "4520() User: 'root' password access: [true]"
|
||||
;;
|
||||
|
||||
@@ -213,7 +217,7 @@ EOF
|
||||
### 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"
|
||||
printf "%s\n" "${user_root_sshpubkey}" >| "${var_target}/root/.ssh/authorized_keys"
|
||||
do_log "info" "file_only" "4520() User: 'root' SSH public key: inserted."
|
||||
|
||||
fi
|
||||
@@ -221,36 +225,36 @@ EOF
|
||||
### 6) Update the 'root' 'totp'-policy and write the '.google_authenticator'-file.
|
||||
if [[ "${user_root_authentication_2fa_ssh}" == "true" || "${user_root_authentication_2fa_tty}" == "true" ]]; then
|
||||
|
||||
write_google_authenticator_file "root" "0" "0"
|
||||
write_google_authenticator_file "root" "0" "0" "${var_target}"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if [[ "${user_root_authentication_2fa_ssh}" == "true" ]]; then
|
||||
|
||||
pam_access_totp_enable "root" "sshd"
|
||||
pam_access_totp_enable "root" "sshd" "${var_target}"
|
||||
var_ssh_totp_update="true"
|
||||
cat << EOF >> "${TARGET}/etc/ssh/sshd_config"
|
||||
cat << EOF >> "${var_target}/etc/ssh/sshd_config"
|
||||
Match User root
|
||||
AuthenticationMethods publickey,keyboard-interactive:pam
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
[[ "${user_root_authentication_2fa_tty}" == "true" ]] && pam_access_totp_enable "root" "login"
|
||||
[[ "${user_root_authentication_2fa_tty}" == "true" ]] && pam_access_totp_enable "root" "login" "${var_target}"
|
||||
|
||||
### 7) Install eza themes.
|
||||
eza_installer "root"
|
||||
eza_installer "root" "${var_target}"
|
||||
|
||||
### 8) Double check permissions.
|
||||
### Directories: 0700
|
||||
find "${TARGET}/root" -type d -exec chmod 0700 {} +
|
||||
find "${var_target}/root" -type d -exec chmod 0700 {} +
|
||||
### Executable files: 0700 (any x-bit set)
|
||||
find "${TARGET}/root" -type f -perm /111 -exec chmod 0700 {} +
|
||||
find "${var_target}/root" -type f -perm /111 -exec chmod 0700 {} +
|
||||
### Non-executable files: 0600
|
||||
find "${TARGET}/root" -type f ! -perm /111 -exec chmod 0600 {} +
|
||||
find "${var_target}/root" -type f ! -perm /111 -exec chmod 0600 {} +
|
||||
### Ownership: UID:GID (do not dereference symlinks; stay on this filesystem)
|
||||
find "${TARGET}/root" -xdev -exec chown -h root:root {} +
|
||||
find "${var_target}/root" -xdev -exec chown -h root:root {} +
|
||||
|
||||
### 9) Final status logging.
|
||||
do_log "info" "file_only" "4520() User: 'root' updated."
|
||||
@@ -292,8 +296,8 @@ EOF
|
||||
var_specific="${!tmp_specific}"
|
||||
|
||||
### 0) A) Check if the 'group' of the 'user' already exists.
|
||||
if ! chroot_exec "${TARGET}" getent group "${var_username}" >/dev/null; then
|
||||
chroot_exec "${TARGET}" groupadd --gid "${var_gid}" "${var_username}"
|
||||
if ! chroot_exec "${var_target}" getent group "${var_username}" >/dev/null; then
|
||||
chroot_exec "${var_target}" groupadd --gid "${var_gid}" "${var_username}"
|
||||
fi
|
||||
|
||||
### 0) B) Generates the user account.
|
||||
@@ -302,7 +306,7 @@ EOF
|
||||
case "${var_restricted}":"${var_system}" in
|
||||
|
||||
false:false)
|
||||
chroot_exec "${TARGET}" useradd \
|
||||
chroot_exec "${var_target}" useradd \
|
||||
--comment "${var_fullname}" \
|
||||
--create-home \
|
||||
--expiredate 2102-12-31 \
|
||||
@@ -312,11 +316,11 @@ EOF
|
||||
--shell "${var_shell}" \
|
||||
--uid "${var_uid}" \
|
||||
"${var_username}"
|
||||
eza_installer "${var_username}"
|
||||
eza_installer "${var_username}" "${var_target}"
|
||||
;;
|
||||
|
||||
true:false)
|
||||
chroot_exec "${TARGET}" useradd \
|
||||
chroot_exec "${var_target}" useradd \
|
||||
--comment "${var_fullname}" \
|
||||
--expiredate 2102-12-31 \
|
||||
--gid "${var_gid}" \
|
||||
@@ -328,7 +332,7 @@ EOF
|
||||
;;
|
||||
|
||||
false:true)
|
||||
chroot_exec "${TARGET}" useradd \
|
||||
chroot_exec "${var_target}" useradd \
|
||||
--comment "${var_fullname}" \
|
||||
--create-home \
|
||||
--expiredate 2102-12-31 \
|
||||
@@ -342,7 +346,7 @@ EOF
|
||||
;;
|
||||
|
||||
true:true)
|
||||
chroot_exec "${TARGET}" useradd \
|
||||
chroot_exec "${var_target}" useradd \
|
||||
--comment "${var_fullname}" \
|
||||
--expiredate 2102-12-31 \
|
||||
--gid "${var_gid}" \
|
||||
@@ -362,20 +366,20 @@ EOF
|
||||
esac
|
||||
|
||||
### 1) Prepare the 'user' account.
|
||||
install -d -m 0700 -o "${var_uid}" -g "${var_gid}" "${TARGET}/home/${var_username}/.ssh"
|
||||
install -m 0600 -o "${var_uid}" -g "${var_gid}" /dev/null "${TARGET}/home/${var_username}/.ssh/authorized_keys"
|
||||
install -m 0600 -o "${var_uid}" -g "${var_gid}" "${VAR_SETUP_PATH}/includes/target/etc/skel/.bashrc" "${TARGET}/home/${var_username}/"
|
||||
install -d -m 0700 -o "${var_uid}" -g "${var_gid}" "${var_target}/home/${var_username}/.ssh"
|
||||
install -m 0600 -o "${var_uid}" -g "${var_gid}" /dev/null "${var_target}/home/${var_username}/.ssh/authorized_keys"
|
||||
install -m 0600 -o "${var_uid}" -g "${var_gid}" "${VAR_SETUP_PATH}/includes/target/etc/skel/.bashrc" "${var_target}/home/${var_username}/"
|
||||
|
||||
if [[ "${var_shell}" == "/bin/zsh" ]]; then
|
||||
|
||||
if [[ -x "${TARGET}${var_shell}" ]]; then
|
||||
if [[ -x "${var_target}${var_shell}" ]]; then
|
||||
|
||||
case "${var_specific,,}" in
|
||||
|
||||
"ciss")
|
||||
zsh_omz_installer "${var_username}"
|
||||
mv "${TARGET}/home/${var_username}/.zshrc" "${TARGET}/home/${var_username}/.zshrc.bak"
|
||||
install -m 0600 -o "${var_uid}" -g "${var_gid}" "${VAR_SETUP_PATH}/includes/target/etc/skel/.zshrc" "${TARGET}/home/${var_username}"
|
||||
zsh_omz_installer "${var_username}" "${var_target}"
|
||||
mv "${var_target}/home/${var_username}/.zshrc" "${var_target}/home/${var_username}/.zshrc.bak"
|
||||
install -m 0600 -o "${var_uid}" -g "${var_gid}" "${VAR_SETUP_PATH}/includes/target/etc/skel/.zshrc" "${var_target}/home/${var_username}"
|
||||
;;
|
||||
|
||||
"physnet")
|
||||
@@ -388,12 +392,12 @@ EOF
|
||||
|
||||
esac
|
||||
|
||||
chroot_exec "${TARGET}" chsh -s "${var_shell}" "${var_username}"
|
||||
chroot_exec "${var_target}" chsh -s "${var_shell}" "${var_username}"
|
||||
do_log "info" "file_only" "4520() Shell: '${var_shell}' used for: '${var_username}'."
|
||||
|
||||
else
|
||||
|
||||
chroot_exec "${TARGET}" chsh -s /bin/bash "${var_username}"
|
||||
chroot_exec "${var_target}" chsh -s /bin/bash "${var_username}"
|
||||
do_log "info" "file_only" "4520() Shell: '${var_shell}' not found for: '${var_username}'. Using '/bin/bash' instead."
|
||||
|
||||
fi
|
||||
@@ -415,7 +419,7 @@ EOF
|
||||
### 3) A) 2) This step is not required for user accounts.
|
||||
|
||||
### 3) A) 3) Disallow all local access for user in '/etc/security/access.conf'.
|
||||
printf '%s\n' "-: ${var_username}:ALL" >> "${TARGET}/etc/security/access.conf"
|
||||
printf '%s\n' "-: ${var_username}:ALL" >> "${var_target}/etc/security/access.conf"
|
||||
|
||||
### 3) A) 4) This step is not required for user accounts.
|
||||
|
||||
@@ -424,7 +428,7 @@ EOF
|
||||
|
||||
true)
|
||||
### 3) B) 1) Allow local access for 'user' only on 'tty1' in '/etc/security/access.conf'.
|
||||
printf '%s\n' "+: ${var_username}:tty1" >> "${TARGET}/etc/security/access.conf"
|
||||
printf '%s\n' "+: ${var_username}:tty1" >> "${var_target}/etc/security/access.conf"
|
||||
|
||||
### 3) B) 2) This step is not required for user accounts.
|
||||
|
||||
@@ -442,13 +446,13 @@ EOF
|
||||
case "${var_auth_pwd}" in
|
||||
|
||||
false)
|
||||
chroot_script "${TARGET}" "passwd -l ${var_username}"
|
||||
chroot_script "${var_target}" "passwd -l ${var_username}"
|
||||
do_log "info" "file_only" "4520() User: '${var_username}' password access: [false]"
|
||||
;;
|
||||
|
||||
true)
|
||||
chroot_script "${TARGET}" "printf '%s:%s\n' \"${var_username}\" '${var_password}' | /usr/sbin/chpasswd -e"
|
||||
#chroot_script "${TARGET}" "/usr/sbin/usermod -p '${var_password}' ${var_username}"
|
||||
chroot_script "${var_target}" "printf '%s:%s\n' \"${var_username}\" '${var_password}' | /usr/sbin/chpasswd -e"
|
||||
#chroot_script "${var_target}" "/usr/sbin/usermod -p '${var_password}' ${var_username}"
|
||||
do_log "info" "file_only" "4520() User: '${var_username}' password access: [true]"
|
||||
;;
|
||||
|
||||
@@ -462,7 +466,7 @@ EOF
|
||||
### 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"
|
||||
printf "%s\n" "${var_sshpubkey}" >| "${var_target}/home/${var_username}/.ssh/authorized_keys"
|
||||
do_log "info" "file_only" "4520() User: '${var_username}' SSH public key: inserted."
|
||||
|
||||
fi
|
||||
@@ -470,43 +474,43 @@ EOF
|
||||
### 6) Update the 'root' 'totp'-policy and write the '.google_authenticator'-file.
|
||||
if [[ "${var_2fa_ssh}" == "true" || "${var_2fa_tty}" == "true" ]]; then
|
||||
|
||||
write_google_authenticator_file "${var_username}" "${var_uid}" "${var_gid}"
|
||||
write_google_authenticator_file "${var_username}" "${var_uid}" "${var_gid}" "${var_target}"
|
||||
|
||||
fi
|
||||
|
||||
if [[ "${var_2fa_ssh}" == "true" ]]; then
|
||||
|
||||
pam_access_totp_enable "${var_username}" "sshd"
|
||||
pam_access_totp_enable "${var_username}" "sshd" "${var_target}"
|
||||
var_ssh_totp_update="true"
|
||||
cat << EOF >> "${TARGET}/etc/ssh/sshd_config"
|
||||
cat << EOF >> "${var_target}/etc/ssh/sshd_config"
|
||||
Match User ${var_username}
|
||||
AuthenticationMethods publickey,keyboard-interactive:pam
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
[[ "${var_2fa_tty}" == "true" ]] && pam_access_totp_enable "${var_username}" "login"
|
||||
[[ "${var_2fa_tty}" == "true" ]] && pam_access_totp_enable "${var_username}" "login" "${var_target}"
|
||||
|
||||
### 7) Check sudo membership for user.
|
||||
if [[ "${var_sudo}" == "true" ]]; then
|
||||
|
||||
chroot_exec "${TARGET}" usermod -aG sudo "${var_username}"
|
||||
chroot_exec "${var_target}" usermod -aG sudo "${var_username}"
|
||||
### Hardening sudo users (idempotent) and ensure WinSCP SFTP-as-root.
|
||||
hardening_sudo "${var_username}" "${var_specific:-none}"
|
||||
hardening_sudo "${var_username}" "${var_specific:-none}" "${var_target}"
|
||||
### Enable per-user TOTP in a given PAM service (login, sshd, su, sudo).
|
||||
pam_access_totp_enable "${var_username}" "sudo"
|
||||
pam_access_totp_enable "${var_username}" "sudo" "${var_target}"
|
||||
|
||||
fi
|
||||
|
||||
### 8) Double check permissions.
|
||||
### Directories: 0700
|
||||
find "${TARGET}/home/${var_username}" -type d -exec chmod 0700 {} +
|
||||
find "${var_target}/home/${var_username}" -type d -exec chmod 0700 {} +
|
||||
### Executable files: 0700 (any x-bit set)
|
||||
find "${TARGET}/home/${var_username}" -type f -perm /111 -exec chmod 0700 {} +
|
||||
find "${var_target}/home/${var_username}" -type f -perm /111 -exec chmod 0700 {} +
|
||||
### Non-executable files: 0600
|
||||
find "${TARGET}/home/${var_username}" -type f ! -perm /111 -exec chmod 0600 {} +
|
||||
find "${var_target}/home/${var_username}" -type f ! -perm /111 -exec chmod 0600 {} +
|
||||
### Ownership: UID:GID (do not dereference symlinks; stay on this filesystem)
|
||||
find "${TARGET}/home/${var_username}" -xdev -exec chown -h "${var_uid}:${var_gid}" {} +
|
||||
find "${var_target}/home/${var_username}" -xdev -exec chown -h "${var_uid}:${var_gid}" {} +
|
||||
|
||||
### 9) Final status logging.
|
||||
do_log "info" "file_only" "4520() Created user: [${var_username}] UID: [${var_uid}] GID: [${var_gid}]"
|
||||
@@ -515,20 +519,20 @@ EOF
|
||||
|
||||
if [[ "${var_ssh_totp_update}" == "true" ]]; then
|
||||
|
||||
sed -i -E "s|^[[:space:]]*KbdInteractiveAuthentication[[:space:]]+.*$|$(printf '%-29s%s' 'KbdInteractiveAuthentication' 'yes')|" "${TARGET}/etc/ssh/sshd_config"
|
||||
sed -i -E "s|^[[:space:]]*KbdInteractiveAuthentication[[:space:]]+.*$|$(printf '%-29s%s' 'KbdInteractiveAuthentication' 'yes')|" "${var_target}/etc/ssh/sshd_config"
|
||||
|
||||
fi
|
||||
|
||||
unset VAR_TEMP_PLAIN_MFA_SEED
|
||||
|
||||
if ! grep -Fqx -- '-: ALL:ALL' "${TARGET}/etc/security/access.conf"; then
|
||||
if ! grep -Fqx -- '-: ALL:ALL' "${var_target}/etc/security/access.conf"; then
|
||||
|
||||
printf '%s\n' '-: ALL:ALL' >> "${TARGET}/etc/security/access.conf"
|
||||
printf '%s\n' '-: ALL:ALL' >> "${var_target}/etc/security/access.conf"
|
||||
|
||||
fi
|
||||
|
||||
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_config"
|
||||
printf "# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf \n" >> "${var_target}/etc/security/access.conf"
|
||||
printf "# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf \n" >> "${var_target}/etc/ssh/sshd_config"
|
||||
|
||||
### Hardening of '/bin/su': only members of the group 'sudo' can su to root.
|
||||
hardening_su
|
||||
@@ -542,21 +546,23 @@ readonly -f accounts_setup
|
||||
#######################################
|
||||
# Install eza CISS theme for the respective user.
|
||||
# Globals:
|
||||
# TARGET
|
||||
# None
|
||||
# Arguments:
|
||||
# 1: Username
|
||||
# 2: Target
|
||||
# Returns:
|
||||
# 0: on success
|
||||
#######################################
|
||||
eza_installer() {
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare var_user="${1}"
|
||||
declare -r var_user="${1}" var_target="${2}"
|
||||
|
||||
case "${1}" in
|
||||
root) declare var_base="/root" ;;
|
||||
*) declare var_base="/home/${var_user}" ;;
|
||||
esac
|
||||
|
||||
chroot_script "${TARGET}" "
|
||||
chroot_script "${var_target}" "
|
||||
cd ${var_base}
|
||||
git clone https://github.com/eza-community/eza-themes.git
|
||||
mkdir -p ${var_base}/.config/eza
|
||||
@@ -630,9 +636,9 @@ hardening_su() {
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare -r pam_su="/etc/pam.d/su"
|
||||
|
||||
[[ -f "${TARGET}${pam_su}" ]] || return 0
|
||||
[[ -f "${var_target}${pam_su}" ]] || return 0
|
||||
|
||||
chroot_stdin "${TARGET}" "__payload__" -- "${pam_su}" <<'EOF'
|
||||
chroot_stdin "${var_target}" "__payload__" -- "${pam_su}" <<'EOF'
|
||||
export LC_ALL=C
|
||||
pam="$1"
|
||||
|
||||
@@ -673,9 +679,11 @@ readonly -f hardening_su
|
||||
#######################################
|
||||
# Hardening sudo users (idempotent) and ensure WinSCP SFTP-as-root.
|
||||
# Globals:
|
||||
# TARGET
|
||||
# None
|
||||
# Arguments:
|
||||
# 1: <username>
|
||||
# 1: username
|
||||
# 2: user_specifics
|
||||
# 3: target
|
||||
# Returns:
|
||||
# 0: on success
|
||||
# ERR_VERIFY_LOGROTATE: on failure
|
||||
@@ -683,15 +691,14 @@ readonly -f hardening_su
|
||||
#######################################
|
||||
hardening_sudo() {
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare var_user="$1"
|
||||
declare var_specific="$2"
|
||||
declare -r var_user="${1}" var_specific="${2}" var_target="${3}"
|
||||
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_sudo_iolog_dir="${var_target}/var/log/sudo-io"
|
||||
declare -r var_sudoers_main="${var_target}/etc/sudoers"
|
||||
declare -r var_sudoers_dir="${var_target}/etc/sudoers.d"
|
||||
declare -r var_lr_conf="${var_target}/etc/logrotate.d/sudo"
|
||||
declare -r var_sudoers_winscp_global="${var_target}/etc/sudoers.d/90-ciss-winscp-sftp"
|
||||
declare -r var_sudoers_winscp_user="${var_target}/etc/sudoers.d/91-ciss-winscp-${var_user}"
|
||||
declare -r var_sftp_bin="/usr/lib/openssh/sftp-server"
|
||||
|
||||
### Create sudo I/O log directory (idempotent).
|
||||
@@ -716,7 +723,7 @@ EOF
|
||||
|
||||
"ciss")
|
||||
### Install global WinSCP SFTP-as-root command alias (idempotent).
|
||||
if [[ -x "${TARGET}${var_sftp_bin}" ]]; then
|
||||
if [[ -x "${var_target}${var_sftp_bin}" ]]; then
|
||||
|
||||
if [[ ! -f "${var_sudoers_winscp_global}" ]]; then
|
||||
|
||||
@@ -779,14 +786,14 @@ EOF
|
||||
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
|
||||
if ! chroot_script "${var_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."
|
||||
do_log "warn" "file_only" "4520() Command: [chroot_script ${var_target} EDITOR=/usr/bin/nano /usr/sbin/visudo -q -c] failed."
|
||||
return "${ERR_VERIFY_VISUDO}"
|
||||
|
||||
else
|
||||
|
||||
do_log "info" "file_only" "4520() Command: [chroot_script ${TARGET} EDITOR=/usr/bin/nano /usr/sbin/visudo -q -c] successful."
|
||||
do_log "info" "file_only" "4520() Command: [chroot_script ${var_target} EDITOR=/usr/bin/nano /usr/sbin/visudo -q -c] successful."
|
||||
|
||||
fi
|
||||
|
||||
@@ -813,14 +820,14 @@ EOF
|
||||
EOF
|
||||
|
||||
### Verify logrotate config in chroot.
|
||||
if ! chroot_script "${TARGET}" "logrotate -d /etc/logrotate.conf >> ${var_logfile}"; then
|
||||
if ! chroot_script "${var_target}" "logrotate -d /etc/logrotate.conf >> ${var_logfile}"; then
|
||||
|
||||
do_log "warn" "file_only" "4520() Command: [chroot_script ${TARGET} logrotate -d /etc/logrotate.conf] failed."
|
||||
do_log "warn" "file_only" "4520() Command: [chroot_script ${var_target} logrotate -d /etc/logrotate.conf] failed."
|
||||
return "${ERR_VERIFY_LOGROTATE}"
|
||||
|
||||
else
|
||||
|
||||
do_log "info" "file_only" "4520() Command: [chroot_script ${TARGET} logrotate -d /etc/logrotate.conf] successful."
|
||||
do_log "info" "file_only" "4520() Command: [chroot_script ${var_target} logrotate -d /etc/logrotate.conf] successful."
|
||||
|
||||
fi
|
||||
|
||||
@@ -848,12 +855,12 @@ pam_access_sync_login_sshd() {
|
||||
declare var_file_sshd="/etc/pam.d/sshd"
|
||||
|
||||
### Guard: The file must exist, no-op otherwise.
|
||||
if [[ ! -f "${TARGET}${var_file_login}" ]]; then
|
||||
if [[ ! -f "${var_target}${var_file_login}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
### 1) If the 'pam_access' line is commented in '/etc/pam.d/login', uncomment exactly one occurrence.
|
||||
chroot_stdin "${TARGET}" "__payload__" <<'EOF'
|
||||
chroot_stdin "${var_target}" "__payload__" <<'EOF'
|
||||
tmp="$(mktemp /etc/pam.d/login.XXXXXX)"
|
||||
export LC_ALL=C
|
||||
awk '
|
||||
@@ -877,9 +884,9 @@ EOF
|
||||
|
||||
### 2) If '/etc/pam.d/login' now has an active pam_access line, ensure '/etc/pam.d/sshd' pam_access line(s) are commented out.
|
||||
### No-op if '/etc/pam.d/sshd' is absent.
|
||||
[[ -f "${TARGET}${var_file_sshd}" ]] || return 0
|
||||
[[ -f "${var_target}${var_file_sshd}" ]] || return 0
|
||||
|
||||
chroot_stdin "${TARGET}" "__payload__" <<'EOF'
|
||||
chroot_stdin "${var_target}" "__payload__" <<'EOF'
|
||||
export LC_ALL=C
|
||||
if grep -Eq '^[[:space:]]*account[[:space:]]+required[[:space:]]+pam_access[.]so([[:space:]]|$)' /etc/pam.d/login; then
|
||||
tmp="$(mktemp /etc/pam.d/sshd.XXXXXX)"
|
||||
@@ -903,25 +910,25 @@ readonly -f pam_access_sync_login_sshd
|
||||
#######################################
|
||||
# Enable per-user TOTP in a given PAM service (login, sshd, su, sudo).
|
||||
# Globals:
|
||||
# TARGET
|
||||
# None
|
||||
# Arguments:
|
||||
# 1: <username>
|
||||
# 2: <pam_module>
|
||||
# 1: username
|
||||
# 2: pam_module
|
||||
# 3: target
|
||||
# Returns:
|
||||
# 0: on success
|
||||
#######################################
|
||||
pam_access_totp_enable() {
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare var_user="$1"
|
||||
declare var_module="$2"
|
||||
declare var_pam_file="/etc/pam.d/${var_module}"
|
||||
declare var_users_file="${TARGET}/etc/ciss/2fa.users"
|
||||
declare var_allowlist="/etc/ciss/2fa.users"
|
||||
declare -r var_user="${1}" var_module="${2}" var_target="${3}"
|
||||
declare -r var_pam_file="/etc/pam.d/${var_module}"
|
||||
declare -r var_users_file="${var_target}/etc/ciss/2fa.users"
|
||||
declare -r var_allowlist="/etc/ciss/2fa.users"
|
||||
|
||||
### Basic sanitation; module must be a safe 'pam.d' filename.
|
||||
[[ -n "${var_user:-}" && -n "${var_module:-}" ]] || return 0
|
||||
[[ "${var_module}" =~ ^[A-Za-z0-9._+-]+$ ]] || return 0
|
||||
[[ -f "${TARGET}${var_pam_file}" ]] || return 0
|
||||
[[ -f "${var_target}${var_pam_file}" ]] || return 0
|
||||
|
||||
### 0) Ensure the allowlist file contains the user (deduplicated).
|
||||
if ! grep -Fxq "${var_user}" "${var_users_file}"; then
|
||||
@@ -931,7 +938,7 @@ pam_access_totp_enable() {
|
||||
### 1) Ensure a single CISS TOTP framework block is present in the PAM file.
|
||||
### The block gates GA by pam_listfile over '/etc/ciss/2fa.users'.
|
||||
### We place it right after pam_unix.so or @include common-auth; fallback: append.
|
||||
chroot_stdin "${TARGET}" "__payload__" -- "${var_pam_file}" "${var_allowlist}" <<'EOF'
|
||||
chroot_stdin "${var_target}" "__payload__" -- "${var_pam_file}" "${var_allowlist}" <<'EOF'
|
||||
export LC_ALL=C
|
||||
pam="$1"
|
||||
allowlist="$2"
|
||||
@@ -969,7 +976,7 @@ rm -f -- "${tmp}" || :
|
||||
EOF
|
||||
|
||||
### 2) Comment out any other active GA lines to avoid double prompts.
|
||||
chroot_stdin "${TARGET}" "__payload__" -- "${var_pam_file}" <<'EOF'
|
||||
chroot_stdin "${var_target}" "__payload__" -- "${var_pam_file}" <<'EOF'
|
||||
export LC_ALL=C
|
||||
pam="$1"
|
||||
tmp="$(mktemp "${pam}.XXXXXX")"
|
||||
@@ -1037,20 +1044,22 @@ readonly -f read_totp_seed
|
||||
# Writes '.google_authenticator'-file for the respective user.
|
||||
# Globals:
|
||||
# DIR_TMP
|
||||
# TARGET
|
||||
# Arguments:
|
||||
# 1: Username
|
||||
# 1: USERNAME
|
||||
# 2: UID
|
||||
# 3: GID
|
||||
# 4: TARGET
|
||||
# Returns:
|
||||
# 0: on success
|
||||
#######################################
|
||||
write_google_authenticator_file() {
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare var_user="${1}" var_user_id="${2}" var_group_id="${3}" var_secret=""
|
||||
declare -r var_user="${1}" var_user_id="${2}" var_group_id="${3}" var_target="${4}"
|
||||
declare var_secret=""
|
||||
|
||||
case "${1}" in
|
||||
root) declare var_base="${TARGET}/root" ;;
|
||||
*) declare var_base="${TARGET}/home/${var_user}" ;;
|
||||
root) declare var_base="${var_target}/root" ;;
|
||||
*) declare var_base="${var_target}/home/${var_user}" ;;
|
||||
esac
|
||||
declare -i i=0
|
||||
|
||||
@@ -1102,19 +1111,20 @@ readonly -f write_google_authenticator_file
|
||||
#######################################
|
||||
# Use the official ohmyzsh-installer but force non-interactive behavior; do not run zsh; do not chsh.
|
||||
# Globals:
|
||||
# TARGET
|
||||
# None
|
||||
# Arguments:
|
||||
# 1: Username
|
||||
# 2: Target
|
||||
# Returns:
|
||||
# 0: on success
|
||||
#######################################
|
||||
zsh_omz_installer() {
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare var_user="${1}"
|
||||
declare -r var_user="${1}" var_target="${2}"
|
||||
|
||||
### Install Oh My Zsh and two plugins for a given user (non-interactive, idempotent).
|
||||
### Args to payload: $1 = username (e.g., "root" or "alice")
|
||||
chroot_stdin "${TARGET}" "__payload__" -- "${var_user}" <<'EOF'
|
||||
chroot_stdin "${var_target}" "__payload__" -- "${var_user}" <<'EOF'
|
||||
export LC_ALL=C
|
||||
user="$1"
|
||||
|
||||
@@ -1225,4 +1235,105 @@ EOF
|
||||
### Prevents accidental 'unset -f'.
|
||||
# shellcheck disable=SC2034
|
||||
readonly -f zsh_omz_installer
|
||||
|
||||
|
||||
|
||||
#######################################
|
||||
# description
|
||||
# Globals:
|
||||
# TARGET
|
||||
# Arguments:
|
||||
# None
|
||||
#######################################
|
||||
write_pam_sshd() {
|
||||
### Declare Arrays, HashMaps, and Variables.
|
||||
declare -r var_target="$1"
|
||||
|
||||
mv "${var_target}/etc/pam.d/sshd" "${var_target}/root/.ciss/cdi/backup/etc/pam.d/sshd"
|
||||
|
||||
insert_header "${var_target}/etc/pam.d/sshd"
|
||||
insert_comments "${var_target}/etc/pam.d/sshd"
|
||||
cat << EOF >> "${var_target}/etc/pam.d/sshd"
|
||||
# ===== CISS 2FA block (MUST be placed at the very top of /etc/pam.d/sshd) =====
|
||||
# If user is NOT listed -> succeed and SKIP next two lines (silent Keyboard-Interactive (KI) success).
|
||||
auth [success=2 default=ignore] pam_listfile.so item=user sense=deny file=/etc/ciss/2fa onerr=ignore
|
||||
|
||||
# For listed users: enforce that the secret file exists, else deny without prompting.
|
||||
# pam_google_authenticator will itself fail if the file is absent; we add a clear hint before it.
|
||||
auth required pam_echo.so file=/etc/ciss/ssh_totp.prompt
|
||||
auth required pam_google_authenticator.so
|
||||
# No 'nullok' here: listed users MUST have a secret; missing -> hard fail.
|
||||
|
||||
# For non-2FA users KI must be a silent success to satisfy AuthenticationMethods.
|
||||
auth sufficient pam_permit.so
|
||||
# ===== CISS 2FA block end =====
|
||||
|
||||
# Keep the rest as shipped by Debian; it will be short-circuited by pam_permit for KI
|
||||
# and never reached for 2FA users after successful GA.
|
||||
|
||||
# PAM configuration for the Secure Shell service
|
||||
|
||||
# Standard Un*x authentication.
|
||||
@include common-auth
|
||||
|
||||
# Disallow non-root logins when /etc/nologin exists.
|
||||
account required pam_nologin.so
|
||||
|
||||
# Uncomment and edit /etc/security/access.conf if you need to set complex
|
||||
# access limits that are hard to express in sshd_config.
|
||||
# account required pam_access.so
|
||||
|
||||
# Standard Un*x authorization.
|
||||
@include common-account
|
||||
|
||||
# SELinux needs to be the first session rule. This ensures that any
|
||||
# lingering context has been cleared. Without this it is possible that a
|
||||
# module could execute code in the wrong domain.
|
||||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
|
||||
|
||||
# Set the loginuid process attribute.
|
||||
session required pam_loginuid.so
|
||||
|
||||
# Create a new session keyring.
|
||||
session optional pam_keyinit.so force revoke
|
||||
|
||||
# Standard Un*x session setup and teardown.
|
||||
@include common-session
|
||||
|
||||
# Print the message of the day upon successful login.
|
||||
# This includes a dynamically generated part from /run/motd.dynamic
|
||||
# and a static (admin-editable) part from /etc/motd.
|
||||
session optional pam_motd.so motd=/run/motd.dynamic
|
||||
session optional pam_motd.so noupdate
|
||||
|
||||
# Print the status of the user's mailbox upon successful login.
|
||||
session optional pam_mail.so standard noenv # [1]
|
||||
|
||||
# Set up user limits from /etc/security/limits.conf.
|
||||
session required pam_limits.so
|
||||
|
||||
# Read environment variables from /etc/environment and
|
||||
# /etc/security/pam_env.conf.
|
||||
session required pam_env.so # [1]
|
||||
# In Debian 4.0 (etch), locale-related environment variables were moved to
|
||||
# /etc/default/locale, so read that as well.
|
||||
session required pam_env.so envfile=/etc/default/locale
|
||||
|
||||
# SELinux needs to intervene at login time to ensure that the process starts
|
||||
# in the proper default security context. Only sessions which are intended
|
||||
# to run in the user's context should be run after this.
|
||||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
|
||||
|
||||
# Standard Un*x password updating.
|
||||
@include common-password
|
||||
|
||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf
|
||||
EOF
|
||||
|
||||
return 0
|
||||
|
||||
}
|
||||
### Prevents accidental 'unset -f'.
|
||||
# shellcheck disable=SC2034
|
||||
readonly -f write_pam_sshd
|
||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||
|
||||
Reference in New Issue
Block a user