diff --git a/app/models.py b/app/models.py
index 5ed6eaf..c3ef0c0 100644
--- a/app/models.py
+++ b/app/models.py
@@ -172,7 +172,7 @@ class Alarm(db.Model):
bridge = db.relationship("Bridge", back_populates="alarms")
def update_state(self, state: AlarmState, text: str):
- if self.state != state:
+ if self.alarm_state != state:
self.state_changed = datetime.utcnow()
self.alarm_state = state
self.text = text
diff --git a/app/portal/templates/alarms.html.j2 b/app/portal/templates/alarms.html.j2
index b039b70..362cdbe 100644
--- a/app/portal/templates/alarms.html.j2
+++ b/app/portal/templates/alarms.html.j2
@@ -3,7 +3,7 @@
{% block content %}
Alarms
- Proxies
+
@@ -11,6 +11,8 @@
Resource |
Type |
State |
+ Message |
+ Last Update |
@@ -18,11 +20,15 @@
{% if alarm.target == "proxy" %}
Proxy: {{ alarm.proxy.url }} ({{ alarm.proxy.origin.domain_name }}) |
+ {% elif alarm.target == "origin" %}
+ Origin: {{ alarm.origin.domain_name }} |
{% elif alarm.target == "service/cloudfront" %}
AWS CloudFront |
{% endif %}
{{ alarm.alarm_type }} |
{{ alarm.alarm_state.name }} |
+ {{ alarm.text }} |
+ {{ alarm.last_updated.strftime("%a, %d %b %Y %H:%M:%S") }} |
{% endfor %}
diff --git a/app/terraform/block_ooni.py b/app/terraform/block_ooni.py
new file mode 100644
index 0000000..b1d3834
--- /dev/null
+++ b/app/terraform/block_ooni.py
@@ -0,0 +1,79 @@
+from collections import defaultdict
+from datetime import datetime
+from datetime import timedelta
+from typing import Dict
+
+import requests
+
+from app import app
+from app.extensions import db
+from app.models import Origin, AlarmState, Alarm
+
+
+def check_origin(domain_name: str):
+ start_date = (datetime.utcnow() - timedelta(days=2)).strftime("%Y-%m-%dT%H%%3A%M")
+ end_date = datetime.utcnow().strftime("%Y-%m-%dT%H%%3A%M")
+ api_url = f"https://api.ooni.io/api/v1/measurements?domain={domain_name}&since={start_date}&until={end_date}"
+ result = defaultdict(lambda: {"anomaly": 0, "confirmed": 0, "failure": 0, "ok": 0})
+ return _check_origin(api_url, result)
+
+
+def _check_origin(api_url: str, result: Dict):
+ print(f"Processing {api_url}")
+ req = requests.get(api_url).json()
+ if not req['results']:
+ return result
+ for r in req['results']:
+ not_ok = False
+ for s in ["anomaly", "confirmed", "failure"]:
+ if s in r and r[s]:
+ result[r["probe_cc"]][s] += 1
+ not_ok = True
+ break
+ if not not_ok:
+ result[r["probe_cc"]]["ok"] += 1
+ if req['metadata']['next_url']:
+ return _check_origin(req['metadata']['next_url'], result)
+ return result
+
+
+def threshold_origin(domain_name):
+ ooni = check_origin(domain_name)
+ for country in ooni:
+ total = sum([
+ ooni[country]["anomaly"],
+ ooni[country]["confirmed"],
+ ooni[country]["failure"],
+ ooni[country]["ok"]
+ ])
+ total_blocks = sum([
+ ooni[country]["anomaly"],
+ ooni[country]["confirmed"]
+ ])
+ block_perc = round((total_blocks / total * 100), 1)
+ ooni[country]["block_perc"] = block_perc
+ ooni[country]["state"] = AlarmState.CRITICAL if block_perc > 20 else AlarmState.OK
+ ooni[country]["message"] = f"Blocked in {block_perc}% of measurements"
+ return ooni
+
+
+def set_ooni_alarm(origin_id: int, country: str, state: AlarmState, text: str):
+ alarm = Alarm.query.filter(
+ Alarm.origin_id == origin_id,
+ Alarm.alarm_type == f"origin-block-ooni-{country}"
+ ).first()
+ if alarm is None:
+ alarm = Alarm()
+ alarm.origin_id = origin_id
+ alarm.alarm_type = f"origin-block-ooni-{country}"
+ alarm.target = "origin"
+ db.session.add(alarm)
+ alarm.update_state(state, text)
+
+
+with app.app_context():
+ origins = Origin.query.filter(Origin.destroyed == None).all()
+ for origin in origins:
+ ooni = threshold_origin(origin.domain_name)
+ for country in ooni:
+ set_ooni_alarm(origin.id, country.lower(), ooni[country]["state"], ooni[country]["message"])
diff --git a/app/terraform/proxy_check.py b/app/terraform/proxy_check.py
index 06c0cf1..d3b788b 100644
--- a/app/terraform/proxy_check.py
+++ b/app/terraform/proxy_check.py
@@ -14,6 +14,7 @@ def set_http_alarm(proxy_id: int, state: AlarmState, text: str):
alarm = Alarm()
alarm.proxy_id = proxy_id
alarm.alarm_type = "http-status"
+ alarm.target = "proxy"
db.session.add(alarm)
alarm.update_state(state, text)