#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-05-05; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.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: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu

### Contributions so far see ./docs/CREDITS.md

### WHY BASH?
# Ease of installation. No compiling or installing gems, CPAN modules, pip packages, etc. Simple to use and read. Clear syntax
# and straightforward output interpretation. Built-in power. Pattern matching, line processing, and regular expression support
# are available natively, no external binaries required. Cross-platform consistency. '/bin/bash' is the default shell on most
# Linux distributions, ensuring scripts run unmodified across systems. macOS compatibility. Since macOS Catalina (10.15), the
# default login shell has been zsh, but bash remains available at '/bin/bash'. Windows support. You can use bash via WSL, MSYS2,
# or Cygwin on Windows systems.

### RESOURCES
# https://github.com/koalaman/shellcheck
# https://github.com/mvdan/sh
# https://google.github.io/styleguide/shellguide.html
# https://mywiki.wooledge.org/BashGuide
# https://styles.goatbytes.io/lang/shell/
# https://www.bashsupport.com/de/
# https://www.gnu.org/software/bash/manual/

### CATCH ARGUMENTS AND DECLARE BASIC VARIABLES.
# shellcheck disable=SC2155,SC2249
declare -agx  ARY_PARAM_ARRAY=("$@")                                     # Arguments passed to script as an array.
declare -girx VAR_START_TIME="${SECONDS}"                                # Start time of script execution.
declare -grx  VAR_PARAM_COUNT="$#"                                       # Arguments passed to script.
declare -grx  VAR_PARAM_STRNG="$*"                                       # Arguments passed to script as string.
declare -grx  VAR_SETUP_FILE="${0##*/}"                                  # 'ciss_debian_live_builder.sh'
declare -grx  VAR_SETUP_FULL="$(cd "$(dirname "${0}")" && pwd)/${0##*/}" # '/root/git/CISS.debian.live.builder/ciss_debian_live_builder.sh'
declare -grx  VAR_SETUP_PATH="$(cd "$(dirname "${0}")" && pwd)"          # '/root/git/CISS.debian.live.builder'
declare -grx  VAR_TMP_SECRET="/dev/shm/cdlb_secrets"                     # Fixed tmpfs path to store securely build artifacts.
declare -grx  VAR_WORKDIR="$(dirname "${VAR_SETUP_FULL}")"               # '/root/git/CISS.debian.live.builder'

### PRELIMINARY CHECKS.
### No ash, dash, ksh, sh.
# shellcheck disable=SC2292
[ -z "${BASH_VERSINFO[0]}" ] && {
  . ./var/global.var.sh
  printf "\e[91m❌ Please make sure you are using 'bash'! Bye... \e[0m\n" >&2
  exit "${ERR_UNSPPTBASH}"
}

### No zsh.
[[ -n "${ZSH_VERSION:-}" ]] && {
  . ./var/global.var.sh
  printf "\e[91m❌ Please make sure you are using 'bash'! Bye... \e[0m\n" >&2
  exit "${ERR_UNSPPTBASH}"
}

### Not root.
[[ ${EUID} -ne 0 ]] && {
  . ./var/global.var.sh
  printf "\e[91m❌ Please make sure you are 'root'! Bye... \e[0m\n" >&2
  exit "${ERR_NOT_USER_0}"
}

### Check to be not called by sh.
# shellcheck disable=SC2312
[[ $(kill -l | grep -c SIG) -eq 0 ]] && {
  . ./var/global.var.sh
  printf "\e[91m❌ Please make sure you are calling the script without leading 'sh'! Bye... \e[0m\n" >&2
  exit "${ERR_UNSPPTBASH}"
}

### Check to be not sourced.
[[ "${BASH_SOURCE[0]}" != "$0" ]] && {
  . ./var/global.var.sh
  printf "\e[91m❌ This script must be executed, not sourced. Please run '%s' directly! Bye... \e[0m\n" "$0" >&2
  exit "${ERR_UNSPPTBASH}"
}

### Minimum Bash version 5.
[[ ${BASH_VERSINFO[0]} -lt 5 ]] && {
  . ./var/global.var.sh
  printf "\e[91m❌ Minimum requirement is bash 5.1. You are using '%s'! Bye... \e[0m\n" "${BASH_VERSION}" >&2
  exit "${ERR_UNSPPTBASH}"
}

### Minimum Bash version 5.1.
[[ ${BASH_VERSINFO[0]} -le 5 ]] && [[ ${BASH_VERSINFO[1]} -le 1 ]] && {
  . ./var/global.var.sh
  printf "\e[91m❌ Minimum requirement is bash 5.1. You are using '%s'! Bye... \e[0m\n" "${BASH_VERSION}" >&2
  exit "${ERR_UNSPPTBASH}"
}

### No arguments.
[[ ${#} -eq 0 ]] && {
  . ./lib/lib_usage.sh
  usage
  exit 1
}

### SOURCING MUST SET EARLY VARIABLES, GUARD_SOURCING().
. ./var/early.var.sh
. ./lib/lib_guard_sourcing.sh
. ./lib/lib_source_guard.sh

### SECURING ENVIRONMENT.
source_guard "./var/bash.var.sh"

### CHECK FOR CONTACT, HELP, VERSION STRING, AND XTRACE DEBUG.
for arg in "$@"; do case "${arg,,}" in -c|--contact) . ./lib/lib_contact.sh   ; contact; exit 0;; esac; done
for arg in "$@"; do case "${arg,,}" in -h|--help)    . ./lib/lib_usage.sh     ; usage  ; exit 0;; esac; done
for arg in "$@"; do case "${arg,,}" in -v|--version) . ./lib/lib_version.sh   ; version; exit 0;; esac; done
for arg in "$@"; do case "${arg,,}" in -d|--debug)   . ./meta_sources_debug.sh; debugger "${@}";; esac; done

### ALL CHECKS DONE. READY TO START THE SCRIPT.
printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ 🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}"
declare -grx VAR_SETUP="true"

### SECURING SECRETS ARTIFACTS.
test ! -L "${VAR_TMP_SECRET}" || {
  . ./var/global.var.sh
  printf "\e[91m❌ Refusing symlink: '%s'! Bye... \e[0m\n" "${VAR_TMP_SECRET}" >&2
  exit "${ERR_SECRETSSYM}"
}
find "${VAR_TMP_SECRET}" -type f -exec chmod 0400 {} +
find "${VAR_TMP_SECRET}" -type f -exec chown root:root {} +

### SOURCING VARIABLES.
[[ "${VAR_SETUP}" == true ]] && {
  source_guard "./var/color.var.sh"
  source_guard "./var/global.var.sh"
}

### SOURCING LIBRARIES.
[[ "${VAR_SETUP}" == true ]] && {
  source_guard "./lib/lib_arg_parser.sh"
  source_guard "./lib/lib_arg_priority_check.sh"
  source_guard "./lib/lib_boot_screen.sh"
  source_guard "./lib/lib_cdi.sh"
  source_guard "./lib/lib_change_splash.sh"
  source_guard "./lib/lib_check_dhcp.sh"
  source_guard "./lib/lib_check_hooks.sh"
  source_guard "./lib/lib_check_kernel.sh"
  source_guard "./lib/lib_check_pkgs.sh"
  source_guard "./lib/lib_check_provider.sh"
  source_guard "./lib/lib_check_secrets.sh"
  source_guard "./lib/lib_check_stats.sh"
  source_guard "./lib/lib_check_var.sh"
  source_guard "./lib/lib_ciss_signatures.sh"
  source_guard "./lib/lib_ciss_upgrades_boot.sh"
  source_guard "./lib/lib_ciss_upgrades_build.sh"
  source_guard "./lib/lib_clean_screen.sh"
  source_guard "./lib/lib_clean_up.sh"
  source_guard "./lib/lib_copy_integrity.sh"
  source_guard "./lib/lib_gnupg.sh"
  source_guard "./lib/lib_hardening_root_pw.sh"
  source_guard "./lib/lib_hardening_ssh_tcp.sh"
  source_guard "./lib/lib_hardening_ultra.sh"
  source_guard "./lib/lib_helper_ip.sh"
  source_guard "./lib/lib_lb_build_start.sh"
  source_guard "./lib/lib_lb_config_start.sh"
  source_guard "./lib/lib_lb_config_write_trixie.sh"
  source_guard "./lib/lib_note_target.sh"
  source_guard "./lib/lib_primordial.sh"
  source_guard "./lib/lib_provider_netcup.sh"
  source_guard "./lib/lib_run_analysis.sh"
  source_guard "./lib/lib_sanitizer.sh"
  source_guard "./lib/lib_trap_on_err.sh"
  source_guard "./lib/lib_trap_on_exit.sh"
  source_guard "./lib/lib_update_microcode.sh"
  source_guard "./lib/lib_usage.sh"
}

### CHECKING REQUIRED PACKAGES.
check_pkgs

### ADVISORY LOCK.
exec 127>/var/lock/ciss_live_builder.lock || {
  printf "\e[91m❌ Cannot open lockfile for writing! Bye... \e[0m\n" >&2
  exit "${ERR_FLOCK_WRTG}"
}

if ! flock -x -n 127; then
  printf "\e[91m❌ Another instance is running! Bye...\e[0m\n" >&2
  exit "${ERR_FLOCK_COLL}"
fi

### CHECK FOR AUTOBUILD MODE.
for arg in "$@"; do case "${arg,,}" in -a=*|--autobuild=*) declare -gx VAR_HANDLER_AUTOBUILD="true"; declare -gx VAR_KERNEL="${arg#*=}";; esac; done; unset arg
for dir in /usr/local/sbin /usr/sbin; do case ":${PATH}:" in *":${dir}:"*) ;; *) PATH="${PATH}:${dir}" ;; esac; done; export PATH; unset dir

### DIALOG OUTPUT FOR INITIALIZATION.
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen; fi

### Updating Status of Dialog Gauge Bar.
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nInitialization done ... \nXXX\n15\n" >&3; fi

### Updating Status of Dialog Gauge Bar.
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nActivate traps ... \nXXX\n50\n" >&3; fi
### Following the CISS Bash naming and ordering scheme:
trap 'trap_on_exit "$?" "${BASH_SOURCE[0]}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_COMMAND}"' EXIT
trap 'trap_on_err  "$?" "${BASH_SOURCE[0]}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_COMMAND}"' ERR

### Updating Status of Dialog Gauge Bar.
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nSanitizing Arguments ... \nXXX\n75\n" >&3; fi
arg_check "$@"
declare -ar  ARY_ARG_SANITIZED=("$@")
declare -grx VAR_ARG_SANITIZED="${ARY_ARG_SANITIZED[*]}"

### Updating Status of Dialog Gauge Bar.
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nParsing Arguments ... \nXXX\n90\n" >&3; fi
arg_parser "$@"

### Updating Status of Dialog Gauge Bar.
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nFinal checks ... \nXXX\n95\n" >&3; fi
clean_ip

### Updating Status of Dialog Gauge Bar.
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nInitialization completed ... \nXXX\n100\n" >&3; sleep 1; fi

### Turn off the dialog wrapper.
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi

### MAIN Program ---------------------------------------------------------------------------------------------------------------
arg_priority_check
check_stats

if ! ${VAR_HANDLER_AUTOBUILD}; then check_provider; fi
if ! ${VAR_HANDLER_AUTOBUILD}; then check_kernel; fi

ciss_upgrades_build
hardening_ssh_tcp

### Preparing the build environment.
lb_config_start

### Writing the build configuration.
lb_config_write_trixie

### Init GNUPGHOME.
init_gnupg

### Integrate primordial SSH identity files.
init_primordial

### Integrate the CISS.debian.live.builder repository into the build directory.
### Modifications from this point onwards must be placed under 'VAR_HANDLER_BUILD_DIR'.
hardening_ultra

### CISS.debian.installer 'GRUB' and 'autostart' generator.
cdi

### Final CISS.debian.live.builder integrations.
change_splash
check_dhcp
ciss_signatures
ciss_upgrades_boot
hardening_root_pw
note_target
provider_netcup
update_microcode
x_hooks
x_remove

### Start the build process ----------------------------------------------------------------------------------------------------
set +o errtrace
lb_build_start
set -o errtrace

run_analysis
copy_db
declare -grx VAR_SCRIPT_SUCCESS="true"
exit 0
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
