mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-24 13:40:57 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,439 @@
|
||||
---
|
||||
name: implementing-device-posture-assessment-in-zero-trust
|
||||
description: >
|
||||
Implementing device posture assessment as a zero trust access control by integrating
|
||||
endpoint health signals from CrowdStrike ZTA, Microsoft Intune, and Jamf into
|
||||
conditional access policies that enforce compliance before granting resource access.
|
||||
domain: cybersecurity
|
||||
subdomain: zero-trust-architecture
|
||||
tags: [device-posture, zero-trust, endpoint-compliance, crowdstrike-zta, intune, conditional-access, jamf]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Implementing Device Posture Assessment in Zero Trust
|
||||
|
||||
## 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.
|
||||
|
||||
```powershell
|
||||
# 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.
|
||||
|
||||
```bash
|
||||
# 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 status
|
||||
```
|
||||
|
||||
### Step 3: Integrate Device Posture with Entra ID Conditional Access
|
||||
|
||||
Create conditional access policies that require compliant devices.
|
||||
|
||||
```powershell
|
||||
# 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 $riskPolicy
|
||||
```
|
||||
|
||||
### Step 4: Configure Okta Device Trust with CrowdStrike Integration
|
||||
|
||||
Set up Okta device trust policies using CrowdStrike posture signals.
|
||||
|
||||
```bash
|
||||
# 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.
|
||||
|
||||
```python
|
||||
#!/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**:
|
||||
1. Define Windows compliance policy in Intune: BitLocker, Secure Boot, TPM, Defender enabled, OS >= 10.0.19045
|
||||
2. Define macOS compliance policy in Jamf: FileVault, Gatekeeper, SIP, Firewall, OS >= 14.0
|
||||
3. Configure CrowdStrike ZTA thresholds: >= 70 for general apps, >= 85 for patient data systems
|
||||
4. Create Entra ID Conditional Access policies requiring compliant device + MFA for all cloud apps
|
||||
5. Configure 24-hour grace period for newly non-compliant devices before blocking
|
||||
6. Set up weekly compliance report for IT showing non-compliant devices and remediation actions
|
||||
7. 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: 1
|
||||
```
|
||||
@@ -0,0 +1,104 @@
|
||||
# Device Posture Assessment - Compliance Requirements Template
|
||||
|
||||
## Organization Information
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Organization | HealthCorp Medical |
|
||||
| Total Endpoints | 2,000 |
|
||||
| MDM Platform | Microsoft Intune (Windows), Jamf Pro (macOS) |
|
||||
| EDR Platform | CrowdStrike Falcon |
|
||||
| IdP | Microsoft Entra ID |
|
||||
|
||||
## Device Posture Tiers
|
||||
|
||||
### Tier 1: Basic Access (General Applications)
|
||||
| Requirement | Windows | macOS | iOS/Android |
|
||||
|------------|---------|-------|-------------|
|
||||
| OS Version | >= 10.0.19045 | >= 14.0 | Latest -2 |
|
||||
| Screen Lock | Enabled | Enabled | Enabled (6-digit PIN) |
|
||||
| Encryption | Recommended | Recommended | Required |
|
||||
| Firewall | Enabled | Enabled | N/A |
|
||||
| CrowdStrike ZTA | >= 50 | >= 50 | N/A |
|
||||
| Applications | Email, Wiki, Chat | Email, Wiki, Chat | Email, Chat |
|
||||
|
||||
### Tier 2: Standard Access (Business Applications)
|
||||
| Requirement | Windows | macOS |
|
||||
|------------|---------|-------|
|
||||
| OS Version | >= 10.0.22621 | >= 14.0 |
|
||||
| Screen Lock | Enabled, 5min timeout | Enabled, 5min timeout |
|
||||
| Disk Encryption | BitLocker Required | FileVault Required |
|
||||
| Firewall | Enabled | Enabled |
|
||||
| Antivirus | Defender Active | XProtect Active |
|
||||
| CrowdStrike ZTA | >= 65 | >= 65 |
|
||||
| Secure Boot | Required | N/A |
|
||||
| Applications | CRM, Internal Tools, Intranet | CRM, Internal Tools, Intranet |
|
||||
|
||||
### Tier 3: Enhanced Access (Sensitive Data)
|
||||
| Requirement | Windows | macOS |
|
||||
|------------|---------|-------|
|
||||
| OS Version | >= 10.0.22631 (latest) | >= 15.0 (latest) |
|
||||
| Disk Encryption | BitLocker + TPM | FileVault + Secure Enclave |
|
||||
| CrowdStrike ZTA | >= 80 | >= 80 |
|
||||
| Patch Level | Within 14 days of release | Within 14 days of release |
|
||||
| Admin Approval | Device admin-approved | Device admin-approved |
|
||||
| MDM Managed | Required | Required |
|
||||
| Applications | Financial Systems, HR Data, Source Code | Financial Systems, HR Data |
|
||||
|
||||
### Tier 4: Critical Access (Regulated Data)
|
||||
| Requirement | Windows | macOS |
|
||||
|------------|---------|-------|
|
||||
| CrowdStrike ZTA | >= 90 | >= 90 |
|
||||
| Patch Level | Within 7 days | Within 7 days |
|
||||
| Code Integrity | HVCI Enabled | SIP Enabled |
|
||||
| Certificate | Corporate certificate present | Corporate certificate present |
|
||||
| Geo Restriction | US only | US only |
|
||||
| Applications | Patient Records (HIPAA), PCI Data | Patient Records (HIPAA) |
|
||||
|
||||
## Compliance Policy Assignments
|
||||
|
||||
| Policy | Device Group | Grace Period | Non-Compliance Action |
|
||||
|--------|-------------|-------------|----------------------|
|
||||
| Tier 1 Baseline | All Managed Devices | 72 hours | Email notification |
|
||||
| Tier 2 Standard | Corporate Workstations | 48 hours | Mark non-compliant |
|
||||
| Tier 3 Enhanced | Sensitive Data Users | 24 hours | Block access |
|
||||
| Tier 4 Critical | HIPAA/PCI Users | 4 hours | Block access + alert SOC |
|
||||
|
||||
## CrowdStrike ZTA Score Mapping
|
||||
|
||||
| ZTA Score Range | Access Tier | Conditional Access Action |
|
||||
|----------------|-------------|--------------------------|
|
||||
| 90-100 | Tier 4 (Critical) | Allow all applications |
|
||||
| 80-89 | Tier 3 (Enhanced) | Allow up to sensitive apps |
|
||||
| 65-79 | Tier 2 (Standard) | Allow business apps only |
|
||||
| 50-64 | Tier 1 (Basic) | Allow general apps only |
|
||||
| < 50 | BLOCKED | Block all access, notify IT |
|
||||
|
||||
## Current Compliance Dashboard
|
||||
|
||||
| Metric | Target | Current | Status |
|
||||
|--------|--------|---------|--------|
|
||||
| Overall Compliance Rate | >= 95% | 93.2% | At Risk |
|
||||
| Encryption Coverage | 100% | 97.8% | On Track |
|
||||
| EDR Coverage | 100% | 99.1% | On Track |
|
||||
| Average ZTA Score | >= 75 | 78.4 | Meeting |
|
||||
| Devices Below ZTA 50 | 0 | 34 | Action Needed |
|
||||
| Stale Devices (>30d) | < 1% | 0.8% | Meeting |
|
||||
| Patch Compliance (14d) | >= 90% | 87.3% | At Risk |
|
||||
|
||||
## Remediation Actions
|
||||
|
||||
| Issue | Automated Remediation | Manual Escalation |
|
||||
|-------|----------------------|-------------------|
|
||||
| BitLocker Disabled | Intune policy pushes enablement | IT ticket after 24h |
|
||||
| FileVault Disabled | Jamf policy enables FileVault | IT ticket after 24h |
|
||||
| OS Outdated | Intune/Jamf pushes update | IT ticket after 48h |
|
||||
| CrowdStrike Stopped | Auto-restart via watchdog | SOC alert after 30min |
|
||||
| Firewall Disabled | GPO re-enables | IT ticket after 4h |
|
||||
|
||||
## Sign-Off
|
||||
|
||||
| Role | Name | Date | Approved |
|
||||
|------|------|------|----------|
|
||||
| CISO | _________________ | __________ | [ ] |
|
||||
| IT Operations Director | _________________ | __________ | [ ] |
|
||||
| Compliance Officer | _________________ | __________ | [ ] |
|
||||
@@ -0,0 +1,36 @@
|
||||
# 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
|
||||
@@ -0,0 +1,71 @@
|
||||
# Device Posture Assessment Implementation Workflow
|
||||
|
||||
## Phase 1: Baseline Assessment (Week 1)
|
||||
|
||||
### 1.1 Inventory Current State
|
||||
1. Export all managed devices from Intune/Jamf/SCCM
|
||||
2. Identify unmanaged devices accessing corporate resources
|
||||
3. Document OS distribution, patch levels, and encryption status
|
||||
4. Measure current compliance rate before enforcement
|
||||
|
||||
### 1.2 Define Posture Requirements
|
||||
1. 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
|
||||
2. Map application sensitivity to required posture tier
|
||||
3. Define grace periods for remediation (24h standard, 4h for critical)
|
||||
|
||||
## Phase 2: MDM Policy Configuration (Week 2-3)
|
||||
|
||||
### 2.1 Intune Compliance Policies
|
||||
1. Create Windows compliance policy: BitLocker, Secure Boot, TPM, Defender, OS version
|
||||
2. Create macOS compliance policy: FileVault, Gatekeeper, SIP, Firewall
|
||||
3. Create iOS/Android compliance policy: Encryption, PIN, jailbreak detection
|
||||
4. Configure non-compliance actions: email notification, mark non-compliant, block after grace
|
||||
5. Assign policies to device groups
|
||||
|
||||
### 2.2 Jamf Pro Configuration
|
||||
1. Create smart groups for compliant/non-compliant macOS devices
|
||||
2. Configure compliance criteria: FileVault, SIP, Gatekeeper, OS version
|
||||
3. Set up automated remediation scripts for common issues
|
||||
4. Configure compliance reporting to Jamf Protect or SIEM
|
||||
|
||||
## Phase 3: EDR Integration (Week 3-4)
|
||||
|
||||
### 3.1 CrowdStrike ZTA Setup
|
||||
1. Enable Zero Trust Assessment module in Falcon console
|
||||
2. Configure ZTA score thresholds per access tier
|
||||
3. Set up API integration for ZTNA platform (Zscaler, Cloudflare, Okta)
|
||||
4. Create host groups for ZTA monitoring
|
||||
5. Build dashboard for ZTA score distribution
|
||||
|
||||
### 3.2 Microsoft Defender for Endpoint
|
||||
1. Enable device risk assessment in Defender Security Center
|
||||
2. Configure risk levels: Low, Medium, High, Critical
|
||||
3. Integrate with Intune compliance via Defender connector
|
||||
4. Set up conditional access policy consuming device risk signal
|
||||
|
||||
## Phase 4: Conditional Access Configuration (Week 4-5)
|
||||
|
||||
### 4.1 Entra ID Conditional Access
|
||||
1. Create policy: Require compliant device for all cloud apps
|
||||
2. Create policy: Block high-risk devices from sensitive apps
|
||||
3. Create policy: Require MFA + compliant device for admin portals
|
||||
4. Configure break-glass exclusions for emergency access
|
||||
5. Start in report-only mode, then switch to enforcement
|
||||
|
||||
### 4.2 Okta Device Trust
|
||||
1. Configure device trust integration with MDM platforms
|
||||
2. Create device assurance policies with CrowdStrike integration
|
||||
3. Set up authentication policies requiring device trust
|
||||
4. Test with enrolled and non-enrolled devices
|
||||
|
||||
## Phase 5: Monitoring and Remediation (Ongoing)
|
||||
|
||||
1. Build compliance dashboard showing real-time posture across fleet
|
||||
2. Configure alerts for posture drift (encryption disabled, EDR stopped)
|
||||
3. Automate remediation: push encryption enablement, deploy patches
|
||||
4. Generate weekly compliance reports for security leadership
|
||||
5. Conduct monthly review of posture requirements vs. threat landscape
|
||||
@@ -0,0 +1,302 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user