mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-10 12:23:20 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
CrowdStrike Falcon Deployment Verification Tool
|
||||
|
||||
Queries the CrowdStrike Falcon API to verify sensor deployment coverage,
|
||||
identify unmanaged endpoints, and generate deployment status reports.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import csv
|
||||
from datetime import datetime, timedelta
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.parse import urlencode
|
||||
from urllib.error import HTTPError
|
||||
|
||||
|
||||
FALCON_BASE_URL = os.environ.get("FALCON_BASE_URL", "https://api.crowdstrike.com")
|
||||
FALCON_CLIENT_ID = os.environ.get("FALCON_CLIENT_ID", "")
|
||||
FALCON_CLIENT_SECRET = os.environ.get("FALCON_CLIENT_SECRET", "")
|
||||
|
||||
|
||||
def get_oauth_token() -> str:
|
||||
"""Obtain OAuth2 bearer token from CrowdStrike API."""
|
||||
url = f"{FALCON_BASE_URL}/oauth2/token"
|
||||
data = urlencode({
|
||||
"client_id": FALCON_CLIENT_ID,
|
||||
"client_secret": FALCON_CLIENT_SECRET,
|
||||
}).encode()
|
||||
|
||||
req = Request(url, data=data, method="POST")
|
||||
req.add_header("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
with urlopen(req) as resp:
|
||||
body = json.loads(resp.read())
|
||||
return body["access_token"]
|
||||
|
||||
|
||||
def api_get(token: str, endpoint: str, params: dict = None) -> dict:
|
||||
"""Make authenticated GET request to Falcon API."""
|
||||
url = f"{FALCON_BASE_URL}{endpoint}"
|
||||
if params:
|
||||
url += "?" + urlencode(params)
|
||||
|
||||
req = Request(url, method="GET")
|
||||
req.add_header("Authorization", f"Bearer {token}")
|
||||
req.add_header("Accept", "application/json")
|
||||
|
||||
with urlopen(req) as resp:
|
||||
return json.loads(resp.read())
|
||||
|
||||
|
||||
def get_all_host_ids(token: str) -> list:
|
||||
"""Retrieve all host device IDs from Falcon."""
|
||||
all_ids = []
|
||||
offset = 0
|
||||
limit = 5000
|
||||
|
||||
while True:
|
||||
result = api_get(token, "/devices/queries/devices-scroll/v1", {
|
||||
"limit": limit,
|
||||
"offset": offset,
|
||||
})
|
||||
resources = result.get("resources", [])
|
||||
if not resources:
|
||||
break
|
||||
all_ids.extend(resources)
|
||||
offset += limit
|
||||
if len(resources) < limit:
|
||||
break
|
||||
|
||||
return all_ids
|
||||
|
||||
|
||||
def get_host_details(token: str, host_ids: list) -> list:
|
||||
"""Retrieve detailed host information for given IDs (batches of 100)."""
|
||||
all_details = []
|
||||
|
||||
for i in range(0, len(host_ids), 100):
|
||||
batch = host_ids[i:i + 100]
|
||||
url = f"{FALCON_BASE_URL}/devices/entities/devices/v2"
|
||||
data = json.dumps({"ids": batch}).encode()
|
||||
|
||||
req = Request(url, data=data, method="POST")
|
||||
req.add_header("Authorization", f"Bearer {token}")
|
||||
req.add_header("Content-Type", "application/json")
|
||||
|
||||
with urlopen(req) as resp:
|
||||
body = json.loads(resp.read())
|
||||
all_details.extend(body.get("resources", []))
|
||||
|
||||
return all_details
|
||||
|
||||
|
||||
def analyze_deployment(hosts: list) -> dict:
|
||||
"""Analyze deployment coverage and sensor health."""
|
||||
now = datetime.utcnow()
|
||||
stale_threshold = now - timedelta(days=7)
|
||||
|
||||
analysis = {
|
||||
"total_hosts": len(hosts),
|
||||
"os_breakdown": {},
|
||||
"status_breakdown": {"online": 0, "offline": 0, "stale": 0},
|
||||
"sensor_versions": {},
|
||||
"rfm_hosts": [],
|
||||
"stale_hosts": [],
|
||||
"unprotected_hosts": [],
|
||||
}
|
||||
|
||||
for host in hosts:
|
||||
platform = host.get("platform_name", "Unknown")
|
||||
analysis["os_breakdown"][platform] = analysis["os_breakdown"].get(platform, 0) + 1
|
||||
|
||||
version = host.get("agent_version", "Unknown")
|
||||
analysis["sensor_versions"][version] = analysis["sensor_versions"].get(version, 0) + 1
|
||||
|
||||
status = host.get("status", "unknown")
|
||||
last_seen = host.get("last_seen", "")
|
||||
|
||||
if last_seen:
|
||||
try:
|
||||
last_seen_dt = datetime.fromisoformat(last_seen.replace("Z", "+00:00")).replace(tzinfo=None)
|
||||
if last_seen_dt < stale_threshold:
|
||||
analysis["status_breakdown"]["stale"] += 1
|
||||
analysis["stale_hosts"].append({
|
||||
"hostname": host.get("hostname", ""),
|
||||
"last_seen": last_seen,
|
||||
"platform": platform,
|
||||
})
|
||||
elif status == "normal":
|
||||
analysis["status_breakdown"]["online"] += 1
|
||||
else:
|
||||
analysis["status_breakdown"]["offline"] += 1
|
||||
except (ValueError, TypeError):
|
||||
analysis["status_breakdown"]["offline"] += 1
|
||||
|
||||
reduced_functionality = host.get("reduced_functionality_mode", "no")
|
||||
if reduced_functionality == "yes":
|
||||
analysis["rfm_hosts"].append({
|
||||
"hostname": host.get("hostname", ""),
|
||||
"reason": host.get("device_policies", {}).get("prevention", {}).get("policy_type", "unknown"),
|
||||
})
|
||||
|
||||
prevention_policy = host.get("device_policies", {}).get("prevention", {})
|
||||
if not prevention_policy.get("applied", False):
|
||||
analysis["unprotected_hosts"].append({
|
||||
"hostname": host.get("hostname", ""),
|
||||
"platform": platform,
|
||||
"reason": "Prevention policy not applied",
|
||||
})
|
||||
|
||||
return analysis
|
||||
|
||||
|
||||
def generate_deployment_report(analysis: dict, output_path: str) -> None:
|
||||
"""Generate deployment status report."""
|
||||
report = {
|
||||
"report_generated": datetime.utcnow().isoformat() + "Z",
|
||||
"deployment_summary": {
|
||||
"total_managed_hosts": analysis["total_hosts"],
|
||||
"online": analysis["status_breakdown"]["online"],
|
||||
"offline": analysis["status_breakdown"]["offline"],
|
||||
"stale_7_days": analysis["status_breakdown"]["stale"],
|
||||
"in_rfm": len(analysis["rfm_hosts"]),
|
||||
"unprotected": len(analysis["unprotected_hosts"]),
|
||||
},
|
||||
"os_distribution": analysis["os_breakdown"],
|
||||
"sensor_version_distribution": analysis["sensor_versions"],
|
||||
"hosts_requiring_attention": {
|
||||
"stale_hosts": analysis["stale_hosts"][:50],
|
||||
"rfm_hosts": analysis["rfm_hosts"][:50],
|
||||
"unprotected_hosts": analysis["unprotected_hosts"][:50],
|
||||
},
|
||||
}
|
||||
|
||||
with open(output_path, "w", encoding="utf-8") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
|
||||
|
||||
def export_stale_hosts_csv(stale_hosts: list, output_path: str) -> None:
|
||||
"""Export stale hosts to CSV for remediation tracking."""
|
||||
with open(output_path, "w", newline="", encoding="utf-8") as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerow(["Hostname", "Platform", "Last Seen", "Action Required"])
|
||||
for host in stale_hosts:
|
||||
writer.writerow([
|
||||
host["hostname"],
|
||||
host.get("platform", ""),
|
||||
host["last_seen"],
|
||||
"Investigate connectivity / reinstall sensor",
|
||||
])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if not FALCON_CLIENT_ID or not FALCON_CLIENT_SECRET:
|
||||
print("Error: Set FALCON_CLIENT_ID and FALCON_CLIENT_SECRET environment variables")
|
||||
print()
|
||||
print("Required environment variables:")
|
||||
print(" FALCON_CLIENT_ID - API client ID from Falcon Console")
|
||||
print(" FALCON_CLIENT_SECRET - API client secret")
|
||||
print(" FALCON_BASE_URL - (Optional) API base URL (default: https://api.crowdstrike.com)")
|
||||
sys.exit(1)
|
||||
|
||||
print("Authenticating with CrowdStrike Falcon API...")
|
||||
token = get_oauth_token()
|
||||
|
||||
print("Retrieving host inventory...")
|
||||
host_ids = get_all_host_ids(token)
|
||||
print(f"Found {len(host_ids)} managed hosts")
|
||||
|
||||
print("Fetching host details...")
|
||||
hosts = get_host_details(token, host_ids)
|
||||
|
||||
print("Analyzing deployment coverage...")
|
||||
analysis = analyze_deployment(hosts)
|
||||
|
||||
report_path = "falcon_deployment_report.json"
|
||||
generate_deployment_report(analysis, report_path)
|
||||
print(f"\nDeployment report: {report_path}")
|
||||
|
||||
if analysis["stale_hosts"]:
|
||||
csv_path = "falcon_stale_hosts.csv"
|
||||
export_stale_hosts_csv(analysis["stale_hosts"], csv_path)
|
||||
print(f"Stale hosts CSV: {csv_path}")
|
||||
|
||||
print(f"\n--- Deployment Summary ---")
|
||||
print(f"Total hosts: {analysis['total_hosts']}")
|
||||
print(f"Online: {analysis['status_breakdown']['online']}")
|
||||
print(f"Offline: {analysis['status_breakdown']['offline']}")
|
||||
print(f"Stale (>7 days): {analysis['status_breakdown']['stale']}")
|
||||
print(f"In RFM: {len(analysis['rfm_hosts'])}")
|
||||
print(f"Unprotected: {len(analysis['unprotected_hosts'])}")
|
||||
print(f"\nOS Distribution: {json.dumps(analysis['os_breakdown'], indent=2)}")
|
||||
print(f"Sensor Versions: {json.dumps(analysis['sensor_versions'], indent=2)}")
|
||||
Reference in New Issue
Block a user