Adding check_conf
This commit is contained in:
parent
8ae639cb73
commit
d6a35d5b82
25
conf/etc/bash_completion.d/check_conf
Executable file
25
conf/etc/bash_completion.d/check_conf
Executable file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# !! GIT FILE !!
|
||||
# https://framagit.org/zorval/scripts/check-nrpe
|
||||
|
||||
_check_conf() {
|
||||
local cur prev
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
|
||||
if [[ "$cur" == -* ]]; then
|
||||
if [[ "$prev" == --copy-repo-to-local ]] || [[ "$prev" == --copy-local-to-repo ]]; then
|
||||
COMPREPLY=( $(compgen -W "--force" -- "$cur") )
|
||||
else
|
||||
COMPREPLY=( $(compgen -W "--copy-repo-to-local --copy-local-to-repo" -- "$cur") )
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
COMPREPLY=( $(compgen -W "--copy-repo-to-local --copy-local-to-repo --force" -- "$cur") )
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -F _check_conf check_conf
|
@ -29,3 +29,4 @@ command[check_chrony] = /usr/local/bin/check_chrony
|
||||
command[check_reboot] = sudo /usr/sbin/needrestart -p -k
|
||||
command[check_restart] = sudo /usr/sbin/needrestart -p -l
|
||||
command[check_git] = sudo /usr/local/sbin/check_git
|
||||
command[check_conf] = sudo /usr/local/sbin/check_conf
|
||||
|
262
conf/usr/local/sbin/check_conf
Executable file
262
conf/usr/local/sbin/check_conf
Executable file
@ -0,0 +1,262 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
################################################################################
|
||||
# BSD 3-Clause License
|
||||
#
|
||||
# Copyright © 2020-2021 Aurélien Grimal - aurelien.grimal@tech-tips.fr
|
||||
# All rights reserved.
|
||||
#
|
||||
# Please see license file on root of this directory
|
||||
################################################################################
|
||||
|
||||
# !! GIT FILE !!
|
||||
# https://framagit.org/zorval/scripts/check-nrpe
|
||||
|
||||
################################################################################
|
||||
|
||||
# Import des modules
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
import hashlib, platform, os, shutil, argparse, subprocess as sp, re
|
||||
except Exception as e:
|
||||
print("[CRITICAL] Impossible d'importer les modules", e)
|
||||
sys.exit(2)
|
||||
|
||||
# Test si le script est bien lancé en root
|
||||
if os.geteuid() != 0:
|
||||
print("[CRITICAL] Il faut être root pour lancer cette commande")
|
||||
sys.exit(2)
|
||||
|
||||
# Variables
|
||||
|
||||
config_dir = '/srv/git/conf'
|
||||
common_config_dir = 'common'
|
||||
wildcard = '__'
|
||||
git_monitored_repos_file = '/etc/zorval/git-monitored-repos'
|
||||
|
||||
try:
|
||||
with open('/etc/hostname', 'r') as etc_hostname:
|
||||
hostname = etc_hostname.read().rstrip()
|
||||
except Exception:
|
||||
print('[CRITICAL] Erreur lors de la lecture du fichier /etc/hostname')
|
||||
|
||||
# Fonctions
|
||||
|
||||
def hash_bytestr_iter(bytesiter, hasher, ashexstr=False):
|
||||
for block in bytesiter:
|
||||
hasher.update(block)
|
||||
return hasher.hexdigest() if ashexstr else hasher.digest()
|
||||
|
||||
def file_as_blockiter(afile, blocksize=65536):
|
||||
with afile:
|
||||
block = afile.read(blocksize)
|
||||
while len(block) > 0:
|
||||
yield block
|
||||
block = afile.read(blocksize)
|
||||
|
||||
def md5sum(file_path):
|
||||
return hash_bytestr_iter(file_as_blockiter(open(file_path, 'rb')), hashlib.md5())
|
||||
|
||||
def walk_git_conf(directory, level=1):
|
||||
directory = directory.rstrip(os.path.sep)
|
||||
if not os.path.isdir(directory):
|
||||
print("[CRITICAL] Le répertoire", directory, "n'existe pas")
|
||||
sys.exit(2)
|
||||
num_sep = directory.count(os.path.sep)
|
||||
# Au moment du tri, on remplace '__' par '###' car dans l'ordre ASCII, le caractère _ est placé après les lettres
|
||||
# Or pour l'application de la précédence, il doit se trouver avant
|
||||
for root_abs, dirs, files in sorted(os.walk(directory), key=lambda d: d[0].replace("__", "###")):
|
||||
root_abs = root_abs.replace("###", "__")
|
||||
num_sep_this = root_abs.count(os.path.sep)
|
||||
if num_sep_this >= num_sep + 2 and root_abs.split(os.path.sep)[num_sep + 2] == '.git':
|
||||
continue
|
||||
if num_sep_this == 6:
|
||||
root_rel = os.path.basename(root_abs)
|
||||
root_rel_ignore = re.sub('.ignore$', '', root_rel)
|
||||
#print("Analyse de", root_abs, "->", root_rel)
|
||||
if root_rel_ignore in [common_config_dir, hostname] or re.search('^' + root_rel_ignore.replace(wildcard, '.*') + '$', hostname):
|
||||
#print(" -> retenu")
|
||||
yield root_abs
|
||||
else:
|
||||
#print(" -> non retenu")
|
||||
pass
|
||||
if num_sep + level <= num_sep_this:
|
||||
del dirs[:]
|
||||
|
||||
# Arguments du script
|
||||
|
||||
parser = argparse.ArgumentParser(description='Script permettant de surveiller / copier des fichiers entre un dépôt git et la machine locale')
|
||||
exclusive_grp = parser.add_mutually_exclusive_group()
|
||||
exclusive_grp.add_argument('--copy-repo-to-local', action='store_true', help='Copie les fichiers manquants / différents depuis le dépôt git ' + config_dir + ' vers la machine locale')
|
||||
exclusive_grp.add_argument('--copy-local-to-repo', action='store_true', help='Copie les fichiers manquants / différents depuis la machine locale vers le dépôt git ' + config_dir)
|
||||
parser.add_argument('--force', action='store_true', help='Force la copie, mode non-interactif - /!\ Dangereux /!\\')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Liste des répertoires valides contenant les fichiers à analyser/comparer
|
||||
# Les répertoires doivent suivre ce modèle :
|
||||
# - {config_dir}/xxxxxxxx/conf/{common_config_dir}
|
||||
# - {config_dir}/xxxxxxxx/conf/{hostname}
|
||||
# - {config_dir}/xxxxxxxx/conf/{part_of_hostname_followed_by_wildcard_pattern}
|
||||
|
||||
conf_dirs = []
|
||||
for directory in walk_git_conf(config_dir, 3):
|
||||
conf_dirs.append(directory)
|
||||
|
||||
# Stockage dans un dictionnaire de chaque fichier à comparer
|
||||
# Clef : chemin absolu du fichier local
|
||||
# Valeur : chemin absolu du fichier dans le dépôt git
|
||||
# Les fichiers déjà trouvés sont remplacés par les éventuels nouveaux, dans l'ordre de parcours (alphanumérique) de 'conf_dirs'
|
||||
|
||||
git_conf_file_dict = {}
|
||||
for directory in conf_dirs:
|
||||
len_dir = len(directory)
|
||||
#print("\nRépertoire =", directory)
|
||||
for item in os.walk(directory):
|
||||
# Si le fichier contient des fichiers (donc est un répertoire non vide)
|
||||
if len(item[2]) > 0:
|
||||
for f in item[2]:
|
||||
local_f_path = item[0][len_dir:] + '/' + f
|
||||
git_f_path = item[0] + '/' + f
|
||||
if directory.endswith('.ignore'):
|
||||
#print(" -> on oublie", local_f_path)
|
||||
git_conf_file_dict.pop(local_f_path, None)
|
||||
else:
|
||||
#print(" -> on retient", local_f_path)
|
||||
git_conf_file_dict.update({ local_f_path : git_f_path })
|
||||
|
||||
# Génération des listes de fichiers manquants et différents
|
||||
|
||||
different_files_dict = {}
|
||||
missing_files_dict = {}
|
||||
|
||||
for f_local, f_repo in git_conf_file_dict.items():
|
||||
try:
|
||||
local_md5 = md5sum(f_local)
|
||||
repo_md5 = md5sum(f_repo)
|
||||
if local_md5 != repo_md5:
|
||||
different_files_dict.update({ f_local : f_repo })
|
||||
except FileNotFoundError:
|
||||
missing_files_dict.update({ f_local : f_repo })
|
||||
|
||||
# Récupération du statut des dépôts git
|
||||
|
||||
monitored_git_repos = []
|
||||
try:
|
||||
with open(git_monitored_repos_file, 'r') as monitored_repos:
|
||||
for line in monitored_repos:
|
||||
git_repo = line.rstrip()
|
||||
if not os.path.exists(git_repo):
|
||||
print('[CRITICAL]', git_repo, 'n\'existe pas, merci de vérifier le fichier', git_monitored_repos_file)
|
||||
sys.exit(2)
|
||||
if not os.path.isdir(git_repo):
|
||||
print('[CRITICAL]', git_repo, 'n\'est pas un répertoire, merci de vérifier le fichier', git_monitored_repos_file)
|
||||
sys.exit(2)
|
||||
monitored_git_repos.append(git_repo)
|
||||
except FileNotFoundError as e:
|
||||
print('[CRITICAL]', e)
|
||||
sys.exit(2)
|
||||
|
||||
git_repos_locally_modified = []
|
||||
for git_repo in monitored_git_repos:
|
||||
|
||||
p = sp.Popen(['git', '--work-tree=' + git_repo, '--git-dir=' + git_repo + '/.git', 'diff', '--name-only'], stdout=sp.PIPE, stderr=sp.PIPE)
|
||||
stdout, stderr = p.communicate(2)
|
||||
rc = p.returncode
|
||||
stdout = stdout.decode('utf-8').replace('\n', ' ')
|
||||
stderr = stderr.decode('utf-8').replace('\n', ' ')
|
||||
if rc != 0:
|
||||
print('[CRITICAL]', git_repo, stderr, 'rc=' + str(rc))
|
||||
sys.exit(2)
|
||||
if stdout != '':
|
||||
git_repos_locally_modified.append(git_repo)
|
||||
|
||||
# Output
|
||||
|
||||
len_diff = len(different_files_dict)
|
||||
len_miss = len(missing_files_dict)
|
||||
|
||||
if len_diff + len_miss > 0 or len(git_repos_locally_modified) > 0:
|
||||
# If copy
|
||||
if args.copy_repo_to_local or args.copy_local_to_repo:
|
||||
# If there are missing files
|
||||
if len_miss > 0:
|
||||
for f_local, f_repo in missing_files_dict.items():
|
||||
if args.copy_local_to_repo:
|
||||
print("[CRITICAL] Je ne peux pas copier un fichier qui n'existe pas (" + f_local + " vers " + f_repo + ")")
|
||||
else:
|
||||
if not args.force:
|
||||
print("\nMerci de confirmer l'exécution de cette commande :")
|
||||
print("cp", f_repo, f_local)
|
||||
answer = input("Votre réponse ([oui|non]) : ")
|
||||
if args.force or answer.lower() in ['y', 'yes', 'o', 'oui']:
|
||||
try:
|
||||
shutil.copy2(f_repo, f_local)
|
||||
except FileNotFoundError:
|
||||
os.makedirs(os.path.dirname(f_local), mode=0o755)
|
||||
shutil.copy2(f_repo, f_local)
|
||||
print("-", f_local, ": copie effectuée")
|
||||
else:
|
||||
print("-", f_local, ": on ne fait rien")
|
||||
# If there are different files
|
||||
if len_diff > 0:
|
||||
for f_local, f_repo in different_files_dict.items():
|
||||
if not args.force:
|
||||
print("\nMerci de confirmer l'exécution de cette commande :")
|
||||
if args.copy_local_to_repo:
|
||||
print("cp", f_local, f_repo)
|
||||
else:
|
||||
print("cp", f_repo, f_local)
|
||||
answer = input("Votre réponse ([oui|non]) : ")
|
||||
if args.force or answer.lower() in ['y', 'yes', 'o', 'oui']:
|
||||
if args.copy_local_to_repo:
|
||||
shutil.copy2(f_local, f_repo)
|
||||
print("-", f_local, ": copie effectuée")
|
||||
else:
|
||||
shutil.copy2(f_repo, f_local)
|
||||
print("-", f_local, ": copie effectuée")
|
||||
else:
|
||||
print("-", f_local, ": on ne fait rien")
|
||||
# Else : just monitoring
|
||||
else:
|
||||
print('[WARNING] ', end='')
|
||||
if len_miss > 0:
|
||||
if len_miss == 1:
|
||||
print('- 1 fichier manquant ', end='')
|
||||
else:
|
||||
print('-', len_miss, 'fichiers manquants ', end='')
|
||||
if len_diff > 0:
|
||||
if len_diff == 1:
|
||||
print('- 1 fichier différent ', end='')
|
||||
else:
|
||||
print('-', len_diff, 'fichiers différents ', end='')
|
||||
if len(git_repos_locally_modified) > 0:
|
||||
if len(git_repos_locally_modified) == 1:
|
||||
print('- 1 dépôt git modifié')
|
||||
print("\nDépôt git modifié :")
|
||||
else:
|
||||
print('-', len(git_repos_locally_modified), 'dépôts git modifiés')
|
||||
print("\nDépôts git modifiés :")
|
||||
for git_repo in git_repos_locally_modified:
|
||||
print('-', git_repo)
|
||||
if len_miss > 0:
|
||||
if len_miss == 1:
|
||||
print("\nFichier manquant :")
|
||||
else:
|
||||
print("\nFichiers manquants :")
|
||||
for f_local, f_repo in missing_files_dict.items():
|
||||
print("- dépôt :", f_repo)
|
||||
print(" local :", f_local)
|
||||
if len_diff > 0:
|
||||
if len_diff == 1:
|
||||
print("\nFichier différent :")
|
||||
else:
|
||||
print("\nFichiers différents :")
|
||||
for f_local, f_repo in different_files_dict.items():
|
||||
print("- dépôt :", f_repo)
|
||||
print(" local :", f_local)
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("[OK] Cette machine est conforme")
|
||||
sys.exit(0)
|
Loading…
Reference in New Issue
Block a user