Intermediate โฑ 100 min ๐Ÿ“‹ 10 Steps

Deploy Security Baselines & Configuration Compliance

Assess endpoints against CIS and Microsoft security baselines, identify configuration drift, create remediation plans, build custom profiles, and generate audit-ready compliance reports.

๐Ÿ“‹ Overview

About This Lab

Security baselines define the minimum security configuration standards for your endpoints. Defender Vulnerability Management evaluates devices against CIS benchmarks, Microsoft security baselines, and custom baselines to identify configuration drift, misconfigurations, and non-compliant devices. This lab covers deploying baselines, assessing compliance, tracking remediation, and building configuration management dashboards.

๐Ÿข Enterprise Use Case

An enterprise must demonstrate CIS Level 1 compliance across 3,000 Windows endpoints for PCI-DSS audit. The security team discovers 40% of endpoints have non-compliant configurations: disabled firewalls, missing BitLocker encryption, and outdated security settings. They need baseline assessments, remediation tracking, and audit-ready reports.

๐ŸŽฏ What You Will Learn

  1. Navigate the security baselines dashboard
  2. Assess devices against CIS benchmarks
  3. Assess devices against Microsoft security baselines
  4. Identify common configuration drift patterns
  5. Create remediation plans for non-compliant devices
  6. Track baseline compliance over time
  7. Build custom baseline profiles
  8. Configure compliance alerts and reports
  9. Integrate with Intune for automated remediation
  10. Generate audit-ready compliance reports

๐Ÿ”‘ Why This Matters

Misconfigurations cause 80% of security breaches. A single endpoint with a disabled firewall or missing encryption can become the entry point for ransomware. Security baselines transform configuration management from ad-hoc to systematic, providing continuous compliance monitoring.

โš™๏ธ Prerequisites

  • Licensing: Microsoft Defender Vulnerability Management add-on or Defender for Endpoint P2
  • Roles: Security Administrator or Global Administrator for baseline policy creation; Security Reader for viewing compliance data
  • Intune: Microsoft Intune enrolled devices for automated remediation (Steps 9โ€“10)
  • Permissions: Microsoft Graph API permissions - Machine.Read.All, SecurityBaselinesAssessment.Read.All for programmatic access
  • Portal Access: Microsoft Defender portal (security.microsoft.com)
  • Tooling: PowerShell 7+ with Az and Microsoft.Graph modules installed

Step 1 ยท Navigate Security Baselines Dashboard

The security baselines dashboard in Defender Vulnerability Management provides a centralised view of how your endpoints measure up against industry-standard benchmarks. Before diving into specific compliance checks, you need to orient yourself with the available baselines, understand the assessment scoring model, and use the API to pull baseline profiles programmatically for automation workflows.

  1. Navigate to Vulnerability management > Baselines assessment
  2. Review available baselines: CIS Level 1, CIS Level 2, Microsoft security baselines
  3. Select a baseline to see the list of configuration checks and their compliance status
  4. Note the overall compliance percentage and most common failures
# ============================================================
# Retrieve MDE Security Baselines via Microsoft Graph API
# ============================================================
# WHAT: Pulls the list of available security baseline profiles
#       and their compliance summaries from the Defender API.
# WHY:  Enables automation of compliance reporting and lets you
#       compare baselines programmatically before choosing which
#       to deploy across your fleet.
# PREREQ: Install-Module Microsoft.Graph -Scope CurrentUser
#         Connect-MgGraph -Scopes "DeviceManagementConfiguration.Read.All"
# ============================================================

# Connect to Microsoft Graph with required scopes
Connect-MgGraph -Scopes "DeviceManagementConfiguration.Read.All",
                        "SecurityEvents.Read.All"

# Get all available security baseline profiles
$baselines = Invoke-MgGraphRequest -Method GET `
    -Uri "https://graph.microsoft.com/beta/security/baselineProfiles" `
    -OutputType PSObject

# Display each baseline with its compliance summary
foreach ($baseline in $baselines.value) {
    Write-Host "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" -ForegroundColor Cyan
    Write-Host "Baseline: $($baseline.displayName)" -ForegroundColor White
    Write-Host "  ID:          $($baseline.id)"
    Write-Host "  Benchmark:   $($baseline.benchmark)"
    Write-Host "  Version:     $($baseline.version)"
    Write-Host "  OS:          $($baseline.operatingSystem)"
    Write-Host "  Created:     $($baseline.createdDateTime)"
}

# Get detailed compliance for a specific baseline profile
$profileId = $baselines.value[0].id   # First baseline
$compliance = Invoke-MgGraphRequest -Method GET `
    -Uri "https://graph.microsoft.com/beta/security/baselineProfiles/$profileId/deviceStates" `
    -OutputType PSObject

# Summarise compliance states
$compliance.value | Group-Object -Property state |
    Select-Object Name, Count |
    Sort-Object Count -Descending |
    Format-Table -AutoSize
💡 Pro Tip: Bookmark the baselines dashboard and check it first thing every morning. A sudden drop in compliance percentage often signals a GPO change, a failed Intune sync, or a rogue admin disabling security controls overnight.

Step 2 ยท Assess CIS Benchmark Compliance

CIS benchmarks are the gold standard for endpoint hardening. DVM maps each CIS Level 1 and Level 2 check to the actual device configuration state, letting you see exactly which settings are compliant and which are not. In this step you will walk through the CIS assessment categories and use Intune to create configuration profiles that enforce the most critical settings automatically.

  1. Select the CIS Windows 11 (or Server 2022) Level 1 baseline
  2. Review each configuration category: Account Policies, Local Policies, Audit Policy, Security Options
  3. For each failed check: review the current setting vs. the recommended setting
  4. Identify the most impactful failures by the number of affected devices
  5. Prioritise remediation based on risk: critical misconfigurations first
# ============================================================
# Create Intune Configuration Profile for CIS Baseline Settings
# ============================================================
# WHAT: Creates a Device Configuration profile in Intune that
#       enforces key CIS Level 1 settings: password policy,
#       firewall, BitLocker, and screen lock.
# WHY:  Manual GPO enforcement doesn't scale. Intune profiles
#       ensure every enrolled device receives and maintains
#       the correct configuration regardless of network location.
# PREREQ: Connect-MgGraph -Scopes "DeviceManagementConfiguration.ReadWrite.All"
# ============================================================

# Connect with Intune write permissions
Connect-MgGraph -Scopes "DeviceManagementConfiguration.ReadWrite.All"

# Define the CIS-aligned configuration profile payload
$profileBody = @{
    "@odata.type"     = "#microsoft.graph.windows10CustomConfiguration"
    displayName       = "CIS Level 1 - Windows 11 Baseline"
    description       = "Enforces CIS Level 1 benchmark settings for password, firewall, BitLocker, and screen lock"
    omaSettings       = @(
        # โ”€โ”€ Password minimum length (CIS 1.1.4) โ”€โ”€
        @{
            "@odata.type" = "#microsoft.graph.omaSettingInteger"
            displayName   = "Minimum Password Length"
            omaUri        = "./Device/Vendor/MSFT/Policy/Config/DeviceLock/MinDevicePasswordLength"
            value         = 14   # CIS recommends 14+ characters
        },
        # โ”€โ”€ Account lockout threshold (CIS 1.2.1) โ”€โ”€
        @{
            "@odata.type" = "#microsoft.graph.omaSettingInteger"
            displayName   = "Account Lockout Threshold"
            omaUri        = "./Device/Vendor/MSFT/Policy/Config/DeviceLock/MaxDevicePasswordFailedAttempts"
            value         = 5    # Lock after 5 failed attempts
        },
        # โ”€โ”€ Screen lock timeout (CIS 2.3.7.5) โ”€โ”€
        @{
            "@odata.type" = "#microsoft.graph.omaSettingInteger"
            displayName   = "Inactivity Lock (seconds)"
            omaUri        = "./Device/Vendor/MSFT/Policy/Config/DeviceLock/MaxInactivityTimeDeviceLock"
            value         = 300  # 5 minutes
        },
        # โ”€โ”€ Enable Windows Firewall - Domain Profile (CIS 9.1.1) โ”€โ”€
        @{
            "@odata.type" = "#microsoft.graph.omaSettingInteger"
            displayName   = "Enable Domain Firewall"
            omaUri        = "./Vendor/MSFT/Firewall/MdmStore/DomainProfile/EnableFirewall"
            value         = 1    # 1 = Enabled
        }
    )
} | ConvertTo-Json -Depth 10

# Create the profile in Intune
Invoke-MgGraphRequest -Method POST `
    -Uri "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations" `
    -Body $profileBody `
    -ContentType "application/json"

Write-Host "โœ… CIS Level 1 configuration profile created in Intune" -ForegroundColor Green
💡 Pro Tip: Start with CIS Level 1 - it covers the essential security controls with minimal operational impact. Only move to Level 2 after achieving 95%+ Level 1 compliance, as Level 2 checks can affect application compatibility and user experience.

Step 3 ยท Assess Microsoft Security Baselines

Microsoft publishes its own security baselines for Windows, Edge, and Microsoft 365 Apps. These baselines reflect Microsoft's internal hardening standards and sometimes differ from CIS recommendations. Using the DeviceTvmSecureConfigurationAssessment table in Advanced Hunting, you can query compliance across both frameworks simultaneously and identify where they overlap or diverge.

  1. Select the Microsoft Windows Security Baseline
  2. Compare with CIS baselines: Microsoft baselines may have different thresholds
  3. Identify overlapping and unique recommendations from each baseline
  4. Choose a primary baseline for your organisation and use the other as supplementary
// ============================================================
// Analyse Secure Configuration Compliance Across All Baselines
// ============================================================
// WHAT: Queries DeviceTvmSecureConfigurationAssessment to show
//       compliance status per configuration check, grouped by
//       sub-category (e.g., Firewall, BitLocker, Antivirus).
// WHY:  Gives you a single-pane view of which configuration
//       areas are strongest and which need urgent attention.
// TABLE: DeviceTvmSecureConfigurationAssessment
// KEY FIELDS:
//   ConfigurationId        - unique ID for each security check
//   ConfigurationSubcategory - grouping (Firewall, Credential Guard, etc.)
//   IsCompliant            - true/false per device per check
//   IsApplicable           - whether the check applies to this device
// OUTPUT: Subcategory, total applicable devices, compliant count, percentage
DeviceTvmSecureConfigurationAssessment
| where IsApplicable == true
| summarize
    TotalDevices   = dcount(DeviceId),
    CompliantCount = dcountif(DeviceId, IsCompliant == true),
    NonCompliant   = dcountif(DeviceId, IsCompliant == false)
    by ConfigurationSubcategory
| extend CompliancePct = round(100.0 * CompliantCount / TotalDevices, 1)
| order by CompliancePct asc   // Worst compliance first
| project ConfigurationSubcategory, TotalDevices, CompliantCount,
          NonCompliant, CompliancePct
// ============================================================
// Top 20 Most-Failing Configuration Checks
// ============================================================
// WHAT: Identifies the individual configuration checks that
//       fail on the most devices - your biggest compliance gaps.
// WHY:  Fixing one broadly-failing check can improve compliance
//       across hundreds of devices in a single remediation effort.
DeviceTvmSecureConfigurationAssessment
| where IsApplicable == true
| where IsCompliant == false
| summarize FailedDevices = dcount(DeviceId)
    by ConfigurationId, ConfigurationSubcategory, ConfigurationDescription
| top 20 by FailedDevices
| project ConfigurationId, ConfigurationSubcategory,
          ConfigurationDescription, FailedDevices
💡 Pro Tip: Export both CIS and Microsoft baseline results side-by-side. Where they agree, you have strong industry consensus. Where they diverge, document the rationale for which recommendation you follow - auditors appreciate a documented decision over blind compliance.

Step 4 ยท Identify Configuration Drift

Configuration drift occurs when devices gradually move out of compliance - often silently. A GPO update may override an Intune policy, a user may disable a firewall for troubleshooting and forget to re-enable it, or an OS update may reset security settings. This step uses KQL to detect drift patterns and pinpoint which devices changed state recently.

  1. Review the compliance trend over time: are devices becoming less compliant?
  2. Identify newly non-compliant devices: what changed?
  3. Look for patterns: are specific device groups or OUs drifting?
  4. Correlate with recent GPO changes, Intune policy updates, or OS patches
// ============================================================
// Detect Configuration Drift - Devices That Became Non-Compliant
// ============================================================
// WHAT: Compares the latest secure-config assessment against
//       the state from 7 days ago to find devices that were
//       compliant but have since drifted out of compliance.
// WHY:  Drift is often invisible until an audit. This query
//       surfaces regressions so you can fix them before they
//       compound into systemic non-compliance.
// HOW:  Two time-windowed summaries are joined by DeviceId +
//       ConfigurationId. Any check that was true (compliant)
//       7 days ago but is now false (non-compliant) is drift.
let currentState = DeviceTvmSecureConfigurationAssessment
| where Timestamp > ago(1d)
| where IsApplicable == true
| project DeviceId, DeviceName, ConfigurationId,
          ConfigurationSubcategory, CurrentCompliant = IsCompliant;
let previousState = DeviceTvmSecureConfigurationAssessment
| where Timestamp between (ago(8d) .. ago(7d))
| where IsApplicable == true
| project DeviceId, ConfigurationId,
          PreviousCompliant = IsCompliant;
currentState
| join kind=inner previousState on DeviceId, ConfigurationId
| where PreviousCompliant == true and CurrentCompliant == false
| summarize DriftedChecks = count() by DeviceName, DeviceId,
            ConfigurationSubcategory
| order by DriftedChecks desc
| project DeviceName, ConfigurationSubcategory, DriftedChecks
💡 Pro Tip: Schedule this drift detection query as a custom detection rule that fires daily. When a device drifts on 5+ configuration checks simultaneously, it usually indicates a policy conflict or a local admin override - investigate immediately.

Step 5 ยท Create Remediation Plans

Remediation plans translate compliance gaps into actionable work items. For each critical baseline failure, you need to assign ownership, define rollback procedures, and track progress against audit deadlines. This step also shows how to use KQL to generate a prioritised remediation queue based on the number of affected devices and the severity of each configuration gap.

  1. For each critical baseline failure, create a remediation task
  2. Assign remediation to the appropriate team: endpoint management, server team, or security
  3. Set deadlines aligned with compliance requirements
  4. Define rollback procedures for each configuration change
  5. Document change control numbers for audit trail
// ============================================================
// Generate Prioritised Remediation Queue
// ============================================================
// WHAT: Builds a ranked remediation list showing which config
//       checks to fix first based on affected device count
//       and the configuration subcategory.
// WHY:  Fixing the top 10 checks can often remediate 80% of
//       your non-compliant devices - maximum impact with
//       minimum effort.
DeviceTvmSecureConfigurationAssessment
| where IsApplicable == true
| where IsCompliant == false
| summarize
    AffectedDevices = dcount(DeviceId),
    SampleDevices   = make_set(DeviceName, 3)  // Show 3 example devices
    by ConfigurationId, ConfigurationSubcategory,
       ConfigurationDescription
| order by AffectedDevices desc
| extend Priority = case(
    AffectedDevices > 500, "๐Ÿ”ด Critical",
    AffectedDevices > 100, "๐ŸŸ  High",
    AffectedDevices > 25,  "๐ŸŸก Medium",
    "๐ŸŸข Low")
| project Priority, ConfigurationId, ConfigurationSubcategory,
          ConfigurationDescription, AffectedDevices, SampleDevices
💡 Pro Tip: Attach the KQL output as evidence in your change management tickets. This creates an audit trail showing that remediation decisions were data-driven and risk-prioritised - exactly what PCI-DSS and ISO 27001 auditors want to see.

Step 6 ยท Track Baseline Compliance Over Time

Compliance is not a one-time achievement - it is a continuous process. Tracking compliance trends over time reveals whether your remediation efforts are working, whether new deployments introduce regressions, and whether your organisation is moving towards or away from its compliance targets. This step sets up the monitoring cadence.

  1. Monitor the compliance percentage trend weekly
  2. Review which remediation tasks have been completed
  3. Verify fixed items remain compliant after the next assessment cycle
  4. Track regression: devices that were compliant but reverted
// ============================================================
// Compliance Trend Over the Last 30 Days
// ============================================================
// WHAT: Shows daily compliance percentage across all devices
//       and configuration checks for the past 30 days.
// WHY:  Trend lines reveal whether remediation is outpacing
//       drift. A flat or declining line means you need to
//       escalate remediation efforts or investigate root causes.
DeviceTvmSecureConfigurationAssessment
| where Timestamp > ago(30d)
| where IsApplicable == true
| summarize
    TotalChecks    = count(),
    CompliantChecks = countif(IsCompliant == true)
    by Day = bin(Timestamp, 1d)
| extend CompliancePct = round(100.0 * CompliantChecks / TotalChecks, 1)
| order by Day asc
| project Day, CompliancePct, TotalChecks, CompliantChecks
💡 Pro Tip: Set a visual compliance target line at 95% in your dashboard. When the trend dips below this threshold, trigger an automated email to the endpoint management team. This creates accountability without manual monitoring.

Step 7 ยท Build Custom Baseline Profiles

No off-the-shelf baseline perfectly fits every organisation. Custom profiles let you combine the most relevant checks from CIS and Microsoft baselines, exclude checks that don't apply to your environment, and add organisation-specific requirements. This step also builds KQL dashboard tiles that give leadership a real-time view of baseline compliance status.

  1. Create a custom baseline tailored to your organisation by selecting specific checks from CIS and Microsoft baselines
  2. Exclude checks that are not applicable (e.g., checks for features not in use)
  3. Add organisation-specific requirements (e.g., mandatory screen lock after 5 minutes)
  4. Assign the custom baseline to specific device groups
// ============================================================
// Dashboard Tile 1: Overall Compliance Scorecard
// ============================================================
// WHAT: Single-number compliance percentage for executive
//       dashboards and status boards.
DeviceTvmSecureConfigurationAssessment
| where Timestamp > ago(1d)
| where IsApplicable == true
| summarize
    TotalChecks     = count(),
    PassedChecks    = countif(IsCompliant == true)
| extend OverallCompliance = strcat(tostring(round(100.0 * PassedChecks / TotalChecks, 1)), "%")
| extend Status = iff(100.0 * PassedChecks / TotalChecks >= 95, "โœ… On Target", "โš ๏ธ Below Target")
| project OverallCompliance, Status, PassedChecks, TotalChecks
// ============================================================
// Dashboard Tile 2: Compliance by Device Group
// ============================================================
// WHAT: Breaks down compliance percentage by MachineGroup so
//       you can see which teams or departments need attention.
// WHY:  Enables targeted remediation campaigns per business
//       unit rather than a one-size-fits-all approach.
DeviceTvmSecureConfigurationAssessment
| where Timestamp > ago(1d)
| where IsApplicable == true
| join kind=inner (
    DeviceInfo
    | where Timestamp > ago(1d)
    | summarize arg_max(Timestamp, MachineGroup) by DeviceId
) on DeviceId
| summarize
    TotalChecks  = count(),
    PassedChecks = countif(IsCompliant == true)
    by MachineGroup
| extend CompliancePct = round(100.0 * PassedChecks / TotalChecks, 1)
| order by CompliancePct asc
| project MachineGroup, CompliancePct, PassedChecks, TotalChecks
// ============================================================
// Dashboard Tile 3: Critical Security Controls Status
// ============================================================
// WHAT: Focused view on the most critical security controls:
//       firewall, antivirus, BitLocker, credential guard.
// WHY:  These are the controls auditors check first and the
//       ones most likely to be exploited if misconfigured.
DeviceTvmSecureConfigurationAssessment
| where Timestamp > ago(1d)
| where IsApplicable == true
| where ConfigurationSubcategory in (
    "Firewall", "Antivirus", "Data encryption",
    "Credential Guard", "Attack surface reduction")
| summarize
    TotalDevices   = dcount(DeviceId),
    CompliantCount = dcountif(DeviceId, IsCompliant == true)
    by ConfigurationSubcategory
| extend CompliancePct = round(100.0 * CompliantCount / TotalDevices, 1)
| extend StatusIcon = case(
    CompliancePct >= 95, "๐ŸŸข",
    CompliancePct >= 80, "๐ŸŸก",
    "๐Ÿ”ด")
| project StatusIcon, ConfigurationSubcategory, CompliancePct,
          CompliantCount, TotalDevices
| order by CompliancePct asc
💡 Pro Tip: Pin these three KQL tiles to a shared Advanced Hunting dashboard. Share the link with your CISO and compliance team so they can check baseline status without filing a request. Self-service visibility reduces friction and builds trust.

Step 8 ยท Configure Compliance Alerts

Proactive alerting ensures that compliance regressions are caught immediately, not during the next quarterly audit. This step configures custom detection rules that fire when critical security controls are disabled, and sets up email notifications so the right teams can respond before an attacker exploits the gap.

  1. Set up alerts for devices dropping below compliance thresholds
  2. Configure email notifications for critical baseline failures (e.g., firewall disabled)
  3. Create custom detection rules in Advanced Hunting for specific configuration changes
  4. Integrate alerts with Microsoft Sentinel for unified monitoring
// ============================================================
// Custom Detection Rule: Critical Security Control Disabled
// ============================================================
// WHAT: Fires an alert when a device has a critical security
//       control (firewall, AV, BitLocker) marked non-compliant.
// WHY:  Disabled firewalls and AV are the #1 exploited
//       misconfiguration in ransomware attacks. Immediate
//       alerting gives you minutes, not days, to respond.
// USAGE: Save this as a Custom Detection Rule with frequency
//        set to "Every hour" and action "Generate alert".
DeviceTvmSecureConfigurationAssessment
| where Timestamp > ago(1h)
| where IsApplicable == true
| where IsCompliant == false
| where ConfigurationSubcategory in (
    "Firewall", "Antivirus", "Data encryption")
| project Timestamp, DeviceId, DeviceName,
          ConfigurationId, ConfigurationSubcategory,
          ConfigurationDescription
| join kind=inner (
    DeviceInfo
    | where Timestamp > ago(1d)
    | summarize arg_max(Timestamp, MachineGroup, OSPlatform) by DeviceId
) on DeviceId
| project Timestamp, DeviceName, MachineGroup, OSPlatform,
          ConfigurationSubcategory, ConfigurationDescription
💡 Pro Tip: Set the custom detection rule frequency to "Every hour" for critical controls (firewall, AV) and "Every 24 hours" for less urgent checks. This balances alert fatigue with detection speed.

Step 9 ยท Integrate with Intune for Remediation

Intune is the enforcement arm of your baseline compliance programme. While DVM identifies gaps, Intune closes them by pushing configuration profiles and remediation scripts to non-compliant devices. This step creates a PowerShell remediation script that runs on Intune-managed devices to fix common baseline failures automatically.

  1. Map baseline failures to Intune configuration profiles
  2. Create Intune security baselines that enforce the same settings DVM is assessing
  3. Deploy Intune remediation scripts for settings that cannot be configured via profiles
  4. Verify that Intune-managed devices show improved compliance scores in DVM
# ============================================================
# Intune Proactive Remediation Script: Fix Firewall & Audit Policy
# ============================================================
# WHAT: Detects and remediates disabled Windows Firewall profiles
#       and missing audit policy settings on Intune-managed devices.
# WHY:  Some baseline failures cannot be fixed with config profiles
#       alone (e.g., advanced audit policies). Proactive remediation
#       scripts run on a schedule and self-heal non-compliant devices.
# DEPLOY: Intune > Devices > Remediations > Create script package
#   Detection script:  Returns exit code 1 if non-compliant
#   Remediation script: Fixes the issue and returns exit code 0
# ============================================================

# --- DETECTION SCRIPT (save as Detect-BaselineCompliance.ps1) ---
$issues = @()

# Check Windows Firewall - all profiles must be enabled
$fwProfiles = Get-NetFirewallProfile
foreach ($profile in $fwProfiles) {
    if ($profile.Enabled -eq $false) {
        $issues += "Firewall profile '$($profile.Name)' is DISABLED"
    }
}

# Check Windows Defender real-time protection
$mpPref = Get-MpPreference
if ($mpPref.DisableRealtimeMonitoring -eq $true) {
    $issues += "Real-time protection is DISABLED"
}

# Check audit policy for logon events
$auditLogon = auditpol /get /subcategory:"Logon" /r | ConvertFrom-Csv
if ($auditLogon.'Inclusion Setting' -notmatch 'Success') {
    $issues += "Logon audit policy missing Success auditing"
}

if ($issues.Count -gt 0) {
    Write-Host "NON-COMPLIANT: $($issues -join '; ')"
    exit 1   # Non-compliant triggers remediation
} else {
    Write-Host "COMPLIANT: All baseline checks passed"
    exit 0   # Compliant, no action needed
}

# --- REMEDIATION SCRIPT (save as Remediate-BaselineCompliance.ps1) ---
try {
    # Enable all firewall profiles
    Set-NetFirewallProfile -Profile Domain,Private,Public -Enabled True
    Write-Host "Firewall profiles enabled"

    # Enable real-time protection
    Set-MpPreference -DisableRealtimeMonitoring $false
    Write-Host "Real-time protection enabled"

    # Enable logon audit policy
    auditpol /set /subcategory:"Logon" /success:enable /failure:enable
    Write-Host "Logon audit policy configured"

    exit 0
} catch {
    Write-Host "Remediation failed: $_"
    exit 1
}
💡 Pro Tip: Deploy remediation scripts with a 1-hour detection schedule for critical controls and a 24-hour schedule for less urgent items. Always test remediation scripts on a pilot group of 10โ€“20 devices before fleet-wide deployment to avoid unintended side effects.

Step 10 ยท Generate Audit-Ready Reports

Audit-ready reports must tell a complete story: what your compliance targets are, where you stand today, what you remediated during the audit period, and what exceptions exist with documented justifications. This step uses PowerShell to pull compliance data from the API and generate a structured report suitable for PCI-DSS, ISO 27001, or NIST auditors.

  1. Export baseline assessment results for the audit period
  2. Include: compliance percentage, failed checks, remediation evidence, timeline
  3. Format reports for specific compliance frameworks (PCI-DSS, ISO 27001, NIST)
  4. Document exceptions with business justification and compensating controls
  5. Schedule recurring exports for quarterly compliance reviews
# ============================================================
# Generate Audit-Ready Baseline Compliance Report
# ============================================================
# WHAT: Exports DVM baseline compliance data via the Defender
#       API and builds a structured CSV report with compliance
#       status, remediation evidence, and exception documentation.
# WHY:  Auditors need evidence in a standardised format. This
#       script produces a report that maps directly to PCI-DSS
#       Requirement 2.2 (configuration standards) and ISO 27001
#       Annex A.12.6 (technical vulnerability management).
# ============================================================

# Connect to Microsoft Graph
Connect-MgGraph -Scopes "SecurityEvents.Read.All"

# Pull secure configuration assessment data
$assessments = Invoke-MgGraphRequest -Method GET `
    -Uri "https://graph.microsoft.com/beta/security/secureConfigurationAssessments?`$top=1000" `
    -OutputType PSObject

# Build the report
$report = foreach ($item in $assessments.value) {
    [PSCustomObject]@{
        DeviceName         = $item.deviceName
        ConfigurationId    = $item.configurationId
        Category           = $item.configurationCategory
        Subcategory        = $item.configurationSubcategory
        Description        = $item.configurationDescription
        IsCompliant        = $item.isCompliant
        IsApplicable       = $item.isApplicable
        AssessmentDate     = $item.timestamp
        RecommendedValue   = $item.recommendedValue
        CurrentValue       = $item.detectedValue
    }
}

# Export to CSV for auditors
$reportPath = "C:\Reports\DVM-Baseline-Compliance-$(Get-Date -Format 'yyyy-MM-dd').csv"
$report | Export-Csv -Path $reportPath -NoTypeInformation -Encoding UTF8
Write-Host "โœ… Report exported to: $reportPath" -ForegroundColor Green

# Generate summary statistics
$totalChecks    = ($report | Where-Object { $_.IsApplicable -eq $true }).Count
$compliantCount = ($report | Where-Object { $_.IsApplicable -eq $true -and $_.IsCompliant -eq $true }).Count
$compliancePct  = [math]::Round(($compliantCount / $totalChecks) * 100, 1)

Write-Host "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" -ForegroundColor Cyan
Write-Host "AUDIT REPORT SUMMARY" -ForegroundColor White
Write-Host "  Total Checks:     $totalChecks"
Write-Host "  Compliant:        $compliantCount"
Write-Host "  Non-Compliant:    $($totalChecks - $compliantCount)"
Write-Host "  Compliance Rate:  $compliancePct%"
Write-Host "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" -ForegroundColor Cyan
💡 Pro Tip: Create a "Compliance Exceptions Register" spreadsheet that documents every intentional deviation from the baseline, the business justification, the compensating control, and the review date. Auditors expect exceptions to be managed, not eliminated - a well-documented exception is better than an undocumented compliance gap.

Summary

What You Accomplished

  • Assessed endpoints against CIS and Microsoft security baselines
  • Identified configuration drift and created remediation plans
  • Built custom baseline profiles for organisational requirements
  • Configured compliance monitoring and alerting
  • Generated audit-ready compliance reports

Next Steps

๐Ÿ“š Documentation Resources

ResourceDescription
Security baselines assessmentOfficial docs for DVM baselines assessment dashboard and configuration
Intune security baselinesDeploy and manage security baselines via Microsoft Intune
Security baselines assessment APIREST API reference for programmatic baseline compliance retrieval
CIS BenchmarksOfficial CIS benchmark documentation and configuration guides
DeviceTvmSecureConfigurationAssessmentAdvanced Hunting schema reference for secure configuration data
Intune compliance policiesCreate and deploy device compliance policies in Intune
โ† Previous Lab Next Lab โ†’