From f050b3c5b86bf6c844fc67597d6949324d75be3d Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 31 Jul 2019 01:08:21 +0200 Subject: [PATCH] First version of http exposure diagnosis --- data/hooks/diagnosis/16-http.py | 54 ++++++++++++++++++++++++++++ data/templates/nginx/server.tpl.conf | 4 +++ locales/en.json | 4 +++ src/yunohost/app.py | 3 +- 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 data/hooks/diagnosis/16-http.py diff --git a/data/hooks/diagnosis/16-http.py b/data/hooks/diagnosis/16-http.py new file mode 100644 index 000000000..b6b92fc77 --- /dev/null +++ b/data/hooks/diagnosis/16-http.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +import os +import random +import requests + +from yunohost.diagnosis import Diagnoser +from yunohost.domain import domain_list +from yunohost.utils.error import YunohostError + + +class HttpDiagnoser(Diagnoser): + + id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] + cache_duration = 3600 + + def run(self): + + nonce_digits = "0123456789abcedf" + + all_domains = domain_list()["domains"] + for domain in all_domains: + + nonce = ''.join(random.choice(nonce_digits) for i in range(16)) + os.system("rm -rf /tmp/.well-known/ynh-diagnosis/") + os.system("mkdir -p /tmp/.well-known/ynh-diagnosis/") + os.system("touch /tmp/.well-known/ynh-diagnosis/%s" % nonce) + + try: + r = requests.post('https://ynhdiagnoser.netlib.re/check-http', json={'domain': domain, "nonce": nonce}, timeout=30).json() + print(r) + if "status" not in r.keys(): + raise Exception("Bad syntax for response ? Raw json: %s" % str(r)) + elif r["status"] == "error" and ("code" not in r.keys() or r["code"] not in ["error_http_check_connection_error", "error_http_check_unknown_error"]): + if "content" in r.keys(): + raise Exception(r["content"]) + else: + raise Exception("Bad syntax for response ? Raw json: %s" % str(r)) + except Exception as e: + print(e) + raise YunohostError("diagnosis_http_could_not_diagnose", error=e) + + if r["status"] == "ok": + yield dict(meta={"domain": domain}, + status="SUCCESS", + summary=("diagnosis_http_ok", {"domain": domain})) + else: + yield dict(meta={"domain": domain}, + status="ERROR", + summary=("diagnosis_http_unreachable", {"domain": domain})) + + +def main(args, env, loggers): + return HttpDiagnoser(args, env, loggers).diagnose() diff --git a/data/templates/nginx/server.tpl.conf b/data/templates/nginx/server.tpl.conf index 4a5e91557..9acc6c0fd 100644 --- a/data/templates/nginx/server.tpl.conf +++ b/data/templates/nginx/server.tpl.conf @@ -16,6 +16,10 @@ server { return 301 https://$http_host$request_uri; } + location /.well-known/ynh-diagnosis/ { + alias /tmp/.well-known/ynh-diagnosis/; + } + location /.well-known/autoconfig/mail/ { alias /var/www/.well-known/{{ domain }}/autoconfig/mail/; } diff --git a/locales/en.json b/locales/en.json index 0a2204725..ac44122fe 100644 --- a/locales/en.json +++ b/locales/en.json @@ -178,9 +178,13 @@ "diagnosis_description_services": "Services status check", "diagnosis_description_diskusage": "Disk usage", "diagnosis_description_ports": "Ports exposure", + "diagnosis_description_http": "HTTP exposure", "diagnosis_ports_could_not_diagnose": "Could not diagnose if ports are reachable from outside. Error: {error}", "diagnosis_ports_unreachable": "Port {port} is not reachable from outside.", "diagnosis_ports_ok": "Relevant ports are reachable from outside!", + "diagnosis_http_could_not_diagnose": "Could not diagnose if domain is reachable from outside. Error: {error}", + "diagnosis_http_ok": "Domain {domain} is reachable from outside.", + "diagnosis_http_unreachable": "Domain {domain} is unreachable through HTTP from outside.", "domain_cannot_remove_main": "Cannot remove main domain. Set a new main domain first", "domain_cert_gen_failed": "Could not generate certificate", "domain_created": "Domain created", diff --git a/src/yunohost/app.py b/src/yunohost/app.py index e9e6ce14e..b4962d5f6 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -1463,7 +1463,8 @@ def app_ssowatconf(): for domain in domains: skipped_urls.extend([domain + '/yunohost/admin', domain + '/yunohost/api']) - # Authorize ACME challenge url + # Authorize ynh remote diagnosis, ACME challenge and mail autoconfig urls + skipped_regex.append("^[^/]*/%.well%-known/ynh%-diagnosis/.*$") skipped_regex.append("^[^/]*/%.well%-known/acme%-challenge/.*$") skipped_regex.append("^[^/]*/%.well%-known/autoconfig/mail/config%-v1%.1%.xml.*$")