Azure Policy Guest Configuration – Part 1 – Creating a Custom Policy

I’ve been working quite a bit with custom Azure Policy Guest Configuration lately, and after encountering a few early bumps I’ve become a big fan. Guest Configuration policies are quite flexible, which in essence gives you the ability to bring almost anything we can do in PowerShell and/or DSC into Azure Policy. Very cool!

The first two use cases I’ve worked on were as follows:

  1. Audit base OS hardening compliance for Windows VMs in Azure.
  2. Audit antimalware compliance for Windows Vms in Azure.

Creating the Guest Configuration Package

For part 1 of this post, let’s focus on use case #1. To accomplish this use case, you’ll use the Microsoft Security Configuration Baseline as the base DSC template by converting the GPO provided in the “BaselineManagement” module to PowerShell DSC. This step is described in detail in Microsoft’s “Convert Group Policy into DSC” quickstart documentation.

Once you’ve successfully converted the Microsoft Security Configuration Baseline GPO to PowerShell DSC, it’s time to create the Guest Configuration policy. Microsoft has made this process quite simple in scenarios such as ours where no customization is required to the DSC configuration. There are other scenarios, including use case #2, where a custom Guest Configuration configuration and resource are required, which is a bit more complex. We’ll cover this use case later in this blog series.

The first step towards creating the baseline Guest Configuration policy is to install the Guest Configuration PowerShell resource module. To install the “GuestConfiguration” resource module, run the following command from a PowerShell prompt:

Install-Module -Name GuestConfiguration

To verify that the module was installed and has been imported, run the following command (see below). The current version at the time of this writing is 1.19.0.0. If you already have the ‘GuestConfiguration’ module installed but do not have the latest version, it’s important to update to the current version to ensure that the latest bug fixes and features are up to date.

PS C:\Users\username> get-command -Module 'GuestConfiguration'

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        New-GuestConfigurationPackage                      1.19.0.0   GuestConfiguration
Function        New-GuestConfigurationPolicy                       1.19.0.0   GuestConfiguration
Function        Protect-GuestConfigurationPackage                  1.19.0.0   GuestConfiguration
Function        Publish-GuestConfigurationPolicy                   1.19.0.0   GuestConfiguration
Function        Test-GuestConfigurationPackage                     1.19.0.0   GuestConfiguration

Now that the ‘GuestConfiguration’ module is installed, it’s time to move on to creating the Guest Configuration policy package. To accomplish this step, you’ll need to ensure that the DSC configuration created when you converted the Microsoft Security Baseline Configuration GPO includes the correct DSC resources. This particular configuration relies on the following resource modules being installed:

Install-Module PSDscResources
Install-Module SecurityPolicyDSC
Install-Module AuditPolicyDSC

Additionally, ensure that the highlighted lines of code are added to the DSC configuration:

Configuration WindowsSecurityBaseline2016
{

	Import-DSCResource -ModuleName 'PSDscResources'
	Import-DSCResource -ModuleName 'AuditPolicyDSC'
	Import-DSCResource -ModuleName 'SecurityPolicyDSC'

	Node localhost
	{
          Registry 'Registry(POL): HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client\DisabledByDefault'
          {
               ValueName = 'DisabledByDefault'
               ValueType = 'Dword'
               Key = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client'
               ValueData = 1
 
          }

Once you’ve updated our code to include the required resources, you’ll need to compile the DSC configuration as a MOF file. To compile the DSC configuration, simply dot source the configuration. The following shows an example of the expected output, including the MOF file location (localhost.mof in this example):

PS C:\Repo\GuestConfiguration\Baseline\2016> .\Baseline2016Updated.ps1


    Directory: C:\Repo\GuestConfiguration\Baseline\2016

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            2/4/2020  4:26 PM         246506 localhost.mof

Now that you have successfully compiled the DSC configuration, the next step is to create a Guest Configuration custom policy package. To do this, you’ll need to run the New-GuestConfiguraitonPackage cmdlet. The following is an example of the format used to create a Guest Configuration package:

New-GuestConfigurationPackage `
-Name WindowsHardeningSample `
-Configuration '.\localhost.mof' `
-Path '.\WindowsHardeningSample' `
-Verbose 

Once the cmdlet completes successfully, you should see output similar to below:

Name                   Path
----                   ----
WindowsHardeningSample C:\Repo\Baseline\2016\WindowsHardeningSample\WindowsHardeningSample.zip

At this point the Guest Configuration package needs to be uploaded to a repository or blob storage that is accessible to the VM being managed. For the purposes of this demo, I will simply utilize a blob storage account and and issue a SAS token with read access to keep it private. Later in this blog series will we will cover how to deploy this all as code.

To upload the newly created Guest Configuration to an Azure blob storage container, navigate to your storage account container and select upload. The Guest Configuration package you created will be located in the directory specified in the -Path parameter for the NewGuestConfiguration cmdlet and is also output to the terminal, in this example ‘C:\Repo\Baseline\2016\WindowsHardeningSample\WindowsHardeningSample.zip’. I will not walk through the steps to upload a file to a storage account but it’s important to note that the Guest Configuration package .zip file must be uploaded to the storage account or other chosen location before proceeding to the next steps.

Creating the Guest Configuration Policy

Once the Guest Configuration package has been uploaded to the repository of choice, in this case a blob container, it’s time to create the Guest Configuration policy. To create a new Guest Configuration policy, run the New-GuestConfigurationPolicy cmdlet following command:

New-GuestConfigurationPolicy `
-ContentUri "https://test.blob.core.windows.net/testazurepolicy/WindowsHardeningSample.zip?sp=r&st=2020-02-07T23:52:11Z&se=2020-02-29T07:52:11Z&spr=https&sv=2019-02-02&sr=b&sig=ILVs1Ik65%2BUrGTTTPdQDPoEYxvu1kT8%2F1K%2FvwXQcjE0%3D" `
-DisplayName "Windows Server 2016 Baseline" `
-Path '.\WindowsHardeningSample\Artifacts' `
-Platform 'Windows' `
-Description 'Ensure VMs running Windows Server 2016 OS meet WTW base hardening requirements' `
-Verbose

Note: Notice the ‘ContentUri’ parameter in the code above. In this example, the ‘ContentUri’ value is the URL provided when creating a SAS token on the uploaded storage blob. It’s also worth noting that if you use the same directory for the ‘Path’ parameter as used in the New-GuestConfigurationPackage cmdlet, the package will be overwritten. In this example I added the Artifacts directory to separate the output.

Name                   Path
----                   ----
WindowsHardeningSample .\WindowsHardeningSample\Artifacts

Publishing the Guest Configuration Policy

It’s now time to publish the Guest Configuration policy using the Publish-GuestConfigurationPolicy cmdlet:

Publish-GuestConfigurationPolicy -Path '.\WindowsHardeningSample' 

Once you verify that the Publish-GuestConfigurationPolicy cmdlet ran successfully, navigate to the ‘Policy’ blade in the Azure portal and verify that the new policy has published as expected.

Note: In this example I did not specify a management group target in the cmdlet, so the new custom initiative and polices will be applied to the subscription where my VSCode session context. In a production environment, I recommend using management groups to organize your Azure Policy deployments and therefore specifically target your policies at the appropriate management group using the ‘-ManagementGroupName’ parameter.

In part 2 of this series we’ll step through how to assign the new policy and touch on why you are seeing an initiative and two policy definitions after publishing your policy.

Note: Custom policies with Guest Configuration is a Preview feature.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s