This commit is contained in:
2026-03-15 18:39:58 +01:00
parent 59db877c85
commit 4f05a86efe
16 changed files with 665 additions and 8 deletions

11
config/bitwarden.yaml Normal file
View File

@@ -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

View File

@@ -70,14 +70,28 @@ Exemples:
EOF 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_run() {
bootstrap_parse_args "$@" || exit 1 bootstrap_parse_args "$@" || exit 1
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
system_reexec_as_root "$@" || exit 1
fi
runtime_init "$BOOTSTRAP_ROOT" runtime_init "$BOOTSTRAP_ROOT"
log_init log_init
ui_header "Postinstall Debian" ui_header "Postinstall Debian"
ui_info "Initialisation du framework" ui_info "Initialisation du framework"
bootstrap_print_session_context
system_require_bash system_require_bash
system_require_debian system_require_debian

View File

@@ -25,6 +25,21 @@ dispatcher_prompt_and_run_module() {
local share_public="" local share_public=""
local archive_name="" local archive_name=""
local docker_data_dir="" 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 default_nfs_ids=""
local nfs_entry="" local nfs_entry=""
local nfs_item_id="" local nfs_item_id=""
@@ -63,8 +78,11 @@ dispatcher_prompt_and_run_module() {
dispatcher_run_module "$module_id" "$target_user" "$selected_groups" dispatcher_run_module "$module_id" "$target_user" "$selected_groups"
;; ;;
network/ssh-server) network/ssh-server)
ui_section "Configuration SSH"
ssh_port="$(prompt_read_default "Port SSH" "${POSTINSTALL_SSH_PORT:-22}")" 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}")" 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}")" 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" 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" dispatcher_run_module "$module_id" "$host_name" "$domain_name"
;; ;;
network/ip-config) network/ip-config)
ui_section "Configuration IP"
iface="$(prompt_read_default "Interface reseau" "${POSTINSTALL_NETWORK_IP_DEFAULT_INTERFACE:-$(system_primary_interface)}")" 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 if [[ "$ip_mode" == "static" ]]; then
ip_address="$(prompt_read_default "Adresse IP" "${POSTINSTALL_NETWORK_IP_DEFAULT_ADDRESS:-10.0.0.10}")" 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}")" 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) network/nfs-client)
# shellcheck source=/dev/null # shellcheck source=/dev/null
source "$RUNTIME_PROJECT_ROOT/modules/network/nfs-client/module.sh" 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_labels=()
nfs_item_ids=() nfs_item_ids=()
if [[ "$nfs_action" == "desactiver des partages" ]]; then 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")" docker_data_dir="$(prompt_read_default "Dossier Docker" "/home/${target_user}/docker")"
dispatcher_run_module "$module_id" "$target_user" "$docker_data_dir" 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" dispatcher_run_module "$module_id"
;; ;;

View File

@@ -5,8 +5,17 @@ RUNTIME_LOG_DIR=""
RUNTIME_LOG_FILE="" RUNTIME_LOG_FILE=""
runtime_init() { runtime_init() {
local uid_suffix=""
RUNTIME_PROJECT_ROOT="$1" 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" RUNTIME_LOG_FILE="$RUNTIME_LOG_DIR/install.log"
mkdir -p "$RUNTIME_LOG_DIR" mkdir -p "$RUNTIME_LOG_DIR"
} }

View File

@@ -3,6 +3,7 @@
set -u set -u
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
POSTINSTALL_ENTRYPOINT="$PROJECT_ROOT/install.sh"
# shellcheck source=core/bootstrap.sh # shellcheck source=core/bootstrap.sh
source "$PROJECT_ROOT/core/bootstrap.sh" source "$PROJECT_ROOT/core/bootstrap.sh"

View File

@@ -1,6 +1,19 @@
#!/usr/bin/env bash #!/usr/bin/env bash
log_init() { 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" : > "$RUNTIME_LOG_FILE"
} }

View File

@@ -4,6 +4,10 @@ package_is_installed() {
dpkg -s "$1" >/dev/null 2>&1 dpkg -s "$1" >/dev/null 2>&1
} }
package_is_available() {
apt-cache show "$1" >/dev/null 2>&1
}
package_refresh_indexes() { package_refresh_indexes() {
apt-get update apt-get update
} }

View File

@@ -30,6 +30,47 @@ system_require_root() {
ui_success "Privileges root valides" 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() { system_user_exists() {
local user_name="$1" local user_name="$1"
id "$user_name" >/dev/null 2>&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
}

View File

@@ -36,7 +36,6 @@ menu_modules_by_prefix() {
} }
menu_category_selection() { menu_category_selection() {
local categories=("network" "containers" "boot" "hardware")
local selection="" local selection=""
ui_section "Installation par categorie" ui_section "Installation par categorie"
@@ -44,15 +43,17 @@ menu_category_selection() {
printf ' 2. containers\n' printf ' 2. containers\n'
printf ' 3. boot\n' printf ' 3. boot\n'
printf ' 4. hardware\n' printf ' 4. hardware\n'
printf ' 5. passwords\n'
printf ' 0. Retour\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 case "$selection" in
0) return 0 ;; 0) return 0 ;;
1) menu_modules_by_prefix "network" "Configuration reseau" ;; 1) menu_modules_by_prefix "network" "Configuration reseau" ;;
2) menu_modules_by_prefix "containers" "Conteneurs" ;; 2) menu_modules_by_prefix "containers" "Conteneurs" ;;
3) menu_modules_by_prefix "boot" "Configuration du boot" ;; 3) menu_modules_by_prefix "boot" "Configuration du boot" ;;
4) menu_modules_by_prefix "hardware" "Materiel" ;; 4) menu_modules_by_prefix "hardware" "Materiel" ;;
5) menu_modules_by_prefix "passwords" "Gestion des mots de passe" ;;
esac esac
} }

View File

@@ -76,15 +76,23 @@ EOF
} }
module_ftp_server_install() { module_ftp_server_install() {
local settings=""
local listen_port="" local listen_port=""
local anonymous_enable="" local anonymous_enable=""
local local_enable="" local local_enable=""
local write_enable="" local write_enable=""
local local_root="" local local_root=""
local settings=""
settings="$(module_ftp_server_settings)" if [[ $# -ge 5 ]]; then
IFS='|' read -r listen_port anonymous_enable local_enable write_enable local_root <<< "$settings" 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_refresh_indexes
package_install vsftpd package_install vsftpd

View File

@@ -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"

View File

@@ -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"

View File

@@ -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" <<EOF
{
"environmentUrls": {
"base": "$POSTINSTALL_BITWARDEN_SERVER_URL"
},
"configuredByAdmin": true,
"notes": {
"uriMatchDetection": "$POSTINSTALL_BITWARDEN_URI_MATCH_DETECTION"
}
}
EOF
chown -R "$target_user:$target_user" "$config_dir"
}
module_bitwarden_write_firefox_policy() {
module_bitwarden_require_directory "$(dirname "$POSTINSTALL_BITWARDEN_FIREFOX_POLICIES_FILE")"
cat > "$POSTINSTALL_BITWARDEN_FIREFOX_POLICIES_FILE" <<EOF
{
"policies": {
"ExtensionSettings": {
"$POSTINSTALL_BITWARDEN_FIREFOX_EXTENSION_ID": {
"installation_mode": "force_installed",
"install_url": "$POSTINSTALL_BITWARDEN_FIREFOX_EXTENSION_URL"
}
},
"3rdparty": {
"Extensions": {
"$POSTINSTALL_BITWARDEN_FIREFOX_EXTENSION_ID": {
"environment": {
"base": "$POSTINSTALL_BITWARDEN_SERVER_URL"
}
}
}
}
}
}
EOF
}
module_bitwarden_write_chromium_policy_file() {
local policy_file="$1"
module_bitwarden_require_directory "$(dirname "$policy_file")"
cat > "$policy_file" <<EOF
{
"3rdparty": {
"extensions": {
"$POSTINSTALL_BITWARDEN_CHROME_EXTENSION_ID": {
"environment": {
"base": "$POSTINSTALL_BITWARDEN_SERVER_URL"
}
}
}
},
"ExtensionInstallForcelist": [
"$POSTINSTALL_BITWARDEN_CHROME_EXTENSION_ID;$POSTINSTALL_BITWARDEN_CHROME_EXTENSION_UPDATE_URL"
]
}
EOF
}
module_bitwarden_install_browser_package_if_available() {
local package_name="$1"
if package_is_installed "$package_name"; then
return 0
fi
if package_is_available "$package_name"; then
package_refresh_indexes
package_install "$package_name"
return 0
fi
ui_warn "Paquet indisponible : $package_name"
return 1
}
module_bitwarden_configure_firefox() {
module_bitwarden_install_browser_package_if_available firefox-esr || true
module_bitwarden_write_firefox_policy
ui_success "Politique Firefox Bitwarden ecrite"
}
module_bitwarden_configure_chromium() {
module_bitwarden_install_browser_package_if_available chromium || true
module_bitwarden_write_chromium_policy_file "$POSTINSTALL_BITWARDEN_CHROMIUM_POLICIES_FILE"
ui_success "Politique Chromium Bitwarden ecrite"
}
module_bitwarden_configure_google_chrome() {
if package_is_available google-chrome-stable || package_is_installed google-chrome-stable; then
module_bitwarden_install_browser_package_if_available google-chrome-stable || true
module_bitwarden_write_chromium_policy_file "$POSTINSTALL_BITWARDEN_CHROME_POLICIES_FILE"
ui_success "Politique Google Chrome Bitwarden ecrite"
else
ui_warn "Google Chrome n'est pas disponible sur cette machine"
fi
}
module_bitwarden_cli_login() {
local email="$1"
local target_user="$2"
local password=""
if ! command -v bw >/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 ))
}

View File

@@ -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'

View File

@@ -186,6 +186,19 @@ Difficulte : moyenne
Statut : implemente 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 ```text
Nom : gnome extension Nom : gnome extension
Description : liste les extension gnome a installer Description : liste les extension gnome a installer
@@ -213,3 +226,4 @@ Statut :
11. network/nfs-client 11. network/nfs-client
12. network/nfs-server 12. network/nfs-server
13. network/ftp-server 13. network/ftp-server
14. passwords/bitwarden