diff --git a/:BW_SESSION=4PzBZ+aZRywhucO6yGZVGZz0NsnNsb4xJ4z7VfLbVZXK4WjJDzxg3blOsVWYecqTlQdvR0V709jqeN3NIZuTmA==~ b/:BW_SESSION=4PzBZ+aZRywhucO6yGZVGZz0NsnNsb4xJ4z7VfLbVZXK4WjJDzxg3blOsVWYecqTlQdvR0V709jqeN3NIZuTmA==~ new file mode 100644 index 0000000..e69de29 diff --git a/config/bitwarden.yaml b/config/bitwarden.yaml new file mode 100644 index 0000000..803926e --- /dev/null +++ b/config/bitwarden.yaml @@ -0,0 +1,11 @@ +bitwarden: + server_url: https://vw.maison43.duckdns.org + email: gil.soulier@gmail.com + target_user: gilles + install_cli: true + install_desktop: true + install_firefox_extension: true + install_chromium_extension: true + install_google_chrome_extension: true + login_cli_now: false + uri_match_detection: host diff --git a/core/bootstrap.sh b/core/bootstrap.sh index 8873d2b..bea8376 100644 --- a/core/bootstrap.sh +++ b/core/bootstrap.sh @@ -70,14 +70,28 @@ Exemples: EOF } +bootstrap_print_session_context() { + ui_info "Utilisateur courant : $(id -un) (uid $(id -u))" + ui_info "Mode de privileges : $(system_privilege_mode)" + + if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then + ui_info "Utilisateur d'origine : $(system_origin_user)" + fi +} + bootstrap_run() { bootstrap_parse_args "$@" || exit 1 + if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then + system_reexec_as_root "$@" || exit 1 + fi + runtime_init "$BOOTSTRAP_ROOT" log_init ui_header "Postinstall Debian" ui_info "Initialisation du framework" + bootstrap_print_session_context system_require_bash system_require_debian diff --git a/core/dispatcher.sh b/core/dispatcher.sh index 8865cc4..0f91400 100644 --- a/core/dispatcher.sh +++ b/core/dispatcher.sh @@ -25,6 +25,21 @@ dispatcher_prompt_and_run_module() { local share_public="" local archive_name="" local docker_data_dir="" + local ftp_port="" + local ftp_anonymous="" + local ftp_local="" + local ftp_write="" + local ftp_root="" + local bitwarden_server_url="" + local bitwarden_email="" + local bitwarden_target_user="" + local bitwarden_install_cli="" + local bitwarden_install_desktop="" + local bitwarden_install_firefox="" + local bitwarden_install_chromium="" + local bitwarden_install_google_chrome="" + local bitwarden_login_now="" + local bitwarden_uri_mode="" local default_nfs_ids="" local nfs_entry="" local nfs_item_id="" @@ -63,8 +78,11 @@ dispatcher_prompt_and_run_module() { dispatcher_run_module "$module_id" "$target_user" "$selected_groups" ;; network/ssh-server) + ui_section "Configuration SSH" ssh_port="$(prompt_read_default "Port SSH" "${POSTINSTALL_SSH_PORT:-22}")" + ui_info "L'authentification par mot de passe simplifie l'acces, mais elle est moins sure que les cles SSH." ssh_password_auth="$(prompt_confirm_default "Autoriser l'authentification par mot de passe" "${POSTINSTALL_SSH_PASSWORD_AUTH:-yes}")" + ui_info "Autoriser root en SSH est pratique pour depanner, mais augmente le risque en cas d'exposition reseau." ssh_root_login="$(prompt_confirm_default "Autoriser la connexion root SSH" "${POSTINSTALL_SSH_ROOT_LOGIN:-no}")" dispatcher_run_module "$module_id" "$ssh_port" "$ssh_password_auth" "$ssh_root_login" ;; @@ -79,8 +97,12 @@ dispatcher_prompt_and_run_module() { dispatcher_run_module "$module_id" "$host_name" "$domain_name" ;; network/ip-config) + ui_section "Configuration IP" iface="$(prompt_read_default "Interface reseau" "${POSTINSTALL_NETWORK_IP_DEFAULT_INTERFACE:-$(system_primary_interface)}")" - ip_mode="$(prompt_read_default "Mode reseau (dhcp ou static)" "${POSTINSTALL_NETWORK_IP_DEFAULT_MODE:-dhcp}")" + ip_mode="$(prompt_select_described_from_list \ + "Mode reseau" \ + "dhcp|La box ou le routeur attribue automatiquement l'adresse IP." \ + "static|Vous fixez manuellement l'adresse IP, la passerelle et le DNS.")" if [[ "$ip_mode" == "static" ]]; then ip_address="$(prompt_read_default "Adresse IP" "${POSTINSTALL_NETWORK_IP_DEFAULT_ADDRESS:-10.0.0.10}")" ip_prefix="$(prompt_read_default "Prefixe CIDR" "${POSTINSTALL_NETWORK_IP_DEFAULT_PREFIX:-22}")" @@ -97,7 +119,10 @@ dispatcher_prompt_and_run_module() { network/nfs-client) # shellcheck source=/dev/null source "$RUNTIME_PROJECT_ROOT/modules/network/nfs-client/module.sh" - nfs_action="$(prompt_select_from_list "Action NFS client" "activer des partages" "desactiver des partages")" + nfs_action="$(prompt_select_described_from_list \ + "Action NFS client" \ + "activer des partages|Ajoute les partages choisis dans fstab et peut les monter immediatement." \ + "desactiver des partages|Retire les partages choisis de fstab et tente de les demonter.")" nfs_item_labels=() nfs_item_ids=() if [[ "$nfs_action" == "desactiver des partages" ]]; then @@ -208,6 +233,53 @@ dispatcher_prompt_and_run_module() { docker_data_dir="$(prompt_read_default "Dossier Docker" "/home/${target_user}/docker")" dispatcher_run_module "$module_id" "$target_user" "$docker_data_dir" ;; + network/ftp-server) + ui_section "Configuration FTP" + ftp_port="$(prompt_read_default "Port FTP" "21")" + ui_info "L'acces anonyme ouvre le serveur sans compte local. A n'activer que sur un reseau de confiance." + ftp_anonymous="$(prompt_confirm_default "Autoriser l'acces anonyme" "no")" + ui_info "L'acces local permet aux comptes du systeme de se connecter au serveur FTP." + ftp_local="$(prompt_confirm_default "Autoriser les utilisateurs locaux" "yes")" + ui_info "L'ecriture permet l'envoi, la suppression ou la modification de fichiers." + ftp_write="$(prompt_confirm_default "Autoriser l'ecriture" "no")" + ftp_root="$(prompt_read_default "Dossier racine FTP" "/home/gilles")" + dispatcher_run_module "$module_id" "$ftp_port" "$ftp_anonymous" "$ftp_local" "$ftp_write" "$ftp_root" + ;; + passwords/bitwarden) + ui_section "Configuration Bitwarden" + bitwarden_server_url="$(prompt_read_default "URL du serveur Bitwarden auto-heberge" "https://vw.maison43.duckdns.org")" + bitwarden_email="$(prompt_read_default "Adresse e-mail Bitwarden" "gil.soulier@gmail.com")" + bitwarden_target_user="$(prompt_read_default "Utilisateur local a configurer" "${POSTINSTALL_DEFAULT_USER:-gilles}")" + bitwarden_install_cli="$(prompt_confirm_default "Installer Bitwarden CLI" "yes")" + bitwarden_install_desktop="$(prompt_confirm_default "Installer l'application desktop Bitwarden" "yes")" + ui_info "Firefox peut etre preconfigure avec une politique systeme pour ton serveur Bitwarden." + bitwarden_install_firefox="$(prompt_confirm_default "Configurer l'extension Firefox Bitwarden" "yes")" + ui_info "Chromium et Chrome peuvent recevoir une politique systeme pour forcer l'extension et le serveur." + bitwarden_install_chromium="$(prompt_confirm_default "Configurer l'extension Chromium Bitwarden" "yes")" + bitwarden_install_google_chrome="$(prompt_confirm_default "Configurer aussi l'extension Google Chrome Bitwarden" "yes")" + bitwarden_login_now="no" + if [[ "$bitwarden_install_cli" == "yes" ]]; then + ui_info "Le mot de passe maitre ne sera pas stocke. Il sera saisi une seule fois si tu choisis la connexion immediate." + bitwarden_login_now="$(prompt_confirm_default "Connecter le CLI Bitwarden tout de suite" "no")" + fi + bitwarden_uri_mode="$(prompt_select_described_from_list \ + "Detection de correspondance URI conseillee" \ + "host|Adapte aux serveurs locaux et sous-domaines. Recommande pour ton usage." \ + "base domain|Plus large, utile pour de grands domaines publics." \ + "exact|Ne correspond que si l'URL est exactement identique.")" + dispatcher_run_module \ + "$module_id" \ + "$bitwarden_server_url" \ + "$bitwarden_email" \ + "$bitwarden_target_user" \ + "$bitwarden_install_cli" \ + "$bitwarden_install_desktop" \ + "$bitwarden_install_firefox" \ + "$bitwarden_install_chromium" \ + "$bitwarden_install_google_chrome" \ + "$bitwarden_login_now" \ + "$bitwarden_uri_mode" + ;; *) dispatcher_run_module "$module_id" ;; diff --git a/core/runtime.sh b/core/runtime.sh index 132474e..8fe4ce2 100644 --- a/core/runtime.sh +++ b/core/runtime.sh @@ -5,8 +5,17 @@ RUNTIME_LOG_DIR="" RUNTIME_LOG_FILE="" runtime_init() { + local uid_suffix="" + RUNTIME_PROJECT_ROOT="$1" - RUNTIME_LOG_DIR="${TMPDIR:-/tmp}/postinstall-debian" + + if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then + RUNTIME_LOG_DIR="${TMPDIR:-/tmp}/postinstall-debian" + else + uid_suffix="$(id -u)" + RUNTIME_LOG_DIR="${TMPDIR:-/tmp}/postinstall-debian-$uid_suffix" + fi + RUNTIME_LOG_FILE="$RUNTIME_LOG_DIR/install.log" mkdir -p "$RUNTIME_LOG_DIR" } diff --git a/install.sh b/install.sh index 43939c1..311f070 100755 --- a/install.sh +++ b/install.sh @@ -3,6 +3,7 @@ set -u PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +POSTINSTALL_ENTRYPOINT="$PROJECT_ROOT/install.sh" # shellcheck source=core/bootstrap.sh source "$PROJECT_ROOT/core/bootstrap.sh" diff --git a/lib/log.sh b/lib/log.sh index 24820cf..4c69a97 100644 --- a/lib/log.sh +++ b/lib/log.sh @@ -1,6 +1,19 @@ #!/usr/bin/env bash log_init() { + local fallback_dir="" + local fallback_file="" + + mkdir -p "$RUNTIME_LOG_DIR" 2>/dev/null || true + if : > "$RUNTIME_LOG_FILE" 2>/dev/null; then + return 0 + fi + + fallback_dir="${TMPDIR:-/tmp}/postinstall-debian-$(id -u)" + fallback_file="$fallback_dir/install.log" + mkdir -p "$fallback_dir" + RUNTIME_LOG_DIR="$fallback_dir" + RUNTIME_LOG_FILE="$fallback_file" : > "$RUNTIME_LOG_FILE" } diff --git a/lib/package.sh b/lib/package.sh index acc1819..8fc76cd 100644 --- a/lib/package.sh +++ b/lib/package.sh @@ -4,6 +4,10 @@ package_is_installed() { dpkg -s "$1" >/dev/null 2>&1 } +package_is_available() { + apt-cache show "$1" >/dev/null 2>&1 +} + package_refresh_indexes() { apt-get update } diff --git a/lib/system.sh b/lib/system.sh index 156b3fb..41ebdd1 100644 --- a/lib/system.sh +++ b/lib/system.sh @@ -30,6 +30,47 @@ system_require_root() { ui_success "Privileges root valides" } +system_can_prompt_password() { + [[ -t 0 && -t 1 ]] +} + +system_reexec_as_root() { + local entrypoint="${POSTINSTALL_ENTRYPOINT:-}" + local quoted_args="" + local arg="" + + if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then + return 0 + fi + + if [[ -z "$entrypoint" || ! -f "$entrypoint" ]]; then + ui_error "Impossible de relancer automatiquement en root depuis cette execution" + return 1 + fi + + if ! system_can_prompt_password; then + ui_error "Privileges root requis et aucun terminal interactif disponible" + return 1 + fi + + for arg in "$@"; do + quoted_args="${quoted_args} $(printf '%q' "$arg")" + done + + if command -v sudo >/dev/null 2>&1; then + ui_info "Privileges root requis, tentative avec sudo" + exec sudo --preserve-env=TMPDIR bash "$entrypoint" "$@" + fi + + if command -v su >/dev/null 2>&1; then + ui_info "Privileges root requis, bascule vers root avec su" + exec su -c "bash $(printf '%q' "$entrypoint")$quoted_args" + fi + + ui_error "Ni sudo ni su ne sont disponibles pour obtenir les privileges root" + return 1 +} + system_user_exists() { local user_name="$1" id "$user_name" >/dev/null 2>&1 @@ -57,3 +98,27 @@ system_primary_interface() { } }' } + +system_origin_user() { + if [[ -n "${SUDO_USER:-}" ]]; then + printf '%s\n' "$SUDO_USER" + return 0 + fi + + if [[ -n "${PKEXEC_UID:-}" ]]; then + getent passwd "$PKEXEC_UID" | cut -d: -f1 + return 0 + fi + + printf '%s\n' "$(id -un)" +} + +system_privilege_mode() { + if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then + printf 'utilisateur\n' + elif [[ -n "${SUDO_USER:-}" ]]; then + printf 'sudo\n' + else + printf 'root direct\n' + fi +} diff --git a/menus/main.sh b/menus/main.sh index 084da6c..04eb743 100644 --- a/menus/main.sh +++ b/menus/main.sh @@ -36,7 +36,6 @@ menu_modules_by_prefix() { } menu_category_selection() { - local categories=("network" "containers" "boot" "hardware") local selection="" ui_section "Installation par categorie" @@ -44,15 +43,17 @@ menu_category_selection() { printf ' 2. containers\n' printf ' 3. boot\n' printf ' 4. hardware\n' + printf ' 5. passwords\n' printf ' 0. Retour\n' - selection="$(prompt_select_number "Selectionner une categorie" 0 4)" + selection="$(prompt_select_number "Selectionner une categorie" 0 5)" case "$selection" in 0) return 0 ;; 1) menu_modules_by_prefix "network" "Configuration reseau" ;; 2) menu_modules_by_prefix "containers" "Conteneurs" ;; 3) menu_modules_by_prefix "boot" "Configuration du boot" ;; 4) menu_modules_by_prefix "hardware" "Materiel" ;; + 5) menu_modules_by_prefix "passwords" "Gestion des mots de passe" ;; esac } diff --git a/modules/network/ftp-server/module.sh b/modules/network/ftp-server/module.sh index cd62c41..c750278 100644 --- a/modules/network/ftp-server/module.sh +++ b/modules/network/ftp-server/module.sh @@ -76,15 +76,23 @@ EOF } module_ftp_server_install() { - local settings="" local listen_port="" local anonymous_enable="" local local_enable="" local write_enable="" local local_root="" + local settings="" - settings="$(module_ftp_server_settings)" - IFS='|' read -r listen_port anonymous_enable local_enable write_enable local_root <<< "$settings" + if [[ $# -ge 5 ]]; then + listen_port="$1" + anonymous_enable="$2" + local_enable="$3" + write_enable="$4" + local_root="$5" + else + settings="$(module_ftp_server_settings)" + IFS='|' read -r listen_port anonymous_enable local_enable write_enable local_root <<< "$settings" + fi package_refresh_indexes package_install vsftpd diff --git a/modules/passwords/bitwarden/config.sh b/modules/passwords/bitwarden/config.sh new file mode 100644 index 0000000..1e8ee7b --- /dev/null +++ b/modules/passwords/bitwarden/config.sh @@ -0,0 +1,20 @@ +POSTINSTALL_BITWARDEN_SETTINGS_FILE="config/bitwarden.yaml" +POSTINSTALL_BITWARDEN_SERVER_URL="https://vw.maison43.duckdns.org" +POSTINSTALL_BITWARDEN_EMAIL="gil.soulier@gmail.com" +POSTINSTALL_BITWARDEN_TARGET_USER="gilles" +POSTINSTALL_BITWARDEN_INSTALL_CLI="true" +POSTINSTALL_BITWARDEN_INSTALL_DESKTOP="true" +POSTINSTALL_BITWARDEN_INSTALL_FIREFOX_EXTENSION="true" +POSTINSTALL_BITWARDEN_INSTALL_CHROMIUM_EXTENSION="true" +POSTINSTALL_BITWARDEN_INSTALL_GOOGLE_CHROME_EXTENSION="true" +POSTINSTALL_BITWARDEN_LOGIN_CLI_NOW="false" +POSTINSTALL_BITWARDEN_URI_MATCH_DETECTION="host" +POSTINSTALL_BITWARDEN_CLI_DOWNLOAD_URL="https://bitwarden.com/download/?app=cli&platform=linux" +POSTINSTALL_BITWARDEN_DESKTOP_DOWNLOAD_URL="https://bitwarden.com/download/?app=desktop&platform=linux" +POSTINSTALL_BITWARDEN_FIREFOX_POLICIES_FILE="/etc/firefox/policies/policies.json" +POSTINSTALL_BITWARDEN_CHROMIUM_POLICIES_FILE="/etc/chromium/policies/managed/bitwarden.json" +POSTINSTALL_BITWARDEN_CHROME_POLICIES_FILE="/etc/opt/chrome/policies/managed/bitwarden.json" +POSTINSTALL_BITWARDEN_FIREFOX_EXTENSION_ID="{446900e4-71c2-419f-a6a7-df9c091e268b}" +POSTINSTALL_BITWARDEN_FIREFOX_EXTENSION_URL="https://addons.mozilla.org/firefox/downloads/latest/bitwarden-password-manager/latest.xpi" +POSTINSTALL_BITWARDEN_CHROME_EXTENSION_ID="nngceckbapebfimnlniiiahkandclblb" +POSTINSTALL_BITWARDEN_CHROME_EXTENSION_UPDATE_URL="https://clients2.google.com/service/update2/crx" diff --git a/modules/passwords/bitwarden/metadata.conf b/modules/passwords/bitwarden/metadata.conf new file mode 100644 index 0000000..a123ca5 --- /dev/null +++ b/modules/passwords/bitwarden/metadata.conf @@ -0,0 +1,4 @@ +MODULE_ID="passwords/bitwarden" +MODULE_NAME="Bitwarden" +MODULE_CATEGORY="passwords" +MODULE_DESCRIPTION="Installe Bitwarden et preconfigure les clients pour un serveur auto-heberge" diff --git a/modules/passwords/bitwarden/module.sh b/modules/passwords/bitwarden/module.sh new file mode 100644 index 0000000..35d5f9c --- /dev/null +++ b/modules/passwords/bitwarden/module.sh @@ -0,0 +1,400 @@ +#!/usr/bin/env bash + +MODULE_BITWARDEN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +MODULE_BITWARDEN_PROJECT_ROOT="$(cd "$MODULE_BITWARDEN_DIR/../../.." && pwd)" + +# shellcheck source=lib/package.sh +source "$MODULE_BITWARDEN_PROJECT_ROOT/lib/package.sh" +# shellcheck source=lib/system.sh +source "$MODULE_BITWARDEN_PROJECT_ROOT/lib/system.sh" +# shellcheck source=modules/passwords/bitwarden/config.sh +source "$MODULE_BITWARDEN_DIR/config.sh" +# shellcheck source=modules/passwords/bitwarden/metadata.conf +source "$MODULE_BITWARDEN_DIR/metadata.conf" + +module_bitwarden_metadata() { + printf '%s|%s|%s\n' "$MODULE_ID" "$MODULE_NAME" "$MODULE_DESCRIPTION" +} + +module_bitwarden_config_path() { + printf '%s/%s\n' "$MODULE_BITWARDEN_PROJECT_ROOT" "$POSTINSTALL_BITWARDEN_SETTINGS_FILE" +} + +module_bitwarden_settings() { + local config_path="" + local server_url="$POSTINSTALL_BITWARDEN_SERVER_URL" + local email="$POSTINSTALL_BITWARDEN_EMAIL" + local target_user="$POSTINSTALL_BITWARDEN_TARGET_USER" + local install_cli="$POSTINSTALL_BITWARDEN_INSTALL_CLI" + local install_desktop="$POSTINSTALL_BITWARDEN_INSTALL_DESKTOP" + local install_firefox_extension="$POSTINSTALL_BITWARDEN_INSTALL_FIREFOX_EXTENSION" + local install_chromium_extension="$POSTINSTALL_BITWARDEN_INSTALL_CHROMIUM_EXTENSION" + local install_google_chrome_extension="$POSTINSTALL_BITWARDEN_INSTALL_GOOGLE_CHROME_EXTENSION" + local login_cli_now="$POSTINSTALL_BITWARDEN_LOGIN_CLI_NOW" + local uri_match_detection="$POSTINSTALL_BITWARDEN_URI_MATCH_DETECTION" + + config_path="$(module_bitwarden_config_path)" + if [[ -f "$config_path" ]]; then + while IFS='=' read -r key value; do + case "$key" in + server_url) server_url="$value" ;; + email) email="$value" ;; + target_user) target_user="$value" ;; + install_cli) install_cli="$value" ;; + install_desktop) install_desktop="$value" ;; + install_firefox_extension) install_firefox_extension="$value" ;; + install_chromium_extension) install_chromium_extension="$value" ;; + install_google_chrome_extension) install_google_chrome_extension="$value" ;; + login_cli_now) login_cli_now="$value" ;; + uri_match_detection) uri_match_detection="$value" ;; + esac + done < <( + awk ' + /^[[:space:]]*server_url:/ { print "server_url=" $2 } + /^[[:space:]]*email:/ { print "email=" $2 } + /^[[:space:]]*target_user:/ { print "target_user=" $2 } + /^[[:space:]]*install_cli:/ { print "install_cli=" $2 } + /^[[:space:]]*install_desktop:/ { print "install_desktop=" $2 } + /^[[:space:]]*install_firefox_extension:/ { print "install_firefox_extension=" $2 } + /^[[:space:]]*install_chromium_extension:/ { print "install_chromium_extension=" $2 } + /^[[:space:]]*install_google_chrome_extension:/ { print "install_google_chrome_extension=" $2 } + /^[[:space:]]*login_cli_now:/ { print "login_cli_now=" $2 } + /^[[:space:]]*uri_match_detection:/ { print "uri_match_detection=" $2 } + ' "$config_path" + ) + fi + + printf '%s|%s|%s|%s|%s|%s|%s|%s|%s|%s\n' \ + "$server_url" \ + "$email" \ + "$target_user" \ + "$install_cli" \ + "$install_desktop" \ + "$install_firefox_extension" \ + "$install_chromium_extension" \ + "$install_google_chrome_extension" \ + "$login_cli_now" \ + "$uri_match_detection" +} + +module_bitwarden_string_to_bool() { + case "$1" in + true|yes|y|1|on) printf 'true\n' ;; + *) printf 'false\n' ;; + esac +} + +module_bitwarden_require_directory() { + install -d -m 0755 "$1" +} + +module_bitwarden_user_home() { + local target_user="$1" + + getent passwd "$target_user" | cut -d: -f6 +} + +module_bitwarden_run_as_user() { + local target_user="$1" + shift + local target_home="" + + if ! system_user_exists "$target_user"; then + ui_error "Utilisateur Bitwarden introuvable : $target_user" + return 1 + fi + + target_home="$(module_bitwarden_user_home "$target_user")" + if [[ -z "$target_home" ]]; then + ui_error "Impossible de determiner le HOME de $target_user" + return 1 + fi + + if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then + runuser -u "$target_user" -- env HOME="$target_home" XDG_CONFIG_HOME="$target_home/.config" "$@" + else + HOME="$target_home" XDG_CONFIG_HOME="$target_home/.config" "$@" + fi +} + +module_bitwarden_download() { + local url="$1" + local destination="$2" + + curl -fsSL "$url" -o "$destination" +} + +module_bitwarden_install_cli() { + local temp_dir="" + local archive_path="" + + if command -v bw >/dev/null 2>&1; then + ui_info "Bitwarden CLI deja installe" + return 0 + fi + + temp_dir="$(mktemp -d)" + archive_path="$temp_dir/bitwarden-cli.zip" + + package_refresh_indexes + package_install curl unzip ca-certificates + module_bitwarden_download "$POSTINSTALL_BITWARDEN_CLI_DOWNLOAD_URL" "$archive_path" + unzip -o "$archive_path" -d "$temp_dir" >/dev/null + + if [[ ! -f "$temp_dir/bw" ]]; then + ui_error "Binaire Bitwarden CLI introuvable apres extraction" + rm -rf "$temp_dir" + return 1 + fi + + install -m 0755 "$temp_dir/bw" /usr/local/bin/bw + rm -rf "$temp_dir" + + ui_success "Bitwarden CLI installe" +} + +module_bitwarden_install_desktop() { + local target_user="$1" + local temp_dir="" + local appimage_path="" + local install_path="/opt/bitwarden/Bitwarden.AppImage" + + temp_dir="$(mktemp -d)" + appimage_path="$temp_dir/Bitwarden.AppImage" + + package_refresh_indexes + package_install curl ca-certificates + module_bitwarden_download "$POSTINSTALL_BITWARDEN_DESKTOP_DOWNLOAD_URL" "$appimage_path" + + if [[ ! -s "$appimage_path" ]]; then + ui_error "Telechargement de l'application Bitwarden echoue" + rm -rf "$temp_dir" + return 1 + fi + + module_bitwarden_require_directory /opt/bitwarden + install -m 0755 "$appimage_path" "$install_path" + rm -rf "$temp_dir" + + cat > /usr/local/bin/bitwarden-desktop <<'EOF' +#!/usr/bin/env bash +exec /opt/bitwarden/Bitwarden.AppImage "$@" +EOF + chmod 0755 /usr/local/bin/bitwarden-desktop + + if system_user_exists "$target_user"; then + module_bitwarden_write_desktop_config "$target_user" + fi + + ui_success "Application desktop Bitwarden installee" +} + +module_bitwarden_write_desktop_config() { + local target_user="$1" + local config_dir="/home/$target_user/.config/Bitwarden" + local config_file="$config_dir/data.json" + + module_bitwarden_require_directory "$config_dir" + cat > "$config_file" < "$POSTINSTALL_BITWARDEN_FIREFOX_POLICIES_FILE" < "$policy_file" </dev/null 2>&1; then + ui_warn "CLI Bitwarden absente, connexion ignoree" + return 0 + fi + + printf 'Mot de passe Bitwarden pour %s : ' "$email" + read -r -s password + printf '\n' + + if [[ -z "$password" ]]; then + ui_warn "Mot de passe vide, connexion CLI ignoree" + return 0 + fi + + module_bitwarden_run_as_user "$target_user" env BW_PASSWORD="$password" bw login "$email" --passwordenv BW_PASSWORD || return 1 + password="" + ui_success "Connexion CLI Bitwarden terminee" +} + +module_bitwarden_install() { + local server_url="${1:-}" + local email="${2:-}" + local target_user="${3:-}" + local install_cli="${4:-}" + local install_desktop="${5:-}" + local install_firefox_extension="${6:-}" + local install_chromium_extension="${7:-}" + local install_google_chrome_extension="${8:-}" + local login_cli_now="${9:-}" + local uri_match_detection="${10:-}" + local settings="" + + if [[ -z "$server_url" ]]; then + settings="$(module_bitwarden_settings)" + IFS='|' read -r server_url email target_user install_cli install_desktop install_firefox_extension install_chromium_extension install_google_chrome_extension login_cli_now uri_match_detection <<< "$settings" + fi + + POSTINSTALL_BITWARDEN_SERVER_URL="$server_url" + POSTINSTALL_BITWARDEN_EMAIL="$email" + POSTINSTALL_BITWARDEN_TARGET_USER="$target_user" + POSTINSTALL_BITWARDEN_INSTALL_CLI="$(module_bitwarden_string_to_bool "$install_cli")" + POSTINSTALL_BITWARDEN_INSTALL_DESKTOP="$(module_bitwarden_string_to_bool "$install_desktop")" + POSTINSTALL_BITWARDEN_INSTALL_FIREFOX_EXTENSION="$(module_bitwarden_string_to_bool "$install_firefox_extension")" + POSTINSTALL_BITWARDEN_INSTALL_CHROMIUM_EXTENSION="$(module_bitwarden_string_to_bool "$install_chromium_extension")" + POSTINSTALL_BITWARDEN_INSTALL_GOOGLE_CHROME_EXTENSION="$(module_bitwarden_string_to_bool "$install_google_chrome_extension")" + POSTINSTALL_BITWARDEN_LOGIN_CLI_NOW="$(module_bitwarden_string_to_bool "$login_cli_now")" + POSTINSTALL_BITWARDEN_URI_MATCH_DETECTION="$uri_match_detection" + + ui_info "Serveur Bitwarden cible : $POSTINSTALL_BITWARDEN_SERVER_URL" + ui_info "Preference a verifier apres premiere connexion : detection d'URI = $POSTINSTALL_BITWARDEN_URI_MATCH_DETECTION" + + if [[ "$POSTINSTALL_BITWARDEN_INSTALL_CLI" == "true" ]]; then + module_bitwarden_install_cli || return 1 + module_bitwarden_run_as_user "$target_user" bw config server "$POSTINSTALL_BITWARDEN_SERVER_URL" || return 1 + fi + + if [[ "$POSTINSTALL_BITWARDEN_INSTALL_DESKTOP" == "true" ]]; then + module_bitwarden_install_desktop "$target_user" || return 1 + fi + + if [[ "$POSTINSTALL_BITWARDEN_INSTALL_FIREFOX_EXTENSION" == "true" ]]; then + module_bitwarden_configure_firefox || return 1 + fi + + if [[ "$POSTINSTALL_BITWARDEN_INSTALL_CHROMIUM_EXTENSION" == "true" ]]; then + module_bitwarden_configure_chromium || return 1 + fi + + if [[ "$POSTINSTALL_BITWARDEN_INSTALL_GOOGLE_CHROME_EXTENSION" == "true" ]]; then + module_bitwarden_configure_google_chrome || return 1 + fi + + if [[ "$POSTINSTALL_BITWARDEN_LOGIN_CLI_NOW" == "true" ]]; then + module_bitwarden_cli_login "$POSTINSTALL_BITWARDEN_EMAIL" "$target_user" || return 1 + fi + + log_info "Bitwarden configure pour $POSTINSTALL_BITWARDEN_SERVER_URL" + ui_success "Bitwarden configure" +} + +module_bitwarden_test() { + local ok=0 + + if command -v bw >/dev/null 2>&1; then + ok=1 + fi + + if [[ -f "$POSTINSTALL_BITWARDEN_FIREFOX_POLICIES_FILE" ]]; then + ok=1 + fi + + if [[ -f "$POSTINSTALL_BITWARDEN_CHROMIUM_POLICIES_FILE" || -f "$POSTINSTALL_BITWARDEN_CHROME_POLICIES_FILE" ]]; then + ok=1 + fi + + test -f "$(module_bitwarden_config_path)" || return 1 + (( ok == 1 )) +} diff --git a/modules/passwords/bitwarden/tests.sh b/modules/passwords/bitwarden/tests.sh new file mode 100644 index 0000000..66cf9c8 --- /dev/null +++ b/modules/passwords/bitwarden/tests.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -u + +PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" + +# shellcheck source=modules/passwords/bitwarden/module.sh +source "$PROJECT_ROOT/modules/passwords/bitwarden/module.sh" + +test -f "$(module_bitwarden_config_path)" +test -f "$PROJECT_ROOT/modules/passwords/bitwarden/module.sh" + +if [[ -f "$POSTINSTALL_BITWARDEN_FIREFOX_POLICIES_FILE" ]]; then + grep -q '"base"' "$POSTINSTALL_BITWARDEN_FIREFOX_POLICIES_FILE" +fi + +if [[ -f "$POSTINSTALL_BITWARDEN_CHROMIUM_POLICIES_FILE" ]]; then + grep -q '"ExtensionInstallForcelist"' "$POSTINSTALL_BITWARDEN_CHROMIUM_POLICIES_FILE" +fi + +printf 'Bitwarden module test OK\n' diff --git a/tools.md b/tools.md index ccc5362..6a6f7d5 100644 --- a/tools.md +++ b/tools.md @@ -186,6 +186,19 @@ Difficulte : moyenne Statut : implemente ``` +### 14. passwords/bitwarden + +```text +Nom : Bitwarden +Description : installe et preconfigure Bitwarden pour un serveur auto-heberge, avec CLI, application desktop et integration navigateurs +Categorie : passwords +Questions : faut-il installer le CLI, l'application desktop, l'extension Firefox, l'extension Chrome ou Chromium, preconfigurer le serveur https://vw.maison43.duckdns.org, connecter le CLI tout de suite avec saisie interactive du mot de passe, et quels reglages par defaut faut-il documenter comme la detection d'URI par hote ? +Methode installation : lire un fichier YAML de configuration, installer les composants choisis, preconfigurer l'URL du serveur auto-heberge, poser les politiques Firefox et Chrome ou Chromium quand c'est possible, proposer une connexion CLI immediate sans stocker le mot de passe +Tests : command -v bw ; bw config server ; test -f /etc/firefox/policies/policies.json ; test -f /etc/opt/chrome/policies/managed/bitwarden.json ou /etc/chromium/policies/managed/bitwarden.json +Difficulte : moyenne a elevee +Statut : implemente +``` + ```text Nom : gnome extension Description : liste les extension gnome a installer @@ -213,3 +226,4 @@ Statut : 11. network/nfs-client 12. network/nfs-server 13. network/ftp-server +14. passwords/bitwarden