Skip to content

PowerSTIG with Azure Automation

Eric Jenkins edited this page Aug 28, 2023 · 11 revisions

PowerSTIG with Azure Automation

PowerSTIG paired with Azure Automation enables better insight into the DSC status of nodes, reporting and visualization of data when logs are fowarded to Log Analytics.

Importing Required Modules into Azure Automation Environment

PowerSTIG (3.3.0) has several modules dependenies that will need to be imported into an Azure automation environment before the PowerSTIG module can be imported.

Note: Currently there is a known issue with Azure Automation when importing the PowerSTIG module directly from the Azure Portal. In order to work around this limitation, the required dependencies must be imported using PowerShell or an ARM template.

Dependencies for PowerSTIG 4.17.0:

  • AccessControlDsc RequiredVersion: 1.4.3
  • AuditPolicyDsc RequiredVersion: 1.4.0
  • AuditSystemDsc RequiredVersion: 1.1.0
  • CertificateDsc RequiredVersion: 5.0.0
  • ComputerManagementDsc RequiredVersion: 8.4.0
  • FileContentDsc RequiredVersion: 1.3.0.151
  • GPRegistryPolicyDsc RequiredVersion: 1.2.0
  • nx RequiredVersion: 1.0
  • PSDscResources RequiredVersion: 2.12.0.0
  • SecurityPolicyDsc RequiredVersion: 2.10.0.0
  • SqlServerDsc RequiredVersion: 15.1.1
  • WindowsDefenderDsc RequiredVersion: 2.2.0
  • xDnsServer RequiredVersion: 1.16.0
  • xWebAdministration RequiredVersion: 3.2.0

Example PowerShell that may be used to import PowerSTIG dependencies

The following PowerShell will script will import the PowerSTIG dependencies into an existing Azure Automation environment. For more informationon how to install PowerSTIG please reference: https://github.com/microsoft/PowerStig

Note: PowerSTIG requires a number of dependent DSC modules, and the version of theses modules will most likely change over time. To ensure you have the correct required modules run this code. **If the modules fail to load, please run this script a second time. **

[CmdletBinding()] 
param 
(  
    [Parameter(mandatory=$true)]
    [string]
    $ResourceGroupName,

    [Parameter(mandatory=$true)]
    [string]
    $AutomationAccountName
) 
#region Login to Azure
try
{
    Write-output "Logging in to Azure..." 
    $azEnvironment = read-host "Please select an Azure Environment   1: Azure Government  or  2: Azure Commercial"
    if ($azEnvironment -eq 1)
    {    
        Add-AzAccount -EnvironmentName "AzureUSGovernment" | Out-Null
    }
    elseif ($azEnvironment -eq 2)
    {
        Add-AzAccount | Out-Null
    }
    else
    {
        throw "Please enter 1 for Azure Government and 2 for Azure Commercial"
    }
}
catch {
    Write-Error -Message $_.Exception
    throw $_.Exception
}

# Find PowerSTIG module 
try 
{    
    $powerStig = (Get-module -Name PowerSTIG -ListAvailable)

    if(!$powerStig)
    {
        Import-Module -Name PowerSTIG
        $powerStig = (Get-module -Name PowerSTIG -ListAvailable)
    }
}
catch 
{
    Write-Error -Message $_.Exception
    throw $_.Exception
}

# Find the required modules for PowerSTIG
$requiredModules = (Import-PowerShellDataFile -Path (Get-Module PowerSTIG -list).path).RequiredModules 

# Create empty hashtable 
$dependencies = @()

# Add the modules to an hashtable 
foreach($module in $requiredModules)
{
    $dependencies +=  @{ModuleName = $module.ModuleName; RequiredVersion = $module.ModuleVersion; }
}

#region Import PowerSTIG dependencies and PowerSTIG version 3.3.0
foreach($dependency in $dependencies)
{
    $galleryRepoUri = "https://www.powershellgallery.com/api/v2/package/" + $dependency.ModuleName + "/" + $dependency.RequiredVersion
    $galleryRepoUri
    New-AzAutomationModule -ResourceGroupName $resourceGroupName -AutomationAccountName $automationAccountName -Name $dependency.ModuleName -ContentLink $galleryRepoUri
}
# Import PowerSTIG into Azure Automation
if($powerStig)
{
    $galleryRepoUri = "https://www.powershellgallery.com/api/v2/package/" + $powerStig.Name + "/" + $powerStig.Version
    $galleryRepoUri
    New-AzAutomationModule -ResourceGroupName $resourceGroupName -AutomationAccountName $automationAccountName -Name $powerStig.Name -ContentLink $galleryRepoUri
}
else 
{
    write-host "Please Install PowerSTIG by running: Install-Module -Name PowerStig -Scope CurrentUser"
}
#endregion  

Importing PowerSTIG Desired State Configuration (DSC) into Azure Automation

The following code will import a PowerSTIG Desired State Configuration from a PS1 file into Azure Automation.

For additional details on the Import-AzAutomationDscConfiguration cmdlet please reference the following link: https://docs.microsoft.com/en-us/powershell/module/az.automation/import-azautomationdscconfiguration?view=azps-2.6.0

[CmdletBinding()] 
param 
(  
    [Parameter(mandatory=$true)]
    [string]
    $ResourceGroupName,

    [Parameter(mandatory=$true)]
    [string]
    $AutomationAccountName,

    [Parameter(mandatory=$true)]
    [string]
    $SourcePath
) 

# Imports Azure Automation DSC Configuration from PS1 provided in $SourcePath 
try 
{
    Import-AzAutomationDscConfiguration -AutomationAccountName $automationAccountName -ResourceGroupName $resourceGroupName -SourcePath $sourcePath -Force -Published
}
catch
{
    Write-Error -Message $_.Exception
    throw $_.Exception
}

Azure Automation Desired State Configuration Onboarding

To onboard a machine for management by Azure Automation State Configuration please referece the following documentation: https://docs.microsoft.com/en-us/azure/automation/automation-dsc-onboarding

Forwarding Azure Automation Desired State Configuration Status Using Log Analytics

Data from Azure State Configuration can be forwarded to Log Analytics. The following link provides the steps required to configure log fowarding for DSC configurations.

Azure State Configuration data can be fowarded by following this set of documentation: https://docs.microsoft.com/en-us/azure/automation/automation-dsc-diagnostics

Sample Queries for Reporting on Desired State Configuration Status with Log Analytics

  • Find all resources that are not compliant
AzureDiagnostics
| where DscResourceStatus_s != "Compliant"
| summarize count() by tostring(DscResourceId_s), DscModuleName_s, bin(TimeGenerated, 4h) 

ExampleQueryOutput1

  • Find all DSC resources that are not complaint per node
AzureDiagnostics
| where DscResourceStatus_s == "NotCompliant"
| where DscConfigurationName_s == <DSC CONFIGURATION NAME>
| where NodeName_s == <NODE NAME>
| distinct NodeName_s , DscResourceId_s, DscResourceStatus_s   

ExampleQueryOutput2

Clone this wiki locally