#!/usr/bin/env bash # PANELS · Redis · Fase 0 (usuarios ACL por módulo) # # Crea dos usuarios ACL (Redis 6+) con acceso restringido por patrón de # llave: panels_iam_redis (~iam:*) y panels_core_redis (~core:*). Un # prefijo de llave por sí solo NO aísla nada — cualquier cliente con la # misma contraseña puede escanear todo el keyspace; el aislamiento real # lo da el ACL server-side, no la convención de nombres. # # Uso: # REDIS_ADMIN_URL="redis://:admin-password@host:6379" \ # IAM_REDIS_PASSWORD="$(openssl rand -base64 32)" \ # CORE_REDIS_PASSWORD="$(openssl rand -base64 32)" \ # ./05-redis-acl.sh set -euo pipefail : "${REDIS_ADMIN_URL:?Define REDIS_ADMIN_URL (redis://[:password@]host:port)}" : "${IAM_REDIS_PASSWORD:?Define IAM_REDIS_PASSWORD}" : "${CORE_REDIS_PASSWORD:?Define CORE_REDIS_PASSWORD}" # Categorías necesarias para sesiones (hash/string + TTL) y cache # (string/hash/set): keyspace cubre DEL/EXPIRE/EXISTS/TTL/SCAN (el patrón de # llave sigue acotando el alcance real). Sin @scripting (no se usa Lua/EVAL, # menor superficie de ataque) ni @admin/@dangerous. ACL_COMMANDS="-@all +@read +@write +@keyspace +@string +@hash +@set +@sortedset +@connection" # Importante: "reset" debe ir PRIMERO (deja al usuario en blanco); si va # después de "on >password" borra la contraseña que se acaba de fijar. echo "Creando usuario panels_iam_redis (~iam:*)..." redis-cli -u "$REDIS_ADMIN_URL" ACL SETUSER panels_iam_redis \ reset \ on ">${IAM_REDIS_PASSWORD}" \ '~iam:*' '&iam:*' \ $ACL_COMMANDS echo "Creando usuario panels_core_redis (~core:*)..." redis-cli -u "$REDIS_ADMIN_URL" ACL SETUSER panels_core_redis \ reset \ on ">${CORE_REDIS_PASSWORD}" \ '~core:*' '&core:*' \ $ACL_COMMANDS redis-cli -u "$REDIS_ADMIN_URL" ACL SAVE >/dev/null 2>&1 || { echo "Aviso: ACL SAVE falló (normal si no hay aclfile configurado; revisar persistencia de ACLs por separado)." } HOST_PORT=$(echo "$REDIS_ADMIN_URL" | sed -E 's#^redis://##; s#^[^@]*@##') echo "Verificando aislamiento (se espera NOPERM al cruzar de modulo)..." IAM_PROBE=$(redis-cli -u "redis://panels_iam_redis:${IAM_REDIS_PASSWORD}@${HOST_PORT}" GET core:probe 2>&1 || true) if echo "$IAM_PROBE" | grep -qi "NOPERM"; then echo "OK: panels_iam_redis no puede leer llaves core:*" else echo "ADVERTENCIA: no se confirmó NOPERM al probar panels_iam_redis -> core:*. Salida: $IAM_PROBE" fi CORE_PROBE=$(redis-cli -u "redis://panels_core_redis:${CORE_REDIS_PASSWORD}@${HOST_PORT}" GET iam:probe 2>&1 || true) if echo "$CORE_PROBE" | grep -qi "NOPERM"; then echo "OK: panels_core_redis no puede leer llaves iam:*" else echo "ADVERTENCIA: no se confirmó NOPERM al probar panels_core_redis -> iam:*. Salida: $CORE_PROBE" fi echo "Listo. Guarda IAM_REDIS_PASSWORD/CORE_REDIS_PASSWORD como secrets (REDIS_URL_IAM/REDIS_URL_CORE)."