mirror of
https://github.com/deunix-educ/Fail2banMqttActionBanishment.git
synced 2026-08-24 03:11:58 +02:00
71 lines
3.0 KiB
Bash
Executable File
71 lines
3.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# sign-node-csr.sh — signe une CSR de noeud avec la CA privée du master,
|
|
# ajoute l'entitlement ACL nécessaire, redémarre mosquitto. Coeur commun à
|
|
# generate-node-cert.sh (flux manuel) et à l'endpoint /api/join/ (flux par
|
|
# jeton, banevents/views.py::join_node) — un seul chemin de code qui
|
|
# touche ca.key, pas deux implémentations à maintenir en parallèle.
|
|
#
|
|
# Usage : sudo ./sign-node-csr.sh <nom_du_noeud> <fichier_csr>
|
|
# Écrit le certificat signé (PEM) sur STDOUT — tous les messages
|
|
# informatifs/d'erreur vont sur STDERR, pour que stdout reste exploitable
|
|
# programmatiquement (ex. capturé tel quel par un appelant Python).
|
|
|
|
set -euo pipefail
|
|
|
|
NODE_NAME="${1:?Usage: $0 <nom_du_noeud> <fichier_csr>}"
|
|
CSR_FILE="${2:?Usage: $0 <nom_du_noeud> <fichier_csr>}"
|
|
CA_DIR="${CA_DIR:-/etc/mosquitto/master-ca}"
|
|
|
|
if [ ! -f "$CA_DIR/ca.key" ]; then
|
|
echo "CA introuvable dans $CA_DIR — lancer master-ca-init.sh d'abord." >&2
|
|
exit 1
|
|
fi
|
|
if [ ! -f "$CSR_FILE" ]; then
|
|
echo "CSR introuvable : $CSR_FILE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
TMP_CERT="$(mktemp)"
|
|
trap 'rm -f "$TMP_CERT"' EXIT
|
|
|
|
openssl x509 -req -in "$CSR_FILE" \
|
|
-CA "$CA_DIR/ca.crt" -CAkey "$CA_DIR/ca.key" -CAcreateserial \
|
|
-out "$TMP_CERT" -days 825 -sha256 2>/dev/null
|
|
|
|
# Entitlement ACL pour ce noeud dans master-acl.conf (idempotent). Les
|
|
# règles globales non scopées (pattern write fail2ban/%u/ban, pattern
|
|
# read fail2ban/%u/action, topic read fail2ban/broadcast/action, cf.
|
|
# generic/mosquitto/master-acl.conf) suffisent pour la publication (%u),
|
|
# mais PAS pour la lecture du canal de diffusion : SUBSCRIBE sur
|
|
# fail2ban/broadcast/action reçoit bien un SUBACK positif, mais aucun
|
|
# message n'est jamais livré (constaté avec mosquitto_sub -v : SUBACK OK,
|
|
# zéro PUBLISH reçu). Seule une règle "topic read" explicite sous un bloc
|
|
# "user <nom>" dédié fait effectivement recevoir les messages (piège
|
|
# mosquitto : un SUBACK positif ne prouve pas qu'un SUBSCRIBE est
|
|
# autorisé, cf. CONTEXT.md).
|
|
ACL_FILE="${ACL_FILE:-/etc/mosquitto/master-acl.conf}"
|
|
if [ -f "$ACL_FILE" ]; then
|
|
if ! grep -q "^user $NODE_NAME\$" "$ACL_FILE"; then
|
|
echo "-> ajout de l'entitlement ACL pour '$NODE_NAME' dans $ACL_FILE" >&2
|
|
{
|
|
echo ""
|
|
echo "user $NODE_NAME"
|
|
echo "topic read fail2ban/broadcast/action"
|
|
echo "topic read fail2ban/broadcast/roster"
|
|
} >> "$ACL_FILE"
|
|
if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet mosquitto.service; then
|
|
systemctl restart mosquitto.service
|
|
fi
|
|
else
|
|
echo "-> entitlement ACL pour '$NODE_NAME' déjà présent dans $ACL_FILE, inchangé" >&2
|
|
fi
|
|
else
|
|
echo "-> ATTENTION : $ACL_FILE introuvable (pas sur le master ?) — pas d'entitlement ACL ajouté." >&2
|
|
echo " Le noeud '$NODE_NAME' ne recevra aucun SYNC_BAN tant que ce bloc n'est pas ajouté à la main :" >&2
|
|
echo " user $NODE_NAME" >&2
|
|
echo " topic read fail2ban/broadcast/action" >&2
|
|
echo " topic read fail2ban/broadcast/roster" >&2
|
|
fi
|
|
|
|
cat "$TMP_CERT"
|