V8.00.000.2025.06.17
All checks were successful
🛡️ Shell Script Linting / 🛡️ Shell Script Linting (push) Successful in 55s
All checks were successful
🛡️ Shell Script Linting / 🛡️ Shell Script Linting (push) Successful in 55s
Signed-off-by: Marc S. Weidner <msw@coresecret.dev>
This commit is contained in:
@@ -672,6 +672,12 @@ software:
|
|||||||
# ssh
|
# ssh
|
||||||
#
|
#
|
||||||
##############################################################################################################################
|
##############################################################################################################################
|
||||||
|
# Installed by 4500_accounts_preparation.sh
|
||||||
|
##############################################################################################################################
|
||||||
|
# bash-completion
|
||||||
|
# fzf
|
||||||
|
#
|
||||||
|
##############################################################################################################################
|
||||||
# Installed by 4510_accounts_hardening.sh
|
# Installed by 4510_accounts_hardening.sh
|
||||||
##############################################################################################################################
|
##############################################################################################################################
|
||||||
# libpam-google-authenticator
|
# libpam-google-authenticator
|
||||||
@@ -684,12 +690,10 @@ software:
|
|||||||
# core software
|
# core software
|
||||||
##############################################################################################################################
|
##############################################################################################################################
|
||||||
- apt-utils
|
- apt-utils
|
||||||
- bash-completion
|
|
||||||
- bat
|
- bat
|
||||||
- debconf
|
- debconf
|
||||||
- debconf-utils
|
- debconf-utils
|
||||||
- dialog
|
- dialog
|
||||||
- fzf
|
|
||||||
- git
|
- git
|
||||||
- knot-dnssecutils
|
- knot-dnssecutils
|
||||||
- knot-dnsutils
|
- knot-dnsutils
|
||||||
@@ -807,34 +811,32 @@ user:
|
|||||||
# root – Superuser account (normally disabled for direct login)
|
# root – Superuser account (normally disabled for direct login)
|
||||||
##############################################################################################################################
|
##############################################################################################################################
|
||||||
root:
|
root:
|
||||||
ensure: present # Must always be 'present'.
|
ensure: present # Must always be 'present'. (Not in use in this version of the installer.)
|
||||||
protected: true # Prevent unintentional edits or deletions.
|
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.
|
shell: /bin/zsh # Login shell (e.g., '/bin/bash', '/bin/zsh'); use '/usr/sbin/nologin' for non-interactive users.
|
||||||
password: "47110815"
|
password: "47110815"
|
||||||
sshpubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINAYZDAqVZUk3LwJsqeVHKvLn8UKkFx642VBbiSS8uSY 2025_ciss.debian.live.ISO_PUBLIC_ONLY"
|
sshpubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINAYZDAqVZUk3LwJsqeVHKvLn8UKkFx642VBbiSS8uSY 2025_ciss.debian.live.ISO_PUBLIC_ONLY"
|
||||||
authentication:
|
authentication:
|
||||||
access:
|
access:
|
||||||
ssh: false # Allow SSH access.
|
ssh: false # Allow SSH access.
|
||||||
tty: true # Allow TTY (local console) login.
|
tty: false # Allow TTY (local console) login.
|
||||||
password:
|
password: false # Allow password login. SSH password login is always disabled.
|
||||||
ssh: false # Allow SSH password login.
|
|
||||||
tty: true # Allow TTY (local console) password login.
|
|
||||||
2fa:
|
2fa:
|
||||||
ssh: false # Require 2FA for SSH access.
|
ssh: true # Require 2FA for SSH access.
|
||||||
tty: true # Require 2FA for TTY (local console) login.
|
tty: true # Require 2FA for TTY (local console) login.
|
||||||
privileges:
|
privileges:
|
||||||
description: "Root user with full system access and administrative privileges."
|
description: "Root user with full system access and administrative privileges."
|
||||||
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).
|
|
||||||
restricted: false # If true, the user is limited in scope (e.g., no login, no file access, --no-create-home)
|
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'.
|
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).
|
||||||
|
|
||||||
##############################################################################################################################
|
##############################################################################################################################
|
||||||
# Primary administrative user with full sudo access
|
# Primary administrative user with full sudo access
|
||||||
##############################################################################################################################
|
##############################################################################################################################
|
||||||
user0:
|
user0:
|
||||||
ensure: present # "present" = create user; "absent" = remove user
|
ensure: present # Must always be 'present'. (Not in use in this version of the installer.)
|
||||||
protected: true # Prevent unintentional edits or deletions.
|
protected: true # Prevent unintentional edits or deletions. (Not in use in this version of the installer.)
|
||||||
name: "msw" # The name of the user account.
|
name: "msw" # The name of the user account.
|
||||||
fullname: "msw" # The full name of the user account holder.
|
fullname: "msw" # The full name of the user account holder.
|
||||||
uid: 1000 # Ensures that the same user has the same UID on all systems.
|
uid: 1000 # Ensures that the same user has the same UID on all systems.
|
||||||
@@ -846,9 +848,7 @@ user:
|
|||||||
access:
|
access:
|
||||||
ssh: true # Allow SSH access.
|
ssh: true # Allow SSH access.
|
||||||
tty: true # Allow TTY (local console) login.
|
tty: true # Allow TTY (local console) login.
|
||||||
password:
|
password: false # Allow password login. SSH password login is always disabled.
|
||||||
ssh: false # Allow SSH password login.
|
|
||||||
tty: true # Allow TTY (local console) password login.
|
|
||||||
2fa:
|
2fa:
|
||||||
ssh: true # Require 2FA for SSH access.
|
ssh: true # Require 2FA for SSH access.
|
||||||
tty: true # Require 2FA for TTY (local console) login.
|
tty: true # Require 2FA for TTY (local console) login.
|
||||||
@@ -876,9 +876,7 @@ user:
|
|||||||
access:
|
access:
|
||||||
ssh: true # Allow SSH access.
|
ssh: true # Allow SSH access.
|
||||||
tty: false # Allow TTY (local console) login.
|
tty: false # Allow TTY (local console) login.
|
||||||
password:
|
password: false # Allow password login. SSH password login is always disabled.
|
||||||
ssh: false # Allow SSH password login.
|
|
||||||
tty: false # Allow TTY (local console) password login.
|
|
||||||
2fa:
|
2fa:
|
||||||
ssh: false # Require 2FA for SSH access.
|
ssh: false # Require 2FA for SSH access.
|
||||||
tty: false # Require 2FA for TTY (local console) login.
|
tty: false # Require 2FA for TTY (local console) login.
|
||||||
|
|||||||
@@ -128,8 +128,8 @@ EOF
|
|||||||
/tmp)
|
/tmp)
|
||||||
#write_crypttab "${var_ephemeral_enclabel}" "LABEL=${var_host_fs_label}" "/dev/random" "offset=2048,cipher=aes-xts-plain64,size=512,sector-size=4096,discard,tmp=ext4"
|
#write_crypttab "${var_ephemeral_enclabel}" "LABEL=${var_host_fs_label}" "/dev/random" "offset=2048,cipher=aes-xts-plain64,size=512,sector-size=4096,discard,tmp=ext4"
|
||||||
write_crypttab "${var_ephemeral_enclabel}" "PARTUUID=${var_host_partuuid}" "/dev/random" "offset=2048,cipher=aes-xts-plain64,size=512,sector-size=4096,discard,plain"
|
write_crypttab "${var_ephemeral_enclabel}" "PARTUUID=${var_host_partuuid}" "/dev/random" "offset=2048,cipher=aes-xts-plain64,size=512,sector-size=4096,discard,plain"
|
||||||
#chroot_script "${TARGET}" "systemctl mask tmp.mount"
|
chroot_script "${TARGET}" "systemctl mask tmp.mount"
|
||||||
#do_log "info" "file_only" "4210() Masked: [tmp.mount]"
|
do_log "info" "file_only" "4210() Masked: [tmp.mount]"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ guard_sourcing
|
|||||||
# Setup ssh server.
|
# Setup ssh server.
|
||||||
# Globals:
|
# Globals:
|
||||||
# TARGET
|
# TARGET
|
||||||
|
# VAR_DROPBEAR
|
||||||
# VAR_FINAL_FQDN
|
# VAR_FINAL_FQDN
|
||||||
# VAR_FINAL_IPV4
|
# VAR_FINAL_IPV4
|
||||||
# VAR_FINAL_IPV6
|
# VAR_FINAL_IPV6
|
||||||
# VAR_SETUP_PATH
|
# VAR_SETUP_PATH
|
||||||
# VAR_USER_MAX
|
|
||||||
# VAR_DROPBEAR
|
|
||||||
# VAR_SSH_PORT
|
|
||||||
# VAR_SSH_CA
|
# VAR_SSH_CA
|
||||||
|
# VAR_SSH_PORT
|
||||||
|
# VAR_USER_MAX
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# None
|
# None
|
||||||
# Returns:
|
# Returns:
|
||||||
|
|||||||
34
func/cdi_4400_hardening/4480_hardening_usb.sh
Normal file
34
func/cdi_4400_hardening/4480_hardening_usb.sh
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SPDX-Version: 3.0
|
||||||
|
# SPDX-CreationInfo: 2025-06-17; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.installer.git
|
||||||
|
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||||
|
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-FileType: SOURCE
|
||||||
|
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
|
||||||
|
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
|
||||||
|
# SPDX-PackageName: CISS.debian.installer
|
||||||
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
|
guard_sourcing
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Hardening 'usb-guard'.
|
||||||
|
# Globals:
|
||||||
|
# TARGET
|
||||||
|
# VAR_SSH_PORT
|
||||||
|
# VAR_UFW_OUT
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
#######################################
|
||||||
|
hardening_usb() {
|
||||||
|
### Declare Arrays, HashMaps, and Variables.
|
||||||
|
declare -r var_logfile="/root/.ciss/cdi/log/4480_hardening_usb.log"
|
||||||
|
|
||||||
|
chroot_logger "${TARGET}${var_logfile}"
|
||||||
|
|
||||||
|
guard_dir && return 0
|
||||||
|
}
|
||||||
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||||
@@ -23,6 +23,17 @@ guard_sourcing
|
|||||||
# 0: on success
|
# 0: on success
|
||||||
#######################################
|
#######################################
|
||||||
accounts_preparation() {
|
accounts_preparation() {
|
||||||
|
### Declare Arrays, HashMaps, and Variables.
|
||||||
|
declare -r var_logfile="/root/.ciss/cdi/log/4130_installation_toolset.log"
|
||||||
|
|
||||||
|
chroot_logger "${TARGET}${var_logfile}"
|
||||||
|
|
||||||
|
chroot_script "${TARGET}" "
|
||||||
|
export INITRD=No
|
||||||
|
apt-get install -y --no-install-recommends --no-install-suggests bash-completion fzf 2>&1 | tee -a ${var_logfile}
|
||||||
|
echo ExitCode: \$? >> ${var_logfile}
|
||||||
|
"
|
||||||
|
|
||||||
mkdir -p "${TARGET}/etc/skel/.ciss"
|
mkdir -p "${TARGET}/etc/skel/.ciss"
|
||||||
|
|
||||||
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.bashrc" "${TARGET}/etc/skel/.bashrc"
|
install -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.bashrc" "${TARGET}/etc/skel/.bashrc"
|
||||||
|
|||||||
@@ -38,15 +38,28 @@ accounts_hardening() {
|
|||||||
echo ExitCode: \$? >> ${var_logfile}
|
echo ExitCode: \$? >> ${var_logfile}
|
||||||
"
|
"
|
||||||
|
|
||||||
### Keep 'tty1' active, disable the rest (VTs).
|
### Preparing 2fa hardening.
|
||||||
|
install -d -m 0755 -o root -g root "${TARGET}/etc/ciss"
|
||||||
|
touch "${TARGET}/etc/ciss/2fa.users"
|
||||||
|
chmod 0640 "${TARGET}/etc/ciss/2fa.users"
|
||||||
|
|
||||||
|
### Keep 'tty1' active, disable the rest.
|
||||||
chroot_script "${TARGET}" "
|
chroot_script "${TARGET}" "
|
||||||
systemctl unmask getty@tty1.service
|
systemctl unmask getty@tty1.service
|
||||||
systemctl enable getty@tty1.service
|
systemctl enable getty@tty1.service
|
||||||
for t in tty2 tty3 tty4 tty5 tty6; do
|
for t in tty2 tty3 tty4 tty5 tty6; do
|
||||||
systemctl mask getty@${t}.service
|
systemctl mask getty@${t}.service
|
||||||
done
|
done
|
||||||
|
systemctl mask serial-getty@.service
|
||||||
"
|
"
|
||||||
|
|
||||||
|
### Hardening file permissions.
|
||||||
|
chown root:root "${TARGET}/etc/passwd" "${TARGET}/etc/group"
|
||||||
|
chown root:shadow "${TARGET}/etc/shadow" "${TARGET}/etc/gshadow"
|
||||||
|
chmod 0644 "${TARGET}/etc/passwd" "${TARGET}/etc/group"
|
||||||
|
chmod 0640 "${TARGET}/etc/shadow" "${TARGET}/etc/gshadow"
|
||||||
|
chmod 0600 "${TARGET}/etc/securetty" "${TARGET}/etc/security/access.conf"
|
||||||
|
|
||||||
### Hardening '/etc/login.defs'.
|
### Hardening '/etc/login.defs'.
|
||||||
mv "${TARGET}/etc/login.defs" "${TARGET}/root/.ciss/cdi/backup/etc/login.defs.bak"
|
mv "${TARGET}/etc/login.defs" "${TARGET}/root/.ciss/cdi/backup/etc/login.defs.bak"
|
||||||
insert_header "${TARGET}/etc/login.defs"
|
insert_header "${TARGET}/etc/login.defs"
|
||||||
@@ -60,6 +73,12 @@ accounts_hardening() {
|
|||||||
insert_comments "${TARGET}/etc/security/pwquality.conf"
|
insert_comments "${TARGET}/etc/security/pwquality.conf"
|
||||||
cat "${VAR_SETUP_PATH}/includes/target/etc/security/pwquality.cnf" >> "${TARGET}/etc/security/pwquality.conf"
|
cat "${VAR_SETUP_PATH}/includes/target/etc/security/pwquality.cnf" >> "${TARGET}/etc/security/pwquality.conf"
|
||||||
|
|
||||||
|
### Hardening '/etc/security/access.conf'.
|
||||||
|
mv "${TARGET}/etc/security/access.conf" "${TARGET}/root/.ciss/cdi/backup/etc/security/access.conf.bak"
|
||||||
|
insert_header "${TARGET}/etc/security/access.conf"
|
||||||
|
insert_comments "${TARGET}/etc/security/access.conf"
|
||||||
|
cat "${VAR_SETUP_PATH}/includes/target/etc/security/access.cnf" >> "${TARGET}/etc/security/access.conf"
|
||||||
|
|
||||||
### Hardening password expiration; defaults to 16,384 days.
|
### Hardening password expiration; defaults to 16,384 days.
|
||||||
install -m 0700 -o root -g root "${VAR_SETUP_PATH}/includes/chroot/hooks/4510_password_expiration.hooks.sh" \
|
install -m 0700 -o root -g root "${VAR_SETUP_PATH}/includes/chroot/hooks/4510_password_expiration.hooks.sh" \
|
||||||
"${TARGET}/root/.ciss/cdi/hooks/4510_password_expiration.hooks.sh"
|
"${TARGET}/root/.ciss/cdi/hooks/4510_password_expiration.hooks.sh"
|
||||||
|
|||||||
@@ -29,57 +29,144 @@ guard_sourcing
|
|||||||
#######################################
|
#######################################
|
||||||
accounts_setup() {
|
accounts_setup() {
|
||||||
### Declare Arrays, HashMaps, and Variables.
|
### Declare Arrays, HashMaps, and Variables.
|
||||||
|
declare -r var_logfile="/root/.ciss/cdi/log/4520_accounts_setup.log"
|
||||||
declare -i i=0
|
declare -i i=0
|
||||||
declare tmp_username="" tmp_fullname="" tmp_uid="" tmp_gid="" tmp_shell="" tmp_password="" tmp_sshpubkey="" tmp_sudo="" \
|
declare tmp_username="" tmp_fullname="" tmp_uid="" tmp_gid="" tmp_shell="" tmp_password="" tmp_sshpubkey="" \
|
||||||
tmp_restricted=""
|
tmp_access_ssh="" 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_sudo="" \
|
declare var_username="" var_fullname="" var_uid="" var_gid="" var_shell="" var_password="" var_sshpubkey="" \
|
||||||
var_restricted="" var_chpasswd="" var_sshdir=""
|
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"
|
||||||
|
|
||||||
|
chroot_logger "${TARGET}${var_logfile}"
|
||||||
|
|
||||||
|
### Prepare the '2fa'-seed variable.
|
||||||
|
read_totp_seed
|
||||||
|
do_log "debug" "file_only" "4520() Command: [read_totp_seed]"
|
||||||
|
|
||||||
### Preparing the root account
|
### 0) The 'root' account is generated via debootstrap by default.
|
||||||
chown root:root "${TARGET}/etc/passwd" "${TARGET}/etc/shadow" "${TARGET}/etc/group" "${TARGET}/etc/gshadow"
|
|
||||||
chmod 0644 "${TARGET}/etc/passwd" "${TARGET}/etc/group"
|
|
||||||
chmod 0600 "${TARGET}/etc/shadow" "${TARGET}/etc/gshadow"
|
|
||||||
|
|
||||||
if [[ -x "${TARGET}${user_root_shell}" ]]; then
|
|
||||||
chroot_exec "${TARGET}" chsh -s "${user_root_shell}" root
|
|
||||||
else
|
|
||||||
chroot_exec "${TARGET}" chsh -s /bin/bash root
|
|
||||||
do_log "warn" "file_only" "4500() Shell: '${user_root_shell}' not found for: 'root'. Using '/bin/bash' instead."
|
|
||||||
fi
|
|
||||||
|
|
||||||
var_chpasswd="root:${user_root_password}"
|
|
||||||
chroot_script "${TARGET}" "echo \"${var_chpasswd}\" | chpasswd -e"
|
|
||||||
var_chpasswd=""
|
|
||||||
|
|
||||||
|
### 1) Prepare the 'root' account.
|
||||||
install -d -m 0700 -o root -g root "${TARGET}/root/.ssh"
|
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 /dev/null "${TARGET}/root/.ssh/authorized_keys"
|
||||||
|
|
||||||
grep -qxF "${user_root_sshpubkey}" "${TARGET}/root/.ssh/authorized_keys" || \
|
|
||||||
printf "%s\n" "${user_root_sshpubkey}" >> "${TARGET}/root/.ssh/authorized_keys"
|
|
||||||
|
|
||||||
if [[ "${user_root_authentication_access_ssh}" == "false" ]]; then
|
|
||||||
if grep -q '^\s*PermitRootLogin' "${TARGET}/etc/ssh/sshd_config"; then
|
|
||||||
sed -i 's/^\s*PermitRootLogin\s\+.*/PermitRootLogin no/' "${TARGET}/etc/ssh/sshd_config"
|
|
||||||
else
|
|
||||||
echo 'PermitRootLogin no' >> "${TARGET}/etc/ssh/sshd_config"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
install -D -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.bashrc" "${TARGET}/root/"
|
install -D -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.bashrc" "${TARGET}/root/"
|
||||||
|
|
||||||
|
if [[ "${user_root_shell}" == "/bin/zsh" ]]; then
|
||||||
|
|
||||||
|
if [[ -x "${TARGET}${user_root_shell}" ]]; then
|
||||||
|
|
||||||
|
chroot_exec "${TARGET}" chsh -s "${user_root_shell}" root
|
||||||
install -D -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.zshrc" "${TARGET}/root/"
|
install -D -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/etc/skel/.zshrc" "${TARGET}/root/"
|
||||||
|
do_log "info" "file_only" "4520() Shell: '${user_root_shell}' used for: 'root'."
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
chroot_exec "${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 -D -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/alias" "${TARGET}/root/.ciss/"
|
install -D -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/alias" "${TARGET}/root/.ciss/"
|
||||||
install -D -m 0700 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/clean_logout.sh" "${TARGET}/root/.ciss/"
|
install -D -m 0700 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/clean_logout.sh" "${TARGET}/root/.ciss/"
|
||||||
install -D -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/shortcuts" "${TARGET}/root/.ciss/"
|
install -D -m 0600 -o root -g root "${VAR_SETUP_PATH}/includes/target/root/.ciss/shortcuts" "${TARGET}/root/.ciss/"
|
||||||
# To be able to copy/paste from vim, one needs to create a '.vimrc' with the following content:
|
|
||||||
|
### 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"
|
echo 'set clipboard=unnamed' >| "${TARGET}/root/.vimrc"
|
||||||
chmod 0600 "${TARGET}/root/.vimrc"
|
chmod 0600 "${TARGET}/root/.vimrc"
|
||||||
|
|
||||||
|
do_log "info" "file_only" "4520() Skeleton: 'root' successfully generated."
|
||||||
|
|
||||||
|
### 2) Check SSH access capabilities.
|
||||||
|
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"
|
||||||
|
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"
|
||||||
|
do_log "info" "file_only" "4520() User: 'root' SSH access: [PermitRootLogin prohibit-password]"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
pam_access_sync_login_sshd
|
||||||
|
|
||||||
|
### 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 '
|
||||||
|
BEGIN{ins=0}
|
||||||
|
{
|
||||||
|
if(!ins && $0 ~ /^\s*auth\s+.*pam_unix\.so/){
|
||||||
|
print "auth requisite pam_securetty.so"
|
||||||
|
ins=1
|
||||||
|
}
|
||||||
|
print
|
||||||
|
}
|
||||||
|
END{ if(!ins) print "auth requisite pam_securetty.so" }
|
||||||
|
' "${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'.
|
||||||
|
printf "-: root:ALL \n" >> "${TARGET}/etc/security/access.conf"
|
||||||
|
|
||||||
|
### 4) Empty "/etc/securetty".
|
||||||
|
cat << 'EOF' >| "${TARGET}/etc/securetty"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
do_log "info" "file_only" "4520() User: 'root' tty access: [false]"
|
||||||
|
;;
|
||||||
|
|
||||||
|
true)
|
||||||
|
### 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'.
|
||||||
|
cat << 'EOF' >| "${TARGET}/etc/securetty"
|
||||||
|
tty1
|
||||||
|
EOF
|
||||||
|
do_log "info" "file_only" "4520() User: 'root' tty access: [true]"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
### Check the password policy for the 'root' account.
|
||||||
|
case "${user_root_authentication_password}" in
|
||||||
|
false)
|
||||||
|
chroot_script "${TARGET}" "passwd -l root"
|
||||||
|
do_log "info" "file_only" "4520() User: 'root' password access: [false]"
|
||||||
|
;;
|
||||||
|
true)
|
||||||
|
var_chpasswd="root:${user_root_password}"
|
||||||
|
chroot_script "${TARGET}" "echo \"${var_chpasswd}\" | chpasswd -e"
|
||||||
|
var_chpasswd=""
|
||||||
|
do_log "info" "file_only" "4520() User: 'root' password access: [true]"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
[[ "${user_root_authentication_2fa_ssh}" == "true" || "${user_root_authentication_2fa_tty}" == "true" ]] && \
|
||||||
|
write_google_authenticator_file "root"
|
||||||
|
|
||||||
|
[[ "${user_root_authentication_2fa_ssh}" == "true" ]] && pam_access_totp_enable "root" "sshd"
|
||||||
|
|
||||||
|
[[ "${user_root_authentication_2fa_tty}" == "true" ]] && pam_access_totp_enable "root" "login"
|
||||||
|
|
||||||
|
|
||||||
do_log "info" "file_only" "User: 'root' updated."
|
do_log "info" "file_only" "User: 'root' updated."
|
||||||
|
|
||||||
### Install all user accounts.
|
|
||||||
|
### Iterate through all remaining 'user' accounts and install them.
|
||||||
for ((i = 0; i <= VAR_USER_MAX; i++)); do
|
for ((i = 0; i <= VAR_USER_MAX; i++)); do
|
||||||
|
### Prepare all user-variables.
|
||||||
tmp_username="user_user${i}_name"
|
tmp_username="user_user${i}_name"
|
||||||
tmp_fullname="user_user${i}_fullname"
|
tmp_fullname="user_user${i}_fullname"
|
||||||
tmp_uid="user_user${i}_uid"
|
tmp_uid="user_user${i}_uid"
|
||||||
@@ -87,6 +174,11 @@ accounts_setup() {
|
|||||||
tmp_shell="user_user${i}_shell"
|
tmp_shell="user_user${i}_shell"
|
||||||
tmp_password="user_user${i}_password"
|
tmp_password="user_user${i}_password"
|
||||||
tmp_sshpubkey="user_user${i}_sshpubkey"
|
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_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"
|
||||||
tmp_sudo="user_user${i}_privileges_sudo"
|
tmp_sudo="user_user${i}_privileges_sudo"
|
||||||
tmp_restricted="user_user${i}_privileges_restricted"
|
tmp_restricted="user_user${i}_privileges_restricted"
|
||||||
|
|
||||||
@@ -97,12 +189,20 @@ accounts_setup() {
|
|||||||
var_shell="${!tmp_shell}"
|
var_shell="${!tmp_shell}"
|
||||||
var_password="${!tmp_password}"
|
var_password="${!tmp_password}"
|
||||||
var_sshpubkey="${!tmp_sshpubkey}"
|
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}"
|
||||||
|
var_2fa_tty"${!tmp_2fa_tty}"
|
||||||
var_sudo="${!tmp_sudo}"
|
var_sudo="${!tmp_sudo}"
|
||||||
var_restricted="${!tmp_restricted}"
|
var_restricted="${!tmp_restricted}"
|
||||||
|
|
||||||
|
### 0) A) Check if the 'group' of the 'user' already exists.
|
||||||
chroot_exec "${TARGET}" getent group "${var_username}" >/dev/null || \
|
chroot_exec "${TARGET}" getent group "${var_username}" >/dev/null || \
|
||||||
chroot_exec "${TARGET}" groupadd --gid "${var_gid}" "${var_username}"
|
chroot_exec "${TARGET}" groupadd --gid "${var_gid}" "${var_username}"
|
||||||
|
|
||||||
|
### 0) B) Generates the user account.
|
||||||
|
### If the 'user' is not restricted in scope, then generate the account accordingly, with a predefined expiry date.
|
||||||
if [[ "${var_restricted}" == "false" ]]; then
|
if [[ "${var_restricted}" == "false" ]]; then
|
||||||
|
|
||||||
chroot_exec "${TARGET}" useradd \
|
chroot_exec "${TARGET}" useradd \
|
||||||
@@ -122,7 +222,6 @@ accounts_setup() {
|
|||||||
--comment "${var_fullname}" \
|
--comment "${var_fullname}" \
|
||||||
--expiredate 2102-12-31 \
|
--expiredate 2102-12-31 \
|
||||||
--gid "${var_gid}" \
|
--gid "${var_gid}" \
|
||||||
--home-dir /home/"${var_username}" \
|
|
||||||
--inactive 0 \
|
--inactive 0 \
|
||||||
--no-create-home \
|
--no-create-home \
|
||||||
--shell "${var_shell}" \
|
--shell "${var_shell}" \
|
||||||
@@ -131,6 +230,43 @@ accounts_setup() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
### 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 -D -m 0600 -o "${var_uid}" -g "${var_gid}" "${VAR_SETUP_PATH}/includes/target/etc/skel/.bashrc" "${TARGET}/home/${var_username}/"
|
||||||
|
|
||||||
|
if [[ "${var_shell}" == "/bin/zsh" ]]; then
|
||||||
|
|
||||||
|
if [[ -x "${TARGET}${var_shell}" ]]; then
|
||||||
|
|
||||||
|
chroot_exec "${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}"
|
||||||
|
do_log "info" "file_only" "4520() Shell: '${var_shell}' not found for: '${var_username}'. Using '/bin/bash' instead."
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
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'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var_chpasswd="${var_username}:${var_password}"
|
var_chpasswd="${var_username}:${var_password}"
|
||||||
chroot_script "${TARGET}" "echo \"${var_chpasswd}\" | chpasswd -e"
|
chroot_script "${TARGET}" "echo \"${var_chpasswd}\" | chpasswd -e"
|
||||||
var_chpasswd=""
|
var_chpasswd=""
|
||||||
@@ -152,6 +288,8 @@ accounts_setup() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unset VAR_TEMP_PLAIN_MFA_SEED
|
unset VAR_TEMP_PLAIN_MFA_SEED
|
||||||
|
|
||||||
guard_dir && return 0
|
guard_dir && return 0
|
||||||
@@ -181,7 +319,6 @@ write_google_authenticator_file() {
|
|||||||
var_secret="$(generate_totp_secret "${var_user}")"
|
var_secret="$(generate_totp_secret "${var_user}")"
|
||||||
|
|
||||||
umask 0077
|
umask 0077
|
||||||
|
|
||||||
{
|
{
|
||||||
printf '%s\n' "${var_secret}"
|
printf '%s\n' "${var_secret}"
|
||||||
printf '"RATE_LIMIT 3 30"\n'
|
printf '"RATE_LIMIT 3 30"\n'
|
||||||
@@ -191,14 +328,19 @@ write_google_authenticator_file() {
|
|||||||
### Emergency Codes:
|
### Emergency Codes:
|
||||||
for i in {0..7}; do printf '%08d\n' "$(( RANDOM % 100000000 ))"; done
|
for i in {0..7}; do printf '%08d\n' "$(( RANDOM % 100000000 ))"; done
|
||||||
} >| "${var_base}/.google_authenticator"
|
} >| "${var_base}/.google_authenticator"
|
||||||
|
|
||||||
guard_trace off
|
|
||||||
|
|
||||||
chown "${var_user}:${var_user}" "${var_base}/.google_authenticator"
|
chown "${var_user}:${var_user}" "${var_base}/.google_authenticator"
|
||||||
|
|
||||||
chmod 0600 "${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
|
umask 0022
|
||||||
|
unset var_secret
|
||||||
|
|
||||||
|
guard_trace off
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -233,9 +375,12 @@ generate_totp_secret() {
|
|||||||
-kdfopt salt:"${var_salt}" -kdfopt info:"${var_info}" -binary HKDF | base32 | tr -d '=' | tr '[:lower:]' '[:upper:]'
|
-kdfopt salt:"${var_salt}" -kdfopt info:"${var_info}" -binary HKDF | base32 | tr -d '=' | tr '[:lower:]' '[:upper:]'
|
||||||
)"
|
)"
|
||||||
|
|
||||||
|
printf '%s\n' "${var_secret}"
|
||||||
|
|
||||||
|
unset var_secret
|
||||||
|
|
||||||
guard_trace off
|
guard_trace off
|
||||||
|
|
||||||
printf '%s\n' "${var_secret}"
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,4 +415,125 @@ read_totp_seed(){
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Ensure the 'pam_access' line is not activated in '/etc/pam.d/login' and '/etc/pam.d/sshd' in parallel.
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
#######################################
|
||||||
|
pam_access_sync_login_sshd() {
|
||||||
|
declare var_file_login="/etc/pam.d/login"
|
||||||
|
declare var_file_sshd="/etc/pam.d/sshd"
|
||||||
|
|
||||||
|
### Guard: files must exist, no-op otherwise.
|
||||||
|
if [[ ! -f "${var_file_login}" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "${var_file_sshd}" ]]; then
|
||||||
|
: ### Still continue, only '/etc/pam.d/login' will be processed
|
||||||
|
fi
|
||||||
|
|
||||||
|
### 1) If the 'pam_access' line is commented in '/etc/pam.d/login', uncomment exactly one occurrence.
|
||||||
|
### Match lines like: [spaces]# [spaces]account required pam_access.so ...
|
||||||
|
if grep -Eq '^[[:space:]]*#[[:space:]]*account[[:space:]]+required[[:space:]]+pam_access\.so([[:space:]]|$)' "${var_file_login}"; then
|
||||||
|
awk '
|
||||||
|
BEGIN { done=0 }
|
||||||
|
{
|
||||||
|
if (!done && $0 ~ /^[[:space:]]*#[[:space:]]*account[[:space:]]+required[[:space:]]+pam_access\.so([[:space:]]|$)/) {
|
||||||
|
sub(/^[[:space:]]*#[[:space:]]*/, "", $0); # drop leading # and following spaces
|
||||||
|
done=1;
|
||||||
|
}
|
||||||
|
print;
|
||||||
|
}
|
||||||
|
' "${var_file_login}" >| "${var_file_login}.new"
|
||||||
|
mv -f "${var_file_login}.new" "${var_file_login}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
if grep -Eq '^[[:space:]]*account[[:space:]]+required[[:space:]]+pam_access\.so([[:space:]]|$)' "${var_file_login}"; then
|
||||||
|
if [[ -f "${var_file_sshd}" ]]; then
|
||||||
|
awk '
|
||||||
|
### Comment only active matches; leave already-commented lines as-is.
|
||||||
|
/^[[:space:]]*account[[:space:]]+required[[:space:]]+pam_access\.so([[:space:]]|$)/ { print "# " $0; next }
|
||||||
|
{ print }
|
||||||
|
' "${var_file_sshd}" > "${var_file_sshd}.new"
|
||||||
|
mv -f "${var_file_sshd}.new" "${var_file_sshd}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Enable per-user TOTP in a given PAM service (login, sshd, su, sudo).
|
||||||
|
# Arguments:
|
||||||
|
# 1: <username>
|
||||||
|
# 2: <pam_module>
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
#######################################
|
||||||
|
pam_access_totp_enable() {
|
||||||
|
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"
|
||||||
|
|
||||||
|
### 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 "${var_pam_file}" ]] || return 0
|
||||||
|
|
||||||
|
### 0) Ensure the allowlist file contains the user (deduplicated).
|
||||||
|
if ! grep -Fxq "${var_user}" "${var_users_file}"; then
|
||||||
|
printf '%s\n' "${var_user}" >> "${var_users_file}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
### 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 and uses nullok.
|
||||||
|
### We place it right after pam_unix.so or @include common-auth; fallback: append.
|
||||||
|
if ! grep -q '^# CISS TOTP START$' "${var_pam_file}"; then
|
||||||
|
awk -v START='# CISS TOTP START' -v END='# CISS TOTP END' '
|
||||||
|
BEGIN{ins=0}
|
||||||
|
{
|
||||||
|
print
|
||||||
|
if (!ins && ($0 ~ /^[[:space:]]*auth[[:space:]]+.*pam_unix\.so/ || $0 ~ /^[[:space:]]*@include[[:space:]]+common-auth/)) {
|
||||||
|
print START
|
||||||
|
print "auth [success=1 default=ignore] pam_listfile.so item=user sense=allow file=/etc/ciss/2fa.users onerr=ignore"
|
||||||
|
print "auth required pam_google_authenticator.so nullok"
|
||||||
|
print END
|
||||||
|
ins=1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END{
|
||||||
|
if (!ins) {
|
||||||
|
print START
|
||||||
|
print "auth [success=1 default=ignore] pam_listfile.so item=user sense=allow file=/etc/ciss/2fa.users onerr=ignore"
|
||||||
|
print "auth required pam_google_authenticator.so nullok"
|
||||||
|
print END
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "${var_pam_file}" > "${var_pam_file}.new" && mv -f "${var_pam_file}.new" "${var_pam_file}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
### 2) Comment out any other active GA lines to avoid double prompts.
|
||||||
|
### We keep the CISS block intact (recognized by the START/END markers).
|
||||||
|
awk '
|
||||||
|
BEGIN{in_ciss=0}
|
||||||
|
/^# CISS TOTP START$/ { in_ciss=1; print; next }
|
||||||
|
/^# CISS TOTP END$/ { in_ciss=0; print; next }
|
||||||
|
{
|
||||||
|
if (!in_ciss && $0 ~ /^[[:space:]]*auth[[:space:]]+.*pam_google_authenticator\.so/ && $0 !~ /^[[:space:]]*#/) {
|
||||||
|
print "# " $0
|
||||||
|
} else {
|
||||||
|
print
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "${var_pam_file}" > "${var_pam_file}.new" && mv -f "${var_pam_file}.new" "${var_pam_file}"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||||
|
|||||||
Reference in New Issue
Block a user