feat: Implement data retention policy

- Replaced `data_storage.py` with `database.py` to use SQLite instead of a JSON file for data storage.
- Added an `enforce_retention_policy` function to `database.py` to delete data older than 7 days.
- Called this function in the main monitoring loop in `monitor_agent.py`.
- Added Docker container monitoring.
- Updated `.gitignore` to ignore `monitoring.db`.
This commit is contained in:
2025-09-15 13:12:05 -05:00
parent 0b64f2ed03
commit 07c768a4cf
16 changed files with 1750356 additions and 74 deletions

44
monitor_agent.py Normal file → Executable file
View File

@@ -6,7 +6,7 @@ import subprocess
import ollama
from discord_webhook import DiscordWebhook
import requests
import data_storage
import database as data_storage
import re
import os
from datetime import datetime, timezone
@@ -14,6 +14,7 @@ import pingparsing
import nmap
import logging
from logging.handlers import TimedRotatingFileHandler
import docker
import schedule
@@ -23,7 +24,7 @@ import config
from syslog_rfc5424_parser import parser
# --- Logging Configuration ---
LOG_FILE = "monitoring_agent.log"
LOG_FILE = "./tmp/monitoring_agent.log"
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
@@ -192,6 +193,23 @@ def get_nmap_scan_results():
logger.error(f"Error performing Nmap scan: {e}")
return {"error": "Nmap scan failed"}
def get_docker_container_status():
"""Gets the status of configured Docker containers."""
if not config.DOCKER_CONTAINERS_TO_MONITOR:
return {"docker_container_status": {}}
try:
client = docker.from_env()
containers = client.containers.list(all=True)
status = {}
for container in containers:
if container.name in config.DOCKER_CONTAINERS_TO_MONITOR:
status[container.name] = container.status
return {"docker_container_status": status}
except Exception as e:
logger.error(f"Error getting Docker container status: {e}")
return {"docker_container_status": {}}
# --- Data Analysis ---
def analyze_data_locally(data, baselines, known_issues, port_applications):
@@ -265,6 +283,16 @@ def analyze_data_locally(data, baselines, known_issues, port_applications):
"reason": f"New port opened on {host_ip}: {port} ({port_info})"
})
# Docker container status check
docker_status = data.get("docker_container_status", {}).get("docker_container_status")
if docker_status:
for container_name, status in docker_status.items():
if status != "running":
anomalies.append({
"severity": "high",
"reason": f"Docker container '{container_name}' is not running. Current status: {status}"
})
return anomalies
# --- LLM Interaction Function ---
@@ -291,7 +319,7 @@ def generate_llm_report(anomalies):
prompt = build_llm_prompt(anomalies)
try:
response = ollama.generate(model="llama3.1:8b", prompt=prompt)
response = ollama.generate(model="phi4-mini", prompt=prompt)
sanitized_response = response['response'].strip()
# Extract JSON from the response
@@ -358,7 +386,7 @@ def send_google_home_alert(message):
data = {
"entity_id": "all",
"media_player_entity_id": config.GOOGLE_HOME_SPEAKER_ID,
"message": simplified_message,
"message": simplified_message, # type: ignore
}
try:
response = requests.post(url, headers=headers, json=data)
@@ -405,6 +433,7 @@ def run_monitoring_cycle(nmap_scan_counter):
cpu_temp = get_cpu_temperature(sensors_output)
gpu_temp = get_gpu_temperature(sensors_output)
login_attempts = get_login_attempts()
docker_container_status = get_docker_container_status()
nmap_results = None
if nmap_scan_counter == 0:
@@ -419,13 +448,15 @@ def run_monitoring_cycle(nmap_scan_counter):
"network_metrics": network_metrics,
"cpu_temperature": cpu_temp,
"gpu_temperature": gpu_temp,
"login_attempts": login_attempts
"login_attempts": login_attempts,
"docker_container_status": docker_container_status
}
if nmap_results:
combined_data["nmap_results"] = nmap_results
data_storage.store_data(combined_data)
data_storage.enforce_retention_policy()
with open("known_issues.json", "r") as f:
known_issues = json.load(f)
@@ -448,6 +479,7 @@ def run_monitoring_cycle(nmap_scan_counter):
def main():
"""Main function to run the monitoring agent."""
data_storage.initialize_database()
if config.TEST_MODE:
logger.info("Running in test mode...")
run_monitoring_cycle(0)
@@ -460,4 +492,4 @@ def main():
time.sleep(300) # Run every 5 minutes
if __name__ == "__main__":
main()
main()