This project implements the Australian Cyber Security Centre (ACSC) Windows hardening guidelines for Windows 10 and Windows 11 workstations using Azure Machine Configuration (formerly Azure Policy Guest Configuration).
Azure Machine Configuration provides native capability to audit or configure operating system settings as code for machines running in Azure and hybrid Arc-enabled machines. This repository contains PowerShell DSC configurations that implement the ACSC Windows hardening recommendations.
This project implements security configurations based on the ACSC Hardening Microsoft Windows 10 and Windows 11 workstations publication.
- β Application hardening
- β Operating system patching
- β Application control
- β Attack surface reduction (ASR)
- β Credential protection (Credential Guard, WDigest)
- β Controlled Folder Access
- β Credential entry (Secure Desktop)
- β Early Launch Antimalware (ELAM)
- β User Account Control (UAC)
- β Exploit protection
- β Local administrator accounts (LAPS)
- β Microsoft Edge hardening
- β Multi-factor authentication (Windows Hello for Business)
- β Operating system architecture (x64)
- β Restricting privileged accounts
- β Secure Boot
- β Account lockout policy
- β Anonymous connections
- β Antivirus software (Microsoft Defender)
- β Audit event management
- β Autoplay and AutoRun
- β Drive encryption (BitLocker)
- β Endpoint device control
- β Network authentication
- β Password policy
- β PowerShell security
- β Remote Desktop Services
- β Windows Firewall
βββ .github/
β βββ workflows/
β βββ release.yml # GitHub Actions automated build workflow
βββ configurations/ # PowerShell DSC configurations
β βββ high-priority/ # High priority ACSC recommendations
β β βββ ACSCHighPriorityHardening.ps1
β βββ medium-priority/ # Medium priority ACSC recommendations
β βββ ACSCMediumPriorityHardening.ps1
βββ packages/ # Machine Configuration packages (generated)
βββ policies/ # Azure Policy definitions (JSON)
β βββ acsc-high-priority-policy.json
β βββ acsc-medium-priority-policy.json
βββ scripts/ # Deployment and utility scripts
β βββ Deploy-ACSCToAzure.ps1
β βββ New-ACSCMachineConfigurationPackage.ps1
βββ build-release.ps1 # Automated build script
βββ docs/ # Documentation
- PowerShell 5.1 (Windows PowerShell) or PowerShell Core 7.x
- PowerShell modules (installed automatically by scripts):
- GuestConfiguration
- Az.Accounts, Az.Resources, Az.Storage
- SecurityPolicyDsc, AuditPolicyDsc, PSDscResources
- Windows Security Baseline - Installed automatically via Chocolatey
- The DSC configurations automatically install Chocolatey and the
winsecuritybaselinepackage - Provides essential Group Policy templates (MSS-legacy.admx, MSSecurityGuide.admx)
- Manual download available: Microsoft Security Compliance Toolkit
- The DSC configurations automatically install Chocolatey and the
- Azure subscription with Azure Policy and Machine Configuration enabled
- Appropriate RBAC permissions:
- Policy Contributor (to create policy definitions)
- Contributor or Owner (to create policy assignments and role assignments)
- Target Windows machines:
- Windows 10 (versions supported by Microsoft)
- Windows 11 (all versions)
- Windows Server 2016, 2019, 2022
- Azure VM or Arc-enabled machine
- Managed identity enabled
- Guest Configuration extension installed
flowchart TD
Start([Start Deployment]) --> Method{Choose<br/>Build Method}
Method -->|GitHub Actions| GitHubBuild
Method -->|Local Build| LocalBuild
GitHubBuild[Create Git Tag<br/>git tag v1.0.0<br/>git push origin v1.0.0]
GitHubBuild --> GitHubAction[GitHub Actions Workflow Triggered<br/>windows-latest runner]
GitHubAction --> InstallModules[Install PowerShell Modules<br/>- GuestConfiguration<br/>- SecurityPolicyDsc<br/>- AuditPolicyDsc<br/>- PSDscResources]
InstallModules --> CompileHigh[Compile High Priority DSC<br/>Windows PowerShell 5.1]
CompileHigh --> CompileMed[Compile Medium Priority DSC<br/>Windows PowerShell 5.1]
CompileMed --> CreatePackages[Create Machine Configuration Packages<br/>- ACSCHighPriorityHardening.zip<br/>- ACSCMediumPriorityHardening.zip]
CreatePackages --> GenerateHashes[Generate SHA256 Hashes<br/>- High.zip.sha256<br/>- Medium.zip.sha256]
GenerateHashes --> CreateRelease[Create GitHub Release<br/>Attach all artifacts]
CreateRelease --> DownloadRelease[Download Release Artifacts]
DownloadRelease --> DeployToAzure
LocalBuild[Run build-release.ps1<br/>-Version '1.0.0']
LocalBuild --> LocalCheck{PowerShell<br/>7.x detected?}
LocalCheck -->|Yes| LaunchPS5[Auto-launch Windows PowerShell 5.1<br/>for DSC compilation]
LocalCheck -->|No| LocalCompile
LaunchPS5 --> LocalCompile
LocalCompile[Compile DSC Configurations<br/>Check for module conflicts]
LocalCompile --> LocalPackage[Create Packages<br/>./release directory]
LocalPackage --> LocalHash[Generate Hashes<br/>and Manifest]
LocalHash --> DeployToAzure
DeployToAzure[Run Deploy-ACSCToAzure.ps1<br/>-SubscriptionId -ResourceGroupName]
DeployToAzure --> ConnectAzure[Connect to Azure<br/>Interactive or Service Principal]
ConnectAzure --> CreateStorage{Storage account<br/>exists?}
CreateStorage -->|No| NewStorage[Create storage account<br/>+ private container]
CreateStorage -->|Yes| UploadPackages
NewStorage --> UploadPackages
UploadPackages[Upload packages to blob storage<br/>Generate SAS tokens]
UploadPackages --> PolicyCheck{Policy definitions<br/>exist?}
PolicyCheck -->|Yes| CleanupOld[Delete old assignments<br/>Delete old definitions<br/>Wait for propagation]
CleanupOld --> CreatePolicy
PolicyCheck -->|No| CreatePolicy
CreatePolicy[Create policy definitions<br/>Mode: Microsoft.GuestConfiguration<br/>assignmentType: ApplyAndAutoCorrect]
CreatePolicy --> CreateAssignment[Create policy assignments<br/>System-assigned managed identity]
CreateAssignment --> WaitIdentity{Managed identity<br/>propagated?}
WaitIdentity -->|Retry| Wait[Wait 10 seconds<br/>Attempt 1-6]
Wait --> WaitIdentity
WaitIdentity -->|Failed| IDError[β Identity creation failed]
WaitIdentity -->|Success| AssignRole
AssignRole[Assign Contributor role<br/>to managed identity]
AssignRole --> PolicyDeployed([β
Policy Deployed])
PolicyDeployed --> VMEval[Azure Policy evaluates VMs<br/>20-30 minutes initial scan]
VMEval --> VMCheck{VM has Guest<br/>Configuration?}
VMCheck -->|No| AutoInstall[Policy auto-installs:<br/>1. Managed identity<br/>2. GuestConfiguration extension]
VMCheck -->|Yes| ApplyConfig
AutoInstall --> ApplyConfig
ApplyConfig[Apply DSC Configuration<br/>1. Install Chocolatey<br/>2. Install WinSecurityBaseline<br/>3. Apply hardening settings]
ApplyConfig --> InitialCompliance[Initial Compliance Check<br/>Report to Azure Policy]
InitialCompliance --> DriftMonitor[π Continuous Monitoring<br/>Check every 15 minutes]
DriftMonitor --> DriftCheck{Drift<br/>detected?}
DriftCheck -->|No| ReportStatus[Report compliance status<br/>Every 24 hours]
DriftCheck -->|Yes| AutoCorrect[Auto-correct configuration<br/>ApplyAndAutoCorrect mode]
AutoCorrect --> ReportStatus
ReportStatus --> DriftMonitor
style Start fill:#e1f5ff
style GitHubBuild fill:#e8f4f8
style LocalBuild fill:#e8f4f8
style CreateRelease fill:#e1ffe1
style PolicyDeployed fill:#e1ffe1
style DriftMonitor fill:#fff4e1
style AutoCorrect fill:#ffe8cc
style IDError fill:#ffe1e1
The repository includes a GitHub Actions workflow for automated builds:
# Tag a release version
git tag v1.0.0
git push origin v1.0.0
# GitHub Actions will automatically:
# - Compile DSC configurations
# - Create Machine Configuration packages
# - Generate SHA256 hashes
# - Create a GitHub Release with all artifactsDownload the release artifacts and deploy to Azure using the provided scripts.
-
Build packages locally
# Creates packages in ./release directory .\build-release.ps1 -Version "1.0.0"
-
Deploy to Azure
.\scripts\Deploy-ACSCToAzure.ps1 ` -SubscriptionId "your-subscription-id" ` -ResourceGroupName "your-resource-group" ` -StorageAccountName "yourstorageaccount"
-
Monitor compliance in Azure Policy dashboard (20-30 minutes for initial evaluation)
-
Install required modules
Install-Module -Name GuestConfiguration, Az.Accounts, Az.Resources, Az.Storage -Force Install-Module -Name SecurityPolicyDsc, AuditPolicyDsc, PSDscResources, cChoco, xPSDesiredStateConfiguration -Force
-
Create packages
.\scripts\New-ACSCMachineConfigurationPackage.ps1 -ConfigurationLevel All
-
Deploy manually using Azure Portal or Azure CLI
Azure Machine Configuration supports two enforcement modes via the assignmentType parameter:
- ApplyAndMonitor: Configuration is applied once and monitored for drift (manual remediation required)
- ApplyAndAutoCorrect: Configuration is applied and automatically corrected every 15 minutes on drift (recommended)
Both configurations in this repository are set to ApplyAndAutoCorrect mode for automatic drift remediation.
- Initial application: Configuration is applied when policy is first assigned
- Continuous monitoring: Azure Guest Configuration agent checks compliance every 15 minutes
- Automatic remediation: If drift is detected, the configuration is automatically reapplied
- Compliance reporting: Status is reported to Azure Policy dashboard every 24 hours
Example: If a user disables Credential Guard, it will be automatically re-enabled within 15 minutes.
Machine Configuration provides detailed compliance reporting through:
- Azure Policy compliance dashboard
- Azure Resource Graph queries
- Guest assignment reports
- Per-setting compliance details
Implementing these configurations provides:
- Enhanced protection against malware and exploits
- Reduced attack surface
- Improved credential security
- Better audit capabilities
- Compliance with Australian government security guidelines
- Implementation Guide - Step-by-step deployment instructions
- Configuration Reference - Detailed setting explanations
- Native Windows Support - Windows SKU and hardware requirements
- Microsoft Security Baselines Comparison - How this relates to Microsoft baselines
- Windows Security Baseline Installation - Required dependency installation
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Submit a pull request with detailed description
- Ensure all configurations are tested
This project is licensed under the MIT License - see the LICENSE file for details.
- ACSC Windows Hardening Guidelines
- Azure Machine Configuration Overview
- Microsoft Security Baselines
- Microsoft Security Compliance Toolkit
Symptoms:
- Error:
Remove-Item: Access to the path 'C:\Users\...\PowerShell\Modules\GuestConfiguration\4.11.0\gcworker\temp' is denied - Multiple
Copy-Item: Could not find a part of the patherrors - Package creation fails with
CreateFromDirectoryerror
Cause: The GuestConfiguration module's internal temp directory has file locks or permission issues preventing cleanup. This typically occurs when:
- Previous package creation was interrupted
- PowerShell processes have file handles on the temp directory
- Insufficient permissions to modify the module directory
Solutions:
-
Run as Administrator (Recommended)
# Close all PowerShell windows # Open PowerShell as Administrator # Run package creation script again
-
Manual cleanup
# Find the temp directory $module = Get-Module -Name GuestConfiguration -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1 $tempPath = Join-Path $module.ModuleBase "gcworker\temp" # Remove it Remove-Item -Path $tempPath -Recurse -Force # Recreate it New-Item -Path $tempPath -ItemType Directory -Force
-
Reboot
- Restart the machine to clear all file locks
- Run package creation script again
-
Alternative: Use build-release.ps1
# The automated build script handles these errors more gracefully .\build-release.ps1 -Version "1.0.0"
Prevention:
- Always run package creation scripts as Administrator
- Close all PowerShell windows before creating packages
- Use the automated build scripts which include better error handling
For issues related to this implementation, please create an issue in this repository. For ACSC guidelines questions, contact the Australian Cyber Security Centre. For Azure Machine Configuration support, contact Microsoft Azure support.