mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-10 21:24:56 +03:00
177 lines
6.2 KiB
Python
177 lines
6.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
BitLocker Compliance Checker
|
|
|
|
Checks BitLocker encryption status across endpoints and generates
|
|
compliance reports for audit purposes.
|
|
"""
|
|
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
import os
|
|
import csv
|
|
from datetime import datetime
|
|
|
|
|
|
def check_bitlocker_status() -> dict:
|
|
"""Check BitLocker status on local Windows endpoint."""
|
|
ps_cmd = """
|
|
$volumes = Get-BitLockerVolume
|
|
$results = @()
|
|
foreach ($vol in $volumes) {
|
|
$protectors = @()
|
|
foreach ($kp in $vol.KeyProtector) {
|
|
$protectors += @{
|
|
Type = $kp.KeyProtectorType.ToString()
|
|
Id = $kp.KeyProtectorId
|
|
}
|
|
}
|
|
$results += @{
|
|
MountPoint = $vol.MountPoint
|
|
VolumeStatus = $vol.VolumeStatus.ToString()
|
|
ProtectionStatus = $vol.ProtectionStatus.ToString()
|
|
EncryptionMethod = $vol.EncryptionMethod.ToString()
|
|
EncryptionPercentage = $vol.EncryptionPercentage
|
|
VolumeType = $vol.VolumeType.ToString()
|
|
KeyProtectors = $protectors
|
|
AutoUnlockEnabled = $vol.AutoUnlockEnabled
|
|
AutoUnlockKeyStored = $vol.AutoUnlockKeyStored
|
|
}
|
|
}
|
|
$tpm = Get-Tpm
|
|
@{
|
|
Hostname = $env:COMPUTERNAME
|
|
Volumes = $results
|
|
TPM = @{
|
|
Present = $tpm.TpmPresent
|
|
Ready = $tpm.TpmReady
|
|
Enabled = $tpm.TpmEnabled
|
|
Activated = $tpm.TpmActivated
|
|
}
|
|
} | ConvertTo-Json -Depth 4
|
|
"""
|
|
|
|
try:
|
|
result = subprocess.run(
|
|
["powershell", "-NoProfile", "-Command", ps_cmd],
|
|
capture_output=True, text=True, timeout=30,
|
|
)
|
|
if result.returncode == 0 and result.stdout.strip():
|
|
return json.loads(result.stdout)
|
|
return {"error": result.stderr or "Failed to check BitLocker status"}
|
|
except FileNotFoundError:
|
|
return {"error": "PowerShell not available (requires Windows)"}
|
|
except subprocess.TimeoutExpired:
|
|
return {"error": "Command timed out"}
|
|
except json.JSONDecodeError as e:
|
|
return {"error": f"Parse error: {e}"}
|
|
|
|
|
|
def assess_compliance(status: dict) -> dict:
|
|
"""Assess BitLocker compliance against security baseline."""
|
|
findings = {
|
|
"hostname": status.get("Hostname", "unknown"),
|
|
"overall_compliant": True,
|
|
"tpm_status": "compliant",
|
|
"volume_findings": [],
|
|
}
|
|
|
|
tpm = status.get("TPM", {})
|
|
if not tpm.get("Present") or not tpm.get("Ready"):
|
|
findings["tpm_status"] = "non-compliant"
|
|
findings["overall_compliant"] = False
|
|
|
|
for vol in status.get("Volumes", []):
|
|
vol_finding = {
|
|
"mount_point": vol["MountPoint"],
|
|
"compliant": True,
|
|
"issues": [],
|
|
}
|
|
|
|
if vol["VolumeStatus"] != "FullyEncrypted":
|
|
vol_finding["compliant"] = False
|
|
vol_finding["issues"].append(f"Not fully encrypted: {vol['VolumeStatus']}")
|
|
|
|
if vol["ProtectionStatus"] != "On":
|
|
vol_finding["compliant"] = False
|
|
vol_finding["issues"].append(f"Protection not enabled: {vol['ProtectionStatus']}")
|
|
|
|
if vol["EncryptionMethod"] not in ("XtsAes256", "XtsAes128"):
|
|
vol_finding["issues"].append(f"Weak encryption method: {vol['EncryptionMethod']}")
|
|
|
|
protector_types = [kp["Type"] for kp in vol.get("KeyProtectors", [])]
|
|
has_recovery = "RecoveryPassword" in protector_types or "NumericalPassword" in protector_types
|
|
if not has_recovery:
|
|
vol_finding["compliant"] = False
|
|
vol_finding["issues"].append("No recovery password protector configured")
|
|
|
|
has_tpm = any(t in protector_types for t in ["Tpm", "TpmPin", "TpmPinStartupKey"])
|
|
if vol["VolumeType"] == "OperatingSystem" and not has_tpm:
|
|
vol_finding["compliant"] = False
|
|
vol_finding["issues"].append("OS volume missing TPM protector")
|
|
|
|
if not vol_finding["compliant"]:
|
|
findings["overall_compliant"] = False
|
|
|
|
findings["volume_findings"].append(vol_finding)
|
|
|
|
return findings
|
|
|
|
|
|
def generate_report(status: dict, compliance: dict, output_path: str) -> None:
|
|
"""Generate BitLocker compliance report."""
|
|
report = {
|
|
"report_generated": datetime.utcnow().isoformat() + "Z",
|
|
"hostname": status.get("Hostname", "unknown"),
|
|
"overall_compliance": "COMPLIANT" if compliance["overall_compliant"] else "NON-COMPLIANT",
|
|
"tpm_status": compliance["tpm_status"],
|
|
"tpm_details": status.get("TPM", {}),
|
|
"volumes": [],
|
|
}
|
|
|
|
for vol, finding in zip(status.get("Volumes", []), compliance["volume_findings"]):
|
|
report["volumes"].append({
|
|
"mount_point": vol["MountPoint"],
|
|
"status": vol["VolumeStatus"],
|
|
"protection": vol["ProtectionStatus"],
|
|
"encryption_method": vol["EncryptionMethod"],
|
|
"encryption_percent": vol["EncryptionPercentage"],
|
|
"key_protectors": [kp["Type"] for kp in vol.get("KeyProtectors", [])],
|
|
"compliant": finding["compliant"],
|
|
"issues": finding["issues"],
|
|
})
|
|
|
|
with open(output_path, "w", encoding="utf-8") as f:
|
|
json.dump(report, f, indent=2)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
output_dir = sys.argv[1] if len(sys.argv) > 1 else "."
|
|
|
|
print("Checking BitLocker status...")
|
|
status = check_bitlocker_status()
|
|
|
|
if "error" in status:
|
|
print(f"Error: {status['error']}")
|
|
print("This tool requires Windows with BitLocker support.")
|
|
sys.exit(1)
|
|
|
|
print("Assessing compliance...")
|
|
compliance = assess_compliance(status)
|
|
|
|
report_path = os.path.join(output_dir, "bitlocker_compliance.json")
|
|
generate_report(status, compliance, report_path)
|
|
print(f"Compliance report: {report_path}")
|
|
|
|
print(f"\n--- BitLocker Compliance ---")
|
|
print(f"Hostname: {compliance['hostname']}")
|
|
print(f"Overall: {'COMPLIANT' if compliance['overall_compliant'] else 'NON-COMPLIANT'}")
|
|
print(f"TPM: {compliance['tpm_status']}")
|
|
|
|
for vf in compliance["volume_findings"]:
|
|
status_icon = "PASS" if vf["compliant"] else "FAIL"
|
|
print(f"\n [{status_icon}] {vf['mount_point']}")
|
|
for issue in vf["issues"]:
|
|
print(f" - {issue}")
|