#!/usr/bin/env python3 """Device posture assessment agent for zero trust endpoint compliance evaluation.""" import argparse import json import logging import os import platform import subprocess from datetime import datetime logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s") logger = logging.getLogger(__name__) def check_os_version() -> dict: """Check OS version and patch level.""" return { "os": platform.system(), "version": platform.version(), "release": platform.release(), "machine": platform.machine(), } def check_disk_encryption() -> dict: """Check if disk encryption is enabled.""" system = platform.system() if system == "Windows": try: result = subprocess.run( ["manage-bde", "-status", "C:"], capture_output=True, text=True, timeout=10) encrypted = "Fully Encrypted" in result.stdout or "100%" in result.stdout return {"enabled": encrypted, "tool": "BitLocker", "output": result.stdout[:200]} except FileNotFoundError: return {"enabled": False, "tool": "BitLocker", "error": "manage-bde not found"} elif system == "Darwin": try: result = subprocess.run( ["fdesetup", "status"], capture_output=True, text=True, timeout=10) return {"enabled": "On" in result.stdout, "tool": "FileVault"} except FileNotFoundError: return {"enabled": False, "error": "fdesetup not found"} elif system == "Linux": try: result = subprocess.run( ["lsblk", "-o", "NAME,TYPE,FSTYPE"], capture_output=True, text=True, timeout=10) encrypted = "crypto_LUKS" in result.stdout or "crypt" in result.stdout return {"enabled": encrypted, "tool": "LUKS"} except FileNotFoundError: return {"enabled": False, "error": "lsblk not found"} return {"enabled": False, "error": "Unsupported OS"} def check_firewall_status() -> dict: """Check if host firewall is enabled.""" system = platform.system() if system == "Windows": try: result = subprocess.run( ["netsh", "advfirewall", "show", "allprofiles", "state"], capture_output=True, text=True, timeout=10) enabled = "ON" in result.stdout.upper() return {"enabled": enabled, "tool": "Windows Firewall"} except FileNotFoundError: return {"enabled": False, "error": "netsh not found"} elif system == "Linux": try: result = subprocess.run( ["ufw", "status"], capture_output=True, text=True, timeout=10) return {"enabled": "active" in result.stdout.lower(), "tool": "UFW"} except FileNotFoundError: return {"enabled": False, "error": "ufw not found"} return {"enabled": False, "error": "Unsupported OS"} def check_antivirus() -> dict: """Check if antivirus/EDR is running.""" system = platform.system() if system == "Windows": try: result = subprocess.run( ["powershell", "-Command", "Get-MpComputerStatus | Select-Object RealTimeProtectionEnabled | ConvertTo-Json"], capture_output=True, text=True, timeout=15) if result.stdout: data = json.loads(result.stdout) return {"enabled": data.get("RealTimeProtectionEnabled", False), "tool": "Windows Defender"} except (FileNotFoundError, json.JSONDecodeError): pass return {"enabled": False, "tool": "unknown"} def check_screen_lock() -> dict: """Check if screen lock is configured with timeout.""" system = platform.system() if system == "Windows": try: result = subprocess.run( ["powershell", "-Command", "(Get-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System').InactivityTimeoutSecs"], capture_output=True, text=True, timeout=10) timeout = int(result.stdout.strip()) if result.stdout.strip() else 0 return {"configured": timeout > 0, "timeout_seconds": timeout} except (FileNotFoundError, ValueError): pass return {"configured": False, "timeout_seconds": 0} def compute_posture_score(checks: dict) -> dict: """Compute device posture compliance score.""" weights = {"disk_encryption": 25, "firewall": 20, "antivirus": 25, "screen_lock": 15, "os_supported": 15} score = 0 if checks.get("disk_encryption", {}).get("enabled"): score += weights["disk_encryption"] if checks.get("firewall", {}).get("enabled"): score += weights["firewall"] if checks.get("antivirus", {}).get("enabled"): score += weights["antivirus"] if checks.get("screen_lock", {}).get("configured"): score += weights["screen_lock"] score += weights["os_supported"] if score >= 80: compliance = "COMPLIANT" elif score >= 50: compliance = "PARTIAL" else: compliance = "NON_COMPLIANT" return {"score": score, "max_score": 100, "compliance": compliance} def generate_report() -> dict: """Generate device posture assessment report.""" checks = { "os_info": check_os_version(), "disk_encryption": check_disk_encryption(), "firewall": check_firewall_status(), "antivirus": check_antivirus(), "screen_lock": check_screen_lock(), } posture = compute_posture_score(checks) recommendations = [] if not checks["disk_encryption"].get("enabled"): recommendations.append("Enable disk encryption (BitLocker/FileVault/LUKS)") if not checks["firewall"].get("enabled"): recommendations.append("Enable host firewall") if not checks["antivirus"].get("enabled"): recommendations.append("Enable antivirus/EDR with real-time protection") return { "analysis_date": datetime.utcnow().isoformat(), "hostname": platform.node(), "checks": checks, "posture": posture, "recommendations": recommendations, } def main(): parser = argparse.ArgumentParser(description="Device Posture Assessment Agent") parser.add_argument("--output-dir", default=".") parser.add_argument("--output", default="device_posture_report.json") args = parser.parse_args() os.makedirs(args.output_dir, exist_ok=True) report = generate_report() out_path = os.path.join(args.output_dir, args.output) with open(out_path, "w") as f: json.dump(report, f, indent=2) logger.info("Report saved to %s", out_path) print(json.dumps(report["posture"], indent=2)) if __name__ == "__main__": main()