AzureAutomationRunbookUtilities.psm1
<#
.SYNOPSIS Get details of the current Azure Automation job. .DESCRIPTION This function identifies the details about the current Azure Automation job by leveraging the $PSPrivateMetadata object which includes the job Id and then checks all the automation accounts in the current context to find the one that has the job matching that Id and returns the job details. .EXAMPLE Get-AARUCurrentJob .NOTES AUTHOR : Jeffrey Fanjoy LASTEDIT: 9/22/2016 Requires: AzureRM.resources Requires: AzureRM.automation #> Function Get-AARUCurrentJob { [CmdletBinding()] Param() Begin { Write-Verbose ("Entering {0}." -f $MyInvocation.MyCommand) } Process { $AutomationAccounts = Find-AzureRmresource -ResourceType 'Microsoft.Automation/AutomationAccounts' foreach ($AutomationAccount in $AutomationAccounts) { $CurrentJob = Get-AzureRmAutomationJob -ResourceGroupName $AutomationAccount.ResourceGroupName -AutomationAccountName $AutomationAccount.Name -Id $PSPrivateMetadata.JobId.Guid -ErrorAction SilentlyContinue if (!([string]::IsNullOrEmpty($CurrentJob))) { Break; } } $CurrentJob } End { Write-Verbose ("Exiting {0}." -f $MyInvocation.MyCommand) } } <# .SYNOPSIS Start a runbook using the properties of an existing job as a template. .DESCRIPTION This function identifies the details of an existing Azure Automation job and then uses those details to start a new job using the same input properties and execution location (Azure or Hybrid Worker). .PARAMETER JobId The GUID of an existing Azure Automation job to use as the template. .EXAMPLE Start-AARURunbookFromJob -JobId '00000000-0000-0000-0000-000000000000' .EXAMPLE Get-AARUCurrentJob | Start-AARURunbookFromJob .NOTES AUTHOR : Jeffrey Fanjoy LASTEDIT: 12/19/2016 Requires: AzureRM.resources Requires: AzureRM.automation #> Function Start-AARURunbookFromJob { [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)] [guid] $JobId ) Begin { Write-Verbose ("Entering {0}." -f $MyInvocation.MyCommand) } Process { $AutomationAccounts = Find-AzureRmresource -ResourceType 'Microsoft.Automation/AutomationAccounts' # Find the job Id provided. foreach ($AutomationAccount in $AutomationAccounts) { $SourceJob = Get-AzureRmAutomationJob -ResourceGroupName $AutomationAccount.ResourceGroupName -AutomationAccountName $AutomationAccount.Name -Id $JobId -ErrorAction SilentlyContinue if (!([string]::IsNullOrEmpty($SourceJob))) { Break; } } if (!($SourceJob)) { throw ("Job id '{0}' was not found." -f $JobId) } else { # Start a new job using the details of the original job to effectively rerun the # job using the same inputs. if ($SourceJob.HybridWorker) { Start-AzureRmAutomationRunbook -ResourceGroupName $SourceJob.ResourceGroupName -AutomationAccountName $SourceJob.AutomationAccountName -Name $SourceJob.RunbookName -Parameters $SourceJob.JobParameters -RunOn $SourceJob.HybridWorker } else { Start-AzureRmAutomationRunbook -ResourceGroupName $SourceJob.ResourceGroupName -AutomationAccountName $SourceJob.AutomationAccountName -Name $SourceJob.RunbookName -Parameters $SourceJob.JobParameters } } } End { Write-Verbose ("Exiting {0}." -f $MyInvocation.MyCommand) } } <# .SYNOPSIS Invoke a scriptblock with retries on scriptblock failure. .DESCRIPTION This function executes a scriptblock provided as a string variable and executes that block trapping any errors that occur. If an error is trapped, an interval of time is passed and then the block is executed again until either the block executes successfully or the maximum number of retries is reached at which point the error is thrown and execution stops. .PARAMETER ScriptBlock The script contents to execute provided as a string. .PARAMETER Retries The maximum number of times to retry the execution of the scriptblock provided in the ScriptBlock parameter. Default value is 5. .PARAMETER RetryInterval The amount of time in seconds to wait between retrying the execution of the scriptblock provided in the ScriptBlock parameter. Default value is 2. .EXAMPLE Invoke-AARUScriptBlock -ScriptBlock { Get-Process -Name powershell } -Retries 5 -RetryInterval 2 .NOTES AUTHOR: Jeffrey Fanjoy LASTEDIT: 5/26/2016 #> Function Invoke-AARUScriptBlock { [CmdletBinding()] Param ( [Parameter(Mandatory=$true,Position=0)] [string] $ScriptBlock, [Parameter(Mandatory=$false)] [int] $Retries = 5, [Parameter(Mandatory=$false)] [int] $RetryInterval = 2 ) Begin { Write-Verbose ("Entering {0}." -f $MyInvocation.MyCommand) } Process { # Set $ErrorActionPreference to "Stop" so that even non-terminating errors terminate and the # try..catch will be able to trap any exceptions. $ErrorActionPreference="Stop" # Construct a proper scriptblock object from the string scriptblock passed in. $ScriptBlockToExecute = [Scriptblock]::Create($ScriptBlock) Write-Verbose ("Executing ScriptBlock [{0}] with retry maximum of [{1}] and retry interval of [{2}]." -f $ScriptBlockToExecute, $Retries, $RetryInterval) # Set the lifecycle variables for use in the while loop. $RetryCount = 1 $Completed = $false while (!$Completed) { try { # Execute the scriptblock & $ScriptBlockToExecute Write-Verbose ("ScriptBlock [{0}] executed successfully." -f $ScriptBlockToExecute) $Completed = $true } catch { if ($RetryCount -ge $Retries) { Write-Verbose ("ScriptBlock [{0}] failed the maximum number of {1} times." -f $ScriptBlockToExecute, $RetryCount) throw $_ } else { Write-Verbose ("ScriptBlock [{0}] failed. Retrying in {1} second(s)." -f $ScriptBlockToExecute, $RetryInterval) Start-Sleep $RetryInterval $RetryCount++ } } } } End { Write-Verbose ("Exiting {0}." -f $MyInvocation.MyCommand) } } <# .SYNOPSIS Login to Azure using an Automation Run As Account. .DESCRIPTION Login to Azure using an Automation Run As Account defined using the Automation connection asset name (e.g. AzureRunAsAccount). Optionally change to a desired subscription using either the subscription name or subscription id. .PARAMETER RunAsAccountName Optional. The name of the Run As Account connection asset in Azure Automation. Default value is AzureRunAsConnection. .PARAMETER SubscriptionName Optional. The name of the subscription to select after logging into Azure. If this parameter is included, then a valid subscription name must be provided. If neither SubscriptionId, nor SubscriptionName parameters are included, the subscription id defined in the Run As Account connection asset will be used. .PARAMETER SubscriptionId Optional. The id of the subscription to select after logging into Azure. If this parameter is included, then a valid subscription id must be provided. If neither SubscriptionId, nor SubscriptionName parameters are included, the subscription id defined in the Run As Account connection asset will be used. .PARAMETER OutputResults Optional. Write the results of logging into Azure and selecting the desired subscription to the output stream. Default value is $false. .EXAMPLE Connect-AARUAzureUsingRunAsAccount -RunAsAccountName 'AzureRunAsConnection' .NOTES AUTHOR : Jeffrey Fanjoy LASTEDIT: 11/11/2016 Requires: AzureRM.profile Requires: Orchestrator.AssetManagement.Cmdlets #> Function Connect-AARUAzureUsingRunAsAccount { [CmdletBinding(DefaultParameterSetName='Default')] Param ( [Parameter(ParameterSetName='Default')] [Parameter(ParameterSetName='SubscriptionName')] [Parameter(ParameterSetName='SubscriptionId')] [Parameter(Mandatory=$false, Position=0)] [string] $RunAsAccountName = 'AzureRunAsConnection', [Parameter(ParameterSetName='SubscriptionName')] [Parameter(Mandatory=$false, Position=1)] [ValidateNotNullOrEmpty()] [string] $SubscriptionName, [Parameter(ParameterSetName='SubscriptionId')] [Parameter(Mandatory=$false, Position=1)] [ValidateNotNullOrEmpty()] [string] $SubscriptionId, [Parameter(Mandatory=$false, Position=2)] [switch] $OutputResults ) Begin { Write-Verbose ("Entering {0}." -f $MyInvocation.MyCommand) Write-Verbose ("`$RunAsAccountName = {0}" -f $RunAsAccountName) Write-Verbose ("`$SubscriptionName = {0}" -f $SubscriptionName) Write-Verbose ("`$SubscriptionId = {0}" -f $SubscriptionId) } Process { # Retrieve the Run As Account connection asset from Azure Automation. Write-Verbose ("Retrieving Run As Account connection '{0}'." -f $RunAsAccountName) $RunAsAccount = Invoke-AARUScriptBlock -ScriptBlock { Get-AutomationConnection -Name $RunAsAccountName } -Retries 3 -RetryInterval 1 if (!($RunAsAccount)) { throw ("Could not retrieve Run As Account connection asset '{0}'. Ensure that this asset exists in the Automation account." -f $RunAsAccountName) } # Login to Azure. Write-Verbose ("Logging into Azure using TenantId '{0}', ApplicationId '{1}' and CertificateThumbprint '{2}'." -f $RunAsAccount.TenantId, $RunAsAccount.ApplicationId, $RunAsAccount.CertificateThumbprint) $AzureAccount = Invoke-AARUScriptBlock -ScriptBlock { Add-AzureRmAccount ` -ServicePrincipal ` -TenantId $RunAsAccount.TenantId ` -ApplicationId $RunAsAccount.ApplicationId ` -CertificateThumbprint $RunAsAccount.CertificateThumbprint } -Retries 3 -RetryInterval 1 # If a subscription id or name is provided, select that subscription, otherwise use the # one from the Run As Account connection. Switch ($PSCmdlet.ParameterSetName) { 'SubscriptionName' { Write-Verbose ("Setting Azure context to subscription '{0}'." -f $SubscriptionName) $Subscription = Invoke-AARUScriptBlock -ScriptBlock { Select-AzureRmSubscription -SubscriptionName $SubscriptionName } -Retries 3 -RetryInterval 1 } 'SubscriptionId' { Write-Verbose ("Setting Azure context to subscription '{0}'." -f $SubscriptionId) $Subscription = Invoke-AARUScriptBlock -ScriptBlock { Select-AzureRmSubscription -SubscriptionId $SubscriptionId } -Retries 3 -RetryInterval 1 } Default { Write-Verbose ("Setting Azure context to subscription '{0}'." -f $RunAsAccount.SubscriptionId) $Subscription = Invoke-AARUScriptBlock -ScriptBlock { Select-AzureRmSubscription -SubscriptionId $RunAsAccount.SubscriptionId } -Retries 3 -RetryInterval 1 } } if ($OutputResults) { Write-Verbose ("Returning Azure context as output.") Get-AzureRmContext | Format-List } } End { Write-Verbose ("Exiting {0}." -f $MyInvocation.MyCommand) } } <# .SYNOPSIS Login to Azure using an Automation Classic Run As Account. .DESCRIPTION Login to Azure using an Automation Classic Run As Account defined using the Automation connection asset name (e.g. AzureClassicRunAsConnection). Optionally change to a desired subscription using either the subscription name or subscription id. .PARAMETER RunAsAccountName Optional. The name of the Classic Run As Account connection asset in Azure Automation. Default value is AzureClassicRunAsConnection. .EXAMPLE Connect-AARUAzureUsingClassicRunAsAccount -RunAsAccountName 'AzureClassicRunAsConnection' .NOTES AUTHOR : Jeffrey Fanjoy LASTEDIT: 10/26/2016 Requires: Azure Requires: Orchestrator.AssetManagement.Cmdlets #> Function Connect-AARUAzureUsingClassicRunAsAccount { [CmdletBinding()] Param ( [Parameter(Mandatory=$false, Position=0)] [string] $RunAsAccountName = 'AzureClassicRunAsConnection' ) Begin { Write-Verbose ("Entering {0}." -f $MyInvocation.MyCommand) Write-Verbose ("`$RunAsAccountName = {0}" -f $RunAsAccountName) } Process { # Retrieve the Run As Account connection asset from Azure Automation. Write-Verbose ("Retrieving Run As Account connection '{0}'." -f $RunAsAccountName) $RunAsAccount = Invoke-AARUScriptBlock -ScriptBlock { Get-AutomationConnection -Name $RunAsAccountName } -Retries 3 -RetryInterval 1 if (!($RunAsAccount)) { throw ("Could not retrieve Run As Account connection asset '{0}'. Ensure that this asset exists in the Automation account." -f $RunAsAccountName) } # Retrieve the certificate asset Write-Verbose ("Retrieving certificate from certificate asset '{0}'." -f $RunAsAccount.CertificateAssetName) $AzureCert = Invoke-AARUScriptBlock -ScriptBlock { Get-AutomationCertificate -Name $RunAsAccount.CertificateAssetName } -Retries 3 -RetryInterval 1 if (!($AzureCert)) { throw ("Could not retrieve certificate asset '{0}'. Ensure that this asset exists in the Automation account." -f $RunAsAccount.CertificateAssetName) } # Login to Azure. Write-Verbose ("Logging into Azure using certificate.") $Subscription = Invoke-AARUScriptBlock -ScriptBlock { Set-AzureSubscription ` -SubscriptionName $RunAsAccount.SubscriptionName ` -SubscriptionId $RunAsAccount.SubscriptionId ` -Certificate $AzureCert Select-AzureSubscription -SubscriptionId $RunAsAccount.SubscriptionId } -Retries 3 -RetryInterval 1 } End { Write-Verbose ("Exiting {0}." -f $MyInvocation.MyCommand) } } |