Share via

azure vm automation powershell script

Karuppasamy MK 0 Reputation points
2023-05-06T16:01:24.4866667+00:00

Hi,

I used the attached powershell script in azure automation and I use this script for add the new/migrated vm to backup vault and policy, enable encrytion, install antimalware, enable Jit etc. Since this is using the runasconnection and going to be depricated and I changed this to to use system manged identity and modified the script. But not this script is not running. It seems something I am missing in the script. can any one suggest what I need to do run this script successfully? I placed the script below as well

THanks.

Powershell script


  
  [CmdletBinding()]
  Param
  (
    [Object]$RecoveryPlanContext,
    [string[]]$vmName,
    [string]$backupRecoveryVaultName ,
    [string]$backupPolicyName,
    [string]$automationAccountName ="Testaa",
    #[string]$ConnectionName = "",
    [string]$logAnalyticsWorkspaceName,
    [string]$dscNodeConfigurationName,
    [string]$antiMalwareExclusions,
    [bool]$enableJustInTime,
    [bool]$enableNetworkWatcher,
    [bool]$enableAntiMalware,
    [bool]$encrypt
  )
Connect-AzAccount -identity
  Import-Module ThreadJob

#$sub = Get-AzSubscription -ErrorAction SilentlyContinue
#if(-not($sub))
#{
#    Connect-AzAccount
#}

  Class automationAccount{
    [string]$accountName 
    [string]$resourceGroup
    [object]$runbooks 
    [object]GetRunbooks(){return $this.runbooks = (Get-AzAutomationRunbook -ResourceGroupName $this.resourceGroup `
                                                                           -AutomationAccountName $this.accountName)}
    [object]GetResourceGroup(){return $this.resourceGroup = ((Get-AzResource -ResourceName $this.accountName `
                                                                             -ResourceType 'Microsoft.Automation/automationAccounts').ResourceGroupName)}                                                                       

    automationAccount([string]$a){
      $this.accountName = $a
      $this.GetResourceGroup()
      $this.GetRunbooks()
    }
  }

 # if($ConnectionName){
 #   $servicePrincipalConnection=Get-AutomationConnection -Name $ConnectionName         
 #   Add-AzAccount `
   #   -ServicePrincipal `
   #   -TenantId $servicePrincipalConnection.TenantId `
  #    -ApplicationId $servicePrincipalConnection.ApplicationId `
   #   -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
  #}

  $jobIDs= New-Object System.Collections.Generic.List[System.Object] 
  
  [automationAccount]$automationAccountObj = [automationAccount]::new($automationAccountName)
  if($automationAccountObj){
    Write-Output "Automation Account $($automationAccountObj.accountName) Found"
  }
  else{
    Write-Error "Automation Account not found!!!"
    exit
  }
  
  Function Set-RecoveryParameters(){
    ################################################################
    #####default Values if Recovery plan is run from ASR failover
    ################################################################
    $Script:backupRecoveryVaultName="RSV1"
    $Script:backupPolicyName="defaultPolicy"
    $Script:logAnalyticsWorkspaceName="test"
    $script:dscNodeConfiguratioName =""
    $Script:enableJustInTime=$true
    $Script:enableNetworkWatcher=$true
    $Script:enableAntiMalware=$true
    $Script:encrypt=$true
  }

  Function Get-VMObj($vmStr){
      Get-AzVm -Name $vmStr
  }

  $threadFunctions = {
    Param
    (
      [string]$encryptionRunbookName = "Enable-VMEncryption",
      [string]$jitRunbookName = "Enable-VMJit",
      [string]$extensionRunbookName = "Install-VMExtension",
      [string]$dscRunbookName = "Enable-DesiredStateConfiguration",
      [string]$backupRunbookName = "Enable-VMBackup"
    )

      Function New-AutomationJob($runbookName,$params){
        Start-AzAutomationRunbook -AutomationAccountName $automationAccountObj.accountName `
                                  -ResourceGroupName $automationAccountObj.resourceGroup `
                                  -Name $runbookName `
                                  -Parameters $params `
                                  -Wait
      }
    
      Function Add-Extension($extensionName,$params,$protectedSettings,$VM){
        if(Search-Runbook -runbookName $extensionRunbookName){
          Write-Output "$extensionRunbookName Found - Installing $extensionName on $($VM.name)"
        
          New-AutomationJob -runbookName $extensionRunbookName `
                            -params @{
                              "Settings"            =$params
                              "protectedSettings"   =$protectedSettings
                              "extensionName"       =$extensionName
                              "extensionType"       =$extensionName
                              "VM"                  =$VM
                            }
        }
        else {
          Write-Error "$extensionRunbookName not found!"
        } 
      }
    
      Function Search-Runbook($runbookName){
        if(($automationAccountObj.runbooks|Select-Object name).name -like $runbookName){
          return $true
        }
        else{
          return $false
        }
      }
    
      Function Add-DiskEncryption($VM){
        if(Search-Runbook -runbookName $encryptionRunbookName){
          Write-Output "$encryptionRunbookName Found - Enabling Azure Disc Encryption on $($VM.name)"
        
          New-AutomationJob -runbookName $encryptionRunbookName `
                            -params @{
                              "encryptScope"    ="All"
                              "VM"              =$VM
                            }
        }
        else {
          Write-Error "$encryptionRunbookName not found!"
        } 
      }

      Function Add-DesiredStateConfiguration($VM,$nodeName){
        if(Search-Runbook -runbookName $dscRunbookName){
          Write-Output "$dscRunbookName Found - Enabling Azure Disc Encryption on $($VM.name)"
        
          New-AutomationJob -runbookName $dscRunbookName `
                            -params @{
                              "nodeConfigurationName"   = $nodeName
                              "VM"                      = $VM
                              "automationAccountName"   = $automationAccountObj.accountName
                            }
        }
        else {
          Write-Error "$dscRunbookname not found!"
        } 
      }
    
      Function Add-AzureBackup($VM,$backupVault,$backupPolicy){
        if(Search-Runbook -runbookName $backupRunbookName){
          Write-Output "$backupRunbookName Found - Enabling Backup on $($VM.name)"
        
          New-AutomationJob -runbookName $backupRunbookName `
                            -params @{
                              "policyName"          =$backupPolicy
                              "recoveryVaultName"   =$backupVault
                              "VM"                  =$VM
                            }
        }
        else {
          Write-Error "$backupRunbook not found!"
        } 
      }
    
      Function Add-JIT($VM){
        if(Search-Runbook -runbookName $jitRunbookName){
          Write-Output "$jitRunbookName Found - Enabling Just in Time Access on $($VM.name)"
        
          New-AutomationJob -runbookName $jitRunbookName `
                            -params @{"VM"=$VM}
        }
        else {
          Write-Error "$jitRunbookName not found!"
        } 
      }
    
      Function Get-LogAnalyticsObj($logAnalyticsWorkspaceName){
        Class logAnalyticsWorkspace{
          [object]$workspace
          [string]$key
        }
        [logAnalyticsWorkspace]$workspace = [logAnalyticsWorkspace]::new()
        $workspace.workspace = Get-AzResource -Name $logAnalyticsWorkspaceName `
                                  | Get-AzOperationalInsightsWorkspace 
        $workspace.key = (Get-AzOperationalInsightsWorkspaceSharedKeys -ResourceGroupName $workspace.workspace.ResourceGroupName `
                                                                      -Name $workspace.workspace.Name).PrimarySharedKey
      
        return $workspace
      }
}

#Main
  if(!$vmName){
    Write-Output "RecoveryPlanContext found"
    $VMRoleObjs= New-Object System.Collections.Generic.List[System.Object] 
    $VMinfo = $RecoveryPlanContext.VmMap | Get-Member | Where-Object MemberType -EQ NoteProperty | select -ExpandProperty RoleName
    $vmMap = $RecoveryPlanContext.VmMap
    Write-Output "VM Info found count $($VMinfo.count)"
     foreach($VMID in $VMinfo)
     {
         $VM = $vmMap.$VMID                
                 if( !(($VM -eq $Null) -Or ($VM.ResourceGroupName -eq $Null) -Or ($VM.RoleName -eq $Null))) {
                  #this check is to ensure that we skip when some data is not available else it will fail
                  Write-Output "$($VM.RoleName) found in recovery context)"
                  $VMRoleObjs.Add($VM.RoleName)
         }
     }
    $vmList = $VMRoleObjs
    Set-RecoveryParameters
  }
  else{
    Write-Output "VM string array found"
    $vmList = $vmName
  }

  $passedParameters = $PSCmdlet.MyInvocation.BoundParameters

  foreach($item in $vmList){
    $vmObj = Get-VMObj -vmStr $item
    Write-Output "Found virtual machine: $($vmObj.name)"
    if($vmObj){
      $newJob = Start-Threadjob -InitializationScript $threadFunctions `
                                -ArgumentList $vmObj,$passedParameters,$automationAccountObj `
                                -ScriptBlock { param($vmObj,$passedParameters,$automationAccountObj) 
                                  if($passedParameters.enableNetworkWatcher){
                                    Add-Extension -extensionName "Microsoft.Azure.NetworkWatcher.NetworkWatcherAgentWindows" `
                                                  -VM $vmObj}
                                  if($passedParameters.enableAntiMalware){
                                    Add-Extension -extensionName "Microsoft.Azure.Security.IaaSAntimalware" `
                                                  -VM $vmObj}
                                  if($passedParameters.logAnalyticsWorkspaceName){
                                    $workspaceObj = Get-LogAnalyticsObj -logAnalyticsWorkspaceName $passedParameters.logAnalyticsWorkspaceName
                                    Add-Extension -extensionName "Microsoft.EnterpriseCloud.Monitoring.MicrosoftMonitoringAgent" `
                                                  -params "{'workspaceId' : '$($workspaceObj.workspace.customerId.guid)'}" `
                                                  -ProtectedSettings "{'workspaceKey' : '$($workspaceObj.key)'}" `
                                                  -VM $vmObj
                                  }
                                  if($passedParameters.dscNodeConfigurationName){Add-DesiredStateConfiguration -VM $vmObj -nodeName $passedParameters.dscNodeConfigurationName}
                                  if($passedParameters.encrypt){Add-DiskEncryption -VM $vmObj}
                                  if($passedParameters.backupRecoveryVaultName -and $passedParameters.backupPolicyName){
                                    Add-AzureBackup -VM $vmObj `
                                                    -backupVault $passedParameters.backupRecoveryVaultName `
                                                    -backupPolicy $passedParameters.backupPolicyName
                                  }
                                  if($passedParameters.enableJustInTime){Add-JIT -VM $vmObj}
                                }
      $jobIDs.Add($newJob.Id) 
    }
  }

  $jobsList = $jobIDs.ToArray() 
  if ($jobsList) 
  { 
      Write-Output "Waiting for automations to Complete" 
      Wait-Job -Id $jobsList 
  } 
  
  foreach($id in $jobsList) 
  { 
      $job = Get-Job -Id $id 
      Write-Output $job.Output
      if ($job.Error) 
      { 
          #Write-Output $job.Error 
      } 
  } 
Azure Automation
Azure Automation

An Azure service that is used to automate, configure, and install updates across hybrid environments.

Windows for business | Windows Server | User experience | PowerShell

2 answers

Sort by: Most helpful
  1. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

  2. Konstantinos Passadis 19,701 Reputation points MVP
    2023-05-06T16:17:18.0266667+00:00

    Hello @Karuppasamy MK !

    Welcome to Microsoft QnA!

    Based on the script you provided, it seems like the issue could be that you are using Connect-AzAccount to connect to Azure, but you are using system-assigned managed identity to authenticate, which doesn't require authentication via a service principal.

    Try removing the Connect-AzAccount cmdlet and use the system-assigned managed identity to authenticate to Azure. You can do this by adding the -Identity parameter to your Start-AzAutomationRunbook cmdlets, like this:

    Start-AzAutomationRunbook -AutomationAccountName $automationAccountObj.accountName `

                          **-ResourceGroupName $automationAccountObj.resourceGroup `**
    
                          **-Name $runbookName `**
    
                          **-Parameters $params `**
    
                          **-Wait `**
    
                          **-Identity**
    

    Also, make sure that the system-assigned managed identity has the necessary permissions to run the runbooks and access the resources in your Azure subscription. You may need to assign the necessary permissions to the managed identity using role-based access control (RBAC).


    The answer or portions of it may have been assisted by AI Source: ChatGPT Subscription

    Kindly mark the answer as Accepted and Upvote in case it helped or post your feedback to help !

    Regards

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.