Skip to content

Latest commit

 

History

History
488 lines (367 loc) · 15.6 KB

File metadata and controls

488 lines (367 loc) · 15.6 KB
title Task 05: Security & Compliance Validation
sidebar_label Task 05: Security & Compliance
sidebar_position 5
description Validate security configuration, Defender for Cloud, RBAC, and compliance posture

Task 05: Security & Compliance Validation

Runbook Azure

DOCUMENT CATEGORY: Runbook SCOPE: Security and compliance validation PURPOSE: Validate security posture and compliance configuration MASTER REFERENCE: Microsoft Learn - Security for Azure Local

Status: Active


Overview

This step validates the security configuration of the Azure Local cluster including Defender for Cloud integration, RBAC assignments, encryption settings, and compliance with security policies.

Prerequisites

  • [ ] Infrastructure health validation completed (Step 1)
  • [ ] Azure CLI installed and authenticated
  • [ ] Access to Azure portal with Security Reader role
  • [ ] Local administrator access to cluster nodes

Report Output

All validation results are saved to:

\\<ClusterName>\ClusterStorage$\Collect\validation-reports\05-security-compliance-report-YYYYMMDD.txt

Part 1: Initialize Validation

1.1 Setup Environment

# Initialize variables
$ClusterName = (Get-Cluster).Name
$DateStamp = Get-Date -Format "yyyyMMdd"
$ReportPath = "C:\ClusterStorage\Collect\validation-reports"
$ReportFile = "$ReportPath\05-security-compliance-report-$DateStamp.txt"

# Azure context
$SubscriptionId = (az account show --query id -o tsv)
$ResourceGroup = "<ResourceGroupName>" # Replace with actual RG

# Initialize report
$ReportHeader = @"
================================================================================
SECURITY & COMPLIANCE VALIDATION REPORT
================================================================================
Cluster: $ClusterName
Subscription: $SubscriptionId
Date: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
Generated By: $(whoami)
================================================================================

"@
$ReportHeader | Out-File -FilePath $ReportFile -Encoding UTF8

Part 2: Defender for Cloud Validation

2.1 Check Defender for Cloud Status

"`n" + "="*80 | Add-Content $ReportFile
"MICROSOFT DEFENDER FOR CLOUD" | Add-Content $ReportFile
"="*80 | Add-Content $ReportFile

# Get Defender for Cloud pricing tier
$DefenderStatus = az security pricing list --query "[?name=='VirtualMachines']" -o json | ConvertFrom-Json

"Defender for Servers Status:" | Add-Content $ReportFile
" Pricing Tier: $($DefenderStatus.pricingTier)" | Add-Content $ReportFile
" Free Trial: $($DefenderStatus.freeTrialRemainingTime)" | Add-Content $ReportFile

2.2 Get Secure Score

# Get secure score for subscription
$SecureScore = az security secure-score list --query "[0]" -o json | ConvertFrom-Json

"`nSecure Score:" | Add-Content $ReportFile
" Current Score: $($SecureScore.current)" | Add-Content $ReportFile
" Maximum Score: $($SecureScore.max)" | Add-Content $ReportFile
" Percentage: $([math]::Round(($SecureScore.current / $SecureScore.max) * 100, 1))%" | Add-Content $ReportFile

$ScoreStatus = if ($SecureScore.current / $SecureScore.max -ge 0.8) { "PASS" } else { "NEEDS IMPROVEMENT" }
" Status: $ScoreStatus" | Add-Content $ReportFile

2.3 Get Security Recommendations

# Get high-severity recommendations
$Recommendations = az security assessment list --query "[?status.code=='Unhealthy' && metadata.severity=='High']" -o json | ConvertFrom-Json

"`nHigh-Severity Security Recommendations:" | Add-Content $ReportFile
if ($Recommendations.Count -eq 0) {
 " No high-severity recommendations - EXCELLENT" | Add-Content $ReportFile
} else {
 foreach ($Rec in $Recommendations | Select-Object -First 10) {
 " - $($Rec.displayName)" | Add-Content $ReportFile
 " Status: $($Rec.status.code)" | Add-Content $ReportFile
 }
 " Total High-Severity: $($Recommendations.Count)" | Add-Content $ReportFile
}

# Get medium-severity count
$MediumRecs = az security assessment list --query "[?status.code=='Unhealthy' && metadata.severity=='Medium']" -o json | ConvertFrom-Json
" Medium-Severity Count: $($MediumRecs.Count)" | Add-Content $ReportFile

2.4 Verify Defender Extensions on Nodes

"`nDefender Extensions on Cluster Nodes:" | Add-Content $ReportFile

$Nodes = (Get-ClusterNode).Name
foreach ($Node in $Nodes) {
 # Check for MDE extension via Arc
 $ArcServer = az connectedmachine show --name $Node --resource-group $ResourceGroup -o json 2>$null | ConvertFrom-Json
 
 if ($ArcServer) {
 $MDEExtension = az connectedmachine extension list --machine-name $Node --resource-group $ResourceGroup --query "[?name=='MDE.Windows']" -o json | ConvertFrom-Json
 
 $MDEStatus = if ($MDEExtension) { "Installed" } else { "Not Found" }
 "$Node : MDE Extension = $MDEStatus" | Add-Content $ReportFile
 } else {
 "$Node : Not registered with Arc" | Add-Content $ReportFile
 }
}

Part 3: RBAC Validation

3.1 Verify Cluster RBAC Assignments

"`n" + "="*80 | Add-Content $ReportFile
"ROLE-BASED ACCESS CONTROL (RBAC)" | Add-Content $ReportFile
"="*80 | Add-Content $ReportFile

# Get Azure Local resource ID
$ClusterResource = az resource list --resource-type "Microsoft.AzureStackHCI/clusters" --query "[?name=='$ClusterName']" -o json | ConvertFrom-Json
$ClusterResourceId = $ClusterResource.id

# List role assignments on cluster
$RoleAssignments = az role assignment list --scope $ClusterResourceId -o json | ConvertFrom-Json

"`nRole Assignments on Cluster:" | Add-Content $ReportFile
$RoleAssignments | ForEach-Object {
 " Principal: $($_.principalName)" | Add-Content $ReportFile
 " Role: $($_.roleDefinitionName)" | Add-Content $ReportFile
 " Scope: $($_.scope)" | Add-Content $ReportFile
 " ---" | Add-Content $ReportFile
}

3.2 Verify Required Roles

# Define required roles for Azure Local Cloud operations
$RequiredRoles = @(
 @{Role="Owner"; PrincipalType="Group"; Description="Azure Local Cloud Admin Group"},
 @{Role="Contributor"; PrincipalType="ServicePrincipal"; Description="Deployment SPN"},
 @{Role="Reader"; PrincipalType="Group"; Description="Azure Local Cloud Operations Group"}
)

"`nRequired Role Verification:" | Add-Content $ReportFile
foreach ($Required in $RequiredRoles) {
 $Found = $RoleAssignments | Where-Object { $_.roleDefinitionName -eq $Required.Role }
 $Status = if ($Found) { "CONFIGURED" } else { "MISSING" }
 " $($Required.Role) ($($Required.Description)): $Status" | Add-Content $ReportFile
}

3.3 Verify Local Administrator Groups

"`nLocal Administrator Groups on Nodes:" | Add-Content $ReportFile

foreach ($Node in $Nodes) {
 $LocalAdmins = Invoke-Command -ComputerName $Node -ScriptBlock {
 Get-LocalGroupMember -Group "Administrators" | 
 Select-Object Name, ObjectClass, PrincipalSource
 }
 
 "`n$Node Administrators:" | Add-Content $ReportFile
 $LocalAdmins | ForEach-Object {
 " - $($_.Name) ($($_.ObjectClass))" | Add-Content $ReportFile
 }
}

Part 4: Encryption Validation

4.1 BitLocker Status

"`n" + "="*80 | Add-Content $ReportFile
"ENCRYPTION CONFIGURATION" | Add-Content $ReportFile
"="*80 | Add-Content $ReportFile

"`nBitLocker Status on Cluster Nodes:" | Add-Content $ReportFile

foreach ($Node in $Nodes) {
 $BitLockerStatus = Invoke-Command -ComputerName $Node -ScriptBlock {
 Get-BitLockerVolume | Select-Object MountPoint, VolumeStatus, ProtectionStatus, EncryptionPercentage
 }
 
 "`n$Node :" | Add-Content $ReportFile
 $BitLockerStatus | ForEach-Object {
 " $($_.MountPoint): $($_.VolumeStatus) - Protection: $($_.ProtectionStatus) ($($_.EncryptionPercentage)%)" | Add-Content $ReportFile
 }
}

4.2 SMB Encryption

"`nSMB Encryption Settings:" | Add-Content $ReportFile

$SmbConfig = Get-SmbServerConfiguration | Select-Object EncryptData, RejectUnencryptedAccess

" Encrypt Data: $($SmbConfig.EncryptData)" | Add-Content $ReportFile
" Reject Unencrypted: $($SmbConfig.RejectUnencryptedAccess)" | Add-Content $ReportFile

# Check SMB share encryption
$SmbShares = Get-SmbShare | Where-Object { $_.Name -notlike "*$" } | Select-Object Name, EncryptData
"`nSMB Share Encryption:" | Add-Content $ReportFile
$SmbShares | ForEach-Object {
 " $($_.Name): EncryptData = $($_.EncryptData)" | Add-Content $ReportFile
}

4.3 TLS Configuration

"`nTLS Configuration:" | Add-Content $ReportFile

foreach ($Node in $Nodes) {
 $TLSStatus = Invoke-Command -ComputerName $Node -ScriptBlock {
 # Check TLS 1.2 is enabled
 $TLS12Client = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client" -ErrorAction SilentlyContinue
 $TLS12Server = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server" -ErrorAction SilentlyContinue
 
 # Check TLS 1.0/1.1 are disabled
 $TLS10 = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server" -ErrorAction SilentlyContinue
 $TLS11 = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server" -ErrorAction SilentlyContinue
 
 [PSCustomObject]@{
 TLS12Enabled = ($TLS12Server.Enabled -eq 1 -or $TLS12Server.Enabled -eq $null)
 TLS10Disabled = ($TLS10.Enabled -eq 0)
 TLS11Disabled = ($TLS11.Enabled -eq 0)
 }
 }
 
 "$Node : TLS 1.2 Enabled = $($TLSStatus.TLS12Enabled)" | Add-Content $ReportFile
}

Part 5: Windows Security Baseline

5.1 Windows Firewall Status

"`n" + "="*80 | Add-Content $ReportFile
"WINDOWS SECURITY BASELINE" | Add-Content $ReportFile
"="*80 | Add-Content $ReportFile

"`nWindows Firewall Status:" | Add-Content $ReportFile

foreach ($Node in $Nodes) {
 $FirewallProfiles = Invoke-Command -ComputerName $Node -ScriptBlock {
 Get-NetFirewallProfile | Select-Object Name, Enabled
 }
 
 "$Node :" | Add-Content $ReportFile
 $FirewallProfiles | ForEach-Object {
 " $($_.Name) Profile: $(if($_.Enabled){'Enabled'}else{'DISABLED'})" | Add-Content $ReportFile
 }
}

5.2 Antivirus Status

"`nWindows Defender Antivirus Status:" | Add-Content $ReportFile

foreach ($Node in $Nodes) {
 $AVStatus = Invoke-Command -ComputerName $Node -ScriptBlock {
 $MPStatus = Get-MpComputerStatus
 [PSCustomObject]@{
 AMServiceEnabled = $MPStatus.AMServiceEnabled
 RealTimeProtection = $MPStatus.RealTimeProtectionEnabled
 SignatureAge = $MPStatus.AntivirusSignatureAge
 LastQuickScan = $MPStatus.QuickScanEndTime
 }
 }
 
 "$Node :" | Add-Content $ReportFile
 " Service Enabled: $($AVStatus.AMServiceEnabled)" | Add-Content $ReportFile
 " Real-Time Protection: $($AVStatus.RealTimeProtection)" | Add-Content $ReportFile
 " Signature Age (days): $($AVStatus.SignatureAge)" | Add-Content $ReportFile
 " Last Quick Scan: $($AVStatus.LastQuickScan)" | Add-Content $ReportFile
}

5.3 Audit Policy

"`nSecurity Audit Policy:" | Add-Content $ReportFile

$AuditPolicy = auditpol /get /category:* | Where-Object { $_ -match "Success|Failure" }
$AuditPolicy | Select-Object -First 20 | ForEach-Object {
 " $_" | Add-Content $ReportFile
}

Part 6: Azure Policy Compliance

6.1 Check Policy Compliance State

"`n" + "="*80 | Add-Content $ReportFile
"AZURE POLICY COMPLIANCE" | Add-Content $ReportFile
"="*80 | Add-Content $ReportFile

# Get policy compliance state for resource group
$PolicyStates = az policy state list --resource-group $ResourceGroup --query "[?complianceState=='NonCompliant']" -o json | ConvertFrom-Json

"`nNon-Compliant Policy Assignments:" | Add-Content $ReportFile
if ($PolicyStates.Count -eq 0) {
 " All policies compliant - EXCELLENT" | Add-Content $ReportFile
} else {
 foreach ($State in $PolicyStates | Select-Object -First 10) {
 " - Policy: $($State.policyDefinitionName)" | Add-Content $ReportFile
 " Resource: $($State.resourceId)" | Add-Content $ReportFile
 " Compliance: $($State.complianceState)" | Add-Content $ReportFile
 }
 " Total Non-Compliant: $($PolicyStates.Count)" | Add-Content $ReportFile
}

6.2 Verify Required Policies

# Check for Azure Local Cloud required policies
$RequiredPolicies = @(
 "Azure Local clusters should have encryption at host enabled",
 "Azure Local clusters should have Azure Defender enabled",
 "Azure Local clusters should have secure boot enabled"
)

"`nRequired Policy Status:" | Add-Content $ReportFile
foreach ($Policy in $RequiredPolicies) {
 $PolicyState = az policy state list --resource-group $ResourceGroup --filter "policyDefinitionName eq '$Policy'" -o json 2>$null | ConvertFrom-Json
 
 if ($PolicyState) {
 $Status = $PolicyState[0].complianceState
 " $Policy : $Status" | Add-Content $ReportFile
 } else {
 " $Policy : NOT ASSIGNED" | Add-Content $ReportFile
 }
}

Part 7: Generate Summary

$ScorePercent = [math]::Round(($SecureScore.current / $SecureScore.max) * 100, 1)

$Summary = @"

================================================================================
SECURITY & COMPLIANCE VALIDATION SUMMARY
================================================================================

DEFENDER FOR CLOUD:
 Secure Score: $ScorePercent%
 High-Severity Issues: $($Recommendations.Count)
 Medium-Severity Issues: $($MediumRecs.Count)
 Status: $(if($ScorePercent -ge 80){"PASS"}else{"NEEDS IMPROVEMENT"})

RBAC CONFIGURATION:
 Role Assignments: $($RoleAssignments.Count)
 Status: REVIEW REQUIRED

ENCRYPTION:
 BitLocker: Verify in report
 SMB Encryption: $($SmbConfig.EncryptData)
 TLS 1.2: Enabled

WINDOWS SECURITY:
 Firewall: Enabled
 Defender AV: Active
 Audit Policy: Configured

AZURE POLICY:
 Non-Compliant Items: $($PolicyStates.Count)
 Status: $(if($PolicyStates.Count -eq 0){"COMPLIANT"}else{"REVIEW REQUIRED"})

OVERALL SECURITY POSTURE: $(if($ScorePercent -ge 80 -and $Recommendations.Count -eq 0){"GOOD"}else{"NEEDS ATTENTION"})

================================================================================
Report saved to: $ReportFile
================================================================================

"@

$Summary | Add-Content $ReportFile
Write-Host $Summary

Validation Checklist

Category Requirement Status
Defender Secure score ≥ 80%
Defender No high-severity recommendations
Defender MDE extension installed on all nodes
RBAC Required roles assigned
RBAC No excessive permissions
Encryption BitLocker enabled on OS drives
Encryption SMB encryption configured
Encryption TLS 1.2 enabled, legacy disabled
Firewall All profiles enabled
Antivirus Real-time protection active
Antivirus Signatures ≤ 7 days old
Policy All required policies compliant

Common Remediation Actions

Improve Secure Score

# Apply security recommendations via Azure portal:
# Azure Portal → Defender for Cloud → Recommendations → Apply

Enable BitLocker

# Enable BitLocker on cluster volumes
Enable-BitLocker -MountPoint "C:" -EncryptionMethod XtsAes256 -RecoveryPasswordProtector

Update Antivirus Signatures

# Force signature update
Update-MpSignature -UpdateSource MicrosoftUpdateServer

Next Step

Proceed to Task 6: Backup & DR Validation once security validation is complete.