forked from JeffBow/AzurePowerShell
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNew-AzureServicePrincipal.ps1
222 lines (174 loc) · 8.04 KB
/
New-AzureServicePrincipal.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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
<#
.SYNOPSIS
Creates self-signed cert and associated Azure AD Azure Service Principal and Azure AD Application that allows
Azure ARM authentication using -servicePrincipal flag
.DESCRIPTION
Along with creating the service principal and associated application ID, the script outputs a sample login script
and the exportable PFX that contains the certificate used for authentication. The certificate is created in the
currentUser\My store so the authentication will work for the user where the script is executed without importing the PFX
.EXAMPLE
.\New-AzureServicePrincipal.ps1 -CertYearsValid 1
.PARAMETER -CertYearsValid[int32]
The number of years the certificate will be valid. Defaults to 3
.PARAMETER -Environment [string]
Name of Environment e.g. AzureUSGovernment. Defaults to AzureCloud
.NOTES
Original Author: https://github.com/JeffBow
------------------------------------------------------------------------
Copyright (C) 2016 Microsoft Corporation
You have a royalty-free right to use, modify, reproduce and distribute
this sample script (and/or any modified version) in any way
you find useful, provided that you agree that Microsoft has no warranty,
obligations or liability for any sample application or script files.
------------------------------------------------------------------------
#>
#Requires -Version 4.0
#Requires -Module AzureRM.Resources
param(
[Parameter(Mandatory=$false)]
[int32]$CertYearsValid= 3,
[Parameter(Mandatory=$false)]
[string]$Environment= "AzureCloud"
)
function Roll-Back
{
param($thumbprint, $ApplicationId, $servicePrincipalID)
if($thumbprint)
{
write-verbose "Removing self-signed cert from CurrentUser\My store" -Verbose
ls cert:\CurrentUser\My | where{$_.Thumbprint -eq $thumbprint} | remove-item -ea SilentlyContinue
}
if($servicePrincipalID)
{
write-verbose "Removing Azure AD Service Principal with object ID of $servicePrincipalID" -Verbose
Remove-AzureRmADServicePrincipal -ObjectId $servicePrincipalID -Force -ea SilentlyContinue
}
if($ApplicationID)
{
write-verbose "Removing Azure AD Application with object ID of $ApplicationID" -Verbose
Get-AzureRmADApplication -ApplicationId $ApplicationId | Remove-AzureRmADApplication -Force -ea SilentlyContinue
}
}
# get Azure Creds
write-host "Enter credentials for the 'target' Azure Subscription..." -F Yellow
$login= Login-AzureRmAccount -EnvironmentName $Environment
$loginID = $login.context.account.id
$sub = Get-AzureRmSubscription -TenantID $login.context.Subscription.TenantID
$SubscriptionId = $sub.SubscriptionId
# check for multiple subs under same account and force user to pick one
if($sub.count -gt 1) {
$SubscriptionId = (Get-AzureRmSubscription | select * | Out-GridView -title "Select Target Subscription" -OutputMode Single).SubscriptionId
Select-AzureRmSubscription -SubscriptionId $SubscriptionId| Out-Null
$sub = Get-AzureRmSubscription -SubscriptionId $SubscriptionId
}
# check for valid sub
if(! $SubscriptionId)
{
write-warning "The provided credentials failed to authenticate or are not associcated to a valid subscription. Exiting the script."
break
}
# Get the tenant id for this subscription
$TenantID = $sub.TenantId
write-host "Logged into $($sub.SubscriptionName) with subscriptionID $SubscriptionId as $loginID" -f Green
# Request password
do {
$SecPassword = read-host "Enter password for the exportable self-signed certificate" -AsSecureString
if($SecPassword.Length -lt 1) {write-warning "Must enter secure password before proceeding. Exiting script." ; EXIT}
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecPassword))
$SecConfirmPassword = read-host "Confirm password for the exportable self-signed certificate" -AsSecureString
$confirmpassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecConfirmPassword))
}
while($Password -ne $confirmpassword )
[string] $guid = (New-Guid).Guid
[string] $ApplicationDisplayName = "AzureSP"+($guid.Substring(0,8))
write-verbose "Creating self-signed certificate" -Verbose
# create self-signed cert for web site
$CurrentDate = get-date
$notAfter = $CurrentDate.AddYears($certYearsValid)
$newCert = New-SelfSignedCertificate -DnsName "$ApplicationDisplayName" -CertStoreLocation cert:\CurrentUser\My -NotAfter $notAfter -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider"
$endDate = $newCert.GetExpirationDateString()
$thumbprint = $NewCert.Thumbprint
$KeyValue = [System.Convert]::ToBase64String($newCert.GetRawCertData())
$CertPath = $ApplicationDisplayName + ".pfx"
$xport = Export-PFXCertificate -Cert $newcert -FilePath $CertPath -Password $SecPassword
write-verbose "Creating Azure AD Application and Service Principal" -Verbose
try
{
$KeyCredential = New-Object Microsoft.Azure.Commands.Resources.Models.ActiveDirectory.PSADKeyCredential
$KeyCredential.StartDate = $CurrentDate
$KeyCredential.EndDate= $endDate
$KeyCredential.KeyId = $guid
#$KeyCredential.Type = "AsymmetricX509Cert"
#$KeyCredential.Usage = "Verify"
$KeyCredential.CertValue = $KeyValue
$Application = New-AzureRmADApplication -DisplayName $ApplicationDisplayName -HomePage ("http://" + $ApplicationDisplayName) -IdentifierUris ("http://" + $guid) -KeyCredentials $keyCredential -ea Stop
$ApplicationId = $Application.ApplicationId
write-verbose "Azure AD Application created with application ID of $applicationID" -Verbose
$servicePrincipal = New-AzureRMADServicePrincipal -ApplicationId $ApplicationId -ea Stop
$servicePrincipalID = $servicePrincipal.Id
write-verbose "Azure AD Service Principal created with object ID of $servicePrincipalID" -Verbose
}
catch
{
write-error $_
write-warning "Failed to create Azure AD Application and Service Principal'. Exiting the script"
roll-back -thumbprint $thumbprint -ApplicationId $ApplicationId -servicePrincipalID $servicePrincipalID
break
}
write-verbose "Adding Role to Service Principal $servicePrincipalID" -Verbose
$NewRole = $null
$Retries = 0;
While ($NewRole -eq $null -and $Retries -le 6)
{
# Sleep here for a few seconds to allow the service principal application to become active (should only take a couple of seconds normally)
Sleep 5
try
{
New-AzureRMRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $ApplicationId -ea Stop | Write-Verbose
}
catch
{
write-warning "Waiting 10 seconds for Service Principal to become active before adding Role Assignment'. Retry $Retriest of 5"
}
Sleep 10
$NewRole = Get-AzureRMRoleAssignment -ServicePrincipalName $ApplicationId -ErrorAction SilentlyContinue
$Retries++;
}
if(! $newRole)
{
write-warning "Failed to add role to Azure AD Service Principal'. Rolling back creation of certificate, application ID and service principal"
roll-back -thumbprint $thumbprint -ApplicationId $ApplicationId -servicePrincipalID $servicePrincipalID
}
else
{
[string]$outstring = @"
`$loginParams = @{
"CertificateThumbprint" = '$thumbprint'
"ApplicationId" = '$ApplicationId'
"TenantId" = '$TenantId'
"EnvironmentName" = '$Environment'
"ServicePrincipal" = `$null
}
# Connect to Azure and with Service Principal
try
{
# Log into Azure
Login-AzureRmAccount @loginParams -ea Stop | out-null
}
catch
{
if (! `$CertificateThumbprint)
{
`$ErrorMessage = "Certificate `$CertificateThumbprint not found."
throw `$ErrorMessage
} else{
Write-Error -Message `$_.Exception
throw `$_.Exception
}
break
}
# do your work here
Get-AzureRmResourceGroup
"@
$outstring | out-file 'Login-AzureRM.ps1'
}