Thispost describes how to use Azure Automation Hybrid Workerin on-premises scenarioswhere you need to authenticate against thelocalresourcesyou want to automate,allwithoutusinganyAzure Automationcredential/certificate,thanks toGroup Managed Service AccountsandPsExec.
Introduction
Azure Automation Hybrid Workeris a great solution for implementinghybrid automation scenarios, where you have on-premisesassetsyou want to manipulate from the same control plane youuse to manage your Azureresources. All your runbooks are stored andinvoked in Azure Automation, but you choose whether you run them in the cloud or on-premises.
No matter the environment you are managing, secure authentication against your resources is always acritical aspect of your automation, particularly when you need to access on-premisesresources.Azure Automation provides several solutions for authentication:
- RunAs Accounts(authenticating againstAzure resourcesonly)–a service principal is created in Azure AD andcan beassigned privileges to whateverAzureresourceassociated to that Azure AD– by default, it is given Contributor privileges in the Azure subscription in which the Automation Account was created.This solutionis normallyusedby hostedworkers, but canalsobe usedwith Hybrid Workers(seehow to).
- Managed Identity(authenticating against Azure resources only)–this is the recommended solution for Hybrid Workers running in Azure, as thereis no need to manageidentitycertificatesand authentication isdone in amuch simplerway.
- Credential,CertificateandConnectionassets–shared Automation resources thatboth hosted and Hybrid Workerscan use toretrievesecurely storedcredentialsor certificatesthat authenticate against Azure or on-premises resources.
Looking at theauthentication options available,onlycredentials/certificates can be used to authenticate againston-premises resources. However,some organizationsmaybe reluctant instoringsuchsensitiveinformationin Azure Automation, even moreretrieving it over the Internet.Therefore,if Automation Hybrid Workercould useanon-premisesidentitywithoutdealingwith secrets, such asGroupManaged Service Accounts(gMSA), there would be no need to store credentials/certificates.Unfortunately,Azure Automation does notnativelysupportgMSA, but if youfollow the remainder of this post,there is a way of usinggMSA, thanks to thePsExectool,which can be used to launch a process in the context of anyidentity, includinggMSA.
Solution architecture
This solution assumes that you haveone or moreAzure AutomationHybrid Workers domain-joined toanon-premises Active Directoryaccording togMSArequirements.ThesamegMSAidentity can be used across multipleHybrid Workers, as it is centrally managed by Active Directory.With therequired permissions assigned to thatgMSAaccount,Hybrid Workers canbe authorizedagainstthe resourcestoperform automation tasksall without dealing with secrets.
As a good practice, if you plan to automate local resources inseveraladministrativetiersor formultiplepurposes requiring different permission levels, you shouldconsiderusingdistinctgMSA/Hybrid Workersgroups for each administrative tier/permission level.
On-premises Hybrid Workers, orchestrated by Azure Automation and depending on local Domain Controllers to get the gMSA account required to access local resources
Implementation details
Due to the limited scenarios in whichgMSAscan be used, we are left with the only option for Hybrid Workers: using the well-knownPsExectool from MicrosoftSysinternals, which can be used to launch a process in the context of any user, includinggMSA. In order to usePowerShellfrom end to end, one can use theInvoke-PsExecwrapper module, but thePsExecexecutable can also be directly called fromPowerShell, provided it is made available in a well-known local directory in the Hybrid Worker machine.
In order to prepare thegMSAaccount, you must follow these steps (a good overview of the process can be foundhere):
1. Create theKDS Root Key in Active Directory(AD), by running the followingPowerShellcommandona domain controller:
- Option 1 – if you want to be sure the KDS Root Key propagatesacross your entire ADtopology andyou can wait for about 10 hours forthe propagationto conclude:
Add-KdsRootKey -EffectiveImmediately
- Option 2–ifKDS Root Key propagation across the entire ADtopologyis not an issue in your scenario:
Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10))
2. Create a security group in the AD for the purpose of grouping all the computers (Hybrid Workers) that will use thisgMSA. Make all the Hybrid Worker machines as members of this security group.Reboot the Hybrid Worker machines.
3. [if you chose option 1 in step 1, ensure 10 hours have elapsed]Create thegMSA, by executing the followingPowerShellcommand:
New-ADServiceAccount -Name "<gMSA name>" -DNSHostName "<gMSA name>.yourdomain.local" -Enabled $True -PrincipalsAllowedToRetrieveManagedPassword <security group created in the previous step> -KerberosEncryptionType AES256
4. Grant all the needed privileges to thegMSAaccount. When looking for thegMSAin the AD, refer to it as <gMSAname>$
5. Install thegMSAin the Hybrid Worker machines using it, by running there thisPowerShellcommand:
Install-ADServiceAccount -Identity <gMSA name>
6. Test if thegMSAwas correctly installed in the Hybrid Worker:
Test-ADServiceAccount -Identity <gMSA name>
Nowthat thegMSAis ready to be used, wemustset up Azure Automation. Inmanyscenarios,Automation runbookshavehundreds of lines, variables, HTML code, etc. Because of this complexity,wemightbe obligedtorun the script from theHybrid Workerlocal file system, instead of just passing it inline toPsExec. However, as we don’t want to have automation code permanently stored in theHybrid Workerlocal file system, we will use two Azure Automation Runbooks: the first one with thePsExecorchestration; and theotherone with the actual automation we want to execute (please, note that it won’t be triggered as a normal runbook, but will rather be temporarily downloaded to the local file system to be later called byPsExec). To make this solution possible, we will need to:
- Ensure we have a configured AzureRunAsAccount in the Automation Account (see instructions).
- Install the AzurePowerShellmodule in the Hybrid Worker (see instructions).
- Install the AzureRunAsAccountcertificate in the Hybrid Worker (see instructions). We will need this certificate to connect to Azuretodownload the main automation script.
- Install theInvoke-PsExecmodulein the Hybrid Worker
- Create thePsExecorchestration Runbook (see sample script below). This runbook:
- Downloadsthe main script from Azure Automation
- Searches and replaces (in the main script) for theparameters’placeholder with the actual parameters we want to pass
- Saves the final script inthelocal file system
- Calls Invoke-PsExecin the context of thegMSAaccount
- Create the main automation Runbook, ensuring we assign the expected JSON parameters variable with a parameters’placeholder, e.g., “JSONParametersPlaceHolder” (see sample script below)
- Invoke the orchestration runbook, passing to it the required parameters
- RunbookName– the name of the main automation runbook to be called withPsExecin the context ofgMSA
- AutomationAccountName– the Automation Account where the main runbook is stored
- AutomationAccountResourceGroup–resourcegroup for the Automation Account above
- gMSAName– the name of thegMSAaccount, in the format of “domain\accountname$”
- ParametersJson–the parametersto send to the main runbook, as a JSON valid string
PsExecOrchestration Runbook
<#Sample scripts provided are not supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.#> Param( [string] $RunbookName, [string] $AutomationAccountName, [string] $AutomationAccountResourceGroup, [string] $gMSAName, [string] $ParametersJson ) $servicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection" "Logging in to Azure..." Add-AzAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint Export-AzAutomationRunbook -ResourceGroupName $AutomationAccountResourceGroup -AutomationAccountName $AutomationAccountName -Name $RunbookName -Slot Published -OutputFolder . $ScriptFilePath = (Get-Item -Path ".\").FullName + "\" + $RunbookName + ".ps1" Write-Output "Replacing JSONParametersPlaceHolder with $ParametersJson ..." (Get-Content $ScriptFilePath).replace('JSONParametersPlaceHolder', $ParametersJson) | Set-Content $ScriptFilePath Write-Output "Using credential $gMSAName ..." # we must use ~ as a password replacement for the gMSA account $creds = New-Object System.Management.Automation.PSCredential ($gMSAName, (ConvertTo-SecureString "~" -AsPlainText -Force)) Invoke-PsExec -Credential $creds -ComputerName $env:computername -PSFile $ScriptFilePath
Main automation Runbook sample
$ParametersJson = "JSONParametersPlaceHolder" <# As an example, we are going to disable a user account sent as a JSON parameter, with the schema { 'Name': 'Account Name', 'SamAccountName' : 'SAM account name' } #> $user = ConvertFrom-Json -InputObject $ParametersJson Write-Output "About to disable $($user.Name)..." Disable-ADAccount $user.SamAccountName Write-Output "Done."
Conclusion
This post describedhow to use Azure Automation Hybrid Worker in scenarios where you need to authenticate againston-premisesresourceswithout using secrets orcertificates, thanks togMSAaccounts andPsExec.
Theorchestration runbook and main automation sample scriptaboveare an example of amorecomplex scenario, in which you need to pass parameters tothemain script. However, if the command to executein the context of thegMSAaccount is simple enough, you can callthePowerShellcommand right from the Invoke-PsExeccmdletand you don’t even need touseAzure AutomationRun As Accounts as you don’tneed to export themain script to the local file system.
Thanks for reading!