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

Signed-off-by: Marc S. Weidner <msw@coresecret.dev>
This commit is contained in:
2025-10-05 13:12:31 +01:00
parent 0414737759
commit b7f1f0a4dd
12 changed files with 171 additions and 44 deletions

View File

@@ -833,13 +833,15 @@ user:
info: "totp:v1"
salt: "CISS:CDI:OTP" # + (Server_FQDN/Username)
##############################################################################################################################
# root Superuser account (normally disabled for direct login)
# Root: The superuser account (normally disabled for direct login).
# Key 'user.root.password' MUST contain a valid yescrypt hashed password string.
# Key 'user.root.sshpubkey' MUST be set in case dropbear is used.
##############################################################################################################################
root:
ensure: present # Must always be 'present'. (Not in use in this version of the installer.)
protected: true # Prevent unintentional edits or deletions. (Not in use in this version of the installer.)
shell: /bin/zsh # Login shell (e.g., '/bin/bash', '/bin/zsh'); use '/usr/sbin/nologin' for non-interactive users.
password: "47110815"
password: "$y$jFT$7pQlcZrgTEGrzkEm7UQW/.$QoCamalYEAV5mN4QWIE.xpHo8kvXa9sym2Uz.9oELwA"
sshpubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINAYZDAqVZUk3LwJsqeVHKvLn8UKkFx642VBbiSS8uSY 2025_ciss.debian.live.ISO_PUBLIC_ONLY"
authentication:
access:
@@ -855,6 +857,7 @@ user:
shell: true # MUST be "true" if the shell is not '/usr/sbin/nologin' or '/bin/false'.
sudo: false # Whether the user can escalate to root using sudo.
system: true # Whether this is a low-UID system user (e.g., for automation).
specific: "ciss"
##############################################################################################################################
# Primary administrative user with full sudo access
@@ -867,7 +870,7 @@ user:
uid: 1000 # Ensures that the same user has the same UID on all systems.
gid: 1000 # Ensures that the same user has the same GID on all systems.
shell: /bin/zsh # Login shell (e.g., '/bin/bash', '/bin/zsh'); use '/usr/sbin/nologin' for non-interactive users.
password: "47110815"
password: "$y$jFT$OGeZONH5ho2JSXvAbyIBQ1$5OhyHqOaMZ9BZcfMOYEwF.nMLFKd9ceiW2oNksPCHVB"
sshpubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINAYZDAqVZUk3LwJsqeVHKvLn8UKkFx642VBbiSS8uSY 2025_ciss.debian.live.ISO_PUBLIC_ONLY"
authentication:
access:
@@ -883,6 +886,7 @@ user:
system: false # Whether this is a low-UID system user (e.g., for automation).
restricted: false # If true, the user is limited in scope (e.g., no login, no file access, --no-create-home)
shell: true # MUST be "true" if the shell is not '/usr/sbin/nologin' or '/bin/false'.
specific: "ciss"
##############################################################################################################################
# ansible System user for automation, no interactive shell
@@ -911,5 +915,6 @@ user:
system: true # Whether this is a low-UID system user (e.g., for automation).
restricted: false # If true, the user is limited in scope (e.g., no login, no file access, --no-create-home)
shell: true # MUST be "true" if the shell is not '/usr/sbin/nologin' or '/bin/false'.
specific: "none"
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml

View File

@@ -81,6 +81,9 @@ chroot_exec() {
fi
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f chroot_exec
#######################################
# Run a complete shell script line inside the chroot using the command 'bash -c'.
@@ -158,6 +161,9 @@ chroot_script() {
fi
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f chroot_script
#######################################
# Run the installer-desired code incl. positional arguments via stdin (HEREDOC) inside the chroot with bash -s.
@@ -248,4 +254,7 @@ chroot_stdin() {
fi
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f chroot_stdin
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -94,4 +94,7 @@ yaml_parser() {
guard_dir && return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f yaml_parser
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -234,4 +234,7 @@ END { print max }
guard_dir && return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f yaml_reader
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -10,6 +10,8 @@
# SPDX-PackageName: CISS.debian.installer
# SPDX-Security-Contact: security@coresecret.eu
# TODO: LUKS Header Cloud Backup
guard_sourcing
#######################################

View File

@@ -140,6 +140,9 @@ EOF
guard_dir && return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f dropbear_setup
#######################################
# Write '/etc/dropbear/initramfs/dropbear.conf'.
@@ -195,6 +198,10 @@ DROPBEAR_OPTIONS="-b /etc/dropbear/banner -E -I 300 -K 60 -p ${dropbear_port}"
EOF
do_log "info" "file_only" "4312() Written: '${TARGET}/etc/dropbear/initramfs/dropbear.conf'."
do_log "info" "file_only" "4312() Written: 'DROPBEAR_OPTIONS=\"-b /etc/dropbear/banner -E -I 300 -K 60 -p ${dropbear_port}\"'."
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f write_dropbear_conf
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -37,9 +37,11 @@ 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_tty="" tmp_auth_pwd="" tmp_2fa_ssh="" tmp_2fa_tty="" tmp_sudo="" tmp_restricted="" tmp_system=""
tmp_access_tty="" tmp_auth_pwd="" tmp_2fa_ssh="" tmp_2fa_tty="" tmp_sudo="" tmp_restricted="" tmp_system="" \
tmp_specific=""
declare var_username="" var_fullname="" var_uid="" var_gid="" var_shell="" var_password="" var_sshpubkey="" \
var_access_tty="" var_auth_pwd="" var_2fa_ssh="" var_2fa_tty="" var_sudo="" var_restricted="" var_system=""
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"
chroot_logger "${TARGET}${var_logfile}"
@@ -60,13 +62,25 @@ accounts_setup() {
if [[ -x "${TARGET}${user_root_shell}" ]]; then
case "${user_root_specific,,}" in
"ciss")
zsh_omz_installer "root"
chroot_exec "${TARGET}" chsh -s "${user_root_shell}" 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/"
;;
"physnet")
:
;;
"none"|*)
:
;;
esac
chroot_exec "${TARGET}" chsh -s "${user_root_shell}" root
do_log "info" "file_only" "4520() Shell: '${user_root_shell}' used for: 'root'."
else
@@ -160,9 +174,8 @@ EOF
do_log "info" "file_only" "4520() User: 'root' password access: [false]"
;;
true)
chpasswd --root "${TARGET}" --crypt-method YESCRYPT <<EOF
root:${user_root_password}
EOF
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"
do_log "info" "file_only" "4520() User: 'root' password access: [true]"
;;
esac
@@ -224,6 +237,7 @@ EOF
tmp_sudo="user_user${i}_privileges_sudo"
tmp_system="user_user${i}_privileges_system"
tmp_restricted="user_user${i}_privileges_restricted"
tmp_specific="user_user${i}_privileges_restricted"
var_username="${!tmp_username}"
var_fullname="${!tmp_fullname}"
@@ -239,6 +253,7 @@ EOF
var_sudo="${!tmp_sudo}"
var_system="${!tmp_system}"
var_restricted="${!tmp_restricted}"
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
@@ -314,10 +329,23 @@ EOF
if [[ -x "${TARGET}${var_shell}" ]]; then
zsh_omz_installer "${var_username}"
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}"
;;
"physnet")
:
;;
"none"|*)
:
;;
esac
chroot_exec "${TARGET}" chsh -s "${var_shell}" "${var_username}"
do_log "info" "file_only" "4520() Shell: '${var_shell}' used for: '${var_username}'."
@@ -369,9 +397,8 @@ EOF
do_log "info" "file_only" "4520() User: '${var_username}' password access: [false]"
;;
true)
chpasswd --root "${TARGET}" --crypt-method YESCRYPT <<EOF
${var_username}:${var_password}
EOF
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}"
do_log "info" "file_only" "4520() User: '${var_username}' password access: [true]"
;;
esac
@@ -404,7 +431,7 @@ EOF
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}" "${var_specific:-none}"
### Enable per-user TOTP in a given PAM service (login, sshd, su, sudo).
pam_access_totp_enable "${var_username}" "sudo"
@@ -443,6 +470,9 @@ EOF
guard_dir && return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f accounts_setup
#######################################
# Install eza CISS theme for the respective user.
@@ -470,6 +500,9 @@ eza_installer() {
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f eza_installer
#######################################
# Generates a deterministic TOTP secret based on:
@@ -515,6 +548,9 @@ generate_totp_secret() {
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f generate_totp_secret
#######################################
# Hardening of '/bin/su': only members of the group 'sudo' can su to root.
@@ -565,6 +601,9 @@ EOF
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f hardening_su
#######################################
# Hardening sudo users (idempotent) and ensure WinSCP SFTP-as-root.
@@ -580,6 +619,7 @@ EOF
hardening_sudo() {
### Declare Arrays, HashMaps, and Variables.
declare var_user="$1"
declare var_specific="$2"
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"
@@ -607,13 +647,16 @@ Defaults log_host, log_year, log_input, log_exit_status, log_subcmds, logfile="/
EOF
fi
case "${var_specific,,}" in
"ciss")
### Install global WinSCP SFTP-as-root command alias (idempotent).
if [[ -x "${TARGET}${var_sftp_bin}" ]]; then
if [[ ! -f "${var_sudoers_winscp_global}" ]]; then
insert_header "${var_sudoers_winscp_global}"
insert_header "${var_sudoers_winscp_global}"
insert_comments "${var_sudoers_winscp_global}"
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).
@@ -649,12 +692,23 @@ EOF
else
insert_header "${var_sudoers_winscp_user}"
insert_header "${var_sudoers_winscp_user}"
insert_comments "${var_sudoers_winscp_user}"
echo "${var_user} ALL=(root) PASSWD: CISS_SFTPROOT" >> "${var_sudoers_winscp_user}"
printf "# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf \n" >> "${var_sudoers_winscp_user}"
fi
chmod 0440 "${var_sudoers_winscp_user}"
;;
"physnet")
:
;;
"none"|*)
:
;;
esac
### Tighten perms on sudoers.d (idempotent).
find "${var_sudoers_dir}" -type f -exec chmod 0440 {} \;
@@ -709,6 +763,9 @@ EOF
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f hardening_sudo
#######################################
# Ensure the 'pam_access' line is not activated in '/etc/pam.d/login' and '/etc/pam.d/sshd' in parallel.
@@ -774,6 +831,9 @@ EOF
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f pam_access_sync_login_sshd
#######################################
# Enable per-user TOTP in a given PAM service (login, sshd, su, sudo).
@@ -869,6 +929,9 @@ EOF
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f pam_access_totp_enable
#######################################
# Reads a 256-bit seed from '${DIR_CNF}/mfa_master.txt' (64 hex chars) into VAR_TEMP_PLAIN_MFA_SEED.
@@ -901,12 +964,14 @@ read_totp_seed(){
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f read_totp_seed
#######################################
# Writes '.google_authenticator'-file for the respective user.
# Globals:
# DIR_TMP
# RANDOM
# TARGET
# Arguments:
# 1: Username
@@ -965,6 +1030,9 @@ write_google_authenticator_file() {
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f write_google_authenticator_file
#######################################
# Use the official ohmyzsh-installer but force non-interactive behavior; do not run zsh; do not chsh.
@@ -1089,4 +1157,7 @@ EOF
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f zsh_omz_installer
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -39,4 +39,7 @@ guard_sourcing() {
declare -grx "${var_guard_var}"=1
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f guard_sourcing
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -25,4 +25,7 @@ source_guard() {
. "${var_file}"
fi
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f source_guard
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -25,4 +25,7 @@ safe_exec() {
do_log "error" "file_only" "0007() Command '${ary_cmd[*]}' failed."
return "${var_errcode}"
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f safe_exec
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -32,6 +32,9 @@ ensure_lowercase() {
ref="${ref,,}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f ensure_lowercase
#######################################
# Converts the value of a passed variable to uppercase.
@@ -53,6 +56,9 @@ ensure_uppercase() {
ref="${ref^^}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f ensure_uppercase
#######################################
# Removes leading and trailing spaces in the value.
@@ -75,6 +81,9 @@ ensure_trimmed() {
ref="${ref%"${ref##*[![:space:]]}"}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f ensure_trimmed
#######################################
# Resets the value of the variable to a default value if it is empty or contains only whitespace.
@@ -102,6 +111,9 @@ reset_to_default() {
fi
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f reset_to_default
#######################################
# Checks whether the content of a variable matches a specific regex.
@@ -129,4 +141,7 @@ assert_match() {
fi
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f assert_match
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -23,4 +23,7 @@ guard_dir() {
cd "${VAR_SETUP_PATH}"
do_log "info" "file_only" "${mod} Finished successfully."
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f guard_dir
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh