diff --git a/PSDeploy/PSDeploy.yml b/PSDeploy/PSDeploy.yml index d21e85d..da2f961 100644 --- a/PSDeploy/PSDeploy.yml +++ b/PSDeploy/PSDeploy.yml @@ -15,6 +15,10 @@ ARM: Script: ARM.ps1 Description: Uses Azure Resource Manager PowerShell cmdlets to deploy a template to Microsoft Azure or Azure Stack +AzureAutomation: + Script: AzureAutomation.ps1 + Description: Deploy a runbook to Azure Automation + Chocolatey: Script: Chocolatey.ps1 Description: Uses Chocolatey on the local computer to push packages to a Chocolatey repository. diff --git a/PSDeploy/PSDeployScripts/AzureAutomation.ps1 b/PSDeploy/PSDeployScripts/AzureAutomation.ps1 new file mode 100644 index 0000000..e3db64c --- /dev/null +++ b/PSDeploy/PSDeployScripts/AzureAutomation.ps1 @@ -0,0 +1,88 @@ +<# + .SYNOPSIS + Deploy a Powershell Runbook to Azure Automation. + .DESCRIPTION + Deploy a Powershell Runbook to Azure Automation. + .PARAMETER Deployment + Deployment to run + .PARAMETER ResourceGroupName + Resource Group to deploy to + .PARAMETER AutomationAccountName + Automation Account to deploy to + .PARAMETER AzureServicePrincipalCredential + Credential of Azure Service Principal + User is Application (client) ID + Password is Secret string / Application Password + .PARAMETER AzureTenantID + Tenant ID of Service Principal + .PARAMETER RunbookType + Type of runbook being deployed, one of "PowerShell", "GraphicalPowerShell", "PowerShellWorkflow", "GraphicalPowerShellWorkflow", "Python2" + .PARAMETER CreateRunbook + If true, will create runbook if it doesn't already exist, otherwise runbook must already exist + + +#> +[cmdletbinding()] +param ( + [ValidateScript({ $_.PSObject.TypeNames[0] -eq 'PSDeploy.Deployment' })] + [psobject[]]$Deployment, + + [Parameter(Mandatory)][string]$ResourceGroupName, + + [Parameter(Mandatory)][string]$AutomationAccountName, + + [Parameter(Mandatory)][pscredential]$AzureServicePrincipalCredential, + + [Parameter(Mandatory)][string]$AzureTenantID, + + [Parameter(Mandatory)] + [ValidateSet("PowerShell", "GraphicalPowerShell", "PowerShellWorkflow", "GraphicalPowerShellWorkflow", "Python2")] + [string]$RunbookType, + + [bool]$CreateRunbook +) + +try +{ + Write-Verbose "Connecting to Azure" + $null = Connect-AzAccount -Credential $AzureServicePrincipalCredential -ServicePrincipal -Tenant $AzureTenantID -ErrorAction Stop +} +catch +{ + throw "Unable to connect to Azure with credentials provided $_" +} + foreach ($deploy in $Deployment) + { + If ($deploy.SourceExists) + { + if($Deploy.SourceType -eq 'File') + { + $rbname = (Split-Path $deploy.source -Leaf).split('.')[0] + Write-Verbose "looking for runbook $rbname" + $get = Get-AzAutomationRunbook -ResourceGroupName $ResourceGroupName -AutomationAccountName $AutomationAccountName -ErrorAction SilentlyContinue -Name $rbname + Write-Verbose "got $($get.count) runbooks" + if ((-not $get) -and (-not $CreateRunbook)) + { + Write-Warning "Runbook $rbname does not exist, please create before deploying or specify CreateRunbook" + } + else + { + try + { + Write-Verbose "Import-AzAutomationRunbook -Path $($deploy.source) -Type $RunbookType -Published -ResourceGroupName $ResourceGroupName -AutomationAccountName $AutomationAccountName -Force -ErrorAction Stop" + $null = Import-AzAutomationRunbook -Path $deploy.source -Type $RunbookType -Published -ResourceGroupName $ResourceGroupName -AutomationAccountName $AutomationAccountName -Force -ErrorAction Stop + } + catch + { + Write-Warning "Unable to update Runbook $_" + } + } + } + else + { + Write-Warning "This can ony be used to deploy individual scripts, not directories" + } + } + } + + $null = Disconnect-AzAccount \ No newline at end of file diff --git a/docs/Example-AzureAutomation-Deployment.md b/docs/Example-AzureAutomation-Deployment.md new file mode 100644 index 0000000..56dff8d --- /dev/null +++ b/docs/Example-AzureAutomation-Deployment.md @@ -0,0 +1,44 @@ +# Azure Automation + +## Prerequisites + +This DeploymentType uses the [Az module](https://docs.microsoft.com/en-us/powershell/azure/new-azureps-module-az) to connect to Azure and deploy runbooks. +Because it's meant to run as part of a build pipeline, it requires a service principal to be created with a password (not certificate). + +[Creating a Service Principal with the Az module](https://docs.microsoft.com/en-us/powershell/azure/create-azure-service-principal-azureps) + +[Creating a Service Principal with the Azure Portal](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal) + +## Options + +All options, except the CreateRunbook switch, are Mandatory + +* **ResourceGroupName:** Resource Group to deploy runbook to +* **AutomationAccountName:** Automation Account to deploy runbook to +* **AzureServicePrincipalCredential:** Credential of Azure Service Principal, User is Application (client) ID, Password is Secret string / Application Password +* **AzureTenantID:** Tenant ID of Service Principal +* **RunbookType:** Type of runbook being deployed, one of "PowerShell", "GraphicalPowerShell", "PowerShellWorkflow", "GraphicalPowerShellWorkflow", "Python2" +* **CreateRunbook:** Boolean, if true, will create runbook if it doesn't already exist, otherwise runbook must already exist + +## Examples + +```Powershell +Deploy ExampleDeployment { + By AzureAutomation { + $cred = Get-Credential + FromSource Runbook.ps1 + To AzureAutomation + WithOptions @{ + ResourceGroupName = "examplegroup" + AutomationAccountName = "example-account" + AzureServicePrincipalCredential = $cred + AzureTenantID = "6b3607b4-375b-447f-9fa1-34e452e1a91b" + RunbookType = "PowerShell" + } + } +} +``` + +Because each runbook requires a runbook type, FromSource can only be an individual script, not a whole directory. +The To will always be AzureAutomation. +This example gets the login credentials interactively, to use this in a pipeline you would need to generate the credential object another way.