majuna/app/terraform/block_ooni.py

86 lines
3 KiB
Python
Raw Permalink Normal View History

2022-04-20 15:34:11 +01:00
from collections import defaultdict
from datetime import datetime, timedelta, timezone
from typing import Any, Dict, Tuple
2022-04-20 15:34:11 +01:00
import requests
from app.alarms import get_or_create_alarm
2022-04-20 15:34:11 +01:00
from app.extensions import db
from app.models.alarms import AlarmState
2022-04-22 14:29:24 +01:00
from app.models.mirrors import Origin
from app.terraform import BaseAutomation
2022-04-20 15:34:11 +01:00
2022-05-16 11:44:03 +01:00
def check_origin(domain_name: str) -> Dict[str, Any]:
2024-12-06 18:15:47 +00:00
start_date = (datetime.now(tz=timezone.utc) - timedelta(days=1)).strftime(
"%Y-%m-%dT%H%%3A%M"
)
end_date = datetime.now(tz=timezone.utc).strftime("%Y-%m-%dT%H%%3A%M")
2022-04-20 15:34:11 +01:00
api_url = f"https://api.ooni.io/api/v1/measurements?domain={domain_name}&since={start_date}&until={end_date}"
2024-12-06 18:15:47 +00:00
result: Dict[str, Dict[str, int]] = defaultdict(
lambda: {"anomaly": 0, "confirmed": 0, "failure": 0, "ok": 0}
)
2022-04-20 15:34:11 +01:00
return _check_origin(api_url, result)
2022-05-16 11:44:03 +01:00
def _check_origin(api_url: str, result: Dict[str, Any]) -> Dict[str, Any]:
2022-04-20 15:34:11 +01:00
print(f"Processing {api_url}")
req = requests.get(api_url, timeout=30).json()
2024-12-06 18:15:47 +00:00
if "results" not in req or not req["results"]:
2022-04-20 15:34:11 +01:00
return result
2024-12-06 18:15:47 +00:00
for r in req["results"]:
2022-04-20 15:34:11 +01:00
not_ok = False
2022-06-17 12:42:42 +01:00
for status in ["anomaly", "confirmed", "failure"]:
if status in r and r[status]:
result[r["probe_cc"]][status] += 1
2022-04-20 15:34:11 +01:00
not_ok = True
break
if not not_ok:
result[r["probe_cc"]]["ok"] += 1
2024-12-06 18:15:47 +00:00
if req["metadata"]["next_url"]:
return _check_origin(req["metadata"]["next_url"], result)
2022-04-20 15:34:11 +01:00
return result
2022-05-16 11:44:03 +01:00
def threshold_origin(domain_name: str) -> Dict[str, Any]:
2022-04-20 15:34:11 +01:00
ooni = check_origin(domain_name)
for country in ooni:
2024-12-06 18:15:47 +00:00
total = sum(
[
ooni[country]["anomaly"],
ooni[country]["confirmed"],
ooni[country]["failure"],
ooni[country]["ok"],
]
)
total_blocks = sum([ooni[country]["anomaly"], ooni[country]["confirmed"]])
2022-04-20 15:34:11 +01:00
block_perc = round((total_blocks / total * 100), 1)
ooni[country]["block_perc"] = block_perc
2024-12-06 18:15:47 +00:00
ooni[country]["state"] = (
AlarmState.WARNING if block_perc > 20 else AlarmState.OK
)
2022-04-20 15:34:11 +01:00
ooni[country]["message"] = f"Blocked in {block_perc}% of measurements"
return ooni
class BlockOONIAutomation(BaseAutomation):
2022-06-17 12:42:42 +01:00
"""
Automation task to import origin and/or proxy reachability results from OONI.
"""
short_name = "block_ooni"
description = "Import origin and/or proxy reachability results from OONI"
frequency = 240
def automate(self, full: bool = False) -> Tuple[bool, str]:
2022-05-16 13:29:48 +01:00
origins = Origin.query.filter(Origin.destroyed.is_(None)).all()
for origin in origins:
ooni = threshold_origin(origin.domain_name)
for country in ooni:
2024-12-06 18:15:47 +00:00
alarm = get_or_create_alarm(
origin.brn, f"origin-block-ooni-{country.lower()}"
)
alarm.update_state(ooni[country]["state"], ooni[country]["message"])
db.session.commit()
return True, ""