├── README.md ├── azure_monitor_logstash ├── README.md └── azure_monitor_logstash.ps1 ├── encrypted_communication_kibana └── encrypted_communication_kibana.ps1 ├── snapshot_restore └── snapshot_restore.ps1 ├── configure_disks └── configure_disks.ps1 ├── encrypted_communication_elasticsearch └── encrypted_communication_elasticsearch.ps1 ├── two_clusters_one_vnet └── two_clusters_one_vnet.ps1 └── cluster_azure-repository_app-service └── cluster_azure-repository_app-service.ps1 /README.md: -------------------------------------------------------------------------------- 1 | # Elastic ARM template examples 2 | 3 | Example scripts that demonstrate different deployment scenarios for [Elastic's ARM template](https://github.com/elastic/azure-marketplace) 4 | 5 | 1. [Storage account and Elasticsearch cluster. Set up the storage account for snapshot/restore](https://github.com/elastic/azure-marketplace-examples/tree/master/snapshot_restore) 6 | 7 | 2. [Configurable size of data node VM SKU, number of disks, their size and type of storage](https://github.com/elastic/azure-marketplace-examples/tree/master/configure_disks) 8 | 9 | 3. [Encrypted communication to Kibana](https://github.com/elastic/azure-marketplace-examples/tree/master/encrypted_communication_kibana) 10 | 11 | 4. [Encrypted communication to Elasticsearch with Application Gateway](https://github.com/elastic/azure-marketplace-examples/tree/master/encrypted_communication_elasticsearch) 12 | 13 | 5. [Two clusters connected to one virtual network](https://github.com/elastic/azure-marketplace-examples/tree/master/two_clusters_one_vnet) 14 | 15 | 6. [Storage account, Elasticsearch cluster and an Azure App Service (web app). Set up the storage account for snapshot/restore and add the App Service to the cluster virtual network](https://github.com/elastic/azure-marketplace-examples/tree/master/cluster_azure-repository_app-service) 16 | 17 | 7. [Elasticsearch, Logstash and Kibana with Logstash Azure Monitor. Sets up event hub namespace, storage account for Logstash read data and activity log profile to export events to event hubs](https://github.com/elastic/azure-marketplace-examples/tree/master/azure_monitor_logstash) 18 | -------------------------------------------------------------------------------- /azure_monitor_logstash/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Deploy a cluster configured with Logstash Azure Monitor module 3 | 4 | This script creates an Elasticsearch cluster along with an instance of Kibana and Logstash, to ingest activity logs from Azure Monitor. 5 | 6 | 3 resource groups are created 7 | 8 | - The Elastic Stack and resources 9 | - A storage account for persisting Logstash read data 10 | - An Event hub namespace 11 | 12 | Run the PowerShell script in this directory. Once the script has finished and deployed all necessary resources, 13 | a one-time set of operations need to be performed to setup the Azure Monitor module: 14 | 15 | 1. SSH into Logstash through Kibana VM 16 | 17 | ```sh 18 | ssh @ 19 | ``` 20 | 21 | Then SSH into the Logstash VM from the Kibana VM 22 | 23 | ```sh 24 | ssh logstash-0 25 | ``` 26 | 27 | 2. Stop the running Logstash service with systemctl 28 | 29 | ```sh 30 | sudo systemctl stop logstash.service 31 | ``` 32 | 33 | 3. Remove `path.config` setting from `/etc/logstash/logstash.yml`. The config file can't be used in conjunction with Azure modules 34 | 35 | ```sh 36 | sudo nano /etc/logstash/logstash.yml 37 | ``` 38 | 39 | 4. Need to run one time setup for Logstash module to export Dashboards to Kibana. 40 | 41 | Get the keystore password from `/etc/sysconfig/logstash` and export to environment variables 42 | 43 | ```sh 44 | logstashPass=$(sudo grep -Po "(?<=^LOGSTASH_KEYSTORE_PASS=).*" /etc/sysconfig/logstash | sed 's/"//g') 45 | 46 | export LOGSTASH_KEYSTORE_PASS="$logstashPass" 47 | ``` 48 | 49 | 5. Run the Logstash setup with logstash user, passing environment variables 50 | 51 | ```sh 52 | sudo -Eu logstash /usr/share/logstash/bin/logstash --path.settings /etc/logstash --setup 53 | ``` 54 | 55 | 6. Once `[Azure Monitor]` Dashboards appear under the Dashboard tab in Kibana, stop Logstash with `CTRL+C`, as we're going to restart 56 | it as a service managed by systemd next. 57 | 58 | 7. Start Logstash service with systemctl 59 | 60 | ```sh 61 | sudo systemctl start logstash.service 62 | ``` -------------------------------------------------------------------------------- /encrypted_communication_kibana/encrypted_communication_kibana.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Deploys an Elasticsearch cluster with Transport Layer Security to Kibana 4 | .Example 5 | & .\encrypted_communication_kibana.ps1 -AdminUserName "russ" ` 6 | -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 7 | -CertPath "C:\cert.crt" -KeyPath "C:\cert.key" ` 8 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 9 | -SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 10 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) 11 | .Example 12 | & .\encrypted_communication_kibana.ps1 -ClientId "clientid" ` 13 | -ClientSecret $(ConvertTo-SecureString -String "clientsecret" -AsPlainText -Force) ` 14 | -TenantId "tenantid" -SubscriptionId "subscriptionid" ` 15 | -CertPath "C:\cert.crt" -KeyPath "C:\cert.key" ` 16 | -AdminUserName "russ" -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 17 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 18 | -SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 19 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) 20 | .Parameter ClientId 21 | the client id to log in with a Service Principal 22 | .Parameter ClientSecret 23 | the client secret to log in with a Service Principal 24 | .Parameter TenantId 25 | the tenant id to log in with a Service Principal 26 | .Parameter SubscriptionId 27 | the subscription id to deploy the resources to. If the current session is not logged into the Azure account, user will 28 | be prompted to log in and select a SubscriptionId 29 | .Parameter CertPath 30 | the path to the certificate to use to encrypt communication with Kibana 31 | .Parameter KeyPath 32 | the path to the private key to use to encrypt communication with Kibana 33 | .Parameter AdminUserName 34 | the admin username in order to log into VMs deployed in the Elasticsearch cluster 35 | .Parameter AdminPassword 36 | the admin password in order to log into VMs deployed in the Elasticsearch cluster 37 | .Parameter SecurityAdminPassword 38 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_admin' (2.x) or 'elastic' (5.x) 39 | .Parameter SecurityReadPassword 40 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_read' 41 | .Parameter SecurityKibanaPassword 42 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_kibana' 43 | #> 44 | [CmdletBinding()] 45 | Param( 46 | [Parameter(Mandatory=$false)] 47 | [string] $ClientId, 48 | 49 | [Parameter(Mandatory=$false)] 50 | [securestring] $ClientSecret, 51 | 52 | [Parameter(Mandatory=$false)] 53 | [string] $TenantId, 54 | 55 | [Parameter(Mandatory=$false)] 56 | [string] $SubscriptionId, 57 | 58 | [Parameter(Mandatory=$true)] 59 | [string] $CertPath, 60 | 61 | [Parameter(Mandatory=$true)] 62 | [string] $KeyPath, 63 | 64 | [Parameter(Mandatory=$true)] 65 | [string] $AdminUserName, 66 | 67 | [Parameter(Mandatory=$true)] 68 | [securestring] $AdminPassword, 69 | 70 | [Parameter(Mandatory=$true)] 71 | [securestring] $SecurityAdminPassword, 72 | 73 | [Parameter(Mandatory=$true)] 74 | [securestring] $SecurityReadPassword, 75 | 76 | [Parameter(Mandatory=$true)] 77 | [securestring] $SecurityKibanaPassword 78 | ) 79 | $ErrorActionPreference = "Stop" 80 | 81 | function Write-Log($Message, $ForegroundColor) { 82 | if ($ForegroundColor -eq $null) { 83 | $ForegroundColor = "White" 84 | } 85 | 86 | Write-Host "[$(Get-Date -format 'u')] $message" -ForegroundColor $ForegroundColor 87 | } 88 | 89 | function Show-Custom($title, $optionValues, $optionDescriptions) { 90 | Write-Host $title 91 | Write-Host 92 | for($i = 0; $i -lt $optionValues.Length; $i++) { 93 | Write-Host "$($i+1))" $optionDescriptions[$i] 94 | } 95 | Write-Host 96 | 97 | while($true) { 98 | Write-Host "Choose an option: " 99 | $option = Read-Host 100 | $option = $option -as [int] 101 | 102 | if($option -ge 1 -and $option -le $optionValues.Length) { 103 | return $optionValues[$option-1] 104 | } 105 | } 106 | } 107 | 108 | function Show-Subscription() { 109 | # Choose subscription. If there's only one we will choose automatically 110 | $subs = Get-AzureRmSubscription 111 | $subscriptionId = "" 112 | 113 | if($subs.Length -eq 0) { 114 | Write-Error "No subscriptions bound to this account." 115 | return 116 | } 117 | 118 | if($subs.Length -eq 1) { 119 | $subscriptionId = $subs[0].SubscriptionId 120 | } 121 | else { 122 | $subscriptionChoices = @() 123 | $subscriptionValues = @() 124 | 125 | foreach($subscription in $subs) { 126 | $subscriptionChoices += "$($subscription.SubscriptionName) ($($subscription.SubscriptionId))"; 127 | $subscriptionValues += ($subscription.SubscriptionId); 128 | } 129 | 130 | $subscriptionId = Show-Custom "Choose a subscription" $subscriptionValues $subscriptionChoices 131 | } 132 | 133 | return $subscriptionId 134 | } 135 | 136 | try { 137 | if ($ClientId -and $ClientSecret -and $TenantId -and $SubscriptionId) { 138 | $credential = new-object -typename System.Management.Automation.PSCredential ` 139 | -argumentlist $ClientId, $ClientSecret 140 | 141 | Add-AzureRmAccount -Credential $credential -Tenant $TenantId -ServicePrincipal -ErrorAction Stop 142 | } 143 | 144 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop 145 | } 146 | catch { 147 | Write-Host "Please Login" 148 | Login-AzureRmAccount 149 | $SubscriptionId = Show-Subscription 150 | Select-AzureRmSubscription-SubscriptionId $SubscriptionId 151 | } 152 | 153 | $templateVersion = "5.1.2" 154 | $templateUrl = "https://raw.githubusercontent.com/elastic/azure-marketplace/$templateVersion/src" 155 | $mainTemplate = "$templateUrl/mainTemplate.json" 156 | $location = "Australia Southeast" 157 | $resourceGroup = "encrypted-kibana-cluster" 158 | $name = "elasticsearch" 159 | $kibanaCert = [Convert]::ToBase64String([System.IO.File]::ReadAllBytes($CertPath)) 160 | $kibanaKey = [Convert]::ToBase64String([System.IO.File]::ReadAllBytes($KeyPath)) 161 | 162 | $templateParameters = @{ 163 | "artifactsBaseUrl"= $templateUrl 164 | "esClusterName" = $name 165 | "kibanaCertBlob" = $kibanaCert 166 | "kibanaKeyBlob" = $kibanaKey 167 | "adminUsername" = $AdminUserName 168 | "authenticationType" = "password" 169 | "adminPassword" = $AdminPassword 170 | "securityAdminPassword" = $SecurityAdminPassword 171 | "securityReadPassword" = $SecurityReadPassword 172 | "securityKibanaPassword" = $SecurityKibanaPassword 173 | } 174 | 175 | Write-Log "Deploying Elasticsearch cluster" 176 | New-AzureRmResourceGroup -Name $resourceGroup -Location $location 177 | $deployment = New-AzureRmResourceGroupDeployment -Name $name -ResourceGroupName $resourceGroup ` 178 | -TemplateUri $mainTemplate -TemplateParameterObject $templateParameters 179 | Write-Log "Elasticsearch cluster deployed" -ForegroundColor "green" 180 | Start-Process $deployment.Outputs.kibana.Value -------------------------------------------------------------------------------- /snapshot_restore/snapshot_restore.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Deploys an Azure Storage Account and Elasticsearch cluster. 4 | .Description 5 | The Storage account is configured with the azure-repository plugin to be used for snapshot/restore for the Elasticsearch cluster. 6 | .Example 7 | & .\snapshot_restore.ps1 -AdminUserName "russ" ` 8 | -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 9 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 10 | -SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 11 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) 12 | .Example 13 | & .\snapshot_restore.ps1 -ClientId "clientid" ` 14 | -ClientSecret $(ConvertTo-SecureString -String "clientsecret" -AsPlainText -Force) ` 15 | -TenantId "tenantid" -SubscriptionId "subscriptionid" ` 16 | -AdminUserName "russ" -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 17 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 18 | -SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 19 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) 20 | .Parameter ClientId 21 | the client id to log in with a Service Principal 22 | .Parameter ClientSecret 23 | the client secret to log in with a Service Principal 24 | .Parameter TenantId 25 | the tenant id to log in with a Service Principal 26 | .Parameter SubscriptionId 27 | the subscription id to deploy the resources to. If the current session is not logged into the Azure account, user will 28 | be prompted to log in and select a SubscriptionId 29 | .Parameter AdminUserName 30 | the admin username in order to log into VMs deployed in the Elasticsearch cluster 31 | .Parameter AdminPassword 32 | the admin password in order to log into VMs deployed in the Elasticsearch cluster 33 | .Parameter SecurityAdminPassword 34 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_admin' (2.x) or 'elastic' (5.x) 35 | .Parameter SecurityReadPassword 36 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_read' 37 | .Parameter SecurityKibanaPassword 38 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_kibana' 39 | #> 40 | [CmdletBinding()] 41 | Param( 42 | [Parameter(Mandatory=$false)] 43 | [string] $ClientId, 44 | 45 | [Parameter(Mandatory=$false)] 46 | [securestring] $ClientSecret, 47 | 48 | [Parameter(Mandatory=$false)] 49 | [string] $TenantId, 50 | 51 | [Parameter(Mandatory=$false)] 52 | [string] $SubscriptionId, 53 | 54 | [Parameter(Mandatory=$true)] 55 | [string] $AdminUserName, 56 | 57 | [Parameter(Mandatory=$true)] 58 | [securestring] $AdminPassword, 59 | 60 | [Parameter(Mandatory=$true)] 61 | [securestring] $SecurityAdminPassword, 62 | 63 | [Parameter(Mandatory=$true)] 64 | [securestring] $SecurityReadPassword, 65 | 66 | [Parameter(Mandatory=$true)] 67 | [securestring] $SecurityKibanaPassword 68 | ) 69 | $ErrorActionPreference = "Stop" 70 | 71 | function Write-Log($Message, $ForegroundColor) { 72 | if ($ForegroundColor -eq $null) { 73 | $ForegroundColor = "White" 74 | } 75 | 76 | Write-Host "[$(Get-Date -format 'u')] $message" -ForegroundColor $ForegroundColor 77 | } 78 | 79 | function Show-Custom($title, $optionValues, $optionDescriptions) { 80 | Write-Host $title 81 | Write-Host 82 | for($i = 0; $i -lt $optionValues.Length; $i++) { 83 | Write-Host "$($i+1))" $optionDescriptions[$i] 84 | } 85 | Write-Host 86 | 87 | while($true) { 88 | Write-Host "Choose an option: " 89 | $option = Read-Host 90 | $option = $option -as [int] 91 | 92 | if($option -ge 1 -and $option -le $optionValues.Length) { 93 | return $optionValues[$option-1] 94 | } 95 | } 96 | } 97 | 98 | function Show-Subscription() { 99 | # Choose subscription. If there's only one we will choose automatically 100 | $subs = Get-AzureRmSubscription 101 | $subscriptionId = "" 102 | 103 | if($subs.Length -eq 0) { 104 | Write-Error "No subscriptions bound to this account." 105 | return 106 | } 107 | 108 | if($subs.Length -eq 1) { 109 | $subscriptionId = $subs[0].SubscriptionId 110 | } 111 | else { 112 | $subscriptionChoices = @() 113 | $subscriptionValues = @() 114 | 115 | foreach($subscription in $subs) { 116 | $subscriptionChoices += "$($subscription.SubscriptionName) ($($subscription.SubscriptionId))"; 117 | $subscriptionValues += ($subscription.SubscriptionId); 118 | } 119 | 120 | $subscriptionId = Show-Custom "Choose a subscription" $subscriptionValues $subscriptionChoices 121 | } 122 | 123 | return $subscriptionId 124 | } 125 | 126 | try { 127 | if ($ClientId -and $ClientSecret -and $TenantId -and $SubscriptionId) { 128 | $credential = new-object -typename System.Management.Automation.PSCredential ` 129 | -argumentlist $ClientId, $ClientSecret 130 | 131 | Add-AzureRmAccount -Credential $credential -Tenant $TenantId -ServicePrincipal -ErrorAction Stop 132 | } 133 | 134 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop 135 | } 136 | catch { 137 | Write-Host "Please Login" 138 | Login-AzureRmAccount 139 | $SubscriptionId = Show-Subscription 140 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId 141 | } 142 | 143 | $location = "Australia Southeast" 144 | $storageResourceGroup = "storage-account" 145 | $storageAccountName = "esclusterbackups" 146 | 147 | Write-Log "Creating storage account" 148 | New-AzureRmResourceGroup -Name $storageResourceGroup -Location $location 149 | New-AzureRmStorageAccount -ResourceGroupName $storageResourceGroup ` 150 | -AccountName $storageAccountName -Type "Standard_LRS" -Location $location 151 | Write-Log "Storage account created" -ForegroundColor "green" 152 | 153 | $storageAccountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $storageResourceGroup ` 154 | -Name $storageAccountName 155 | $templateVersion = "5.1.2" 156 | $templateUrl = "https://raw.githubusercontent.com/elastic/azure-marketplace/$templateVersion/src" 157 | $mainTemplate = "$templateUrl/mainTemplate.json" 158 | $resourceGroup = "repository-cluster" 159 | $name = "elasticsearch" 160 | 161 | $templateParameters = @{ 162 | "artifactsBaseUrl"= $templateUrl 163 | "esClusterName" = $name 164 | "adminUsername" = $AdminUserName 165 | "authenticationType" = "password" 166 | "adminPassword" = $AdminPassword 167 | "securityAdminPassword" = $SecurityAdminPassword 168 | "securityReadPassword" = $SecurityReadPassword 169 | "securityKibanaPassword" = $SecurityKibanaPassword 170 | "azureCloudPlugin" = "Yes" 171 | "azureCloudStorageAccountName" = $storageAccountName 172 | "azureCloudStorageAccountKey" = $storageAccountKeys[0].Value 173 | } 174 | 175 | Write-Log "Creating Elasticsearch cluster" 176 | New-AzureRmResourceGroup -Name $resourceGroup -Location $location 177 | New-AzureRmResourceGroupDeployment -Name $name -ResourceGroupName $resourceGroup ` 178 | -TemplateUri $mainTemplate -TemplateParameterObject $templateParameters 179 | Write-Log "Elasticsearch cluster created" -ForegroundColor "green" -------------------------------------------------------------------------------- /configure_disks/configure_disks.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Deploys an Elasticsearch cluster with a configurable number of disks and sizes 4 | .Example 5 | & .\configure_disks.ps1 -DataNodeVms "Standard_D1" -DiskCount 2 -DiskSize Small -StorageType Standard ` 6 | -AdminUserName "russ" -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 7 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 8 | -SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 9 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) 10 | .Example 11 | & .\configure_disks.ps1 -DataNodeVms "Standard_D1" -DiskCount 2 -DiskSize Small -StorageType Standard ` 12 | -ClientId "clientid" -ClientSecret $(ConvertTo-SecureString -String "clientsecret" -AsPlainText -Force) ` 13 | -TenantId "tenantid" -SubscriptionId "subscriptionid" ` 14 | -AdminUserName "russ" -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 15 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 16 | -SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 17 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) 18 | .Parameter ClientId 19 | the client id to log in with a Service Principal 20 | .Parameter ClientSecret 21 | the client secret to log in with a Service Principal 22 | .Parameter TenantId 23 | the tenant id to log in with a Service Principal 24 | .Parameter SubscriptionId 25 | the subscription id to deploy the resources to. If the current session is not logged into the Azure account, user will 26 | be prompted to log in and select a SubscriptionId 27 | .Parameter DataNodeVms 28 | The name of the VM SKU to use for data nodes 29 | .Parameter DiskCount 30 | The number of disks to attach to each VM 31 | .Parameter DiskSize 32 | The size of the disks 33 | .Parameter StorageType 34 | The type of storage. Default will be Premium storage for thos VM SKUs that support it. 35 | .Parameter AdminUserName 36 | the admin username in order to log into VMs deployed in the Elasticsearch cluster 37 | .Parameter AdminPassword 38 | the admin password in order to log into VMs deployed in the Elasticsearch cluster 39 | .Parameter SecurityAdminPassword 40 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_admin' (2.x) or 'elastic' (5.x) 41 | .Parameter SecurityReadPassword 42 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_read' 43 | .Parameter SecurityKibanaPassword 44 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_kibana' 45 | #> 46 | [CmdletBinding()] 47 | Param( 48 | [Parameter(Mandatory=$false)] 49 | [string] $ClientId, 50 | 51 | [Parameter(Mandatory=$false)] 52 | [securestring] $ClientSecret, 53 | 54 | [Parameter(Mandatory=$false)] 55 | [string] $TenantId, 56 | 57 | [Parameter(Mandatory=$false)] 58 | [string] $SubscriptionId, 59 | 60 | [Parameter(Mandatory=$true)] 61 | [string] $DataNodeVms, 62 | 63 | [Parameter(Mandatory=$true)] 64 | [int][ValidateSet(0,1,2,4,8,16,32,40)] $DiskCount, 65 | 66 | [Parameter(Mandatory=$true)] 67 | [string][ValidateSet("Small","Medium","Large")] $DiskSize, 68 | 69 | [Parameter(Mandatory=$true)] 70 | [string][ValidateSet("Default","Standard")] $StorageType, 71 | 72 | [Parameter(Mandatory=$true)] 73 | [string] $AdminUserName, 74 | 75 | [Parameter(Mandatory=$true)] 76 | [securestring] $AdminPassword, 77 | 78 | [Parameter(Mandatory=$true)] 79 | [securestring] $SecurityAdminPassword, 80 | 81 | [Parameter(Mandatory=$true)] 82 | [securestring] $SecurityReadPassword, 83 | 84 | [Parameter(Mandatory=$true)] 85 | [securestring] $SecurityKibanaPassword 86 | ) 87 | $ErrorActionPreference = "Stop" 88 | 89 | function Write-Log($Message, $ForegroundColor) { 90 | if ($ForegroundColor -eq $null) { 91 | $ForegroundColor = "White" 92 | } 93 | 94 | Write-Host "[$(Get-Date -format 'u')] $message" -ForegroundColor $ForegroundColor 95 | } 96 | 97 | function Show-Custom($title, $optionValues, $optionDescriptions) { 98 | Write-Host $title 99 | Write-Host 100 | for($i = 0; $i -lt $optionValues.Length; $i++) { 101 | Write-Host "$($i+1))" $optionDescriptions[$i] 102 | } 103 | Write-Host 104 | 105 | while($true) { 106 | Write-Host "Choose an option: " 107 | $option = Read-Host 108 | $option = $option -as [int] 109 | 110 | if($option -ge 1 -and $option -le $optionValues.Length) { 111 | return $optionValues[$option-1] 112 | } 113 | } 114 | } 115 | 116 | function Show-Subscription() { 117 | # Choose subscription. If there's only one we will choose automatically 118 | $subs = Get-AzureRmSubscription 119 | $subscriptionId = "" 120 | 121 | if($subs.Length -eq 0) { 122 | Write-Error "No subscriptions bound to this account." 123 | return 124 | } 125 | 126 | if($subs.Length -eq 1) { 127 | $subscriptionId = $subs[0].SubscriptionId 128 | } 129 | else { 130 | $subscriptionChoices = @() 131 | $subscriptionValues = @() 132 | 133 | foreach($subscription in $subs) { 134 | $subscriptionChoices += "$($subscription.SubscriptionName) ($($subscription.SubscriptionId))"; 135 | $subscriptionValues += ($subscription.SubscriptionId); 136 | } 137 | 138 | $subscriptionId = Show-Custom "Choose a subscription" $subscriptionValues $subscriptionChoices 139 | } 140 | 141 | return $subscriptionId 142 | } 143 | 144 | try { 145 | if ($ClientId -and $ClientSecret -and $TenantId -and $SubscriptionId) { 146 | $credential = new-object -typename System.Management.Automation.PSCredential ` 147 | -argumentlist $ClientId, $ClientSecret 148 | 149 | Add-AzureRmAccount -Credential $credential -Tenant $TenantId -ServicePrincipal -ErrorAction Stop 150 | } 151 | 152 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop 153 | } 154 | catch { 155 | Write-Host "Please Login" 156 | Login-AzureRmAccount 157 | $SubscriptionId = Show-Subscription 158 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId 159 | } 160 | 161 | $location = "Australia Southeast" 162 | $templateVersion = "5.1.2" 163 | $templateUrl = "https://raw.githubusercontent.com/elastic/azure-marketplace/$templateVersion/src" 164 | $mainTemplate = "$templateUrl/mainTemplate.json" 165 | $resourceGroup = "configure-disks" 166 | $name = "elasticsearch" 167 | 168 | $templateParameters = @{ 169 | "artifactsBaseUrl"= $templateUrl 170 | "esClusterName" = $name 171 | "adminUsername" = $AdminUserName 172 | "authenticationType" = "password" 173 | "adminPassword" = $AdminPassword 174 | "securityAdminPassword" = $SecurityAdminPassword 175 | "securityReadPassword" = $SecurityReadPassword 176 | "securityKibanaPassword" = $SecurityKibanaPassword 177 | "vmSizeDataNodes" = $DataNodeVms 178 | "vmDataDiskCount" = $DiskCount 179 | "vmDataDiskSize" = $DiskSize 180 | "storageAccountType" = $StorageType 181 | } 182 | 183 | Write-Log "Deploying Elasticsearch cluster" 184 | New-AzureRmResourceGroup -Name $resourceGroup -Location $location 185 | New-AzureRmResourceGroupDeployment -Name $name -ResourceGroupName $resourceGroup ` 186 | -TemplateUri $mainTemplate -TemplateParameterObject $templateParameters 187 | Write-Log "Deployed Elasticsearch cluster" -ForegroundColor "green" -------------------------------------------------------------------------------- /encrypted_communication_elasticsearch/encrypted_communication_elasticsearch.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Deploys an Elasticsearch cluster with Transport Layer Security to Elasticsearch 4 | .Description 5 | Uses Application Gateway for external access and SSL offload 6 | .Example 7 | & .\encrypted_communication_elasticsearch.ps1 -AdminUserName "russ" ` 8 | -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 9 | -CertPath "C:\cert.pfx" -CertPassword $(ConvertTo-SecureString -String "Password" -AsPlainText -Force) ` 10 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 11 | -SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 12 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) 13 | .Example 14 | & .\encrypted_communication_elasticsearch.ps1 -ClientId "clientid" ` 15 | -ClientSecret $(ConvertTo-SecureString -String "clientsecret" -AsPlainText -Force) ` 16 | -TenantId "tenantid" -SubscriptionId "subscriptionid" ` 17 | -CertPath "C:\cert.pfx" -CertPassword $(ConvertTo-SecureString -String "Password" -AsPlainText -Force) ` 18 | -AdminUserName "russ" -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 19 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 20 | -SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 21 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) 22 | .Parameter ClientId 23 | the client id to log in with a Service Principal 24 | .Parameter ClientSecret 25 | the client secret to log in with a Service Principal 26 | .Parameter TenantId 27 | the tenant id to log in with a Service Principal 28 | .Parameter SubscriptionId 29 | the subscription id to deploy the resources to. If the current session is not logged into the Azure account, user will 30 | be prompted to log in and select a SubscriptionId 31 | .Parameter CertPath 32 | the path to the certificate to use to encrypt communication with Application Gateway 33 | .Parameter CertPassword 34 | the password for the certificate. Optional as may not have a password 35 | .Parameter AdminUserName 36 | the admin username in order to log into VMs deployed in the Elasticsearch cluster 37 | .Parameter AdminPassword 38 | the admin password in order to log into VMs deployed in the Elasticsearch cluster 39 | .Parameter SecurityAdminPassword 40 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_admin' (2.x) or 'elastic' (5.x) 41 | .Parameter SecurityReadPassword 42 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_read' 43 | .Parameter SecurityKibanaPassword 44 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_kibana' 45 | #> 46 | [CmdletBinding()] 47 | Param( 48 | [Parameter(Mandatory=$false)] 49 | [string] $ClientId, 50 | 51 | [Parameter(Mandatory=$false)] 52 | [securestring] $ClientSecret, 53 | 54 | [Parameter(Mandatory=$false)] 55 | [string] $TenantId, 56 | 57 | [Parameter(Mandatory=$false)] 58 | [string] $SubscriptionId, 59 | 60 | [Parameter(Mandatory=$true)] 61 | [string] $CertPath, 62 | 63 | [Parameter(Mandatory=$false)] 64 | [securestring] $CertPassword, 65 | 66 | [Parameter(Mandatory=$true)] 67 | [string] $KeyPath, 68 | 69 | [Parameter(Mandatory=$true)] 70 | [string] $AdminUserName, 71 | 72 | [Parameter(Mandatory=$true)] 73 | [securestring] $AdminPassword, 74 | 75 | [Parameter(Mandatory=$true)] 76 | [securestring] $SecurityAdminPassword, 77 | 78 | [Parameter(Mandatory=$true)] 79 | [securestring] $SecurityReadPassword, 80 | 81 | [Parameter(Mandatory=$true)] 82 | [securestring] $SecurityKibanaPassword 83 | ) 84 | $ErrorActionPreference = "Stop" 85 | 86 | function Write-Log($Message, $ForegroundColor) { 87 | if ($ForegroundColor -eq $null) { 88 | $ForegroundColor = "White" 89 | } 90 | 91 | Write-Host "[$(Get-Date -format 'u')] $message" -ForegroundColor $ForegroundColor 92 | } 93 | 94 | function Show-Custom($title, $optionValues, $optionDescriptions) { 95 | Write-Host $title 96 | Write-Host 97 | for($i = 0; $i -lt $optionValues.Length; $i++) { 98 | Write-Host "$($i+1))" $optionDescriptions[$i] 99 | } 100 | Write-Host 101 | 102 | while($true) { 103 | Write-Host "Choose an option: " 104 | $option = Read-Host 105 | $option = $option -as [int] 106 | 107 | if($option -ge 1 -and $option -le $optionValues.Length) { 108 | return $optionValues[$option-1] 109 | } 110 | } 111 | } 112 | 113 | function Show-Subscription() { 114 | # Choose subscription. If there's only one we will choose automatically 115 | $subs = Get-AzureRmSubscription 116 | $subscriptionId = "" 117 | 118 | if($subs.Length -eq 0) { 119 | Write-Error "No subscriptions bound to this account." 120 | return 121 | } 122 | 123 | if($subs.Length -eq 1) { 124 | $subscriptionId = $subs[0].SubscriptionId 125 | } 126 | else { 127 | $subscriptionChoices = @() 128 | $subscriptionValues = @() 129 | 130 | foreach($subscription in $subs) { 131 | $subscriptionChoices += "$($subscription.SubscriptionName) ($($subscription.SubscriptionId))"; 132 | $subscriptionValues += ($subscription.SubscriptionId); 133 | } 134 | 135 | $subscriptionId = Show-Custom "Choose a subscription" $subscriptionValues $subscriptionChoices 136 | } 137 | 138 | return $subscriptionId 139 | } 140 | 141 | try { 142 | if ($ClientId -and $ClientSecret -and $TenantId -and $SubscriptionId) { 143 | $credential = new-object -typename System.Management.Automation.PSCredential ` 144 | -argumentlist $ClientId, $ClientSecret 145 | 146 | Add-AzureRmAccount -Credential $credential -Tenant $TenantId -ServicePrincipal -ErrorAction Stop 147 | } 148 | 149 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop 150 | } 151 | catch { 152 | Write-Host "Please Login" 153 | Login-AzureRmAccount 154 | $SubscriptionId = Show-Subscription 155 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId 156 | } 157 | 158 | $templateVersion = "5.1.2" 159 | $templateUrl = "https://raw.githubusercontent.com/elastic/azure-marketplace/$templateVersion/src" 160 | $mainTemplate = "$templateUrl/mainTemplate.json" 161 | $location = "Australia Southeast" 162 | $resourceGroup = "app-gateway-cluster" 163 | $name = "elasticsearch" 164 | $gatewayCert = [Convert]::ToBase64String([System.IO.File]::ReadAllBytes($CertPath)) 165 | 166 | $templateParameters = @{ 167 | "artifactsBaseUrl"= $templateUrl 168 | "esClusterName" = $name 169 | "loadBalancerType" = "gateway" 170 | "appGatewayCertBlob" = $gatewayCert 171 | "appGatewayCertPassword" = $CertPassword 172 | "adminUsername" = $AdminUserName 173 | "authenticationType" = "password" 174 | "adminPassword" = $AdminPassword 175 | "securityAdminPassword" = $SecurityAdminPassword 176 | "securityReadPassword" = $SecurityReadPassword 177 | "securityKibanaPassword" = $SecurityKibanaPassword 178 | } 179 | 180 | Write-Log "Deploying Elasticsearch cluster" 181 | New-AzureRmResourceGroup -Name $resourceGroup -Location $location 182 | New-AzureRmResourceGroupDeployment -Name $name -ResourceGroupName $resourceGroup -TemplateUri $mainTemplate -TemplateParameterObject $templateParameters 183 | Write-Log "Elasticsearch cluster deployed" -ForegroundColor "green" -------------------------------------------------------------------------------- /two_clusters_one_vnet/two_clusters_one_vnet.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Deploys two Elasticsearch clusters into a separate Virtual Network 4 | .Example 5 | & .\two_clusters_one_vnet.ps1 -AdminUserName "russ" ` 6 | -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 7 | -SecurityBootstrapPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 8 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 9 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 10 | -SecurityLogstashPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 11 | -SecurityBeatsPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 12 | -SecurityApmPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 13 | -SecurityRemoteMonitoringPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) 14 | .Example 15 | & .\two_clusters_one_vnet.ps1 -ClientId "clientid" ` 16 | -ClientSecret $(ConvertTo-SecureString -String "clientsecret" -AsPlainText -Force) ` 17 | -TenantId "tenantid" -SubscriptionId "subscriptionid" ` 18 | -AdminUserName "russ" -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 19 | -SecurityBootstrapPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 20 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 21 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 22 | -SecurityLogstashPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 23 | -SecurityBeatsPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 24 | -SecurityApmPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 25 | -SecurityRemoteMonitoringPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) 26 | .Parameter ClientId 27 | the client id to log in with a Service Principal 28 | .Parameter ClientSecret 29 | the client secret to log in with a Service Principal 30 | .Parameter TenantId 31 | the tenant id to log in with a Service Principal 32 | .Parameter SubscriptionId 33 | the subscription id to deploy the resources to. If the current session is not logged into the Azure account, user will 34 | be prompted to log in and select a SubscriptionId 35 | .Parameter AdminUserName 36 | the admin username in order to log into VMs deployed in the Elasticsearch cluster 37 | .Parameter AdminPassword 38 | the admin password in order to log into VMs deployed in the Elasticsearch cluster 39 | .Parameter SecurityBootstrapPassword 40 | the password to bootstrap an Elasticsearch cluster 41 | .Parameter SecurityAdminPassword 42 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'elastic' 43 | .Parameter SecurityKibanaPassword 44 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'kibana' 45 | .Parameter SecurityLogstashPassword 46 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'logstash_system' 47 | .Parameter SecurityBeatsPassword 48 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'beats_system' 49 | .Parameter SecurityApmPassword 50 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'apm_system' 51 | .Parameter SecurityRemoteMonitoringPassword 52 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'remote_monitoring_user' 53 | #> 54 | [CmdletBinding()] 55 | Param( 56 | [Parameter(Mandatory=$false)] 57 | [string] $ClientId, 58 | 59 | [Parameter(Mandatory=$false)] 60 | [securestring] $ClientSecret, 61 | 62 | [Parameter(Mandatory=$false)] 63 | [string] $TenantId, 64 | 65 | [Parameter(Mandatory=$false)] 66 | [string] $SubscriptionId, 67 | 68 | [Parameter(Mandatory=$true)] 69 | [string] $AdminUserName, 70 | 71 | [Parameter(Mandatory=$true)] 72 | [securestring] $AdminPassword, 73 | 74 | [Parameter(Mandatory=$true)] 75 | [securestring] $SecurityBootstrapPassword, 76 | 77 | [Parameter(Mandatory=$true)] 78 | [securestring] $SecurityAdminPassword, 79 | 80 | [Parameter(Mandatory=$true)] 81 | [securestring] $SecurityKibanaPassword, 82 | 83 | [Parameter(Mandatory=$true)] 84 | [securestring] $SecurityLogstashPassword, 85 | 86 | [Parameter(Mandatory=$true)] 87 | [securestring] $SecurityBeatsPassword, 88 | 89 | [Parameter(Mandatory=$true)] 90 | [securestring] $SecurityApmPassword, 91 | 92 | [Parameter(Mandatory=$true)] 93 | [securestring] $SecurityRemoteMonitoringPassword 94 | ) 95 | $ErrorActionPreference = "Stop" 96 | 97 | function Write-Log($Message, $ForegroundColor) { 98 | if ($null -eq $ForegroundColor) { 99 | $ForegroundColor = "White" 100 | } 101 | 102 | Write-Host "[$(Get-Date -format 'u')] $message" -ForegroundColor $ForegroundColor 103 | } 104 | 105 | function Show-Custom($title, $optionValues, $optionDescriptions) { 106 | Write-Host $title 107 | Write-Host 108 | for($i = 0; $i -lt $optionValues.Length; $i++) { 109 | Write-Host "$($i+1))" $optionDescriptions[$i] 110 | } 111 | Write-Host 112 | 113 | while($true) { 114 | Write-Host "Choose an option: " 115 | $option = Read-Host 116 | $option = $option -as [int] 117 | 118 | if($option -ge 1 -and $option -le $optionValues.Length) { 119 | return $optionValues[$option-1] 120 | } 121 | } 122 | } 123 | 124 | function Show-Subscription() { 125 | # Choose subscription. If there's only one we will choose automatically 126 | $subs = Get-AzureRmSubscription 127 | $subscriptionId = "" 128 | 129 | if($subs.Length -eq 0) { 130 | Write-Error "No subscriptions bound to this account." 131 | return 132 | } 133 | 134 | if($subs.Length -eq 1) { 135 | $subscriptionId = $subs[0].Id 136 | } 137 | else { 138 | $subscriptionChoices = @() 139 | $subscriptionValues = @() 140 | 141 | foreach($subscription in $subs) { 142 | $subscriptionChoices += "$($subscription.Name) ($($subscription.Id))"; 143 | $subscriptionValues += ($subscription.Id); 144 | } 145 | 146 | $subscriptionId = Show-Custom "Choose a subscription" $subscriptionValues $subscriptionChoices 147 | } 148 | 149 | return $subscriptionId 150 | } 151 | 152 | function ConvertTo-UInt32 ([IPAddress]$IpAddress) { 153 | $bytes = $IpAddress.GetAddressBytes() 154 | if ([BitConverter]::IsLittleEndian) { 155 | [Array]::Reverse($bytes) 156 | } 157 | return [BitConverter]::ToUInt32($bytes, 0) 158 | } 159 | 160 | function ConvertTo-IpAddress([UInt32]$UInt32) { 161 | $bytes = [BitConverter]::GetBytes($UInt32) 162 | if ([BitConverter]::IsLittleEndian) { 163 | [Array]::Reverse($bytes) 164 | } 165 | return [IPAddress]::new($bytes) 166 | } 167 | 168 | function Get-AvailablePrivateIpAddresses($VNet, $SubnetName, $Count) { 169 | $subnet = Get-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $VNet -Name $SubnetName 170 | $addressPrefixParts = $subnet.AddressPrefix.Split("/") 171 | $ipAddress = [IPAddress]::Parse($addressPrefixParts[0]) 172 | $cidr = [Convert]::ToByte($addressPrefixParts[1]) 173 | $maskUInt = [Convert]::ToUInt32("1" * $cidr + "0" * (32 - $cidr), 2) 174 | [UInt32] $networkUInt = $maskUInt -band (ConvertTo-UInt32 $ipAddress.Address) 175 | [UInt32] $broadcastUInt = 4294967295 -bxor $maskUInt -bor $networkUInt 176 | $subnetCount = $broadcastUInt - ($networkUInt + 1) 177 | 178 | if ($Count -and $subnetCount -lt $Count) { 179 | Write-Error -Message "Requested $Count available addresses but subnet contains maximum $subnetCount addresses" 180 | return 181 | } 182 | 183 | $availableAddresses = New-Object "System.Collections.Generic.HashSet[IpAddress]" 184 | for($i = $networkUInt; $i -le $broadcastUInt; $i++) { 185 | [IpAddress] $testAddress = ConvertTo-IpAddress ($i) 186 | if ($availableAddresses.Contains($testAddress)) { 187 | continue; 188 | } 189 | 190 | $result = Test-AzureRmPrivateIPAddressAvailability -VirtualNetwork $vnet ` 191 | -IPAddress $($testAddress.IPAddressToString) 192 | if ($result.Available) { 193 | $availableAddresses.Add($testAddress) > $null 194 | } 195 | 196 | foreach($a in $result.AvailableIPAddresses) { 197 | $availableAddress = [IpAddress]::Parse($a) 198 | if ($availableAddress.Address -ge $networkAddress.Address -and ` 199 | $availableAddress.Address -le $broadcastAddress.Address) { 200 | $availableAddresses.Add($availableAddress) > $null 201 | } 202 | } 203 | 204 | if ($Count -and $availableAddresses.Count -ge $Count) { 205 | break; 206 | } 207 | } 208 | 209 | if ($availableAddresses.Count -lt $Count) { 210 | Write-Error "Insufficent available addresses in subnet. Requested $Count, available $($availableAddresses.Count)" 211 | return 212 | } 213 | 214 | return $availableAddresses 215 | } 216 | 217 | try { 218 | if ($ClientId -and $ClientSecret -and $TenantId -and $SubscriptionId) { 219 | $credential = new-object -typename System.Management.Automation.PSCredential ` 220 | -argumentlist $ClientId, $ClientSecret 221 | 222 | Add-AzureRmAccount -Credential $credential -Tenant $TenantId -ServicePrincipal -ErrorAction Stop 223 | } 224 | 225 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop 226 | } 227 | catch { 228 | Write-Host "Please Login" 229 | Login-AzureRmAccount 230 | $SubscriptionId = Show-Subscription 231 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId 232 | } 233 | 234 | $location = "Australia Southeast" 235 | $vnetResourceGroup = "vnet" 236 | $vnetName = "es-net" 237 | $addressPrefix = "10.0.0.0/24" 238 | 239 | Write-Log "Deploying virtual network" 240 | New-AzureRmResourceGroup -Name $vnetResourceGroup -Location $location 241 | New-AzureRmVirtualNetwork -ResourceGroupName $vnetResourceGroup -Name $vnetName ` 242 | -AddressPrefix $addressPrefix -Location $location 243 | Write-Log "Virtual network deployed" -ForegroundColor "green" 244 | 245 | $vnet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $vnetResourceGroup 246 | $subnetName = "es-subnet" 247 | 248 | Write-Log "Adding subnet to virtual network" 249 | Add-AzureRmVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix "10.0.0.0/25" -VirtualNetwork $vnet 250 | Set-AzureRmVirtualNetwork -VirtualNetwork $vnet 251 | Write-Log "subnet added" -ForegroundColor "green" 252 | 253 | $templateVersion = "7.0.0" 254 | $templateUrl = "https://raw.githubusercontent.com/elastic/azure-marketplace/$templateVersion/src" 255 | $mainTemplate = "$templateUrl/mainTemplate.json" 256 | $firstCluster = "first-cluster" 257 | $name = $firstCluster 258 | $availableAddresses = Get-AvailablePrivateIpAddresses -VNet $vnet -SubnetName $subnetName -Count 8 259 | 260 | $templateParameters = @{ 261 | "artifactsBaseUrl"= $templateUrl 262 | "esClusterName" = $firstCluster 263 | "adminUsername" = $AdminUserName 264 | "authenticationType" = "password" 265 | "adminPassword" = $AdminPassword 266 | "securityBootstrapPassword" = $SecurityBootstrapPassword 267 | "securityAdminPassword" = $SecurityAdminPassword 268 | "securityKibanaPassword" = $SecurityKibanaPassword 269 | "securityLogstashPassword" = $SecurityLogstashPassword 270 | "securityBeatsPassword" = $SecurityBeatsPassword 271 | "securityApmPassword" = $SecurityApmPassword 272 | "securityRemoteMonitoringPassword" = $SecurityRemoteMonitoringPassword 273 | "vmHostNamePrefix" = "f-" 274 | "vNetNewOrExisting" = "existing" 275 | "vNetName" = $vnetName 276 | "vNetExistingResourceGroup" = $vnetResourceGroup 277 | "vNetLoadBalancerIp" = "$(($availableAddresses | Select-Object -First 1).IPAddressToString)" 278 | "vNetClusterSubnetName" = $subnetName 279 | } 280 | 281 | Write-Log "Deploying first cluster" 282 | New-AzureRmResourceGroup -Name $firstCluster -Location $location 283 | New-AzureRmResourceGroupDeployment -Name $name -ResourceGroupName $firstCluster ` 284 | -TemplateUri $mainTemplate -TemplateParameterObject $templateParameters 285 | Write-Log "Deployed first cluster" -ForegroundColor "green" 286 | 287 | $secondCluster = "second-cluster" 288 | $name = $secondCluster 289 | $availableAddresses = Get-AvailablePrivateIpAddresses -VNet $vnet -SubnetName $subnetName -Count 8 290 | 291 | $templateParameters = @{ 292 | "artifactsBaseUrl"= $templateUrl 293 | "esClusterName" = $secondCluster 294 | "adminUsername" = $AdminUserName 295 | "authenticationType" = "password" 296 | "adminPassword" = $AdminPassword 297 | "securityBootstrapPassword" = $SecurityBootstrapPassword 298 | "securityAdminPassword" = $SecurityAdminPassword 299 | "securityKibanaPassword" = $SecurityKibanaPassword 300 | "securityLogstashPassword" = $SecurityLogstashPassword 301 | "securityBeatsPassword" = $SecurityBeatsPassword 302 | "securityApmPassword" = $SecurityApmPassword 303 | "securityRemoteMonitoringPassword" = $SecurityRemoteMonitoringPassword 304 | "vmHostNamePrefix" = "s-" 305 | "vNetNewOrExisting" = "existing" 306 | "vNetName" = $vnetName 307 | "vNetExistingResourceGroup" = $vnetResourceGroup 308 | "vNetLoadBalancerIp" = "$(($availableAddresses | Select-Object -First 1).IPAddressToString)" 309 | "vNetClusterSubnetName" = $subnetName 310 | } 311 | 312 | Write-Log "Deploying second cluster" 313 | New-AzureRmResourceGroup -Name $secondCluster -Location $location 314 | New-AzureRmResourceGroupDeployment -Name $name -ResourceGroupName $secondCluster ` 315 | -TemplateUri $mainTemplate -TemplateParameterObject $templateParameters 316 | Write-Log "Deployed second cluster" -ForegroundColor "green" -------------------------------------------------------------------------------- /azure_monitor_logstash/azure_monitor_logstash.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Deploys Elasticsearch, Kibana and Logstash, with Azure Monitor Logstash module configured. 4 | .Description 5 | Deploys Elasticsearch, Kibana and Logstash, with Azure Monitor Logstash module configured. 6 | Additional steps must currently be taken on the Logstash VM to complete Azure Monitor configuration 7 | .Parameter ClientId 8 | the client id to log in with a Service Principal 9 | .Parameter ClientSecret 10 | the client secret to log in with a Service Principal 11 | .Parameter TenantId 12 | the tenant id to log in with a Service Principal 13 | .Parameter SubscriptionId 14 | the subscription id to deploy the resources to. If the current session is not logged into the Azure account, user will 15 | be prompted to log in and select a SubscriptionId 16 | .Parameter AdminUserName 17 | the admin username in order to log into VMs deployed in the Elasticsearch cluster 18 | .Parameter AdminPassword 19 | the admin password in order to log into VMs deployed in the Elasticsearch cluster 20 | .Parameter SecurityBootstrapPassword 21 | the bootstrap password to initially log into the Elasticsearch cluster through X-Pack Security 22 | .Parameter SecurityAdminPassword 23 | the password to log into the Elasticsearch cluster through X-Pack Security with built-in user 'elastic' 24 | .Parameter SecurityKibanaPassword 25 | the password to log into the Elasticsearch cluster through X-Pack Security with built-in user 'kibana' 26 | .Parameter SecurityLogstashPassword 27 | the password to log into the Elasticsearch cluster through X-Pack Security with built-in user 'logstash_system' 28 | .Parameter SecurityBeatsPassword 29 | the password to log into the Elasticsearch cluster through X-Pack Security with built-in user 'beats_system' 30 | .Parameter SecurityApmPassword 31 | the password to log into the Elasticsearch cluster through X-Pack Security with built-in user 'apm_system' 32 | .Parameter SecurityRemoteMonitoringPassword 33 | the password to log into the Elasticsearch cluster through X-Pack Security with built-in user 'remote_monitoring_user' 34 | .Parameter EventHubResourceGroup 35 | the resource group for event hubs 36 | .Parameter EventHubNamespaceName 37 | the namespace for event hubs 38 | .Parameter StorageResourceGroup 39 | the resource group for the Storage account 40 | .Parameter StorageAccountName 41 | the name of the storage account. Must be universally unique 42 | .Parameter ResourceGroup 43 | the resource group for Elasticsearch, Logstash and Kibana 44 | .Parameter Name 45 | the name of the Elasticsearch cluster 46 | .Parameter Location 47 | Azure location for all deployed resources 48 | #> 49 | [CmdletBinding()] 50 | Param( 51 | [Parameter(Mandatory=$false)] 52 | [string] $ClientId, 53 | 54 | [Parameter(Mandatory=$false)] 55 | [securestring] $ClientSecret, 56 | 57 | [Parameter(Mandatory=$false)] 58 | [string] $TenantId, 59 | 60 | [Parameter(Mandatory=$false)] 61 | [string] $SubscriptionId, 62 | 63 | [Parameter(Mandatory=$false, HelpMessage="Admin user to log into VMs")] 64 | [string] $AdminUserName = "russ", 65 | 66 | [Parameter(Mandatory=$true, HelpMessage="Password for the Admin user to log into VMs")] 67 | [securestring] $AdminPassword, 68 | 69 | [Parameter(Mandatory=$true, HelpMessage="Password to bootstrap the cluster with")] 70 | [securestring] $SecurityBootstrapPassword, 71 | 72 | [Parameter(Mandatory=$true, HelpMessage="Password for the built-in 'elastic' user")] 73 | [securestring] $SecurityAdminPassword, 74 | 75 | [Parameter(Mandatory=$true, HelpMessage="Password for the built-in 'kibana' user")] 76 | [securestring] $SecurityKibanaPassword, 77 | 78 | [Parameter(Mandatory=$true, HelpMessage="Password for the built-in 'logstash_system' user")] 79 | [securestring] $SecurityLogstashPassword, 80 | 81 | [Parameter(Mandatory=$true, HelpMessage="Password for the built-in 'beats_system' user")] 82 | [securestring] $SecurityBeatsPassword, 83 | 84 | [Parameter(Mandatory=$true, HelpMessage="Password for the built-in 'apm_system' user")] 85 | [securestring] $SecurityApmPassword, 86 | 87 | [Parameter(Mandatory=$true, HelpMessage="Password for the built-in 'remote_monitoring_user' user")] 88 | [securestring] $SecurityRemoteMonitoringPassword, 89 | 90 | [Parameter(Mandatory=$false)] 91 | [string] $EventHubResourceGroup = "logstash-monitor-eventhubs", 92 | 93 | [Parameter(Mandatory=$false)] 94 | [string] $EventHubNamespaceName = "logstash-monitor-eventhubs", 95 | 96 | [Parameter(Mandatory=$false)] 97 | [string] $StorageResourceGroup = "logstash-monitor-storage", 98 | 99 | [Parameter(Mandatory=$false)] 100 | [string] $StorageAccountName = "logstashstorage$([System.Guid]::NewGuid().ToString().Replace('-', '').Substring(0, 9))", 101 | 102 | [Parameter(Mandatory=$false)] 103 | [string] $ResourceGroup = "logstash-monitor", 104 | 105 | [Parameter(Mandatory=$false)] 106 | [string] $Name = "logstash-monitor", 107 | 108 | [Parameter(Mandatory=$false)] 109 | [string] $Location = "Australia Southeast" 110 | ) 111 | 112 | $ErrorActionPreference = "Stop" 113 | 114 | function Write-Log($Message, $ForegroundColor) { 115 | if ($null -eq $ForegroundColor) { 116 | $ForegroundColor = "White" 117 | } 118 | 119 | Write-Host "[$(Get-Date -format 'u')] $Message" -ForegroundColor $ForegroundColor 120 | } 121 | 122 | function Show-Custom($title, $optionValues, $optionDescriptions) { 123 | Write-Host $title 124 | Write-Host 125 | for($i = 0; $i -lt $optionValues.Length; $i++) { 126 | Write-Host "$($i+1))" $optionDescriptions[$i] 127 | } 128 | Write-Host 129 | 130 | while($true) { 131 | Write-Host "Choose an option: " 132 | $option = Read-Host 133 | $option = $option -as [int] 134 | 135 | if($option -ge 1 -and $option -le $optionValues.Length) { 136 | return $optionValues[$option-1] 137 | } 138 | } 139 | } 140 | 141 | function Show-Subscription() { 142 | $subs = Get-AzureRmSubscription 143 | $subscriptionId = "" 144 | 145 | if($subs.Length -eq 0) { 146 | Write-Error "No subscriptions bound to this account." 147 | return 148 | } 149 | 150 | if($subs.Length -eq 1) { 151 | $subscriptionId = $subs[0].Id 152 | } 153 | else { 154 | $subscriptionChoices = @() 155 | $subscriptionValues = @() 156 | 157 | foreach($subscription in $subs) { 158 | $subscriptionChoices += "$($subscription.Name) ($($subscription.Id))"; 159 | $subscriptionValues += ($subscription.Id); 160 | } 161 | 162 | $subscriptionId = Show-Custom "Choose a subscription" $subscriptionValues $subscriptionChoices 163 | } 164 | 165 | return $subscriptionId 166 | } 167 | 168 | function ConvertTo-PlainText { 169 | param( 170 | [System.Security.SecureString] 171 | [Parameter(ValueFromPipeline = $true)] 172 | $secureString 173 | ) 174 | 175 | $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString) 176 | try { 177 | return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) 178 | } 179 | finally { 180 | [Runtime.InteropServices.Marshal]::FreeBSTR($bstr) 181 | } 182 | } 183 | 184 | try { 185 | if ($ClientId -and $ClientSecret -and $TenantId -and $SubscriptionId) { 186 | $credential = new-object -typename System.Management.Automation.PSCredential ` 187 | -argumentlist $ClientId, $ClientSecret 188 | 189 | Add-AzureRmAccount -Credential $credential -Tenant $TenantId -ServicePrincipal -ErrorAction Stop 190 | } 191 | 192 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop 193 | } 194 | catch { 195 | Write-Host "Please Login" 196 | Login-AzureRmAccount 197 | $SubscriptionId = Show-Subscription 198 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId 199 | } 200 | 201 | # create event hub namespace 202 | Write-Log "Create event hub namespace $EventHubNamespaceName in resource group $EventHubResourceGroup" 203 | 204 | New-AzureRmResourceGroup -Name $EventHubResourceGroup -Location $Location 205 | $eventHubNamespace = New-AzureRmEventHubNamespace -ResourceGroupName $EventHubResourceGroup -NamespaceName $EventHubNamespaceName -Location $Location 206 | Write-Log "Created event hub namespace $EventHubNamespaceName" 207 | $eventHubEndpoint = $eventHubNamespace.ServiceBusEndpoint.Replace("https://", "sb://") 208 | 209 | Write-Log "Get the SAS key for event hub namespace $EventHubNamespaceName" 210 | # get shared access key for the event hub namespace. Doesn't look like there is a PowerShell cmdlet to do this anymore :( 211 | $sharedAccessKey = (Invoke-AzureRmResourceAction -ResourceGroupName $EventHubResourceGroup -ResourceType Microsoft.EventHub/namespaces/AuthorizationRules ` 212 | -ResourceName $EventHubNamespaceName/RootManageSharedAccessKey -Action listKeys -ApiVersion 2015-08-01 -Force).primaryKey 213 | 214 | ############################## 215 | # create the Azure Log Profile 216 | ############################## 217 | 218 | Write-Log "Check for existing log profile" 219 | $logProfile = Get-AzureRmLogProfile -ErrorAction Ignore 220 | if ($null -ne $logProfile) { 221 | Write-Log "Existing log profile $($logProfile.Name)" 222 | Write-Log "Delete existing log profile $($logProfile.Name)" 223 | Remove-AzureRmLogProfile -Name $logProfile.Name 224 | Write-Log "Deleted existing log profile $($logProfile.Name)" 225 | } 226 | 227 | $logProfileName = "default" 228 | $locations = (Get-AzureRmLocation).Location 229 | $locations += "global" 230 | $serviceBusRuleId = "/subscriptions/$subscriptionId/resourceGroups/$EventHubResourceGroup" + ` 231 | "/providers/Microsoft.EventHub/namespaces/$EventHubNamespaceName" + ` 232 | "/authorizationrules/RootManageSharedAccessKey" 233 | 234 | Write-Log "Create log profile $logProfileName" 235 | Add-AzureRmLogProfile -Name $logProfileName -Location $locations -ServiceBusRuleId $serviceBusRuleId 236 | Write-Log "Created log profile $logProfileName" 237 | 238 | ############################################################## 239 | # set up storage account for persisting logstash read position 240 | ############################################################## 241 | 242 | Write-Log "Create storage account $StorageAccountName in resource group $StorageResourceGroup" 243 | New-AzureRmResourceGroup -Name $StorageResourceGroup -Location $Location 244 | $storageAccount = New-AzureRmStorageAccount -ResourceGroupName $StorageResourceGroup -AccountName $StorageAccountName -Type "Standard_LRS" -Location $Location 245 | Write-Log "Created storage account $StorageAccountName" 246 | 247 | $storageAccountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $storageResourceGroup -Name $storageAccountName 248 | $uri = New-Object -TypeName System.Uri $storageAccount.Context.BlobEndPoint 249 | 250 | ##################################### 251 | # build the storage connection string 252 | ##################################### 253 | 254 | $storageConnectionString = "DefaultEndpointsProtocol=$($uri.Scheme);AccountName=$storageAccountName;" + ` 255 | "AccountKey=$($storageAccountKeys[0].Value);EndpointSuffix=$($storageAccount.Context.EndPointSuffix);" 256 | 257 | 258 | # assumes we're using Azure DNS resolution, which can resolve by hostname 259 | $kibanaIp = "kibana" 260 | $logstashConsumerGroup = "logstash" 261 | $elasticUserPassword = ConvertTo-PlainText $SecurityAdminPassword 262 | $kibanaUserPassword = ConvertTo-PlainText $SecurityKibanaPassword 263 | 264 | ######################################################### 265 | # Build the yaml to append to the template's logstash.yml 266 | ######################################################### 267 | 268 | $logstashYaml = @" 269 | modules: 270 | - name: azure 271 | var.elasticsearch.hosts: `"`${ELASTICSEARCH_URL}`" 272 | var.elasticsearch.username: elastic 273 | var.elasticsearch.password: `"$elasticUserPassword`" 274 | var.kibana.ssl.enabled: false 275 | var.kibana.host: `"$($kibanaIp):5601`" 276 | var.kibana.username: elastic 277 | var.kibana.password: `"$kibanaUserPassword`" 278 | var.input.azure_event_hubs.consumer_group: "$logstashConsumerGroup" 279 | var.input.azure_event_hubs.storage_connection: "$storageConnectionString" 280 | var.input.azure_event_hubs.threads: 9 281 | var.input.azure_event_hubs.event_hub_connections: 282 | "@ 283 | 284 | ############################################################ 285 | # Get all the event hubs set up by the log profile. This can 286 | # take some time to propagate so loop until they're visible 287 | ############################################################ 288 | 289 | Write-Log "Get the event hubs in event hub namespace $EventHubNamespaceName" 290 | $eventHubs = Get-AzureRmEventHub -ResourceGroupName $EventHubResourceGroup -Namespace $EventHubNamespaceName 291 | while ($null -eq $eventHubs) { 292 | $sleepySeconds = 5 293 | Write-Log "No event hubs in event namespace $EventHubNamespaceName. Trying again in $sleepySeconds seconds..." 294 | Start-Sleep -Seconds $sleepySeconds 295 | $eventHubs = Get-AzureRmEventHub -ResourceGroupName $EventHubResourceGroup -Namespace $EventHubNamespaceName 296 | } 297 | 298 | $entityPaths = $eventHubs | ForEach-Object { $_.Name } 299 | 300 | $entityPaths | ForEach-Object { 301 | Write-Log "Add consumer group $logstashConsumerGroup to event hub $_" 302 | New-AzureRmEventHubConsumerGroup -ResourceGroupName $EventHubResourceGroup -Namespace $EventHubNamespaceName -Name $logstashConsumerGroup -EventHub $_ 303 | Write-Log "Add event hub $_ to logstash.yml" 304 | $logstashYaml += "`n - `"Endpoint=$eventHubEndpoint;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=$sharedAccessKey;EntityPath=$_`"" 305 | } 306 | 307 | ########################################### 308 | # Deploy Elasticsearch, Logstash and Kibana 309 | ########################################### 310 | 311 | # last template version tag released to Marketplace 312 | $templateVersion = "7.3.0" 313 | $templateUrl = "https://raw.githubusercontent.com/elastic/azure-marketplace/$templateVersion/src/" 314 | $elasticTemplate = "$($templateUrl)mainTemplate.json" 315 | 316 | # You probably want to change these parameters to suit your needs 317 | $clusterParameters = @{ 318 | "_artifactsLocation"= $templateUrl 319 | "esVersion" = $templateVersion 320 | "esClusterName" = $name 321 | "vmDataDiskCount" = 2 322 | "vmDataNodeCount" = 3 323 | "vmSizeDataNodes" = "Standard_D1_v2" 324 | "vmSizeMasterNodes" = "Standard_D1_v2" 325 | "dataNodesAreMasterEligible" = "Yes" 326 | 327 | "kibana" = "Yes" 328 | "vmSizeKibana" = "Standard_D1_v2" 329 | 330 | "logstash" = "Yes" 331 | "vmSizeLogstash" = "Standard_D1_v2" 332 | "logstashKeystorePassword" = $SecurityBootstrapPassword 333 | "logstashAdditionalYaml" = $logstashYaml 334 | 335 | # Deploy only an internal load balancer. Elasticsearch is not directly accessible on a public IP 336 | "loadBalancerType" = "internal" 337 | 338 | "xpackPlugins" = "Yes" 339 | "adminUsername" = $AdminUserName 340 | "authenticationType" = "password" 341 | "adminPassword" = $AdminPassword 342 | "securityBootstrapPassword" = $SecurityBootstrapPassword 343 | "securityAdminPassword" = $SecurityAdminPassword 344 | "securityKibanaPassword" = $SecurityKibanaPassword 345 | "securityLogstashPassword" = $SecurityLogstashPassword 346 | "securityBeatsPassword" = $SecurityBeatsPassword 347 | "securityApmPassword" = $SecurityApmPassword 348 | "securityRemoteMonitoringPassword" = $SecurityRemoteMonitoringPassword 349 | } 350 | 351 | 352 | Write-Log "Deploying Elasticsearch, Logstash, Kibana" 353 | New-AzureRmResourceGroup -Name $resourceGroup -Location $location 354 | $deployment = New-AzureRmResourceGroupDeployment -Name $name -ResourceGroupName $resourceGroup -TemplateUri $elasticTemplate -TemplateParameterObject $clusterParameters 355 | Write-Log "Deployed Elasticsearch, Logstash, Kibana" 356 | 357 | #launch Kibana after deployment finishes 358 | Start-Process $deployment.Outputs.kibana.Value 359 | 360 | <# 361 | 362 | ########################################################## 363 | Steps on Logstash VM to finish Azure Monitor configuration 364 | ########################################################## 365 | 366 | 1. SSH into Logstash through Kibana VM 367 | 368 | ssh @ 369 | 370 | ssh logstash-0 371 | 372 | 2. Stop Logstash service with systemctl 373 | 374 | sudo systemctl stop logstash.service 375 | 376 | 3. Remove path.config setting from /etc/logstash/logstash.yml. Can't be used in conjunction with Azure modules 377 | 378 | sudo nano /etc/logstash/logstash.yml 379 | 380 | 4. Need to run one time setup for Logstash module to export Dashboards to Kibana. 381 | Get the keystore password from /etc/sysconfig/logstash and export to environment variables 382 | 383 | logstashPass=$(sudo grep -Po "(?<=^LOGSTASH_KEYSTORE_PASS=).*" /etc/sysconfig/logstash | sed 's/"//g') 384 | 385 | export LOGSTASH_KEYSTORE_PASS="$logstashPass" 386 | 387 | 5. Run Logstash setup with logstash user, passing environment variables 388 | 389 | sudo -Eu logstash /usr/share/logstash/bin/logstash --path.settings /etc/logstash --setup 390 | 391 | 6. Once [Azure Monitor] Dashboards appear under the Dashboard tab in Kibana, stop Logstash with CTRL+C 392 | 393 | 7. Start Logstash service with systemctl 394 | 395 | sudo systemctl start logstash.service 396 | 397 | #> 398 | -------------------------------------------------------------------------------- /cluster_azure-repository_app-service/cluster_azure-repository_app-service.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Deploys an Azure Storage Account, Elasticsearch cluster and Azure App Service. 4 | .Description 5 | The Storage account is configured with the azure-repository plugin to be used for snapshot/restore for the Elasticsearch cluster. 6 | The Azure App Service is connected to the Virtual Network deployed as part of the cluster so that it can connect to the cluster. 7 | .Example 8 | & .\cluster_azure-repository_app-service.ps1 -AdminUserName "russ" ` 9 | -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 10 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 11 | -SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 12 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) 13 | .Example 14 | & .\cluster_azure-repository_app-service.ps1 -ClientId "clientid" ` 15 | -ClientSecret $(ConvertTo-SecureString -String "clientsecret" -AsPlainText -Force) ` 16 | -TenantId "tenantid" -SubscriptionId "subscriptionid" ` 17 | -AdminUserName "russ" -AdminPassword $(ConvertTo-SecureString -String "Password1234" -AsPlainText -Force) ` 18 | -SecurityAdminPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 19 | -SecurityReadPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) ` 20 | -SecurityKibanaPassword $(ConvertTo-SecureString -String "Password123" -AsPlainText -Force) 21 | .Parameter ClientId 22 | the client id to log in with a Service Principal 23 | .Parameter ClientSecret 24 | the client secret to log in with a Service Principal 25 | .Parameter TenantId 26 | the tenant id to log in with a Service Principal 27 | .Parameter SubscriptionId 28 | the subscription id to deploy the resources to. If the current session is not logged into the Azure account, user will 29 | be prompted to log in and select a SubscriptionId 30 | .Parameter AdminUserName 31 | the admin username in order to log into VMs deployed in the Elasticsearch cluster 32 | .Parameter AdminPassword 33 | the admin password in order to log into VMs deployed in the Elasticsearch cluster 34 | .Parameter SecurityAdminPassword 35 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_admin' (2.x) or 'elastic' (5.x) 36 | .Parameter SecurityReadPassword 37 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_read' 38 | .Parameter SecurityKibanaPassword 39 | the password to log into the Elasticsearch cluster through X-Pack Security with user 'es_kibana' 40 | #> 41 | [CmdletBinding()] 42 | Param( 43 | [Parameter(Mandatory=$false)] 44 | [string] $ClientId, 45 | 46 | [Parameter(Mandatory=$false)] 47 | [securestring] $ClientSecret, 48 | 49 | [Parameter(Mandatory=$false)] 50 | [string] $TenantId, 51 | 52 | [Parameter(Mandatory=$false)] 53 | [string] $SubscriptionId, 54 | 55 | [Parameter(Mandatory=$true)] 56 | [string] $AdminUserName, 57 | 58 | [Parameter(Mandatory=$true)] 59 | [securestring] $AdminPassword, 60 | 61 | [Parameter(Mandatory=$true)] 62 | [securestring] $SecurityAdminPassword, 63 | 64 | [Parameter(Mandatory=$true)] 65 | [securestring] $SecurityReadPassword, 66 | 67 | [Parameter(Mandatory=$true)] 68 | [securestring] $SecurityKibanaPassword 69 | ) 70 | $ErrorActionPreference = "Stop" 71 | 72 | function Write-Log($Message, $ForegroundColor) { 73 | if ($ForegroundColor -eq $null) { 74 | $ForegroundColor = "White" 75 | } 76 | 77 | Write-Host "[$(Get-Date -format 'u')] $message" -ForegroundColor $ForegroundColor 78 | } 79 | 80 | function Show-Custom($title, $optionValues, $optionDescriptions) { 81 | Write-Host $title 82 | Write-Host 83 | for($i = 0; $i -lt $optionValues.Length; $i++) { 84 | Write-Host "$($i+1))" $optionDescriptions[$i] 85 | } 86 | Write-Host 87 | 88 | while($true) { 89 | Write-Host "Choose an option: " 90 | $option = Read-Host 91 | $option = $option -as [int] 92 | 93 | if($option -ge 1 -and $option -le $optionValues.Length) { 94 | return $optionValues[$option-1] 95 | } 96 | } 97 | } 98 | 99 | function Show-Subscription() { 100 | # Choose subscription. If there's only one we will choose automatically 101 | $subs = Get-AzureRmSubscription 102 | $subscriptionId = "" 103 | 104 | if($subs.Length -eq 0) { 105 | Write-Error "No subscriptions bound to this account." 106 | return 107 | } 108 | 109 | if($subs.Length -eq 1) { 110 | $subscriptionId = $subs[0].SubscriptionId 111 | } 112 | else { 113 | $subscriptionChoices = @() 114 | $subscriptionValues = @() 115 | 116 | foreach($subscription in $subs) { 117 | $subscriptionChoices += "$($subscription.SubscriptionName) ($($subscription.SubscriptionId))"; 118 | $subscriptionValues += ($subscription.SubscriptionId); 119 | } 120 | 121 | $subscriptionId = Show-Custom "Choose a subscription" $subscriptionValues $subscriptionChoices 122 | } 123 | 124 | return $subscriptionId 125 | } 126 | 127 | function New-StorageAccount($storageAccountResourceGroup, $storageAccountName, $location) { 128 | $account = Get-AzureRmStorageAccount -ResourceGroupName $storageAccountResourceGroup -Name $storageAccountName -ErrorAction Ignore 129 | 130 | if ($account -ne $null) { 131 | Write-Log "Storage account $storageAccountName in resource group $storageAccountResourceGroup already exists. Using this." -ForegroundColor "green" 132 | return 133 | } 134 | 135 | Write-Log "Creating Storage account $storageAccountName in resource group $storageAccountResourceGroup" 136 | New-AzureRmResourceGroup -Name $storageAccountResourceGroup -Location $location 137 | New-AzureRmStorageAccount -ResourceGroupName $storageAccountResourceGroup -AccountName $storageAccountName -Type "Standard_LRS" -Location $location 138 | Write-Log "Finished creating Storage account" -ForegroundColor "green" 139 | } 140 | 141 | function New-ElasticsearchCluster($resourceGroupName, $clusterName, $location, $elasticTemplateUri, $elasticParameters) { 142 | $resourceGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -Location $location -ErrorAction Ignore 143 | 144 | if ($resourceGroup -ne $null) { 145 | Write-Log "Resource group $resourceGroupName already exists. Using this." -ForegroundColor "green" 146 | return 147 | } 148 | 149 | Write-Log "Deploying Elasticsearch cluster $clusterName from $elasticTemplateUri" 150 | New-AzureRmResourceGroup -Name $resourceGroupName -Location $location 151 | New-AzureRmResourceGroupDeployment -Name $clusterName -ResourceGroupName $resourceGroupName -TemplateUri $elasticTemplateUri -TemplateParameterObject $elasticParameters 152 | Write-Log "Finished Deploying Elasticsearch cluster" -ForegroundColor "green" 153 | } 154 | 155 | function New-Website($resourceGroupName, $webAppName, $location, $webAppParameters) { 156 | $resourceGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -Location $location -ErrorAction Ignore 157 | 158 | if ($resourceGroup -ne $null) { 159 | Write-Log "Resource group $resourceGroupName already exists. Using this." -ForegroundColor "green" 160 | return 161 | } 162 | 163 | $deployFromGithubTemplate = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-web-app-github-deploy/azuredeploy.json" 164 | New-AzureRmResourceGroup -Name $resourceGroupName -Location $location 165 | New-AzureRmResourceGroupDeployment -Name $webAppName -ResourceGroupName $resourceGroupName ` 166 | -TemplateUri $deployFromGithubTemplate -TemplateParameterObject $webAppParameters 167 | Write-Log "Finished Deploying Nusearch website" -ForegroundColor "green" 168 | } 169 | 170 | function Add-VNetGateway($resourceGroupName, $vnetName, $vnetIpName, $location, $vnetIpConfigName, $vnetGatewayName, $certificateData, $vnetPointToSiteAddressSpace) { 171 | 172 | $gateway = Get-AzureRmVirtualNetworkGateway -Name $vnetGatewayName -ResourceGroupName $resourceGroupName -ErrorAction Ignore 173 | 174 | if ($gateway -ne $null) { 175 | Write-Log "Virtual Network Gateway $vnetGatewayName already exists. Using this." -ForegroundColor "green" 176 | return 177 | } 178 | 179 | $vnet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $resourceGroupName 180 | $subnet = Get-AzureRmVirtualNetworkSubnetConfig -Name "GatewaySubnet" -VirtualNetwork $vnet 181 | 182 | Write-Log "Creating a public IP address for this Virtual Network" 183 | $pip = New-AzureRmPublicIpAddress -Name $vnetIpName -ResourceGroupName $resourceGroupName -Location $location -AllocationMethod Dynamic 184 | $ipconf = New-AzureRmVirtualNetworkGatewayIpConfig -Name $vnetIpConfigName -Subnet $subnet -PublicIpAddress $pip 185 | Write-Log "Finished creating a public IP address for this Virtual Network" -ForegroundColor "green" 186 | 187 | Write-Log "Adding a root certificate to this Virtual Network" 188 | $root = New-AzureRmVpnClientRootCertificate -Name "AppServiceCertificate.cer" -PublicCertData $certificateData 189 | Write-Log "Finished Adding a root certificate to this Virtual Network" -ForegroundColor "green" 190 | 191 | Write-Log "Creating Virtual Network Gateway. This may take up to an hour." 192 | $gateway = New-AzureRmVirtualNetworkGateway -Name $vnetGatewayName -ResourceGroupName $resourceGroupName ` 193 | -Location $location -IpConfigurations $ipconf -GatewayType Vpn -VpnType RouteBased -EnableBgp $false ` 194 | -GatewaySku Basic -VpnClientAddressPool $vnetPointToSiteAddressSpace -VpnClientRootCertificates $root 195 | Write-Log "Finished creating Virtual Network Gateway" -ForegroundColor "green" 196 | } 197 | 198 | function Add-AppServiceToExistingVnet($subscriptionId, $webAppResourceGroup, $webAppName, $vnetName, $vnetResourceGroup) { 199 | Write-Log "Getting App information" 200 | $webApp = Get-AzureRmResource -ResourceName $webAppName -ResourceType "Microsoft.Web/sites" ` 201 | -ApiVersion 2015-08-01 -ResourceGroupName $webAppResourceGroup 202 | $location = $webApp.Location 203 | 204 | $webAppConfig = Get-AzureRmResource -ResourceName "$($webAppName)/web" -ResourceType "Microsoft.Web/sites/config" ` 205 | -ApiVersion 2015-08-01 -ResourceGroupName $webAppResourceGroup 206 | $vnet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $vnetResourceGroup 207 | 208 | # Virtual Network settings 209 | $vnetName = $vnet.Name 210 | $vnetGatewayName="$($vnetName)-gateway" 211 | $vnetIpName="$($vnetName)-gateway-ip" 212 | $vnetIpConfigName="$($vnetName)-gateway-ip-conf" 213 | $vnetGatewayAddressSpace="10.0.0.128/28" 214 | $vnetPointToSiteAddressSpace="172.16.0.0/16" 215 | 216 | Write-Log "Creating Virtual Network Connection for website $webAppName to Virtual Network $($vnet.Name)" 217 | $virtualNetworkParameters = @{ 218 | "vnetResourceId" = "/subscriptions/$($subscriptionId)/resourceGroups/$($vnet.ResourceGroupName)/providers/Microsoft.Network/virtualNetworks/$($vnetName)" 219 | } 220 | $virtualNetworkConnection = New-AzureRmResource -Location $location -Properties $virtualNetworkParameters -ResourceName "$($webAppName)/$($vnet.Name)" -ResourceType "Microsoft.Web/sites/virtualNetworkConnections" -ApiVersion 2015-08-01 -ResourceGroupName $webAppResourceGroup -Force 221 | Write-Log "Virtual Network Connection created" -ForegroundColor "green" 222 | 223 | $gatewaySubnet = Get-AzureRmVirtualNetworkSubnetConfig -Name "GatewaySubnet" -VirtualNetwork $vnet -ErrorAction Ignore 224 | if ($gatewaySubnet -ne $null) { 225 | Write-Log "GatewaySubnet already exists for Virtual Network $($vnet.Name). Using this." -ForegroundColor "green" 226 | } 227 | else { 228 | Write-Log "Creating GatewaySubnet in Virtual Network $($vnet.Name)" 229 | Add-AzureRmVirtualNetworkSubnetConfig -Name "GatewaySubnet" -AddressPrefix $vnetGatewayAddressSpace -VirtualNetwork $vnet 230 | Set-AzureRmVirtualNetwork -VirtualNetwork $vnet 231 | Write-Log "GatewaySubnet created in Virtual Network $($vnet.Name)" -ForegroundColor "green" 232 | } 233 | 234 | # Create the VNet Gateway 235 | Add-VNetGateway $vnet.ResourceGroupName $vnetName $vnetIpName $location $vnetIpConfigName $vnetGatewayName $virtualNetworkConnection.Properties.CertBlob $vnetPointToSiteAddressSpace 236 | $gateway = Get-AzureRmVirtualNetworkGateway -ResourceGroupName $vnet.ResourceGroupName -Name $vnetGatewayName 237 | 238 | # Now finish joining by getting the VPN package and giving it to the App 239 | Write-Log "Retrieving VPN Package and supplying to Web App" 240 | $packageUri = Get-AzureRmVpnClientPackage -ResourceGroupName $vnet.ResourceGroupName -VirtualNetworkGatewayName $gateway.Name -ProcessorArchitecture Amd64 241 | 242 | # Put the VPN client configuration package onto the App 243 | $virtualNetworkGatewayParameters = @{ 244 | "vnetName" = $vnet.Name; 245 | "vpnPackageUri" = $packageUri.ToString().Trim('"') 246 | } 247 | 248 | Write-Log "Adding website $webAppName to Virtual Network $($vnet.Name)" 249 | New-AzureRmResource -Location $location -Properties $virtualNetworkGatewayParameters -ResourceName "$($webAppName)/$($vnet.Name)/primary" -ResourceType "Microsoft.Web/sites/virtualNetworkConnections/gateways" -ApiVersion 2015-08-01 -ResourceGroupName $webAppResourceGroup -Force 250 | Write-Log "Finished adding website $webAppName to Virtual Network $($vnet.Name)" -ForegroundColor "green" 251 | } 252 | 253 | function Add-AppSettings($resourceGroupName, $webAppName, $appSettings) { 254 | Write-Log "Updating App Settings for website" 255 | $webApp = Get-AzureRMWebAppSlot -ResourceGroupName $resourceGroupName -Name $webAppName -Slot production 256 | $existingAppSettings = $webApp.SiteConfig.AppSettings 257 | 258 | $hash = @{} 259 | foreach ($kvp in $existingAppSettings) { 260 | $hash[$kvp.Name] = $kvp.Value 261 | } 262 | foreach ($kvp in $appSettings.GetEnumerator()) { 263 | $hash[$kvp.Name] = $kvp.Value 264 | } 265 | 266 | Set-AzureRMWebAppSlot -ResourceGroupName $resourceGroupName -Name $webAppName -AppSettings $hash -Slot production 267 | Write-Log "App Settings for website updated" -ForegroundColor "green" 268 | } 269 | 270 | ################## 271 | # Start of Process 272 | ################## 273 | 274 | try { 275 | if ($ClientId -and $ClientSecret -and $TenantId -and $SubscriptionId) { 276 | $credential = new-object -typename System.Management.Automation.PSCredential ` 277 | -argumentlist $ClientId, $ClientSecret 278 | 279 | Add-AzureRmAccount -Credential $credential -Tenant $TenantId -ServicePrincipal -ErrorAction Stop 280 | } 281 | 282 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop 283 | } 284 | catch { 285 | Write-Host "Please Login" 286 | Login-AzureRmAccount 287 | $SubscriptionId = Show-Subscription 288 | Select-AzureRmSubscription -SubscriptionId $SubscriptionId 289 | } 290 | 291 | $location = "Australia Southeast" 292 | 293 | ################################################################################################# 294 | # Create the storage account, or use existing one if resource group with same name already exists 295 | ################################################################################################# 296 | 297 | $storageAccountResourceGroup = "nusearch-storage" 298 | $storageAccountName = "nusearchdata" 299 | 300 | New-StorageAccount $storageAccountResourceGroup $storageAccountName $location 301 | $storageAccountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $storageAccountResourceGroup -Name $storageAccountName 302 | 303 | ######################################################################################### 304 | # Create the cluster, or use existing one if resource group with same name already exists 305 | ######################################################################################### 306 | 307 | $templateVersion = "5.1.2" 308 | $clusterResourceGroup = "nusearch-cluster" 309 | $clusterName = "nusearch-cluster" 310 | $templateUrl = "https://raw.githubusercontent.com/elastic/azure-marketplace/$templateVersion/src" 311 | $mainTemplate = "$templateUrl/mainTemplate.json" 312 | 313 | # parameters match those of the version of the template that we are targeting 314 | $templateParameters = @{ 315 | "artifactsBaseUrl"= $templateUrl 316 | "esClusterName" = $clusterName 317 | "adminUsername" = $AdminUserName 318 | "vNetLoadBalancerIp" = "10.0.0.4" 319 | "vNetName" = "es-net" 320 | "authenticationType" = "password" 321 | "adminPassword" = $AdminPassword 322 | "securityAdminPassword" = $SecurityAdminPassword 323 | "securityReadPassword" = $SecurityReadPassword 324 | "securityKibanaPassword" = $SecurityKibanaPassword 325 | "azureCloudPlugin" = "Yes" 326 | "azureCloudStorageAccountName" = $storageAccountName 327 | "azureCloudStorageAccountKey" = $storageAccountKeys[0].Value 328 | } 329 | 330 | New-ElasticsearchCluster $clusterResourceGroup $clusterName $location $mainTemplate $templateParameters 331 | 332 | ######################################################################################### 333 | # Create the website, or use existing one if resource group with same name already exists 334 | ######################################################################################### 335 | 336 | $webAppResourceGroup = "nusearch-web" 337 | $webAppName = "nusearch-app" 338 | $webAppParameters = @{ 339 | "siteName" = $webAppName 340 | "hostingPlanName" = "nusearch" 341 | "sku" = "S1" 342 | "workerSize" = "1" 343 | "repoURL" = "https://github.com/elastic/elasticsearch-net-example.git" 344 | "branch" = "5.x-deploy" 345 | } 346 | 347 | New-Website $webAppResourceGroup $webAppName $location $webAppParameters 348 | 349 | ######################################## 350 | # Add the website to the Virtual Network 351 | ######################################## 352 | 353 | Add-AppServiceToExistingVnet $subscriptionId $webAppResourceGroup $webAppName $templateParameters.vNetName $clusterResourceGroup 354 | 355 | ################################################################################ 356 | # Update the app settings for the website to point to the internal load balancer 357 | ################################################################################ 358 | 359 | $appSettings = @{ 360 | "ElasticClient:Host" = "$($templateParameters.vNetLoadBalancerIp)" 361 | "ElasticClient:Username" = "es_read" 362 | "ElasticClient:Password" = $SecurityReadPassword 363 | } 364 | 365 | Add-AppSettings $webAppResourceGroup $webAppName $appSettings 366 | 367 | <# 368 | TODO: automate these as part of the example 369 | 370 | Configure azure repository for snapshots 371 | ---------------------------------------- 372 | 373 | PUT _snapshot/nusearchdata 374 | { 375 | "type": "azure", 376 | "settings": { 377 | "container": "backups" 378 | } 379 | } 380 | 381 | POST _snapshot/nusearchdata/_verify 382 | 383 | GET _snapshot/nusearchdata/_all 384 | 385 | POST /_snapshot/nusearchdata/snapshot_1/_restore?wait_for_completion=true 386 | 387 | 388 | Need to Sync Network in Azure Portal! 389 | ------------------------------------- 390 | 391 | nusearch-web -> App Service Plan -> Networking -> VNet Integration -> click network name -> click Sync Network 392 | 393 | #> 394 | --------------------------------------------------------------------------------