84 lines
2.8 KiB
Python
84 lines
2.8 KiB
Python
import os
|
|
import time
|
|
from datetime import datetime, timezone, timedelta
|
|
|
|
# Fallback base URL since 'request.host_url' is not available in background threads
|
|
SERVER_BASE_URL = os.getenv("SERVER_BASE_URL", "https://smartwave.matthiasg.dev")
|
|
|
|
|
|
def job_server_cve_audit(shodan_auditor, db):
|
|
"""Job 1: Audits Flask server public IP for CVEs and saves to MongoDB."""
|
|
print("[Cron] Starting Server CVE Audit...")
|
|
|
|
audit_results = shodan_auditor.audit_server_vulnerabilities()
|
|
|
|
db.cve_audit_results.insert_one({
|
|
"audit_results": audit_results,
|
|
"timestamp": datetime.now(timezone.utc)
|
|
})
|
|
|
|
print(f"[Cron] Server CVE Audit finished. Status: {audit_results.get('status')}")
|
|
|
|
|
|
def job_client_ip_audit(shodan_auditor, db):
|
|
"""
|
|
Job 2: Fetches distinct client IPs logged in the last 24h and audits them.
|
|
Deduplicates IPs and applies rate limits to protect Shodan API credits.
|
|
"""
|
|
print("[Cron] Starting Client IP Security Audit...")
|
|
|
|
pipeline = [
|
|
{"$group": {
|
|
"_id": "$client_ip",
|
|
"microwave_ids": {"$addToSet": "$microwave_id"},
|
|
"last_seen": {"$max": "$received_at"}
|
|
}}
|
|
]
|
|
|
|
recent_clients = list(db.device_ips.aggregate(pipeline))
|
|
|
|
for entry in recent_clients:
|
|
client_ip = entry["_id"]
|
|
|
|
# Skip local/private IPs
|
|
if not client_ip or client_ip in ["127.0.0.1", "localhost"] or client_ip.startswith(("10.", "192.168.", "172.16.")):
|
|
continue
|
|
|
|
profile = shodan_auditor.profile_client_ip(client_ip)
|
|
|
|
# Upsert client profile in a separate collection
|
|
db.client_audit_results.update_one(
|
|
{"client_ip": client_ip},
|
|
{
|
|
"$set": {
|
|
"client_ip": client_ip,
|
|
"microwave_ids": entry["microwave_ids"],
|
|
"last_seen": entry["last_seen"],
|
|
"profile": profile,
|
|
"audited_at": datetime.now(timezone.utc)
|
|
}
|
|
},
|
|
upsert=True
|
|
)
|
|
|
|
# Pause 1 second to respect Shodan API rate limits (1 req/sec)
|
|
time.sleep(1)
|
|
|
|
print(f"[Cron] Client IP Security Audit completed for {len(recent_clients)} IPs.")
|
|
|
|
|
|
def job_request_telemetry(send_command_func):
|
|
"""Job 3: Triggers MQTT command to request telemetry from all microwaves."""
|
|
print("[Cron] Sending MQTT Telemetry Request to cmd/all...")
|
|
|
|
telemetry_url = f"{SERVER_BASE_URL.rstrip('/')}/telemetry"
|
|
cmd_payload = {
|
|
"action": "request_telemetry",
|
|
"endpoint": telemetry_url
|
|
}
|
|
|
|
try:
|
|
send_command_func(topic="cmd/all", payload=cmd_payload)
|
|
print("[Cron] Telemetry request successfully published.")
|
|
except Exception as e:
|
|
print(f"[Cron Error] Failed to publish MQTT command: {str(e)}") |