feat(browser): clean_chrome_profile_extensions + fix policy backup en managed/
Rediseño de apply_chromium_extension_policy y nueva función de purga in-place, tras resolver por qué las extensiones bloqueadas reaparecían en Chromium 148. - apply_chromium_extension_policy: añade --block (ExtensionInstallBlocklist). Reemplaza el modo ExtensionSettings "*": blocked (que rompía las extensiones unpacked vía --load-extension, p.ej. la de captura de web_proxy con el error 'Loading of unpacked extensions is disabled by the administrator') por una blocklist específica. FIX RAÍZ: los backups se guardan fuera de policies/managed/ (en policy-backups/), porque Chromium lee TODOS los archivos del directorio managed/ sin filtrar extensión de nombre — un extensions.json.bak ahí se mergea con la policy y reinyecta las extensiones del backup (location=7). - clean_chrome_profile_extensions (nueva): purga in-place de un perfil existente (borra carpetas de Extensions/ + refs en Preferences/Secure Preferences) dejando solo la whitelist. Complementa la policy: la policy evita reinstalación, esta desinstala lo ya presente. Requiere chromium cerrado. Ambas: dominio browser, grupo navegator, guard de auto-ejecución, dry-run.
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
# apply_chromium_extension_policy — Escribe de forma idempotente la política managed de Chromium
|
||||
# que fuerza la instalación de un conjunto de extensiones en CUALQUIER perfil del navegador.
|
||||
# que fuerza la instalación de una whitelist de extensiones y bloquea (desinstala) una blocklist
|
||||
# concreta, sin tocar el resto. Usa ExtensionInstallForcelist + ExtensionInstallBlocklist.
|
||||
|
||||
apply_chromium_extension_policy() {
|
||||
local policy_path="/etc/chromium/policies/managed/extensions.json"
|
||||
local update_url="https://clients2.google.com/service/update2/crx"
|
||||
local dry_run=0
|
||||
local -a ext_ids=()
|
||||
local -a keep_ids=()
|
||||
local -a block_ids=()
|
||||
|
||||
# --- Parseo de argumentos ---
|
||||
while [[ $# -gt 0 ]]; do
|
||||
@@ -16,7 +18,15 @@ apply_chromium_extension_policy() {
|
||||
echo "apply_chromium_extension_policy: --keep requiere un ID de extensión" >&2
|
||||
return 1
|
||||
fi
|
||||
ext_ids+=("$2")
|
||||
keep_ids+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--block)
|
||||
if [[ -z "${2:-}" ]]; then
|
||||
echo "apply_chromium_extension_policy: --block requiere un ID de extensión" >&2
|
||||
return 1
|
||||
fi
|
||||
block_ids+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--policy-path)
|
||||
@@ -41,31 +51,53 @@ apply_chromium_extension_policy() {
|
||||
;;
|
||||
*)
|
||||
echo "apply_chromium_extension_policy: argumento desconocido: $1" >&2
|
||||
echo "Uso: apply_chromium_extension_policy --keep <ext_id> [--keep <ext_id>]... [--policy-path <path>] [--update-url <url>] [--dry-run]" >&2
|
||||
echo "Uso: apply_chromium_extension_policy [--keep <ext_id>]... [--block <ext_id>]... [--policy-path <path>] [--update-url <url>] [--dry-run]" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# --- Validar que hay al menos una extensión ---
|
||||
if [[ ${#ext_ids[@]} -eq 0 ]]; then
|
||||
echo "apply_chromium_extension_policy: se requiere al menos un --keep <ext_id>" >&2
|
||||
# --- Validar que hay al menos una extensión a forzar o bloquear ---
|
||||
if [[ ${#keep_ids[@]} -eq 0 && ${#block_ids[@]} -eq 0 ]]; then
|
||||
echo "apply_chromium_extension_policy: se requiere al menos un --keep o un --block <ext_id>" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# --- Construir el JSON ---
|
||||
local forcelist_entries=""
|
||||
local first=1
|
||||
for id in "${ext_ids[@]}"; do
|
||||
if [[ $first -eq 0 ]]; then
|
||||
forcelist_entries+=","$'\n'
|
||||
fi
|
||||
forcelist_entries+=" \"${id};${update_url}\""
|
||||
first=0
|
||||
done
|
||||
# Dos claves complementarias, ninguna bloquea las extensiones unpacked (--load-extension),
|
||||
# de modo que extensiones locales como la de captura de web_proxy siguen cargando:
|
||||
# 1. ExtensionInstallForcelist: fuerza la instalación de la whitelist (--keep), que además
|
||||
# no se puede desinstalar desde la UI.
|
||||
# 2. ExtensionInstallBlocklist: bloquea Y desinstala las extensiones de la blocklist
|
||||
# (--block) en cualquier perfil. Solo afecta a los IDs listados; el resto no se toca.
|
||||
local forcelist_json="[]" blocklist_json="[]"
|
||||
if [[ ${#keep_ids[@]} -gt 0 ]]; then
|
||||
local entries="" first=1
|
||||
for id in "${keep_ids[@]}"; do
|
||||
[[ $first -eq 0 ]] && entries+=","$'\n'
|
||||
entries+=" \"${id};${update_url}\""
|
||||
first=0
|
||||
done
|
||||
forcelist_json=$(printf '[\n%s\n ]' "$entries")
|
||||
fi
|
||||
if [[ ${#block_ids[@]} -gt 0 ]]; then
|
||||
local entries="" first=1
|
||||
for id in "${block_ids[@]}"; do
|
||||
[[ $first -eq 0 ]] && entries+=","$'\n'
|
||||
entries+=" \"${id}\""
|
||||
first=0
|
||||
done
|
||||
blocklist_json=$(printf '[\n%s\n ]' "$entries")
|
||||
fi
|
||||
|
||||
local new_json
|
||||
new_json=$(printf '{\n "ExtensionInstallForcelist": [\n%s\n ]\n}\n' "$forcelist_entries")
|
||||
new_json=$(cat <<JSONEOF
|
||||
{
|
||||
"ExtensionInstallForcelist": ${forcelist_json},
|
||||
"ExtensionInstallBlocklist": ${blocklist_json}
|
||||
}
|
||||
JSONEOF
|
||||
)
|
||||
|
||||
# --- Modo dry-run ---
|
||||
if [[ $dry_run -eq 1 ]]; then
|
||||
@@ -88,11 +120,24 @@ apply_chromium_extension_policy() {
|
||||
fi
|
||||
|
||||
# --- Backup del archivo existente ---
|
||||
# CRÍTICO: el backup NUNCA puede vivir dentro del directorio de la policy. Chromium lee TODOS
|
||||
# los archivos del directorio managed/ (sin filtrar por extensión de nombre), así que un
|
||||
# "extensions.json.bak.YYYYMMDD" dentro de managed/ se mergea con la policy efectiva y reinyecta
|
||||
# las extensiones del backup. Por eso el backup se guarda en un directorio hermano (policy-backups)
|
||||
# que chromium no lee.
|
||||
local backup_path=""
|
||||
if [[ -f "$policy_path" ]]; then
|
||||
local date_suffix
|
||||
local date_suffix policy_dir backup_dir
|
||||
date_suffix=$(date +%Y%m%d)
|
||||
backup_path="${policy_path}.bak.${date_suffix}"
|
||||
policy_dir="$(dirname "$policy_path")"
|
||||
case "$(basename "$policy_dir")" in
|
||||
managed|recommended) backup_dir="$(dirname "$policy_dir")/policy-backups" ;;
|
||||
*) backup_dir="$policy_dir" ;;
|
||||
esac
|
||||
backup_path="${backup_dir}/$(basename "$policy_path").bak.${date_suffix}"
|
||||
if [[ ! -d "$backup_dir" ]]; then
|
||||
if [[ $EUID -ne 0 ]]; then sudo mkdir -p "$backup_dir" 2>/dev/null; else mkdir -p "$backup_dir"; fi
|
||||
fi
|
||||
if [[ ! -f "$backup_path" ]]; then
|
||||
echo "apply_chromium_extension_policy: creando backup → ${backup_path}"
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
@@ -129,7 +174,7 @@ apply_chromium_extension_policy() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Escribir el JSON vía tmpfile + sudo cp / tee ---
|
||||
# --- Escribir el JSON vía tmpfile + sudo cp ---
|
||||
local tmpfile
|
||||
tmpfile=$(mktemp /tmp/chromium_policy_XXXXXX.json)
|
||||
echo "$new_json" > "$tmpfile"
|
||||
@@ -138,7 +183,6 @@ apply_chromium_extension_policy() {
|
||||
sudo cp "$tmpfile" "$policy_path" || {
|
||||
echo "apply_chromium_extension_policy: no se pudo escribir ${policy_path}" >&2
|
||||
rm -f "$tmpfile"
|
||||
# Restaurar backup si hubo
|
||||
if [[ -n "$backup_path" && -f "$backup_path" ]]; then
|
||||
echo "apply_chromium_extension_policy: restaurando backup tras error..."
|
||||
sudo cp "$backup_path" "$policy_path" 2>/dev/null || true
|
||||
@@ -165,7 +209,6 @@ apply_chromium_extension_policy() {
|
||||
elif command -v jq &>/dev/null; then
|
||||
jq . "$policy_path" &>/dev/null && validation_ok=1
|
||||
else
|
||||
# Sin parser disponible, asumir OK (el JSON lo generamos nosotros)
|
||||
validation_ok=1
|
||||
fi
|
||||
|
||||
@@ -184,10 +227,15 @@ apply_chromium_extension_policy() {
|
||||
# --- Resumen final ---
|
||||
echo "apply_chromium_extension_policy: política aplicada correctamente."
|
||||
echo " Ruta : ${policy_path}"
|
||||
echo " Extensiones forzadas (${#ext_ids[@]}):"
|
||||
for id in "${ext_ids[@]}"; do
|
||||
echo " - ${id}"
|
||||
done
|
||||
if [[ ${#keep_ids[@]} -gt 0 ]]; then
|
||||
echo " Forzadas (${#keep_ids[@]}):"
|
||||
for id in "${keep_ids[@]}"; do echo " - ${id}"; done
|
||||
fi
|
||||
if [[ ${#block_ids[@]} -gt 0 ]]; then
|
||||
echo " Bloqueadas/desinstaladas (${#block_ids[@]}):"
|
||||
for id in "${block_ids[@]}"; do echo " - ${id}"; done
|
||||
fi
|
||||
echo " Extensiones unpacked (--load-extension, p.ej. web_proxy): NO afectadas."
|
||||
if [[ -n "$backup_path" && -f "$backup_path" ]]; then
|
||||
echo " Backup : ${backup_path}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user