npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
When to Use
- When enforcing device health as a prerequisite for accessing corporate applications
- When integrating CrowdStrike ZTA scores, Intune compliance, or Jamf device status into access decisions
- When implementing CISA Zero Trust Maturity Model device pillar requirements
- When building conditional access policies that adapt based on real-time endpoint security posture
- When detecting and blocking access from compromised, unmanaged, or non-compliant devices
Do not use for IoT or headless devices that cannot run posture agents, as a standalone security control without identity verification, or when real-time posture data is unavailable and stale compliance data would create false trust.
Prerequisites
- Endpoint Detection and Response (EDR): CrowdStrike Falcon with ZTA module, or Microsoft Defender for Endpoint
- Mobile Device Management (MDM): Microsoft Intune, Jamf Pro, or VMware Workspace ONE
- Identity Provider: Microsoft Entra ID, Okta, or Ping Identity with conditional access capability
- ZTNA Platform: Zscaler ZPA, Cloudflare Access, Palo Alto Prisma Access, or cloud-native IAP
- API access to EDR/MDM platforms for posture signal ingestion
Workflow
Step 1: Define Device Compliance Baselines
Establish minimum security requirements for each device category.
# Microsoft Intune: Create device compliance policy via Graph API
Connect-MgGraph -Scopes "DeviceManagementConfiguration.ReadWrite.All"
# Windows 10/11 Compliance Policy
$compliancePolicy = @{
"@odata.type" = "#microsoft.graph.windows10CompliancePolicy"
displayName = "Zero Trust - Windows Compliance"
description = "Minimum device requirements for zero trust access"
osMinimumVersion = "10.0.19045"
bitLockerEnabled = $true
secureBootEnabled = $true
codeIntegrityEnabled = $true
tpmRequired = $true
antivirusRequired = $true
antiSpywareRequired = $true
defenderEnabled = $true
firewallEnabled = $true
passwordRequired = $true
passwordMinimumLength = 12
passwordRequiredType = "alphanumeric"
storageRequireEncryption = $true
scheduledActionsForRule = @(
@{
ruleName = "PasswordRequired"
scheduledActionConfigurations = @(
@{
actionType = "block"
gracePeriodHours = 24
notificationTemplateId = ""
notificationMessageCCList = @()
}
)
}
)
}
New-MgDeviceManagementDeviceCompliancePolicy -BodyParameter $compliancePolicy
# macOS Compliance Policy via Jamf Pro API
curl -X POST "https://jamf.company.com/api/v1/compliance-policies" \
-H "Authorization: Bearer ${JAMF_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "Zero Trust - macOS Compliance",
"rules": [
{"type": "os_version", "operator": ">=", "value": "14.0"},
{"type": "filevault_enabled", "value": true},
{"type": "firewall_enabled", "value": true},
{"type": "gatekeeper_enabled", "value": true},
{"type": "sip_enabled", "value": true},
{"type": "auto_update_enabled", "value": true},
{"type": "screen_lock_timeout", "operator": "<=", "value": 300},
{"type": "falcon_sensor_running", "value": true}
]
}'Step 2: Configure CrowdStrike Zero Trust Assessment
Enable ZTA scoring and configure score thresholds for access tiers.
# CrowdStrike Falcon API: Query ZTA scores for all endpoints
curl -X GET "https://api.crowdstrike.com/zero-trust-assessment/entities/assessments/v1?ids=${DEVICE_AID}" \
-H "Authorization: Bearer ${CS_TOKEN}" \
-H "Content-Type: application/json"
# Response includes:
# {
# "aid": "device-agent-id",
# "assessment": {
# "overall": 82,
# "os": 90,
# "sensor_config": 85,
# "version": "7.14.16703"
# },
# "assessment_items": {
# "os_signals": [
# {"signal_id": "firmware_protection", "meets_criteria": "yes"},
# {"signal_id": "disk_encryption", "meets_criteria": "yes"},
# {"signal_id": "kernel_protection", "meets_criteria": "yes"}
# ],
# "sensor_signals": [
# {"signal_id": "sensor_version", "meets_criteria": "yes"},
# {"signal_id": "prevention_policies", "meets_criteria": "yes"}
# ]
# }
# }
# Define ZTA score thresholds for access tiers
# Tier 1 (Basic Access): ZTA >= 50
# Tier 2 (Standard Access): ZTA >= 65
# Tier 3 (Sensitive Access): ZTA >= 80
# Tier 4 (Critical Access): ZTA >= 90
# Query devices below minimum threshold
curl -X GET "https://api.crowdstrike.com/zero-trust-assessment/queries/assessments/v1?filter=assessment.overall:<50" \
-H "Authorization: Bearer ${CS_TOKEN}"
# CrowdStrike ZTA signals evaluated:
# - OS patch level and version
# - Disk encryption (BitLocker/FileVault)
# - Sensor version and configuration
# - Prevention policy enforcement
# - Firmware protection (Secure Boot)
# - Kernel protection (SIP, Code Integrity)
# - Firewall statusStep 3: Integrate Device Posture with Entra ID Conditional Access
Create conditional access policies that require compliant devices.
# Create Conditional Access policy requiring compliant device
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess"
$caPolicy = @{
displayName = "Zero Trust - Require Compliant Device"
state = "enabled"
conditions = @{
applications = @{
includeApplications = @("All")
}
users = @{
includeUsers = @("All")
excludeGroups = @("BreakGlass-Admins-Group-ID")
}
platforms = @{
includePlatforms = @("all")
}
clientAppTypes = @("browser", "mobileAppsAndDesktopClients")
}
grantControls = @{
operator = "AND"
builtInControls = @("mfa", "compliantDevice")
}
sessionControls = @{
signInFrequency = @{
value = 4
type = "hours"
isEnabled = $true
authenticationType = "primaryAndSecondaryAuthentication"
frequencyInterval = "timeBased"
}
persistentBrowser = @{
mode = "never"
isEnabled = $true
}
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $caPolicy
# Create risk-based policy using device compliance + sign-in risk
$riskPolicy = @{
displayName = "Zero Trust - Block High Risk Sign-Ins on Non-Compliant Devices"
state = "enabled"
conditions = @{
applications = @{ includeApplications = @("All") }
users = @{ includeUsers = @("All") }
signInRiskLevels = @("high", "medium")
devices = @{
deviceFilter = @{
mode = "include"
rule = "device.isCompliant -ne True"
}
}
}
grantControls = @{
operator = "OR"
builtInControls = @("block")
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $riskPolicyStep 4: Configure Okta Device Trust with CrowdStrike Integration
Set up Okta device trust policies using CrowdStrike posture signals.
# Okta: Configure CrowdStrike device trust integration
# Admin Console > Security > Device Integrations > Add Integration
# Okta API: Create device assurance policy
curl -X POST "https://company.okta.com/api/v1/device-assurances" \
-H "Authorization: SSWS ${OKTA_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "Corporate Device Assurance",
"platform": "WINDOWS",
"osVersion": {
"minimum": "10.0.19045"
},
"diskEncryptionType": {
"include": ["ALL_INTERNAL_VOLUMES"]
},
"screenLockType": {
"include": ["BIOMETRIC", "PASSCODE"]
},
"secureHardwarePresent": true,
"thirdPartySignalProviders": {
"dtc": {
"browserVersion": {
"minimum": "120.0"
},
"builtInDnsClientEnabled": true,
"chromeRemoteDesktopAppBlocked": true,
"crowdStrikeCustomerId": "CS_CUSTOMER_ID",
"crowdStrikeAgentId": "REQUIRED",
"crowdStrikeVerifiedState": {
"include": ["RUNNING"]
}
}
}
}'
# Create Okta authentication policy with device assurance
curl -X POST "https://company.okta.com/api/v1/policies" \
-H "Authorization: SSWS ${OKTA_API_TOKEN}" \
-H "Content-Type: application/json" \
--data '{
"name": "Zero Trust Application Policy",
"type": "ACCESS_POLICY",
"conditions": null,
"rules": [
{
"name": "Managed Device Access",
"conditions": {
"device": {
"assurance": {
"include": ["DEVICE_ASSURANCE_POLICY_ID"]
},
"managed": true,
"registered": true
},
"people": {
"groups": {"include": ["EMPLOYEES_GROUP_ID"]}
}
},
"actions": {
"appSignOn": {
"access": "ALLOW",
"verificationMethod": {
"factorMode": "1FA",
"type": "ASSURANCE"
}
}
}
},
{
"name": "Unmanaged Device - Block",
"conditions": {
"device": { "managed": false }
},
"actions": {
"appSignOn": { "access": "DENY" }
}
}
]
}'Step 5: Implement Continuous Posture Monitoring
Set up real-time monitoring of device compliance state changes.
#!/usr/bin/env python3
"""Monitor device posture compliance drift in real-time."""
import requests
import time
import json
from datetime import datetime, timezone
CROWDSTRIKE_BASE = "https://api.crowdstrike.com"
INTUNE_BASE = "https://graph.microsoft.com/v1.0"
def get_cs_token(client_id: str, client_secret: str) -> str:
resp = requests.post(f"{CROWDSTRIKE_BASE}/oauth2/token", data={
"client_id": client_id,
"client_secret": client_secret
})
return resp.json()["access_token"]
def get_low_zta_devices(token: str, threshold: int = 50) -> list:
resp = requests.get(
f"{CROWDSTRIKE_BASE}/zero-trust-assessment/queries/assessments/v1",
headers={"Authorization": f"Bearer {token}"},
params={"filter": f"assessment.overall:<{threshold}", "limit": 100}
)
return resp.json().get("resources", [])
def get_intune_noncompliant(token: str) -> list:
resp = requests.get(
f"{INTUNE_BASE}/deviceManagement/managedDevices",
headers={"Authorization": f"Bearer {token}"},
params={
"$filter": "complianceState eq 'noncompliant'",
"$select": "id,deviceName,userPrincipalName,complianceState,lastSyncDateTime,operatingSystem"
}
)
return resp.json().get("value", [])
def check_posture_drift(cs_token: str, intune_token: str):
print(f"\n[{datetime.now(timezone.utc).isoformat()}] Device Posture Check")
print("=" * 60)
low_zta = get_low_zta_devices(cs_token, threshold=50)
print(f"CrowdStrike ZTA < 50: {len(low_zta)} devices")
noncompliant = get_intune_noncompliant(intune_token)
print(f"Intune Non-Compliant: {len(noncompliant)} devices")
for device in noncompliant[:10]:
print(f" - {device['deviceName']} ({device['userPrincipalName']}): "
f"{device['complianceState']} | Last sync: {device['lastSyncDateTime']}")
return {"low_zta_count": len(low_zta), "noncompliant_count": len(noncompliant)}Key Concepts
| Term | Definition |
|---|---|
| Device Posture | Collection of endpoint security attributes (OS version, encryption, EDR status, patch level) evaluated before granting access |
| CrowdStrike ZTA Score | Numerical score (1-100) calculated by CrowdStrike Falcon assessing endpoint security posture based on OS signals and sensor configuration |
| Device Compliance Policy | MDM-defined rules specifying minimum security requirements (encryption, PIN, OS version) that devices must meet |
| Conditional Access | Policy engine (Entra ID, Okta) that evaluates user identity, device compliance, location, and risk before allowing access |
| Device Trust | Verification that an endpoint is managed, enrolled, and meets security baselines before treating it as trusted |
| Posture Drift | Degradation of device security posture over time (expired patches, disabled encryption) that should trigger access revocation |
Tools & Systems
- CrowdStrike Falcon ZTA: Real-time endpoint posture scoring based on OS and sensor security signals
- Microsoft Intune: MDM platform enforcing device compliance policies and reporting to Entra ID Conditional Access
- Jamf Pro: Apple device management with compliance rules for macOS and iOS endpoints
- Microsoft Entra ID Conditional Access: Policy engine consuming Intune compliance and risk signals for access decisions
- Okta Device Trust: Device assurance policies integrating with CrowdStrike, Chrome Enterprise, and MDM platforms
- Cloudflare Device Posture: WARP client-based posture checks for disk encryption, OS version, and third-party EDR
Common Scenarios
Scenario: Enforcing Device Compliance for 2,000 Endpoints Across Windows and macOS
Context: A healthcare company with 2,000 endpoints (70% Windows, 30% macOS) must enforce HIPAA-compliant device posture before allowing access to patient data systems. Devices are managed by Intune (Windows) and Jamf (macOS) with CrowdStrike Falcon deployed on all endpoints.
Approach:
- Define Windows compliance policy in Intune: BitLocker, Secure Boot, TPM, Defender enabled, OS >= 10.0.19045
- Define macOS compliance policy in Jamf: FileVault, Gatekeeper, SIP, Firewall, OS >= 14.0
- Configure CrowdStrike ZTA thresholds: >= 70 for general apps, >= 85 for patient data systems
- Create Entra ID Conditional Access policies requiring compliant device + MFA for all cloud apps
- Configure 24-hour grace period for newly non-compliant devices before blocking
- Set up weekly compliance report for IT showing non-compliant devices and remediation actions
- Implement automated remediation via Intune: push BitLocker enablement, deploy pending patches
Pitfalls: Grace periods must be long enough for IT to remediate but short enough to limit risk exposure. CrowdStrike ZTA scores can fluctuate with sensor updates; avoid setting thresholds too aggressively initially. BYOD devices may lack MDM enrollment; provide a separate Browser Access path with reduced functionality for unmanaged devices.
Output Format
Device Posture Assessment Report
==================================================
Organization: HealthCorp
Report Date: 2026-02-23
Total Managed Devices: 2,000
COMPLIANCE BY PLATFORM:
Windows (1,400 devices):
Compliant: 1,302 (93.0%)
Non-compliant: 98 (7.0%)
Top Issue: Missing patches (45), BitLocker disabled (23)
macOS (600 devices):
Compliant: 567 (94.5%)
Non-compliant: 33 (5.5%)
Top Issue: OS outdated (18), FileVault disabled (8)
CROWDSTRIKE ZTA SCORES:
Average Score: 78.4
Devices >= 85 (Critical): 1,456 (72.8%)
Devices >= 70 (Standard): 1,812 (90.6%)
Devices < 50 (Blocked): 34 (1.7%)
CONDITIONAL ACCESS IMPACT (last 7 days):
Total sign-in attempts: 45,678
Blocked by posture: 312 (0.7%)
Remediated within 24h: 289 (92.6%)
Still non-compliant: 23
POSTURE DRIFT ALERTS:
Encryption disabled: 5
EDR sensor stopped: 3
OS downgraded: 1References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 3
api-reference.md1.5 KB
API Reference: Device Posture Assessment Agent
Dependencies
| Library | Version | Purpose |
|---|---|---|
| (stdlib only) | Python 3.8+ | Platform detection, subprocess for OS security checks |
CLI Usage
python scripts/agent.py --output-dir /reports/ --output device_posture.jsonFunctions
check_os_version() -> dict
Uses platform.system(), platform.version() for OS identification.
check_disk_encryption() -> dict
Windows: manage-bde -status C: (BitLocker). macOS: fdesetup status (FileVault). Linux: lsblk for LUKS.
check_firewall_status() -> dict
Windows: netsh advfirewall show allprofiles state. Linux: ufw status.
check_antivirus() -> dict
Windows: PowerShell Get-MpComputerStatus for Defender real-time protection.
check_screen_lock() -> dict
Windows: Registry InactivityTimeoutSecs check.
compute_posture_score(checks) -> dict
Weighted scoring: encryption (25), firewall (20), AV (25), screen lock (15), OS (15). Returns COMPLIANT/PARTIAL/NON_COMPLIANT.
Posture Checks
| Check | Weight | Tool |
|---|---|---|
| Disk Encryption | 25 | BitLocker/FileVault/LUKS |
| Firewall | 20 | Windows Firewall/UFW |
| Antivirus/EDR | 25 | Defender/endpoint agent |
| Screen Lock | 15 | OS policy |
| OS Supported | 15 | Platform detection |
Output Schema
{
"hostname": "WORKSTATION-01",
"posture": {"score": 85, "compliance": "COMPLIANT"},
"recommendations": ["Enable disk encryption"]
}standards.md2.2 KB
Device Posture Assessment - Standards & References
NIST SP 800-207: Zero Trust Architecture
- Section 2, Tenet 5: "The enterprise monitors and measures the integrity and security posture of all owned and associated assets"
- Section 3.3: Agent/Gateway Model includes device health as access input
- URL: https://csrc.nist.gov/publications/detail/sp/800-207/final
CISA Zero Trust Maturity Model v2.0 - Device Pillar
- Traditional: Limited visibility into device health
- Initial: Compliance enforcement via MDM
- Advanced: Continuous monitoring with automated remediation
- Optimal: Real-time posture integrated into every access decision
- URL: https://www.cisa.gov/zero-trust-maturity-model
NIST SP 800-124r2: Guidelines for Managing Mobile Device Security
- Section 3.2: Device compliance checking requirements
- Section 4.1: MDM security capabilities for posture enforcement
- URL: https://csrc.nist.gov/publications/detail/sp/800-124/rev-2/final
CrowdStrike ZTA Documentation
- ZTA Overview: https://www.crowdstrike.com/products/zero-trust-protection/
- ZTA API: https://falcon.crowdstrike.com/documentation/156/zero-trust-assessment-apis
- ZTA Scoring Methodology: OS signals + sensor configuration signals
Microsoft Intune Compliance
- Compliance Policies: https://learn.microsoft.com/en-us/mem/intune/protect/device-compliance-get-started
- Conditional Access Integration: https://learn.microsoft.com/en-us/entra/identity/conditional-access/concept-conditional-access-grant
- Device Health Attestation: https://learn.microsoft.com/en-us/windows/security/operating-system-security/system-security/protect-high-value-assets-by-controlling-the-health-of-windows-10-based-devices
Jamf Pro Compliance
- Smart Groups: https://learn.jamf.com/en-US/bundle/jamf-pro-documentation-current/page/Smart_Groups.html
- Compliance Reporter: https://learn.jamf.com/en-US/bundle/jamf-compliance-editor-documentation/page/Jamf_Compliance_Editor.html
HIPAA Security Rule (45 CFR 164.312)
- (a)(1): Access control - device posture as access control mechanism
- (d): Device and media controls - encryption and integrity requirements
workflows.md3.2 KB
Device Posture Assessment Implementation Workflow
Phase 1: Baseline Assessment (Week 1)
1.1 Inventory Current State
- Export all managed devices from Intune/Jamf/SCCM
- Identify unmanaged devices accessing corporate resources
- Document OS distribution, patch levels, and encryption status
- Measure current compliance rate before enforcement
1.2 Define Posture Requirements
- Establish minimum requirements per device tier:
- Tier 1 (Basic): OS updated within 90 days, screen lock enabled
- Tier 2 (Standard): Disk encryption, firewall, antivirus, OS within 60 days
- Tier 3 (Enhanced): EDR running, ZTA score >= 70, OS within 30 days, TPM/Secure Boot
- Tier 4 (Critical): ZTA score >= 90, fully managed, patched within 7 days
- Map application sensitivity to required posture tier
- Define grace periods for remediation (24h standard, 4h for critical)
Phase 2: MDM Policy Configuration (Week 2-3)
2.1 Intune Compliance Policies
- Create Windows compliance policy: BitLocker, Secure Boot, TPM, Defender, OS version
- Create macOS compliance policy: FileVault, Gatekeeper, SIP, Firewall
- Create iOS/Android compliance policy: Encryption, PIN, jailbreak detection
- Configure non-compliance actions: email notification, mark non-compliant, block after grace
- Assign policies to device groups
2.2 Jamf Pro Configuration
- Create smart groups for compliant/non-compliant macOS devices
- Configure compliance criteria: FileVault, SIP, Gatekeeper, OS version
- Set up automated remediation scripts for common issues
- Configure compliance reporting to Jamf Protect or SIEM
Phase 3: EDR Integration (Week 3-4)
3.1 CrowdStrike ZTA Setup
- Enable Zero Trust Assessment module in Falcon console
- Configure ZTA score thresholds per access tier
- Set up API integration for ZTNA platform (Zscaler, Cloudflare, Okta)
- Create host groups for ZTA monitoring
- Build dashboard for ZTA score distribution
3.2 Microsoft Defender for Endpoint
- Enable device risk assessment in Defender Security Center
- Configure risk levels: Low, Medium, High, Critical
- Integrate with Intune compliance via Defender connector
- Set up conditional access policy consuming device risk signal
Phase 4: Conditional Access Configuration (Week 4-5)
4.1 Entra ID Conditional Access
- Create policy: Require compliant device for all cloud apps
- Create policy: Block high-risk devices from sensitive apps
- Create policy: Require MFA + compliant device for admin portals
- Configure break-glass exclusions for emergency access
- Start in report-only mode, then switch to enforcement
4.2 Okta Device Trust
- Configure device trust integration with MDM platforms
- Create device assurance policies with CrowdStrike integration
- Set up authentication policies requiring device trust
- Test with enrolled and non-enrolled devices
Phase 5: Monitoring and Remediation (Ongoing)
- Build compliance dashboard showing real-time posture across fleet
- Configure alerts for posture drift (encryption disabled, EDR stopped)
- Automate remediation: push encryption enablement, deploy patches
- Generate weekly compliance reports for security leadership
- Conduct monthly review of posture requirements vs. threat landscape
Scripts 2
agent.py6.7 KB
#!/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()
process.py12.0 KB
#!/usr/bin/env python3
"""
Device Posture Assessment - Compliance Audit Tool
Queries CrowdStrike ZTA scores, Microsoft Intune compliance status,
and generates a consolidated device posture compliance report.
Requirements:
pip install requests msal pandas
"""
import json
import sys
from datetime import datetime, timezone
from typing import Any
import requests
class DevicePostureAuditor:
"""Audit device posture compliance across EDR and MDM platforms."""
def __init__(self, cs_client_id: str, cs_client_secret: str,
azure_tenant_id: str, azure_client_id: str, azure_client_secret: str):
self.cs_client_id = cs_client_id
self.cs_client_secret = cs_client_secret
self.azure_tenant_id = azure_tenant_id
self.azure_client_id = azure_client_id
self.azure_client_secret = azure_client_secret
self.cs_token = None
self.azure_token = None
def authenticate_crowdstrike(self):
"""Get CrowdStrike API bearer token."""
resp = requests.post(
"https://api.crowdstrike.com/oauth2/token",
data={
"client_id": self.cs_client_id,
"client_secret": self.cs_client_secret
},
timeout=30
)
resp.raise_for_status()
self.cs_token = resp.json()["access_token"]
print("[AUTH] CrowdStrike authenticated")
def authenticate_azure(self):
"""Get Microsoft Graph API token."""
resp = requests.post(
f"https://login.microsoftonline.com/{self.azure_tenant_id}/oauth2/v2.0/token",
data={
"client_id": self.azure_client_id,
"client_secret": self.azure_client_secret,
"scope": "https://graph.microsoft.com/.default",
"grant_type": "client_credentials"
},
timeout=30
)
resp.raise_for_status()
self.azure_token = resp.json()["access_token"]
print("[AUTH] Microsoft Graph authenticated")
def get_zta_scores(self) -> dict[str, Any]:
"""Get CrowdStrike ZTA score distribution."""
print("\n[1/4] Querying CrowdStrike ZTA scores...")
headers = {"Authorization": f"Bearer {self.cs_token}"}
# Get all device AIDs with ZTA assessments
resp = requests.get(
"https://api.crowdstrike.com/zero-trust-assessment/queries/assessments/v1",
headers=headers,
params={"limit": 5000},
timeout=60
)
resp.raise_for_status()
device_ids = resp.json().get("resources", [])
if not device_ids:
print(" No ZTA assessments found")
return {"total": 0, "distribution": {}}
# Get detailed assessments in batches of 100
scores = []
for i in range(0, len(device_ids), 100):
batch = device_ids[i:i+100]
resp = requests.get(
"https://api.crowdstrike.com/zero-trust-assessment/entities/assessments/v1",
headers=headers,
params={"ids": batch},
timeout=60
)
if resp.status_code == 200:
for resource in resp.json().get("resources", []):
assessment = resource.get("assessment", {})
scores.append({
"aid": resource.get("aid"),
"overall": assessment.get("overall", 0),
"os_score": assessment.get("os", 0),
"sensor_score": assessment.get("sensor_config", 0)
})
# Calculate distribution
distribution = {
"critical_90_100": sum(1 for s in scores if s["overall"] >= 90),
"high_80_89": sum(1 for s in scores if 80 <= s["overall"] < 90),
"medium_65_79": sum(1 for s in scores if 65 <= s["overall"] < 80),
"low_50_64": sum(1 for s in scores if 50 <= s["overall"] < 65),
"blocked_below_50": sum(1 for s in scores if s["overall"] < 50),
}
avg_score = sum(s["overall"] for s in scores) / len(scores) if scores else 0
print(f" Total devices: {len(scores)}")
print(f" Average ZTA score: {avg_score:.1f}")
print(f" Distribution: {distribution}")
return {
"total": len(scores),
"average_score": round(avg_score, 1),
"distribution": distribution,
"below_threshold_50": distribution["blocked_below_50"]
}
def get_intune_compliance(self) -> dict[str, Any]:
"""Get Microsoft Intune device compliance status."""
print("\n[2/4] Querying Intune compliance status...")
headers = {"Authorization": f"Bearer {self.azure_token}"}
resp = requests.get(
"https://graph.microsoft.com/v1.0/deviceManagement/managedDevices",
headers=headers,
params={
"$select": "id,deviceName,userPrincipalName,complianceState,"
"operatingSystem,osVersion,isEncrypted,lastSyncDateTime,"
"managementAgent",
"$top": 999
},
timeout=60
)
resp.raise_for_status()
devices = resp.json().get("value", [])
stats = {
"total": len(devices),
"compliant": 0,
"noncompliant": 0,
"in_grace_period": 0,
"unknown": 0,
"os_distribution": {},
"encryption_status": {"encrypted": 0, "not_encrypted": 0},
"stale_devices": 0,
"noncompliant_details": []
}
now = datetime.now(timezone.utc)
for device in devices:
compliance = device.get("complianceState", "unknown")
os_name = device.get("operatingSystem", "unknown")
encrypted = device.get("isEncrypted", False)
stats["os_distribution"][os_name] = stats["os_distribution"].get(os_name, 0) + 1
if encrypted:
stats["encryption_status"]["encrypted"] += 1
else:
stats["encryption_status"]["not_encrypted"] += 1
if compliance == "compliant":
stats["compliant"] += 1
elif compliance == "noncompliant":
stats["noncompliant"] += 1
stats["noncompliant_details"].append({
"device": device.get("deviceName"),
"user": device.get("userPrincipalName"),
"os": f"{os_name} {device.get('osVersion', '')}",
"encrypted": encrypted
})
elif compliance == "inGracePeriod":
stats["in_grace_period"] += 1
else:
stats["unknown"] += 1
# Check for stale devices (no sync in 30 days)
last_sync = device.get("lastSyncDateTime")
if last_sync:
try:
sync_dt = datetime.fromisoformat(last_sync.replace("Z", "+00:00"))
if (now - sync_dt).days > 30:
stats["stale_devices"] += 1
except (ValueError, TypeError):
pass
compliance_rate = (stats["compliant"] / stats["total"] * 100) if stats["total"] else 0
print(f" Total: {stats['total']}, Compliant: {stats['compliant']} ({compliance_rate:.1f}%)")
print(f" Non-compliant: {stats['noncompliant']}, Grace period: {stats['in_grace_period']}")
print(f" Encryption: {stats['encryption_status']}")
print(f" Stale devices (>30d no sync): {stats['stale_devices']}")
return stats
def correlate_posture(self, zta: dict, intune: dict) -> dict[str, Any]:
"""Correlate ZTA and MDM compliance for overall posture score."""
print("\n[3/4] Correlating posture signals...")
total_devices = max(zta["total"], intune["total"])
zta_passing = zta["total"] - zta.get("below_threshold_50", 0)
intune_passing = intune["compliant"] + intune["in_grace_period"]
overall_compliance = min(
(zta_passing / zta["total"] * 100) if zta["total"] else 0,
(intune_passing / intune["total"] * 100) if intune["total"] else 0
)
summary = {
"estimated_total_devices": total_devices,
"zta_passing_rate": round((zta_passing / zta["total"] * 100) if zta["total"] else 0, 1),
"intune_passing_rate": round((intune_passing / intune["total"] * 100) if intune["total"] else 0, 1),
"overall_compliance_rate": round(overall_compliance, 1),
"risk_level": "LOW" if overall_compliance >= 90 else "MEDIUM" if overall_compliance >= 75 else "HIGH"
}
print(f" ZTA passing: {summary['zta_passing_rate']}%")
print(f" Intune passing: {summary['intune_passing_rate']}%")
print(f" Overall compliance: {summary['overall_compliance_rate']}%")
print(f" Risk level: {summary['risk_level']}")
return summary
def generate_report(self, zta: dict, intune: dict, correlated: dict) -> str:
"""Generate consolidated posture report."""
print("\n[4/4] Generating report...")
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
report = f"""
Device Posture Compliance Report
{'=' * 55}
Generated: {now}
1. CROWDSTRIKE ZTA SCORES
Total devices assessed: {zta['total']}
Average ZTA score: {zta['average_score']}
Score >= 90 (Critical OK): {zta['distribution'].get('critical_90_100', 0)}
Score 80-89 (High OK): {zta['distribution'].get('high_80_89', 0)}
Score 65-79 (Medium OK): {zta['distribution'].get('medium_65_79', 0)}
Score 50-64 (Low): {zta['distribution'].get('low_50_64', 0)}
Score < 50 (BLOCKED): {zta['distribution'].get('blocked_below_50', 0)}
2. INTUNE COMPLIANCE
Total managed devices: {intune['total']}
Compliant: {intune['compliant']}
Non-compliant: {intune['noncompliant']}
In grace period: {intune['in_grace_period']}
Stale (>30d no sync): {intune['stale_devices']}
Encrypted: {intune['encryption_status']['encrypted']}
Not encrypted: {intune['encryption_status']['not_encrypted']}
3. OVERALL POSTURE
ZTA passing rate: {correlated['zta_passing_rate']}%
Intune passing rate: {correlated['intune_passing_rate']}%
Combined compliance: {correlated['overall_compliance_rate']}%
Risk level: {correlated['risk_level']}
4. RECOMMENDATIONS
"""
recs = []
if zta["distribution"].get("blocked_below_50", 0) > 0:
recs.append(f" - {zta['distribution']['blocked_below_50']} devices below ZTA 50 - investigate immediately")
if intune["encryption_status"]["not_encrypted"] > 0:
recs.append(f" - {intune['encryption_status']['not_encrypted']} devices lack encryption - enforce BitLocker/FileVault")
if intune["stale_devices"] > 0:
recs.append(f" - {intune['stale_devices']} stale devices - verify active use or remove")
if correlated["overall_compliance_rate"] < 95:
recs.append(f" - Overall compliance {correlated['overall_compliance_rate']}% below 95% target")
if not recs:
recs.append(" - All devices meet compliance requirements")
report += "\n".join(recs)
return report
def main():
if len(sys.argv) < 6:
print("Usage: python process.py <cs_client_id> <cs_client_secret> "
"<azure_tenant_id> <azure_client_id> <azure_client_secret>")
sys.exit(1)
auditor = DevicePostureAuditor(*sys.argv[1:6])
auditor.authenticate_crowdstrike()
auditor.authenticate_azure()
zta = auditor.get_zta_scores()
intune = auditor.get_intune_compliance()
correlated = auditor.correlate_posture(zta, intune)
report = auditor.generate_report(zta, intune, correlated)
print(report)
filename = f"device_posture_report_{datetime.now().strftime('%Y%m%d')}.txt"
with open(filename, "w") as f:
f.write(report)
print(f"\nReport saved to: {filename}")
if __name__ == "__main__":
main()