123 lines
3.6 KiB
Python
123 lines
3.6 KiB
Python
import os
|
|
import requests
|
|
from datetime import datetime
|
|
|
|
# ----------------------------
|
|
# Config da .env
|
|
# ----------------------------
|
|
CF_API_TOKEN = os.getenv("CF_API_TOKEN")
|
|
CF_ZONE = os.getenv("CF_ZONE")
|
|
CF_SUBDOMAINS = [s.strip() for s in os.getenv("CF_SUBDOMAINS", "").split(",") if s.strip()]
|
|
PUBLIC_IP_API = os.getenv("PUBLIC_IP_API", "https://api.ipify.org")
|
|
|
|
# Validazione configurazione
|
|
if not CF_API_TOKEN or not CF_ZONE or not CF_SUBDOMAINS:
|
|
raise ValueError("Mancano variabili ambiente: CF_API_TOKEN, CF_ZONE, CF_SUBDOMAINS")
|
|
|
|
HEADERS = {
|
|
"Authorization": f"Bearer {CF_API_TOKEN}",
|
|
"Content-Type": "application/json"
|
|
}
|
|
|
|
# ----------------------------
|
|
# Funzioni
|
|
# ----------------------------
|
|
def get_public_ip():
|
|
"""Recupera l'IP pubblico"""
|
|
try:
|
|
ip = requests.get(PUBLIC_IP_API, timeout=5).text.strip()
|
|
return ip
|
|
except Exception:
|
|
return "N/A"
|
|
|
|
_zone_id_cache = None
|
|
|
|
def get_zone_id():
|
|
"""Recupera l'ID della zona Cloudflare (con cache)"""
|
|
global _zone_id_cache
|
|
if _zone_id_cache:
|
|
return _zone_id_cache
|
|
|
|
try:
|
|
resp = requests.get(
|
|
"https://api.cloudflare.com/client/v4/zones",
|
|
headers=HEADERS,
|
|
params={"name": CF_ZONE},
|
|
timeout=10
|
|
).json()
|
|
if resp["success"] and resp["result"]:
|
|
_zone_id_cache = resp["result"][0]["id"]
|
|
return _zone_id_cache
|
|
else:
|
|
raise Exception(f"Zona '{CF_ZONE}' non trovata o errore API.")
|
|
except Exception as e:
|
|
print(f"[ERROR] get_zone_id: {e}")
|
|
return None
|
|
|
|
def get_dns_records():
|
|
"""Recupera i record DNS dei sottodomini"""
|
|
zone_id = get_zone_id()
|
|
if not zone_id:
|
|
return []
|
|
|
|
public_ip = get_public_ip()
|
|
records = []
|
|
|
|
for sub in CF_SUBDOMAINS:
|
|
fqdn = f"{sub}.{CF_ZONE}"
|
|
try:
|
|
resp = requests.get(
|
|
f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records",
|
|
headers=HEADERS,
|
|
params={"name": fqdn},
|
|
timeout=10
|
|
).json()
|
|
|
|
if not resp["success"] or not resp["result"]:
|
|
# Record non trovato
|
|
now = datetime.utcnow().isoformat()
|
|
records.append({
|
|
"name": fqdn,
|
|
"dns_ip": "N/A",
|
|
"public_ip": public_ip,
|
|
"proxied": False,
|
|
"status": "MISSING",
|
|
"last_updated": now,
|
|
"last_updated_human": now
|
|
})
|
|
continue
|
|
|
|
dns = resp["result"][0]
|
|
last_updated = dns.get("modified_on", datetime.utcnow().isoformat())
|
|
records.append({
|
|
"name": fqdn,
|
|
"dns_ip": dns["content"],
|
|
"public_ip": public_ip,
|
|
"proxied": dns["proxied"],
|
|
"status": "OK" if dns["content"] == public_ip else "MISMATCH",
|
|
"last_updated": last_updated,
|
|
"last_updated_human": last_updated
|
|
})
|
|
|
|
except Exception as e:
|
|
print(f"[ERROR] get_dns_records ({fqdn}): {e}")
|
|
now = datetime.utcnow().isoformat()
|
|
records.append({
|
|
"name": fqdn,
|
|
"dns_ip": "ERROR",
|
|
"public_ip": public_ip,
|
|
"proxied": False,
|
|
"status": "ERROR",
|
|
"last_updated": now,
|
|
"last_updated_human": now
|
|
})
|
|
|
|
return records
|
|
|
|
# ----------------------------
|
|
# Test rapido
|
|
# ----------------------------
|
|
if __name__ == "__main__":
|
|
from pprint import pprint
|
|
pprint(get_dns_records())
|