Kaido Jarvemets - Logo

Azure Arc-enabled Servers Custom Script Extension for Windows

Background

As a server administrator, it’s important to ensure that our servers are monitored, secured, and configured on a regular basis, whether it’s daily, weekly, or monthly. However, the question is how can we efficiently carry out all of these tasks?

In the past, our options were limited to using Desired State ConfigurationGroup PoliciesConfiguration Manager, or scheduling a Scheduled Task to run certain management tasks at specific times. Another option was to create custom PowerShell scripts, which had the advantage of built-in remoting. However, when it came to performing actions on a large number of servers simultaneously, this approach often required significant time and effort to complete.

Today, we have a game-changer in hybrid-cloud management: Azure Arc. This powerful solution offers many features that can significantly simplify the process of managing servers, without the need for a VPN connection. With Azure Arc, administrators can manage servers across on-premises, edge, and multi-cloud environments, using a centralized platform. This provides greater visibility, control, and automation capabilities, allowing for more efficient management and configuration of resources.

By using Azure Arc, administrators can save time and streamline their server management, all while ensuring security and compliance across the entire hybrid-cloud infrastructure.

In addition to the benefits of centralized server management, Azure Arc also enables the use of Machine Configuration Services, which can take datacenter management to a whole new level. However, for the purposes of this post, we will be focusing specifically on the Custom Script Extension for Windows. In a future post, we will explore an alternative approach to achieving similar results.

Introduction to Custom Script Extension for Windows

The Custom Script Extension for Windows is a feature of Azure Arc-enabled Servers that enables you to run scripts on your Windows servers, allowing you to automate common tasks and configurations. This extension is particularly useful for managing servers at scale and ensuring consistency across your server infrastructure. In this blog post, I will focus on the Custom Script Extension for Windows and how to execute scripts from various locations.

Before you continue, I recommend reading the official documentation about the extension and limitations around script executions.

Custom Script Extension for Windows use-cases

As an administrator, there are many similar things that we need to do weekly basis:

  • Install new software
  • Gather inventory data
  • Update applications/settings
  • Configure OS or application settings
  • Ad-hoc data collection
  • Other management tasks

The possibilities of what you can achieve with the solutions offered by Microsoft are not limited to the examples that I have just provided. There is ample opportunity for creativity when it comes to leveraging these tools. For example, if you have an Azure Log Analytics Workspace, you can gather and store custom data to Log Analytics, which can then be used to build a variety of workbooks. Additionally, creating an Azure Automation Runbook is a simple way to run specific activities daily, weekly, or monthly, offering even more options for automation and efficiency. By exploring the full range of tools available through Azure, administrators can find innovative and effective solutions to meet their server management needs.

PS! When it comes to Azure Automation, the first 500 minutes of usage are free of charge.

Custom Script Extension Requirements

All my examples are based on the Az.ConnectedMachine PowerShell module, and you can download it from the PowerShell Script Gallery. You can also use the Azure Portal (portal.azure.com) to upload and assign the scripts.

PS! This time we will do everything through PowerShell.

You can see all the enabled extensions from the server configuration panel or using the Get-AzConnectedMachineExtension PowerShell command.

Here are the things you need to test this out in your environment:

Supported Operating systems

List of Windows operating systems

  • Windows Server 2022 + Core
  • Windows Server 2019 + Core
  • Windows Server 2016 + Core
  • Windows Server 2012 R2
  • Windows Server 2008 R2

List of Linux operating systems

  • CentOS Linux 8
  • CentOS Linux 7
  • CentOS Linux 6
  • Debian 10
  • Oracle Linux 8
  • Oracle Linux 7
  • Red Hat Enterprise Linux Server 8
  • Red Hat Enterprise Linux Server 7
  • SUSE Linux Enterprise Server 15
  • SUSE Linux Enterprise Server 12
  • Unbuntu 20.04 LTS
  • Unbuntu 18.04 LTS

Script location

Your scripts can be in a different location and no need to upload the script to Azure Blob Storage but if needed, you can store all your management scripts in one place and then it will be easier for you to manage these.

  • Azure Blob Storage
    • GitHub
    • Internal file server

Supported script properties

Please remember that all property names are case-sensitive.

Property

Optional or Required

Description

fileUris

Optional

Script URL. This can be Azure Blob Storage, GitHub, File server etc.

commandToExecute

Required

Command to execute. If the script is on the local file server, then fileUris property is not needed.

timestamp

Optional

Change this value only to trigger a rerun of the script. Any integer value is acceptable if it’s different from the previous value.

storageAccountName

Optional

The name of storage account. If you specify storage credentials, all fileUris values must be URLs for Azure blobs.

storageAccountKey

Optional

The access key of the storage account.

managedIdentity

Optional

The managed identity for downloading files. This can be defined in the protected settings only

The New-AzConnectedMachineExtension command offers both ProtectedSetting and Setting parameters. If your script contains sensitive data or if you’ve specified properties such as storageAccountName and storageAccountKey, it’s important to define this information under the ProtectedSetting parameter. This ensures that all sensitive data is encrypted and securely sent to the server.

Another consideration when using the New-AzConnectedMachineExtension command is the use of the fileUris and commandToExecute properties, which can be set using either the ProtectedSetting or Setting parameter. It’s important to note that if these values are assigned using the Settings parameter, they will be treated as public settings, as the data will not be encrypted. As a result, it’s important for administrators to carefully consider the sensitivity of any data included in these properties when using public settings

Running scripts from GitHub Repository

In the following example, the Install-Arc7ZIP PowerShell script has been saved to a public GitHub repository, meaning that anyone with access to the repository can view and use the script

				
					<#
    =================================================================================
    DISCLAIMER:
    This script is provided "as-is" with no warranties. Usage of this script is at
    your own risk. The author is not liable for any damages or losses arising from
    using this script. Please review the full legal disclaimer at:
    https://kaidojarvemets.com/legal-disclaimer/
    =================================================================================
#>
$Settings = @{
    fileUris = @("https://raw.githubusercontent.com/Kaidja/AzureArc/main/Install-Arc7ZIP.ps1")
    commandToExecute = "powershell -ExecutionPolicy Unrestricted -File Install-Arc7ZIP.ps1"
}

$CustomScriptProperties = @{
    MachineName = "ADFS01"
    Name = "CustomScriptExtension"
    ResourceGroupName = "RG-PROD-IT-ARC"
    Publisher = "Microsoft.Compute"
    ProtectedSetting = $Settings
    Location = "West Europe"
    ExtensionType = "CustomScriptExtension"
}

New-AzConnectedMachineExtension @CustomScriptProperties -Verbose 
				
			

From the target virtual machine, you can find the following log file:

				
					C:\ProgramData\GuestConfig\extension_logs\Microsoft.Compute.CustomScriptExtension\CustomScriptHandler.log
				
			

From that file, we can see that the script was downloaded from my public GitHub repository. If something goes wrong, we should also see the extension issues from that log file.

You can see all the downloaded scripts on the target virtual machine from the following location:

  • C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.10.14\Downloads

Running scripts from Azure Blob Storage using SAS (Shared Access Signature)

We have two options if you want to apply scripts from Azure Blob Storage. We can generate the SAS or add the storage account name and key. We generate the SAS token and apply the extension to our test server.

  1. Create storage account
  2. Create Container
  3. Select Container and choose Upload
  4. Browse your script and click Upload
  5. Select the script and choose Generate SAS
  6. Specify the date range, permissions etc. and click Generate SAS token and URL
  7. Copy the Blob SAS URL value and assign it fileUris variable
				
					$Settings = @{
    fileUris = @("https://XXXXX.blob.core.windows.net/myscriptcontainer/Install-Arc7ZIP.ps1 ?sp=r&st=MYSASTOKEN")
    commandToExecute = "powershell -ExecutionPolicy Unrestricted -File Install-Arc7ZIP.ps1"
}

$CustomScriptProperties = @{
    MachineName = "ADFS01"
    Name = "CustomScriptExtension"
    ResourceGroupName = "RG-PROD-IT-ARC"
    Publisher = "Microsoft.Compute"
    ProtectedSetting = $Settings
    Location = "West Europe"
    ExtensionType = "CustomScriptExtension"
}

New-AzConnectedMachineExtension @CustomScriptProperties -Verbose  
				
			

Running scripts from Azure Blob Storage using Storage Account Name and Key

Now we will apply the script using the storage account name and key. To do that, we need to gather data from the Azure Portal.

  1. Open your Azure Storage Account
  2. Select Access Key
  3. Copy the Storage account name and Key values
  4. Specify storageAccountName and storageAccountKey properties in your script
				
					$Settings = @{
    fileUris = @("https://scriptskaido.blob.core.windows.net/managementscripts/Install-Arc7ZIP.ps1")
    commandToExecute = "powershell -ExecutionPolicy Unrestricted -File Install-Arc7ZIP.ps1"
    storageAccountName = "myscripts"
    storageAccountKey = "MY STORAG ACCOUNT KEY
}

$CustomScriptProperties = @{
    MachineName = "ADFS01"
    Name = "CustomScriptExtension"
    ResourceGroupName = "RG-PROD-IT-ARC"
    Publisher = "Microsoft.Compute"
    ProtectedSetting = $Settings
    Location = "West Europe"
    ExtensionType = "CustomScriptExtension"
}

New-AzConnectedMachineExtension @CustomScriptProperties -Verbose 
				
			

Running scripts from a local share

If you have your scripts on an internal file share, then you can use the script block below. In this example, I have removed the fileUris property and defined the location in the commandToExecute property.

				
					$Settings = @{
    commandToExecute = "powershell -ExecutionPolicy Unrestricted -File \\SERVER01\Scripts\Install-Arc7ZIP.ps1"
}

$CustomScriptProperties = @{
    MachineName = "ADFS01"
    Name = "CustomScriptExtension"
    ResourceGroupName = "RG-PROD-IT-ARC"
    Publisher = "Microsoft.Compute"
    ProtectedSetting = $Settings
    Location = "West Europe"
    ExtensionType = "CustomScriptExtension"
}

New-AzConnectedMachineExtension @CustomScriptProperties -Verbose 
				
			

Conclusion

Azure Arc for Servers Extensions simplifies your day-to-day administration tasks and brings the power of cloud-native management to your on-premise servers. If you haven’t yet tested Azure Arc, it’s time to start a proof of concept and experience the future of hybrid-cloud management.

Leave a Reply

Contact me

If you’re interested in learning about Azure Arc-enabled Servers Custom Script Extension for Windows. I can help you understand how this solution can benefit your organization and provide a customized solution tailored to your specific needs.

Table of Contents