From 4cbd1b06c2d572c908a3d7a6d4e82b6738f7a3da Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 31 Jul 2019 21:25:44 +0200 Subject: [PATCH] Add a regenconf diagnoser to report manually modified files... --- data/hooks/diagnosis/70-regenconf.py | 42 +++++++++++++++++++++++++++ locales/en.json | 5 ++++ src/yunohost/regenconf.py | 43 ++++++++++++++-------------- 3 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 data/hooks/diagnosis/70-regenconf.py diff --git a/data/hooks/diagnosis/70-regenconf.py b/data/hooks/diagnosis/70-regenconf.py new file mode 100644 index 000000000..94c41feb5 --- /dev/null +++ b/data/hooks/diagnosis/70-regenconf.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +import os + +from yunohost.diagnosis import Diagnoser +from yunohost.regenconf import manually_modified_files, manually_modified_files_compared_to_debian_default + + +class RegenconfDiagnoser(Diagnoser): + + id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] + cache_duration = 300 + dependencies = [] + + def run(self): + + regenconf_modified_files = manually_modified_files() + debian_modified_files = manually_modified_files_compared_to_debian_default(ignore_handled_by_regenconf=True) + + if regenconf_modified_files == []: + yield dict(meta={"test": "regenconf"}, + status="SUCCESS", + summary=("diagnosis_regenconf_allgood", {}) + ) + else: + for f in regenconf_modified_files: + yield dict(meta={"test": "regenconf", "file": f}, + status="WARNING", + summary=("diagnosis_regenconf_manually_modified", {"file": f}), + details=[("diagnosis_regenconf_manually_modified_details", {})] + ) + + for f in debian_modified_files: + yield dict(meta={"test": "debian", "file": f}, + status="WARNING", + summary=("diagnosis_regenconf_manually_modified_debian", {"file": f}), + details=[("diagnosis_regenconf_manually_modified_debian_details", {})] + ) + + +def main(args, env, loggers): + return RegenconfDiagnoser(args, env, loggers).diagnose() diff --git a/locales/en.json b/locales/en.json index 65b3ef64d..105891571 100644 --- a/locales/en.json +++ b/locales/en.json @@ -174,6 +174,11 @@ "diagnosis_diskusage_verylow": "Storage {mountpoint} (on device {device}) has only {free_percent}% space remaining. You should really consider cleaning up some space.", "diagnosis_diskusage_low": "Storage {mountpoint} (on device {device}) has only {free_percent}% space remaining. Be careful", "diagnosis_diskusage_ok": "Storage {mountpoint} (on device {device}) still has {free_percent}% space left!", + "diagnosis_regenconf_allgood": "All configurations files are in line with the recommended configuration!", + "diagnosis_regenconf_manually_modified": "Configuration file {file} was manually modified.", + "diagnosis_regenconf_manually_modified_details": "This is probably OK as long as you know what you're doing ;) !", + "diagnosis_regenconf_manually_modified_debian": "Configuration file {file} was manually modified compared to Debian's default.", + "diagnosis_regenconf_manually_modified_debian_details": "This may probably be OK, but gotta keep an eye on it...", "diagnosis_description_ip": "Internet connectivity", "diagnosis_description_dnsrecords": "DNS records", "diagnosis_description_services": "Services status check", diff --git a/src/yunohost/regenconf.py b/src/yunohost/regenconf.py index b7a42dd9d..b09824d58 100644 --- a/src/yunohost/regenconf.py +++ b/src/yunohost/regenconf.py @@ -525,31 +525,32 @@ def _process_regen_conf(system_conf, new_conf=None, save=True): def manually_modified_files(): - # We do this to have --quiet, i.e. don't throw a whole bunch of logs - # just to fetch this... - # Might be able to optimize this by looking at what the regen conf does - # and only do the part that checks file hashes... - cmd = "yunohost tools regen-conf --dry-run --output-as json --quiet" - j = json.loads(subprocess.check_output(cmd.split())) - - # j is something like : - # {"postfix": {"applied": {}, "pending": {"/etc/postfix/main.cf": {"status": "modified"}}} - output = [] - for app, actions in j.items(): - for action, files in actions.items(): - for filename, infos in files.items(): - if infos["status"] == "modified": - output.append(filename) + regenconf_categories = _get_regenconf_infos() + for category, infos in regenconf_categories.items(): + conffiles = infos["conffiles"] + for path, hash_ in conffiles.items(): + if hash_ != _calculate_hash(path): + output.append(path) return output -def manually_modified_files_compared_to_debian_default(): +def manually_modified_files_compared_to_debian_default(ignore_handled_by_regenconf=False): # from https://serverfault.com/a/90401 - r = subprocess.check_output("dpkg-query -W -f='${Conffiles}\n' '*' \ - | awk 'OFS=\" \"{print $2,$1}' \ - | md5sum -c 2>/dev/null \ - | awk -F': ' '$2 !~ /OK/{print $1}'", shell=True) - return r.strip().split("\n") + files = subprocess.check_output("dpkg-query -W -f='${Conffiles}\n' '*' \ + | awk 'OFS=\" \"{print $2,$1}' \ + | md5sum -c 2>/dev/null \ + | awk -F': ' '$2 !~ /OK/{print $1}'", shell=True) + files = files.strip().split("\n") + + if ignore_handled_by_regenconf: + regenconf_categories = _get_regenconf_infos() + regenconf_files = [] + for infos in regenconf_categories.values(): + regenconf_files.extend(infos["conffiles"].keys()) + + files = [f for f in files if f not in regenconf_files] + + return files