/
cluster_azure-repository_app-service.ps1
393 lines (316 loc) · 17.6 KB
/
cluster_azure-repository_app-service.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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
<#
.Synopsis
Deploys an Azure Storage Account, Elasticsearch cluster and Azure App Service.
.Description
The Storage account is configured with the azure-repository plugin to be used for snapshot/restore for the Elasticsearch cluster.
The Azure App Service is connected to the Virtual Network deployed as part of the cluster so that it can connect to the cluster.
.Example
& .\cluster_azure-repository_app-service.ps1 -AdminUserName "russ" `
-AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) `
-SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) `
-SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) `
-SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force)
.Example
& .\cluster_azure-repository_app-service.ps1 -ClientId "clientid" `
-ClientSecret $(ConvertTo-SecureString -String "clientsecret" -AsPlainText -Force) `
-TenantId "tenantid" -SubscriptionId "subscriptionid" `
-AdminUserName "russ" -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) `
-SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) `
-SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) `
-SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force)
.Parameter ClientId
the client id to log in with a Service Principal
.Parameter ClientSecret
the client secret to log in with a Service Principal
.Parameter TenantId
the tenant id to log in with a Service Principal
.Parameter SubscriptionId
the subscription id to deploy the resources to. If the current session is not logged into the Azure account, user will
be prompted to log in and select a SubscriptionId
.Parameter AdminUserName
the admin username in order to log into VMs deployed in the Elasticsearch cluster
.Parameter AdminPassword
the admin password in order to log into VMs deployed in the Elasticsearch cluster
.Parameter SecurityAdminPassword
the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_admin' (2.x) or 'elastic' (5.x)
.Parameter SecurityReadPassword
the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_read'
.Parameter SecurityKibanaPassword
the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_kibana'
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$false)]
[string] $ClientId,
[Parameter(Mandatory=$false)]
[securestring] $ClientSecret,
[Parameter(Mandatory=$false)]
[string] $TenantId,
[Parameter(Mandatory=$false)]
[string] $SubscriptionId,
[Parameter(Mandatory=$true)]
[string] $AdminUserName,
[Parameter(Mandatory=$true)]
[securestring] $AdminPassword,
[Parameter(Mandatory=$true)]
[securestring] $SecurityAdminPassword,
[Parameter(Mandatory=$true)]
[securestring] $SecurityReadPassword,
[Parameter(Mandatory=$true)]
[securestring] $SecurityKibanaPassword
)
$ErrorActionPreference = "Stop"
function Write-Log($Message, $ForegroundColor) {
if ($ForegroundColor -eq $null) {
$ForegroundColor = "White"
}
Write-Host "[$(Get-Date -format 'u')] $message" -ForegroundColor $ForegroundColor
}
function Show-Custom($title, $optionValues, $optionDescriptions) {
Write-Host $title
Write-Host
for($i = 0; $i -lt $optionValues.Length; $i++) {
Write-Host "$($i+1))" $optionDescriptions[$i]
}
Write-Host
while($true) {
Write-Host "Choose an option: "
$option = Read-Host
$option = $option -as [int]
if($option -ge 1 -and $option -le $optionValues.Length) {
return $optionValues[$option-1]
}
}
}
function Show-Subscription() {
# Choose subscription. If there's only one we will choose automatically
$subs = Get-AzureRmSubscription
$subscriptionId = ""
if($subs.Length -eq 0) {
Write-Error "No subscriptions bound to this account."
return
}
if($subs.Length -eq 1) {
$subscriptionId = $subs[0].SubscriptionId
}
else {
$subscriptionChoices = @()
$subscriptionValues = @()
foreach($subscription in $subs) {
$subscriptionChoices += "$($subscription.SubscriptionName) ($($subscription.SubscriptionId))";
$subscriptionValues += ($subscription.SubscriptionId);
}
$subscriptionId = Show-Custom "Choose a subscription" $subscriptionValues $subscriptionChoices
}
return $subscriptionId
}
function New-StorageAccount($storageAccountResourceGroup, $storageAccountName, $location) {
$account = Get-AzureRmStorageAccount -ResourceGroupName $storageAccountResourceGroup -Name $storageAccountName -ErrorAction Ignore
if ($account -ne $null) {
Write-Log "Storage account $storageAccountName in resource group $storageAccountResourceGroup already exists. Using this." -ForegroundColor "green"
return
}
Write-Log "Creating Storage account $storageAccountName in resource group $storageAccountResourceGroup"
New-AzureRmResourceGroup -Name $storageAccountResourceGroup -Location $location
New-AzureRmStorageAccount -ResourceGroupName $storageAccountResourceGroup -AccountName $storageAccountName -Type "Standard_LRS" -Location $location
Write-Log "Finished creating Storage account" -ForegroundColor "green"
}
function New-ElasticsearchCluster($resourceGroupName, $clusterName, $location, $elasticTemplateUri, $elasticParameters) {
$resourceGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -Location $location -ErrorAction Ignore
if ($resourceGroup -ne $null) {
Write-Log "Resource group $resourceGroupName already exists. Using this." -ForegroundColor "green"
return
}
Write-Log "Deploying Elasticsearch cluster $clusterName from $elasticTemplateUri"
New-AzureRmResourceGroup -Name $resourceGroupName -Location $location
New-AzureRmResourceGroupDeployment -Name $clusterName -ResourceGroupName $resourceGroupName -TemplateUri $elasticTemplateUri -TemplateParameterObject $elasticParameters
Write-Log "Finished Deploying Elasticsearch cluster" -ForegroundColor "green"
}
function New-Website($resourceGroupName, $webAppName, $location, $webAppParameters) {
$resourceGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -Location $location -ErrorAction Ignore
if ($resourceGroup -ne $null) {
Write-Log "Resource group $resourceGroupName already exists. Using this." -ForegroundColor "green"
return
}
$deployFromGithubTemplate = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-web-app-github-deploy/azuredeploy.json"
New-AzureRmResourceGroup -Name $resourceGroupName -Location $location
New-AzureRmResourceGroupDeployment -Name $webAppName -ResourceGroupName $resourceGroupName `
-TemplateUri $deployFromGithubTemplate -TemplateParameterObject $webAppParameters
Write-Log "Finished Deploying Nusearch website" -ForegroundColor "green"
}
function Add-VNetGateway($resourceGroupName, $vnetName, $vnetIpName, $location, $vnetIpConfigName, $vnetGatewayName, $certificateData, $vnetPointToSiteAddressSpace) {
$gateway = Get-AzureRmVirtualNetworkGateway -Name $vnetGatewayName -ResourceGroupName $resourceGroupName -ErrorAction Ignore
if ($gateway -ne $null) {
Write-Log "Virtual Network Gateway $vnetGatewayName already exists. Using this." -ForegroundColor "green"
return
}
$vnet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $resourceGroupName
$subnet = Get-AzureRmVirtualNetworkSubnetConfig -Name "GatewaySubnet" -VirtualNetwork $vnet
Write-Log "Creating a public IP address for this Virtual Network"
$pip = New-AzureRmPublicIpAddress -Name $vnetIpName -ResourceGroupName $resourceGroupName -Location $location -AllocationMethod Dynamic
$ipconf = New-AzureRmVirtualNetworkGatewayIpConfig -Name $vnetIpConfigName -Subnet $subnet -PublicIpAddress $pip
Write-Log "Finished creating a public IP address for this Virtual Network" -ForegroundColor "green"
Write-Log "Adding a root certificate to this Virtual Network"
$root = New-AzureRmVpnClientRootCertificate -Name "AppServiceCertificate.cer" -PublicCertData $certificateData
Write-Log "Finished Adding a root certificate to this Virtual Network" -ForegroundColor "green"
Write-Log "Creating Virtual Network Gateway. This may take up to an hour."
$gateway = New-AzureRmVirtualNetworkGateway -Name $vnetGatewayName -ResourceGroupName $resourceGroupName `
-Location $location -IpConfigurations $ipconf -GatewayType Vpn -VpnType RouteBased -EnableBgp $false `
-GatewaySku Basic -VpnClientAddressPool $vnetPointToSiteAddressSpace -VpnClientRootCertificates $root
Write-Log "Finished creating Virtual Network Gateway" -ForegroundColor "green"
}
function Add-AppServiceToExistingVnet($subscriptionId, $webAppResourceGroup, $webAppName, $vnetName, $vnetResourceGroup) {
Write-Log "Getting App information"
$webApp = Get-AzureRmResource -ResourceName $webAppName -ResourceType "Microsoft.Web/sites" `
-ApiVersion 2015-08-01 -ResourceGroupName $webAppResourceGroup
$location = $webApp.Location
$webAppConfig = Get-AzureRmResource -ResourceName "$($webAppName)/web" -ResourceType "Microsoft.Web/sites/config" `
-ApiVersion 2015-08-01 -ResourceGroupName $webAppResourceGroup
$vnet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $vnetResourceGroup
# Virtual Network settings
$vnetName = $vnet.Name
$vnetGatewayName="$($vnetName)-gateway"
$vnetIpName="$($vnetName)-gateway-ip"
$vnetIpConfigName="$($vnetName)-gateway-ip-conf"
$vnetGatewayAddressSpace="10.0.0.128/28"
$vnetPointToSiteAddressSpace="172.16.0.0/16"
Write-Log "Creating Virtual Network Connection for website $webAppName to Virtual Network $($vnet.Name)"
$virtualNetworkParameters = @{
"vnetResourceId" = "/subscriptions/$($subscriptionId)/resourceGroups/$($vnet.ResourceGroupName)/providers/Microsoft.Network/virtualNetworks/$($vnetName)"
}
$virtualNetworkConnection = New-AzureRmResource -Location $location -Properties $virtualNetworkParameters -ResourceName "$($webAppName)/$($vnet.Name)" -ResourceType "Microsoft.Web/sites/virtualNetworkConnections" -ApiVersion 2015-08-01 -ResourceGroupName $webAppResourceGroup -Force
Write-Log "Virtual Network Connection created" -ForegroundColor "green"
$gatewaySubnet = Get-AzureRmVirtualNetworkSubnetConfig -Name "GatewaySubnet" -VirtualNetwork $vnet -ErrorAction Ignore
if ($gatewaySubnet -ne $null) {
Write-Log "GatewaySubnet already exists for Virtual Network $($vnet.Name). Using this." -ForegroundColor "green"
}
else {
Write-Log "Creating GatewaySubnet in Virtual Network $($vnet.Name)"
Add-AzureRmVirtualNetworkSubnetConfig -Name "GatewaySubnet" -AddressPrefix $vnetGatewayAddressSpace -VirtualNetwork $vnet
Set-AzureRmVirtualNetwork -VirtualNetwork $vnet
Write-Log "GatewaySubnet created in Virtual Network $($vnet.Name)" -ForegroundColor "green"
}
# Create the VNet Gateway
Add-VNetGateway $vnet.ResourceGroupName $vnetName $vnetIpName $location $vnetIpConfigName $vnetGatewayName $virtualNetworkConnection.Properties.CertBlob $vnetPointToSiteAddressSpace
$gateway = Get-AzureRmVirtualNetworkGateway -ResourceGroupName $vnet.ResourceGroupName -Name $vnetGatewayName
# Now finish joining by getting the VPN package and giving it to the App
Write-Log "Retrieving VPN Package and supplying to Web App"
$packageUri = Get-AzureRmVpnClientPackage -ResourceGroupName $vnet.ResourceGroupName -VirtualNetworkGatewayName $gateway.Name -ProcessorArchitecture Amd64
# Put the VPN client configuration package onto the App
$virtualNetworkGatewayParameters = @{
"vnetName" = $vnet.Name;
"vpnPackageUri" = $packageUri.ToString().Trim('"')
}
Write-Log "Adding website $webAppName to Virtual Network $($vnet.Name)"
New-AzureRmResource -Location $location -Properties $virtualNetworkGatewayParameters -ResourceName "$($webAppName)/$($vnet.Name)/primary" -ResourceType "Microsoft.Web/sites/virtualNetworkConnections/gateways" -ApiVersion 2015-08-01 -ResourceGroupName $webAppResourceGroup -Force
Write-Log "Finished adding website $webAppName to Virtual Network $($vnet.Name)" -ForegroundColor "green"
}
function Add-AppSettings($resourceGroupName, $webAppName, $appSettings) {
Write-Log "Updating App Settings for website"
$webApp = Get-AzureRMWebAppSlot -ResourceGroupName $resourceGroupName -Name $webAppName -Slot production
$existingAppSettings = $webApp.SiteConfig.AppSettings
$hash = @{}
foreach ($kvp in $existingAppSettings) {
$hash[$kvp.Name] = $kvp.Value
}
foreach ($kvp in $appSettings.GetEnumerator()) {
$hash[$kvp.Name] = $kvp.Value
}
Set-AzureRMWebAppSlot -ResourceGroupName $resourceGroupName -Name $webAppName -AppSettings $hash -Slot production
Write-Log "App Settings for website updated" -ForegroundColor "green"
}
##################
# Start of Process
##################
try {
if ($ClientId -and $ClientSecret -and $TenantId -and $SubscriptionId) {
$credential = new-object -typename System.Management.Automation.PSCredential `
-argumentlist $ClientId, $ClientSecret
Add-AzureRmAccount -Credential $credential -Tenant $TenantId -ServicePrincipal -ErrorAction Stop
}
Select-AzureRmSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop
}
catch {
Write-Host "Please Login"
Login-AzureRmAccount
$SubscriptionId = Show-Subscription
Select-AzureRmSubscription -SubscriptionId $SubscriptionId
}
$location = "Australia Southeast"
#################################################################################################
# Create the storage account, or use existing one if resource group with same name already exists
#################################################################################################
$storageAccountResourceGroup = "nusearch-storage"
$storageAccountName = "nusearchdata"
New-StorageAccount $storageAccountResourceGroup $storageAccountName $location
$storageAccountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $storageAccountResourceGroup -Name $storageAccountName
#########################################################################################
# Create the cluster, or use existing one if resource group with same name already exists
#########################################################################################
$templateVersion = "5.1.2"
$clusterResourceGroup = "nusearch-cluster"
$clusterName = "nusearch-cluster"
$templateUrl = "https://raw.githubusercontent.com/elastic/azure-marketplace/$templateVersion/src"
$mainTemplate = "$templateUrl/mainTemplate.json"
# parameters match those of the version of the template that we are targeting
$templateParameters = @{
"artifactsBaseUrl"= $templateUrl
"esClusterName" = $clusterName
"adminUsername" = $AdminUserName
"vNetLoadBalancerIp" = "10.0.0.4"
"vNetName" = "es-net"
"authenticationType" = "password"
"adminPassword" = $AdminPassword
"securityAdminPassword" = $SecurityAdminPassword
"securityReadPassword" = $SecurityReadPassword
"securityKibanaPassword" = $SecurityKibanaPassword
"azureCloudPlugin" = "Yes"
"azureCloudStorageAccountName" = $storageAccountName
"azureCloudStorageAccountKey" = $storageAccountKeys[0].Value
}
New-ElasticsearchCluster $clusterResourceGroup $clusterName $location $mainTemplate $templateParameters
#########################################################################################
# Create the website, or use existing one if resource group with same name already exists
#########################################################################################
$webAppResourceGroup = "nusearch-web"
$webAppName = "nusearch-app"
$webAppParameters = @{
"siteName" = $webAppName
"hostingPlanName" = "nusearch"
"sku" = "S1"
"workerSize" = "1"
"repoURL" = "https://github.com/elastic/elasticsearch-net-example.git"
"branch" = "5.x-deploy"
}
New-Website $webAppResourceGroup $webAppName $location $webAppParameters
########################################
# Add the website to the Virtual Network
########################################
Add-AppServiceToExistingVnet $subscriptionId $webAppResourceGroup $webAppName $templateParameters.vNetName $clusterResourceGroup
################################################################################
# Update the app settings for the website to point to the internal load balancer
################################################################################
$appSettings = @{
"ElasticClient:Host" = "$($templateParameters.vNetLoadBalancerIp)"
"ElasticClient:Username" = "es_read"
"ElasticClient:Password" = $SecurityReadPassword
}
Add-AppSettings $webAppResourceGroup $webAppName $appSettings
<#
TODO: automate these as part of the example
Configure azure repository for snapshots
----------------------------------------
PUT _snapshot/nusearchdata
{
"type": "azure",
"settings": {
"container": "backups"
}
}
POST _snapshot/nusearchdata/_verify
GET _snapshot/nusearchdata/_all
POST /_snapshot/nusearchdata/snapshot_1/_restore?wait_for_completion=true
Need to Sync Network in Azure Portal!
-------------------------------------
nusearch-web -> App Service Plan -> Networking -> VNet Integration -> click network name -> click Sync Network
#>