Public/New-AzureRmStartStopVmAutomation.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
using namespace Microsoft.Azure.Commands.Profile.Models

Set-StrictMode -Version Latest

$script:ErrorActionPreference = "Stop"

<#
.SYNOPSIS
Create a new Automation Account which includes two RunBooks. Them makes start/stop a virtual machine.
 
.DESCRIPTION
This function creates seven objects in a resource group as follows
 
 - ActiveDirectory Application
 - ActiveDirectory Service Principal
 - Automation Account
 - Variable Asset
 - Credential Asset
 - Runbook which makes start a virtual machine
 - Runbook which makes stop a virtual machine
 
.PARAMETER ResourceGroupName
A name of existing resource group.
 
 
.PARAMETER AutomationAccountName
A name of new automation account.
 
 
.EXAMPLE
New-AzureRmStartStopVmAutomation -ResourceGroupName rg01 -AutomationAccountName aa01
 
 
#>

function New-AzureRmStartStopVmAutomation {
    param(
        [parameter(mandatory=$true)]
        [String]
        $ResourceGroupName,

        [ValidateLength(6,50)]
        [parameter(mandatory=$true)]
        [String]
        $AutomationAccountName
    )

    [PSAzureContext]$Context = Get-AzureRmContext
    [String]$Location = (Get-AzureRmResourceGroup -Name $ResourceGroupName).Location
    [String]$ApplicationName = $AutomationAccountName + "_" + (New-Guid).ToString()
    [SecureString]$SecureString = ReadSecureString -Prompt "AD Application's Password:"
    [String]$Password = DecryptSecureString -SecureString $SecureString

    [String]$SubscriptionId = $Context.Subscription.SubscriptionId.ToString()
    [String]$TenantId = $Context.Tenant.TenantId.ToString()
    [String]$HomePage = "https://management.azure.com/subscriptions/${SubscriptionId}/resourcegroups/${ResourceGroupName}/providers/Microsoft.Automation/automationAccounts/${AutomationAccountName}"
    [String]$IdentifierUri = "https://spn/${ApplicationName}"
    [String[]]$RoleDefinitionNames = @("Reader","Virtual Machine Contributor")
    [String]$CredentialAssetName = "AzureCredential"
    [String]$TenantIdAssetName = "TenantId"
    [String]$MyModuleRoot = Split-Path -Path $PSScriptRoot -Parent

    try {
        # Create a new Application
        $NewApp = New-AzureRmADApplication `
            -DisplayName $ApplicationName `
            -Password $Password `
            -HomePage $HomePage `
            -IdentifierUris $IdentifierUri `
            -EndDate '9999-12-31'
        Write-Verbose -Message "Application Name='$($NewApp.DisplayName)' ApplicationId='$($NewApp.ApplicationId)' created."

        # Create a new Service Principal
        $NewSp = New-AzureRmADServicePrincipal `
            -ApplicationId $NewApp.ApplicationId
        Write-Verbose -Message "Service Principal Name='$($NewSp.ServicePrincipalName)' ObjectId='$($NewSp.Id)' created."

        # Wait for Service Principal avail
        Write-Verbose -Message 'Waiting for Service Principal.'
        $TmpSp = Get-AzureRmADServicePrincipal -ServicePrincipalName $NewSp.ServicePrincipalName
        while (!$TmpSp) {
            Start-Sleep -Seconds 1
            $TmpSp = Get-AzureRmADServicePrincipal -ServicePrincipalName $NewSp.ServicePrincipalName
        }

        # Assign Roles
        foreach ($i in $RoleDefinitionNames) {
            $null = New-AzureRmRoleAssignment `
                -ResourceGroupName $ResourceGroupName `
                -ServicePrincipalName $NewSp.ServicePrincipalName `
                -RoleDefinitionName $i
            Write-Verbose -Message "Role ${i} assigned."
        }

        # Create a new Automation Account
        New-AzureRmAutomationAccount `
            -ResourceGroupName $ResourceGroupName `
            -Name $AutomationAccountName `
            -Location $Location
        Write-Verbose -Message "Automation Account '$($AutomationAccountName)' created in '${ResourceGroupName}'."
        
        # Create a Variable Asset
        $null = New-AzureRmAutomationVariable `
            -ResourceGroupName $ResourceGroupName `
            -AutomationAccountName $AutomationAccountName `
            -Name $TenantIdAssetName `
            -Value $TenantId `
            -Encrypted $false
        Write-Verbose -Message "Variable Asset created in '${AutomationAccountName}'."

        # Create a Credential Asset
        $PsCred = New-Object `
            -TypeName System.Management.Automation.PSCredential `
            -ArgumentList $NewApp.ApplicationId,$SecureString

        $null = New-AzureRmAutomationCredential `
            -ResourceGroupName $ResourceGroupName `
            -AutomationAccountName $AutomationAccountName `
            -Name $CredentialAssetName `
            -Value $PsCred
        Write-Verbose -Message "Credential Asset created in '${AutomationAccountName}'."

        # Import RunBooks
        $null = Import-AzureRmAutomationRunbook `
            -ResourceGroupName $ResourceGroupName `
            -AutomationAccountName $AutomationAccountName `
            -Name "Start-SingleAzureRmVm" `
            -Type PowerShellWorkflow `
            -Path "$MyModuleRoot\RunBook\Start-SingleAzureRmVm.ps1" `
            -Published
        Write-Verbose -Message "RunBook 'Start-SingleAzureRmVm' imported."

        $null = Import-AzureRmAutomationRunbook `
            -ResourceGroupName $ResourceGroupName `
            -AutomationAccountName $AutomationAccountName `
            -Name "Stop-SingleAzureRmVm" `
            -Type PowerShellWorkflow `
            -Path "$MyModuleRoot\RunBook\Stop-SingleAzureRmVm.ps1" `
            -Published
        Write-Verbose -Message "RunBook 'Stop-SingleAzureRmVm' imported."
    }
    catch [Exception] {
        Write-Host `
            -ForegroundColor $host.PrivateData.ErrorForegroundColor `
            -BackgroundColor $host.PrivateData.ErrorBackgroundColor `
            -Object $_.exception `
            -ErrorAction SilentlyContinue

        # Clean garbage.
        Remove-AzureRmAutomationAccount `
            -ResourceGroupName $ResourceGroupName `
            -Name $AutomationAccountName `
            -Force `
            -ErrorAction SilentlyContinue
        
        # the service principal also removed.
        if ($NewApp) {
            Remove-AzureRmADApplication `
                -ApplicationObjectId $NewApp.ApplicationObjectId `
                -Force `
                -ErrorAction SilentlyContinue
        }
    }
}