A little more about hardened Azure VM deployment

One of my Azure security related articles provided step-by-step guidance on how to use Azure Automation with Desired State Configuration (DSC) to deploy security policy on multiple Azure VMs. Instead of clear explanation, the article was just written in a format of step-by-step. Hence, I’ve received some requests to elaborate more about this article so it is fully useful to readers. If you haven’t had a chance to read the article, here you go.

This article is to explain more about why to do instead of what to do for each steps. The sample deployment targets to Account Policy in Local Security Policy.

Why Azure Automation DSC?

Azure Automation is a SaaS (Software-as-a-service) based cloud service providing you the ability to automate Azure resource deployment and configuration. Azure Automation uses a term called runbook work with Azure resources. There are five runbooks currently available in Azure automation. Four of them support PowerShell and the rest is Python which is in preview as of this article.

runbook is a compilation of routine procedures and operations that the system administrator or operator carries out.

Besides runbook, Azure Automation also supports Desired State Configuration to allow you to maintain configuration deployment and change across Azure virtual machines and even on-premises machine. Virtual machine state is pretty much like a snapshot if you work with virtualization technologies such as Hyper-V. Desired state configuration by its name is to let a system administrator to deploy the same state he wishes on every virtual machine. The configuration can be pre-defined before the deployment. Virtual machine state in the article’s context contains virtual machine configuration such as Security Policy, local firewall configuration, local administrator group or so on.

In fact, Azure Automation DSC is not the only tool supporting configuration deployment on Azure virtual machine. With the beginner level, you can use Custom Script Extension to run a scripted deployment on a virtual machine. However,  with Custom Script Extension, you cannot deploy your configuration on multiple virtual machines. Moreover, every time you need to deploy a new version of your script, you must repeat the extension installation and uploading script again, on every virtual machine.

Upper level is Azure Automation DSC which is not hard to use. Azure Automation uses methodology of CICD. The more advanced level would be using enterprise-grade 3rd party product such as Chef, Puppet, Octopus.

Now let’s get started a little more deeper for every deployment step you did in the article I mentioned.

Create an Azure automation account

The very first step to is to create an Azure automation account. Each account is considered a unit which stores your configuration script or runbook. Azure automation account is also an Azure resource and needs a resource group to be put into. Saying I need to create an automation account which the purpose of managing and deploying some security configuration on my on-boarding virtual machine. The name is SecPolAutomation (SecPol stands for Security Policy).

The subscription of your automation account must be the same with target resources you are going to deploy the configuration. The resource group doesn’t have to be the same.

You are asked to use whether Run As account feature or not. The Run As account will create a service principal in Azure AD and a certificate. This kind of account is also assigned Contributor role-based access control in order to make sure that it has privilege to execute the configuration.

Importing Module Gallery

Because my plan is to deploy a sample security policy configuration against Account Policy. Hence, I need to add Security Policy DSC resource to my newly created automation account. From the blade, I click Modules then Browse gallery. Type “SecurityPolicy” on the search box. The exact name of the module is SecurityPolicyDsc.

SecurityPolicyDsc is created by the Microsoft Power Shell team to allow to interact with four categories of Windows Server security policy.

  • User Rights Assignment
  • Security Template
  • Account Policy
  • Security Option

Without SecurityPolicyDsc module, your script has no interaction with security setting on the target virtual machine. Click the module and click Import. The DSC resources are temporarily stored in your Azure Automation account’s storage which you will need to import to virtual machine. You then need to wait around 5 minutes until the module is imported successfully.

Adding your script to DSC configuration

Let’s prepare a script first. I forked this script from this repo for quick demostration.

configuration AccountPolicies
    Import-DscResource -ModuleName SecurityPolicyDsc

    node localhost
        AccountPolicy AccountPolicies
            Name = 'PasswordPolicies'
            Enforce_password_history = 15
            Maximum_Password_Age = 12
            Minimum_Password_Age = 2
            Minimum_Password_Length = 8
            Password_must_meet_complexity_requirements = 'Enabled'
            Store_passwords_using_reversible_encryption = 'Disabled'


From the script above, my purpose is to make sure corporate password & account policies are applied consistently across all virtual machines in my environment. For example, the minimum password length must be 8. Or the password must set to meet complexity requirement.

Import-DscResource -ModuleName SecurityPolicyDsc is to make sure your virtual machine connects to the repository of SecurityPolicyDsc module to import to it locally.

Now you need to upload your script onto Pull machine in Azure. In fact, this is not a virtual machine you can manage but somewhere your script is uploaded to. All target virtual machines shall pull script from this location before the script is executed.

Before you go to DSC configuration to add a configuration, you need to make sure the name of configuration in your code snippet matches with the script’s file name. Otherwise, Azure returns bad request message: An error occured while import the DSC configuration ‘SecPoolAccountPolicy’. Error details: BadRequest: The configuration name in the script must match the configuration name..

For example, from my code snippet above, the configuration name is AccountPolicies but my file name is SecPoolAccountPolicy.ps1, then I cannot import the script successfully.

Compiling DSC Configuration

In previous step, you completed adding your configuration by importing the DSC script to configure account policy setting in Local Security Policy for your window server. However, the script is just uploaded to the pull server. It needs to be compiled to generate a node configuration file.

From the DSC Configuration, click on the uploaded script to compile. Wait until the compilation is completed. You can double check your DSC code by clicking View configuration source. The expanded blade shows you the source code.

If the compilation is completed, there is a node configuration automatically generated in DSC node configuration.

Adding DSC Node

A node represents a target virtual machine you want to execute your script. This term is used commonly in CICD deployment. Every node pulls configuration (whether it is a script of a kind of file) from pull server (master node) to execute.

Every node needs to be running before getting added. When adding, you need to configure registration setting. Keep the access key by default. This is an encrypted access key of your Azure automation.

Under Node configuration name, chose the node configuration which stores your script. Choose how frequent (in minutes) you need to contact the pull server to update the node configuration under Refresh Frequency. Under Configuration Mode Frequency, decide how frequent you want the background application of DSC to attempt to execute your script on the target node.

There are three configuration modes:

  • ApplyOnly: the DSC script just gets applied only.
  • ApplyAndMonitor: the DSC script gets applied and monitored. If the state is changeg then the DSC reports the discrepancy in the log.
  • ApplyAndAutoCorrect: in this mode, the DSC script gets applied and if the target node drifts from the desired state (e.g. state is reverted back to the origin), the DSC reports the discrepancy and re-apply the node configuration.

Once all nodes are connected successfully, the node configuration will be triggered to execute your script. If the status is Compliant, the node configuration is successfully deployed.

To verify the result, connect to each node to verify Local Security Policy

or use Get-DscConfiguration

Note again, this article complements to the article Hardened Azure Virtual Machine Deployment using Azure Automation DSC.

This entry was posted in Security Automation and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published.