Ajout d'un script Python pour synchroniser les droits administrateurs dans Nextcloud et mise à jour du script de synchronisation existant pour utiliser ce nouveau script. Configuration des permissions et ajout du script à cron pour une exécution horaire.
This commit is contained in:
parent
f0ffd6d709
commit
107dd922bb
@ -84,7 +84,7 @@
|
||||
--mapping-uid preferred_username
|
||||
--mapping-display-name name
|
||||
--mapping-email email
|
||||
--mapping-groups groups
|
||||
--mapping-groups realm_roles
|
||||
--mapping-quota quota
|
||||
--unique-uid preferred_username
|
||||
--group-provisioning true
|
||||
@ -109,3 +109,25 @@
|
||||
until: allow_local_remote_servers is success
|
||||
retries: 3
|
||||
delay: 5
|
||||
|
||||
- name: Copier le script de synchronisation des droits admin
|
||||
copy:
|
||||
src: "{{ git_dest }}/nextcloud/sync_admin_rights.sh"
|
||||
dest: "/etc/cron.hourly/sync_admin_rights"
|
||||
mode: "0755"
|
||||
remote_src: yes
|
||||
register: copy_script
|
||||
until: copy_script is success
|
||||
retries: 3
|
||||
delay: 5
|
||||
|
||||
- name: Configurer les permissions du script
|
||||
file:
|
||||
path: "/etc/cron.hourly/sync_admin_rights"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
register: set_permissions
|
||||
until: set_permissions is success
|
||||
retries: 3
|
||||
delay: 5
|
||||
|
||||
@ -9,10 +9,12 @@ NC='\033[0m' # No Color
|
||||
SUDO_PASSWORD="12345"
|
||||
|
||||
# Liste des playbooks à exécuter
|
||||
#TODO: Supprimer "playbooks/dev/3_1_keycloak_dev.yml"
|
||||
PLAYBOOKS=(
|
||||
"playbooks/1_docker.yml"
|
||||
"playbooks/2_portainer.yml"
|
||||
"playbooks/3_keycloak.yml"
|
||||
"playbooks/dev/3_1_keycloak_dev.yml"
|
||||
"playbooks/4_mysql.yml"
|
||||
"playbooks/5_nextcloud.yml"
|
||||
"playbooks/0_front.yml"
|
||||
|
||||
@ -2,6 +2,7 @@ import { getServerSession } from "next-auth";
|
||||
import { authOptions } from "../../auth/[...nextauth]/route";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
//TODO: Ajouter la suppression automatique du compte Nextcloud
|
||||
export async function DELETE(
|
||||
req: Request,
|
||||
{ params }: { params: { id: string } }
|
||||
|
||||
@ -1,58 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Activer le mode debug et sortie en cas d'erreur
|
||||
set -e
|
||||
set -u
|
||||
# Chemin vers les scripts
|
||||
SCRIPT_DIR="/opt/Neah-Enkun/nextcloud"
|
||||
PYTHON_SCRIPT="${SCRIPT_DIR}/sync_admins.py"
|
||||
LOG_FILE="/var/log/nextcloud_admin_sync.log"
|
||||
|
||||
# Configuration
|
||||
CONTAINER="neah-nextcloud"
|
||||
LOG_FILE="/var/log/nextcloud/admin_sync.log"
|
||||
# Nom du conteneur Nextcloud
|
||||
CONTAINER_NAME="neah-nextcloud"
|
||||
|
||||
log() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
# Vérifier que le conteneur est en cours d'exécution
|
||||
if ! docker ps | grep -q $CONTAINER_NAME; then
|
||||
echo "$(date) - Le conteneur $CONTAINER_NAME n'est pas en cours d'exécution" >> $LOG_FILE
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Créer le répertoire de logs si nécessaire
|
||||
mkdir -p "$(dirname "$LOG_FILE")"
|
||||
# Exécuter le script Python
|
||||
echo "$(date) - Lancement de la synchronisation des administrateurs" >> $LOG_FILE
|
||||
python3 $PYTHON_SCRIPT --container $CONTAINER_NAME
|
||||
|
||||
log "Début de la synchronisation des droits administrateurs"
|
||||
# Vérifier le code de sortie
|
||||
EXIT_CODE=$?
|
||||
if [ $EXIT_CODE -ne 0 ]; then
|
||||
echo "$(date) - La synchronisation a échoué avec le code $EXIT_CODE" >> $LOG_FILE
|
||||
exit $EXIT_CODE
|
||||
fi
|
||||
|
||||
# Récupérer la liste des administrateurs actuels
|
||||
log "Récupération des administrateurs actuels..."
|
||||
current_admins=$(docker exec -u 33 $CONTAINER php occ user:list --output=json | jq -r 'to_entries[] | select(.value.isEnabled == true and .value.isAdmin == true) | .key')
|
||||
|
||||
# Pour chaque admin actuel
|
||||
for admin in $current_admins; do
|
||||
log "Vérification des droits pour l'administrateur: $admin"
|
||||
|
||||
# Vérifier si l'utilisateur est dans le groupe admin
|
||||
is_in_admin_group=$(docker exec -u 33 $CONTAINER php occ group:list --output=json | \
|
||||
jq -r --arg group "admin" --arg user "$admin" '.[$group].users | contains([$user]) // false')
|
||||
|
||||
if [ "$is_in_admin_group" = "false" ]; then
|
||||
log "Retrait des droits admin pour: $admin"
|
||||
docker exec -u 33 $CONTAINER php occ user:info "$admin" --output=json
|
||||
docker exec -u 33 $CONTAINER php occ group:removeuser admin "$admin"
|
||||
fi
|
||||
done
|
||||
|
||||
# Récupérer la liste des membres du groupe admin
|
||||
log "Récupération des membres du groupe admin..."
|
||||
admin_group_members=$(docker exec -u 33 $CONTAINER php occ group:list --output=json | \
|
||||
jq -r '.admin.users[]? // empty')
|
||||
|
||||
# Pour chaque membre du groupe admin
|
||||
for member in $admin_group_members; do
|
||||
log "Vérification des droits admin pour le membre: $member"
|
||||
|
||||
# Vérifier si l'utilisateur a les droits admin
|
||||
is_admin=$(docker exec -u 33 $CONTAINER php occ user:list --output=json | \
|
||||
jq -r --arg user "$member" '.[$user].isAdmin // false')
|
||||
|
||||
if [ "$is_admin" = "false" ]; then
|
||||
log "Ajout des droits admin pour: $member"
|
||||
docker exec -u 33 $CONTAINER php occ group:adduser admin "$member"
|
||||
fi
|
||||
done
|
||||
|
||||
log "Fin de la synchronisation des droits administrateurs"
|
||||
echo "$(date) - Synchronisation terminée avec succès" >> $LOG_FILE
|
||||
exit 0
|
||||
166
nextcloud/sync_admins.py
Normal file
166
nextcloud/sync_admins.py
Normal file
@ -0,0 +1,166 @@
|
||||
import subprocess
|
||||
import logging
|
||||
import json
|
||||
import argparse
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
# Configuration du logging
|
||||
log_file = "/var/log/nextcloud_admin_sync.log"
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s [%(levelname)s] %(message)s",
|
||||
handlers=[
|
||||
logging.FileHandler(log_file),
|
||||
logging.StreamHandler(sys.stdout)
|
||||
]
|
||||
)
|
||||
logger = logging.getLogger("admin_sync")
|
||||
|
||||
def run_command(command):
|
||||
"""Exécute une commande shell et retourne le résultat"""
|
||||
logger.debug(f"Exécution de la commande: {command}")
|
||||
try:
|
||||
result = subprocess.run(command, shell=True, check=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
text=True)
|
||||
return result.stdout.strip()
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.error(f"Erreur lors de l'exécution de la commande: {e}")
|
||||
logger.error(f"Sortie d'erreur: {e.stderr}")
|
||||
return None
|
||||
|
||||
def get_nextcloud_groups(container_name):
|
||||
"""Récupère tous les groupes Nextcloud avec leurs membres"""
|
||||
cmd = f"docker exec -u 33 {container_name} php occ group:list --output=json"
|
||||
output = run_command(cmd)
|
||||
if output:
|
||||
try:
|
||||
return json.loads(output)
|
||||
except json.JSONDecodeError:
|
||||
logger.error("Impossible de décoder la sortie JSON des groupes")
|
||||
return {}
|
||||
return {}
|
||||
|
||||
def get_group_members(groups_data, group_name):
|
||||
"""Récupère les membres d'un groupe spécifique à partir des données de group:list"""
|
||||
if group_name in groups_data:
|
||||
return groups_data[group_name]
|
||||
return []
|
||||
|
||||
def get_admin_groups(container_name, groups):
|
||||
"""Identifie les groupes admin"""
|
||||
admin_groups = []
|
||||
for group_name in groups:
|
||||
# Vérifier si le nom du groupe est 'admin'
|
||||
if group_name == 'admin':
|
||||
admin_groups.append(group_name)
|
||||
else:
|
||||
# Vérifier si le displayName du groupe est 'admin'
|
||||
cmd = f"docker exec -u 33 {container_name} php occ group:info {group_name} --output=json"
|
||||
output = run_command(cmd)
|
||||
if output:
|
||||
try:
|
||||
group_info = json.loads(output)
|
||||
if 'displayName' in group_info and group_info['displayName'] == 'admin':
|
||||
admin_groups.append(group_name)
|
||||
except json.JSONDecodeError:
|
||||
logger.error(f"Impossible de décoder les infos du groupe {group_name}")
|
||||
|
||||
return admin_groups
|
||||
|
||||
def get_current_admins(container_name):
|
||||
"""Récupère la liste actuelle des administrateurs en utilisant la commande group:list pour le groupe admin"""
|
||||
cmd = f"docker exec -u 33 {container_name} php occ group:list --output=json"
|
||||
output = run_command(cmd)
|
||||
if output:
|
||||
try:
|
||||
groups_data = json.loads(output)
|
||||
# Le groupe "admin" contient les administrateurs Nextcloud
|
||||
if "admin" in groups_data:
|
||||
return groups_data["admin"]
|
||||
else:
|
||||
logger.warning("Groupe 'admin' non trouvé dans Nextcloud")
|
||||
return []
|
||||
except json.JSONDecodeError:
|
||||
logger.error("Impossible de décoder la sortie JSON des groupes")
|
||||
return []
|
||||
|
||||
def set_admin_status(container_name, username, is_admin=True):
|
||||
"""Définit ou révoque le statut d'administrateur pour un utilisateur en ajoutant/retirant l'utilisateur du groupe admin"""
|
||||
if is_admin:
|
||||
cmd = f"docker exec -u 33 {container_name} php occ group:adduser admin {username}"
|
||||
status = "accordé"
|
||||
else:
|
||||
cmd = f"docker exec -u 33 {container_name} php occ group:removeuser admin {username}"
|
||||
status = "révoqué"
|
||||
|
||||
output = run_command(cmd)
|
||||
if output is not None:
|
||||
logger.info(f"Statut d'administrateur {status} pour {username}")
|
||||
return True
|
||||
else:
|
||||
logger.error(f"Impossible de {status} le statut d'administrateur pour {username}")
|
||||
return False
|
||||
|
||||
def main(container_name):
|
||||
logger.info("=== Début de la synchronisation des administrateurs ===")
|
||||
|
||||
# Récupération de tous les groupes avec leurs membres
|
||||
groups_data = get_nextcloud_groups(container_name)
|
||||
if not groups_data:
|
||||
logger.error("Impossible de récupérer les groupes Nextcloud")
|
||||
return False
|
||||
|
||||
groups = list(groups_data.keys())
|
||||
logger.info(f"Groupes trouvés: {len(groups)}")
|
||||
|
||||
# Identification des groupes admin
|
||||
admin_groups = get_admin_groups(container_name, groups)
|
||||
logger.info(f"Groupes admin identifiés: {admin_groups}")
|
||||
|
||||
# Récupération des utilisateurs dans les groupes admin
|
||||
should_be_admins = set()
|
||||
for group in admin_groups:
|
||||
members = get_group_members(groups_data, group)
|
||||
logger.info(f"Groupe {group}: {len(members)} membres")
|
||||
should_be_admins.update(members)
|
||||
|
||||
logger.info(f"Utilisateurs qui devraient être administrateurs: {len(should_be_admins)}")
|
||||
|
||||
# Récupération des administrateurs actuels
|
||||
current_admins = get_current_admins(container_name)
|
||||
logger.info(f"Administrateurs actuels: {len(current_admins)}")
|
||||
|
||||
# Attribution des droits admin aux nouveaux admins
|
||||
for username in should_be_admins:
|
||||
if username not in current_admins:
|
||||
logger.info(f"Attribution des droits admin à {username}")
|
||||
set_admin_status(container_name, username, True)
|
||||
|
||||
# Révocation des droits admin pour ceux qui ne sont plus dans un groupe admin
|
||||
for username in current_admins:
|
||||
if username not in should_be_admins:
|
||||
logger.info(f"Révocation des droits admin pour {username}")
|
||||
set_admin_status(container_name, username, False)
|
||||
|
||||
# Résumé
|
||||
new_admins = get_current_admins(container_name)
|
||||
logger.info("=== Résumé de la synchronisation ===")
|
||||
logger.info(f"Groupes admin: {', '.join(admin_groups)}")
|
||||
logger.info(f"Utilisateurs dans des groupes admin: {len(should_be_admins)}")
|
||||
logger.info(f"Administrateurs avant synchronisation: {len(current_admins)}")
|
||||
logger.info(f"Administrateurs après synchronisation: {len(new_admins)}")
|
||||
logger.info(f"Ajouts: {len(should_be_admins - set(current_admins))}")
|
||||
logger.info(f"Suppressions: {len(set(current_admins) - should_be_admins)}")
|
||||
logger.info("=== Fin de la synchronisation ===")
|
||||
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Synchronise les administrateurs Nextcloud avec Keycloak')
|
||||
parser.add_argument('--container', default='neah-nextcloud',
|
||||
help='Nom du conteneur Nextcloud (défaut: neah-nextcloud)')
|
||||
args = parser.parse_args()
|
||||
|
||||
main(args.container)
|
||||
Loading…
x
Reference in New Issue
Block a user