RDSFarm
This commit is contained in:
Родитель
8a831a49b0
Коммит
f14273beb0
Двоичные данные
rds-deployment-existing-ad/Configuration.zip
Двоичные данные
rds-deployment-existing-ad/Configuration.zip
Двоичный файл не отображается.
|
@ -1,64 +1,16 @@
|
|||
# Create Remote Desktop Sesson Collection deployment using existing AD.
|
||||
This template will create a Remote Desktop Sesson Collection farm using the PowerShell DSC Extension. Please note this expects that AD is already setup (The Vnet and Subnet names are currently in variables so, you need to update it to use yours). it creates the following resources:
|
||||
# Create Remote Desktop Sesson Collection deployment
|
||||
|
||||
+ One Storage Account
|
||||
+ One external load balancer
|
||||
+ One VM configured as RDS Connection Broker and Licensing Server role
|
||||
+ One VM configured as RDS Gateway and Web access Server role
|
||||
+ One (or more) VMs configured as RDSH host role. NOTE: Because HA is not supported on Azure Stack Development Kit, please use only one VM or it will fail.
|
||||
+ The imageSKU is choice in parameter and rest of image configuration is defined in variables - but the scripts that configure this deployment have only been tested with windows server 2012 R2 data center image and may not work on other images.
|
||||
This template deploys the following resources:
|
||||
|
||||
## Deploying from Portal
|
||||
<ul><li>storage account;</li><li>RD Gateway/RD Web Access vm;</li><li>RD Connection Broker/RD Licensing Server vm;</li><li>a number of RD Session hosts (number defined by 'numberOfRdshInstances' parameter)</li></ul>
|
||||
|
||||
+ Login into Azurestack portal
|
||||
+ Click "New" -> "Custom" -> "Template deployment"
|
||||
+ Deploy ad-non-ha template. if you already have deployed ad-non-ha, then you can use that AD deployment by its resource group for this deployment.
|
||||
+ Copy conent in azuredeploy.json, Click "Edit Tempalte" and paste content, then Click "Save"
|
||||
+ Fill the parameters. Again, this uses existing AD. Please see note above.
|
||||
+ Click "Create new" to create new Resource Group
|
||||
+ Click "Create"
|
||||
The template will use existing DC, join all vms to the domain and configure RDS roles in the deployment.
|
||||
|
||||
## Deploying from PowerShell
|
||||
Click the button below to deploy
|
||||
|
||||
Download azuredeploy.json and azuredeploy.azurestack.parameters.json to local machine
|
||||
|
||||
Modify parameter value in azuredeploy.azurestack.parameters.json as needed
|
||||
|
||||
Allow cookies in IE: Open IE at c:\Program Files\Internet Explorer\iexplore.exe -> Internet Options -> Privacy -> Advanced -> Click OK -> Click OK again
|
||||
|
||||
Launch a PowerShell console
|
||||
|
||||
Change working folder to the folder containing this template
|
||||
|
||||
```PowerShell
|
||||
|
||||
# Add specific Azure Stack Environment
|
||||
|
||||
$AadTenantId = <Tenant Id> #GUID Specific to the AAD Tenant
|
||||
|
||||
Add-AzureRmEnvironment -Name 'Azure Stack' `
|
||||
<EFBFBD><EFBFBD><EFBFBD> -ActiveDirectoryEndpoint ("https://login.windows.net/$AadTenantId/") `
|
||||
<EFBFBD><EFBFBD><EFBFBD> -ActiveDirectoryServiceEndpointResourceId "https://azurestack.local-api/" `
|
||||
<EFBFBD><EFBFBD><EFBFBD> -ResourceManagerEndpoint ("https://api.azurestack.local/") `
|
||||
<EFBFBD><EFBFBD><EFBFBD> -GalleryEndpoint ("https://gallery.azurestack.local/") `
|
||||
<EFBFBD><EFBFBD><EFBFBD> -GraphEndpoint "https://graph.windows.net/"
|
||||
|
||||
# Get Azure Stack Environment Information
|
||||
$env = Get-AzureRmEnvironment 'Azure Stack'
|
||||
|
||||
# Authenticate to AAD with Azure Stack Environment
|
||||
Add-AzureRmAccount -Environment $env -Verbose
|
||||
|
||||
# Get Azure Stack Environment Subscription
|
||||
$SubName = <Subscription Name> # The sbuscription name is the offer name by default
|
||||
Get-AzureRmSubscription -SubscriptionName $SubName | Select-AzureRmSubscription
|
||||
|
||||
#Resource group name. Please make sure the resource group does not exist
|
||||
$resourceGroupName = "rdsResourceGroup"
|
||||
$deploymentName = "RDSDeployment"
|
||||
$location = "Local"
|
||||
New-AzurermResourceGroup -Name $resourceGroupName -Location $location
|
||||
|
||||
#Start new Deployment
|
||||
New-AzurermResourceGroupDeployment -Name $deploymentName -ResourceGroupName $resourceGroupName `
|
||||
<EFBFBD><EFBFBD><EFBFBD> -TemplateParameterFile .\azuredeploy.parameters.json -TemplateFile .\azuredeploy.json
|
||||
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2Frds-deployment-existing-ad%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://azuredeploy.net/deploybutton.png"/>
|
||||
</a>
|
||||
<a href="http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2Frds-deployment-existing-ad%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://armviz.io/visualizebutton.png"/>
|
||||
</a>
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"dnsLabelPrefix": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Unique public DNS prefix for the deployment. The fqdn will look something like '<dnsname>.westus.cloudapp.azure.com'. Up to 62 chars, digits or dashes, lowercase, should start with a letter: must conform to '^[a-z][a-z0-9-]{1,61}[a-z0-9]$'. For example johndns1 will result the final RDWEB access url like https://johndns1.westus.cloudapp.azure.com/RDWeb"
|
||||
}
|
||||
},
|
||||
"adDomainName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
|
@ -10,14 +16,14 @@
|
|||
"defaultValue": "contoso.com"
|
||||
},
|
||||
"adVnetName": {
|
||||
"type": "string",
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The vnet name of AD domain. For example johnvnet1"
|
||||
},
|
||||
"defaultValue": "[concat('ADVNET',resourceGroup().name)]"
|
||||
},
|
||||
"defaultValue": "[concat('ADVNET',resourceGroup().name)]"
|
||||
},
|
||||
"adSubnetName": {
|
||||
"type": "string",
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The subnet name of AD domain. For example johnsubnet1"
|
||||
},
|
||||
|
@ -41,261 +47,327 @@
|
|||
"type": "string",
|
||||
"allowedValues": [
|
||||
"2012-R2-Datacenter",
|
||||
"Windows-Server-Technical-Preview"
|
||||
"2016-Datacenter"
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Windows server SKU"
|
||||
},
|
||||
"defaultValue": "2012-R2-Datacenter"
|
||||
"defaultValue": "2016-Datacenter"
|
||||
},
|
||||
"NumberOfRemoteDesktopSessionHosts": {
|
||||
"numberOfRdshInstances": {
|
||||
"type": "int",
|
||||
"defaultValue": 1,
|
||||
"metadata": {
|
||||
"description": "Number of RemoteDesktopSessionHosts"
|
||||
}
|
||||
},
|
||||
"rdshVmSize": {
|
||||
"type": "string",
|
||||
"allowedValues": [
|
||||
"Standard_A0",
|
||||
"Standard_A1",
|
||||
"Standard_A2",
|
||||
"Standard_A3",
|
||||
"Standard_A4",
|
||||
"Standard_A5",
|
||||
"Standard_A6",
|
||||
"Standard_A7",
|
||||
"Standard_D1",
|
||||
"Standard_D2",
|
||||
"Standard_D3",
|
||||
"Standard_D4",
|
||||
"Standard_D5"
|
||||
],
|
||||
"metadata": {
|
||||
"description": "The size of the RDSH VMs"
|
||||
},
|
||||
"defaultValue": "Standard_A4"
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"dnsLabelPrefix": "[concat('rdsdns', resourceGroup().name)]",
|
||||
"gwdnsLabelPrefix": "[concat('gw', resourceGroup().name)]",
|
||||
"cbdnsLabelPrefix": "[concat('cb', resourceGroup().name)]",
|
||||
"rdshVmSize": "Standard_A2",
|
||||
"storageAccountName": "[concat('sa', resourceGroup().name)]",
|
||||
"storageAccountType": "Standard_LRS",
|
||||
"uniqueStorageAccountContainerName": "[concat('sc', resourceGroup().name)]",
|
||||
"imagePublisher": "MicrosoftWindowsServer",
|
||||
"imageOffer": "WindowsServer",
|
||||
"dnsServerPrivateIp": "10.0.0.4",
|
||||
"subnet-id": "[concat(resourceId('Microsoft.Network/virtualNetworks',parameters('adVnetName')),'/subnets/',parameters('adSubnetName'))]",
|
||||
"publicIpRef": "publicIp",
|
||||
"brokerIpRef": "brokerpublicIp",
|
||||
"gatewayIpRef": "gatewaypublicIp",
|
||||
"assetLocation": "https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/rds-deployment-existing-ad/"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"name": "[variables('publicIpRef')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "Dynamic",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[variables('dnsLabelPrefix')]"
|
||||
}
|
||||
"variables": {
|
||||
"gwdnsLabelPrefix": "[toLower(concat('gwd', resourceGroup().name))]",
|
||||
"cbdnsLabelPrefix": "[toLower(concat('cbd', resourceGroup().name))]",
|
||||
"storageAccountName": "[tolower(concat('rdsa', uniqueString(resourceGroup().id)))]",
|
||||
"storageAccountType": "Standard_LRS",
|
||||
"uniqueStorageAccountContainerName": "[toLower(concat('sac', resourceGroup().name))]",
|
||||
"imagePublisher": "MicrosoftWindowsServer",
|
||||
"imageOffer": "WindowsServer",
|
||||
"dnsServerPrivateIp": "10.0.0.4",
|
||||
"subnet-id": "[concat(resourceId('Microsoft.Network/virtualNetworks',parameters('adVnetName')),'/subnets/',parameters('adSubnetName'))]",
|
||||
"publicIpRef": "publicIp",
|
||||
"brokerIpRef": "brokerpublicIp",
|
||||
"gatewayIpRef": "gatewaypublicIp",
|
||||
"assetLocation": "https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/rds-deployment/"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"name": "[variables('publicIpRef')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "Dynamic",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[parameters('dnsLabelPrefix')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"name": "[variables('gatewayIpRef')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "Dynamic",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[variables('gwdnsLabelPrefix')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"name": "[variables('brokerIpRef')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "Dynamic",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[variables('cbdnsLabelPrefix')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Storage/storageAccounts",
|
||||
"name": "[variables('storageAccountName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"accountType": "[variables('storageAccountType')]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "gw-availabilityset",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "cb-availabilityset",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "rdsh-availabilityset",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/loadBalancers",
|
||||
"name": "loadBalancer",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/publicIPAddresses/',variables('publicIpRef'))]"
|
||||
],
|
||||
"properties": {
|
||||
"frontendIPConfigurations": [
|
||||
{
|
||||
"name": "LBFE",
|
||||
"properties": {
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIpRef'))]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"backendAddressPools": [
|
||||
{
|
||||
"name": "LBBAP"
|
||||
}
|
||||
],
|
||||
"loadBalancingRules": [
|
||||
{
|
||||
"name": "LBRule01",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadbalancer'),'/frontendIPConfigurations/LBFE')]"
|
||||
},
|
||||
"backendAddressPool": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadbalancer'),'/backendAddressPools/LBBAP')]"
|
||||
},
|
||||
"protocol": "Tcp",
|
||||
"frontendPort": 443,
|
||||
"backendPort": 443,
|
||||
"enableFloatingIP": false,
|
||||
"idleTimeoutInMinutes": 5,
|
||||
"loadDistribution": "SourceIPProtocol",
|
||||
"probe": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadbalancer'),'/probes/tcpProbe')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "LBRule02",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadbalancer'),'/frontendIPConfigurations/LBFE')]"
|
||||
},
|
||||
"backendAddressPool": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadbalancer'),'/backendAddressPools/LBBAP')]"
|
||||
},
|
||||
"protocol": "Udp",
|
||||
"frontendPort": 3391,
|
||||
"backendPort": 3391,
|
||||
"enableFloatingIP": false,
|
||||
"idleTimeoutInMinutes": 5,
|
||||
"loadDistribution": "SourceIPProtocol",
|
||||
"probe": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadbalancer'),'/probes/tcpProbe')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"name": "tcpProbe",
|
||||
"properties": {
|
||||
"protocol": "Tcp",
|
||||
"port": 443,
|
||||
"intervalInSeconds": 5,
|
||||
"numberOfProbes": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tcpProbe01",
|
||||
"properties": {
|
||||
"protocol": "Tcp",
|
||||
"port": 3391,
|
||||
"intervalInSeconds": 5,
|
||||
"numberOfProbes": 2
|
||||
}
|
||||
}
|
||||
],
|
||||
"inboundNatRules": [
|
||||
{
|
||||
"name": "rdp",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadBalancer'),'/frontendIPConfigurations/LBFE')]"
|
||||
},
|
||||
"protocol": "tcp",
|
||||
"frontendPort": 3389,
|
||||
"backendPort": 3389,
|
||||
"enableFloatingIP": false
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "gw-nic",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"Microsoft.Network/loadBalancers/loadBalancer"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('gatewayIpRef'))]"
|
||||
},
|
||||
"subnet": {
|
||||
"id": "[variables('subnet-id')]"
|
||||
},
|
||||
"loadBalancerBackendAddressPools": [
|
||||
{
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadBalancer'),'/backendAddressPools/LBBAP')]"
|
||||
}
|
||||
],
|
||||
"loadBalancerInboundNatRules": [
|
||||
{
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadBalancer'),'/inboundNatRules/rdp')]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"dnsSettings": {
|
||||
"dnsServers": [
|
||||
"[variables('dnsServerPrivateIp')]"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "cb-nic",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"Microsoft.Network/loadBalancers/loadBalancer"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('brokerIpRef'))]"
|
||||
},
|
||||
"subnet": {
|
||||
"id": "[variables('subnet-id')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"dnsSettings": {
|
||||
"dnsServers": [
|
||||
"[variables('dnsServerPrivateIp')]"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "[concat('rdsh-', copyindex(), '-nic')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"copy": {
|
||||
"name": "rdsh-nic-loop",
|
||||
"count": "[parameters('numberOfRdshInstances')]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"name": "[variables('gatewayIpRef')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"Microsoft.Network/loadBalancers/loadBalancer"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "Dynamic",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[variables('gwdnsLabelPrefix')]"
|
||||
}
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"subnet": {
|
||||
"id": "[variables('subnet-id')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"name": "[variables('brokerIpRef')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "Dynamic",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[variables('cbdnsLabelPrefix')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Storage/storageAccounts",
|
||||
"name": "[variables('storageAccountName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"accountType": "[variables('storageAccountType')]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "gw-availabilityset",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "cb-availabilityset",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "rdsh-availabilityset",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/loadBalancers",
|
||||
"name": "loadBalancer",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/publicIPAddresses/',variables('publicIpRef'))]"
|
||||
],
|
||||
"properties": {
|
||||
"frontendIPConfigurations": [
|
||||
{
|
||||
"name": "LBFE",
|
||||
"properties": {
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIpRef'))]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"backendAddressPools": [
|
||||
{
|
||||
"name": "LBBAP"
|
||||
}
|
||||
],
|
||||
"inboundNatRules": [
|
||||
{
|
||||
"name": "https",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadBalancer'),'/frontendIPConfigurations/LBFE')]"
|
||||
},
|
||||
"protocol": "tcp",
|
||||
"frontendPort": 443,
|
||||
"backendPort": 443,
|
||||
"enableFloatingIP": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "gateway",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadBalancer'),'/frontendIPConfigurations/LBFE')]"
|
||||
},
|
||||
"protocol": "udp",
|
||||
"frontendPort": 3391,
|
||||
"backendPort": 3391,
|
||||
"enableFloatingIP": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "gw-nic",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"Microsoft.Network/loadBalancers/loadBalancer",
|
||||
"[concat('Microsoft.Network/publicIPAddresses/',variables('gatewayIpRef'))]"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('gatewayIpRef'))]"
|
||||
},
|
||||
"subnet": {
|
||||
"id": "[variables('subnet-id')]"
|
||||
},
|
||||
"loadBalancerBackendAddressPools": [
|
||||
{
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadBalancer'),'/backendAddressPools/LBBAP')]"
|
||||
}
|
||||
],
|
||||
"loadBalancerInboundNatRules": [
|
||||
{
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadBalancer'),'/inboundNatRules/https')]"
|
||||
},
|
||||
{
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadBalancer'),'/inboundNatRules/gateway')]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"dnsSettings": {
|
||||
"dnsServers": [
|
||||
"[variables('dnsServerPrivateIp')]"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "cb-nic",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"Microsoft.Network/loadBalancers/loadBalancer",
|
||||
"[concat('Microsoft.Network/publicIPAddresses/',variables('brokerIpRef'))]"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('brokerIpRef'))]"
|
||||
},
|
||||
"subnet": {
|
||||
"id": "[variables('subnet-id')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"dnsSettings": {
|
||||
"dnsServers": [
|
||||
"[variables('dnsServerPrivateIp')]"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "[concat('rdsh-', copyindex(), '-nic')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"copy": {
|
||||
"name": "rdsh-nic-loop",
|
||||
"count": "[parameters('NumberOfRemoteDesktopSessionHosts')]"
|
||||
},
|
||||
"dependsOn": [
|
||||
"Microsoft.Network/loadBalancers/loadBalancer"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"subnet": {
|
||||
"id": "[variables('subnet-id')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"dnsSettings": {
|
||||
"dnsServers": [
|
||||
"[variables('dnsServerPrivateIp')]"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
}
|
||||
],
|
||||
"dnsSettings": {
|
||||
"dnsServers": [
|
||||
"[variables('dnsServerPrivateIp')]"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines",
|
||||
"name": "gw-vm",
|
||||
|
@ -327,7 +399,7 @@
|
|||
"osDisk": {
|
||||
"name": "osdisk",
|
||||
"vhd": {
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','gw-vm-os-disk.vhd')]"
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),'2016-01-01').primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','gw-vm-os-disk.vhd')]"
|
||||
},
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage"
|
||||
|
@ -382,7 +454,7 @@
|
|||
"location": "[resourceGroup().location]",
|
||||
"copy": {
|
||||
"name": "rdsh-vm-loop",
|
||||
"count": "[parameters('NumberOfRemoteDesktopSessionHosts')]"
|
||||
"count": "[parameters('numberOfRdshInstances')]"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
|
||||
|
@ -391,7 +463,7 @@
|
|||
],
|
||||
"properties": {
|
||||
"hardwareProfile": {
|
||||
"vmSize": "[variables('rdshVmSize')]"
|
||||
"vmSize": "[parameters('rdshVmSize')]"
|
||||
},
|
||||
"availabilitySet": {
|
||||
"id": "[resourceId('Microsoft.Compute/availabilitySets', 'rdsh-availabilityset')]"
|
||||
|
@ -411,7 +483,7 @@
|
|||
"osDisk": {
|
||||
"name": "osdisk",
|
||||
"vhd": {
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','rdsh-',copyindex(),'-os-disk.vhd')]"
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),'2016-01-01').primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','rdsh-',copyindex(),'-os-disk.vhd')]"
|
||||
|
||||
},
|
||||
"caching": "ReadWrite",
|
||||
|
@ -493,7 +565,7 @@
|
|||
"osDisk": {
|
||||
"name": "osdisk",
|
||||
"vhd": {
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','cb-vm-os-disk.vhd')]"
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),'2016-01-01').primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','cb-vm-os-disk.vhd')]"
|
||||
},
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage"
|
||||
|
@ -521,11 +593,11 @@
|
|||
"properties": {
|
||||
"publisher": "Microsoft.Powershell",
|
||||
"type": "DSC",
|
||||
"typeHandlerVersion": "2.11",
|
||||
"typeHandlerVersion": "2.75",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"ModulesUrl": "[concat(variables('assetLocation'),'/Configuration.zip')]",
|
||||
"ConfigurationFunction": "Configuration.ps1\\RDSDeployment",
|
||||
"modulesUrl": "[concat(variables('assetLocation'),'/Configuration.zip')]",
|
||||
"configurationFunction": "Configuration.ps1\\RDSDeployment",
|
||||
"Properties": {
|
||||
"adminCreds": {
|
||||
"UserName": "[parameters('adminUsername')]",
|
||||
|
@ -533,8 +605,8 @@
|
|||
},
|
||||
"connectionBroker": "[concat('broker.',parameters('adDomainName'))]",
|
||||
"domainName": "[parameters('adDomainName')]",
|
||||
"externalfqdn": "[concat('gateway.',parameters('adDomainName'))]",
|
||||
"numberOfRdshInstances": "[parameters('NumberOfRemoteDesktopSessionHosts')]",
|
||||
"externalfqdn": "[reference(variables('gatewayIpRef')).dnsSettings.fqdn]",
|
||||
"numberOfRdshInstances": "[parameters('numberOfRdshInstances')]",
|
||||
"sessionHostNamingPrefix": "rdsh-",
|
||||
"webAccessServer": "[concat('gateway.',parameters('adDomainName'))]"
|
||||
}
|
||||
|
@ -546,5 +618,5 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"dnsLabelPrefix": {
|
||||
"value": "GEN-UNIQUE"
|
||||
},
|
||||
"adminPassword": {
|
||||
"value": "GEN-PASSWORD"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"itemDisplayName": "RDS deployment using existing active directory",
|
||||
"description": "This template creates a simple RDSH deployment using existing active directory in same resource group",
|
||||
"summary": "Creates RDSH deployment using existing active directory in same resource group",
|
||||
"githubUsername": "azurestack",
|
||||
"dateUpdated": "2016-09-20"
|
||||
"itemDisplayName": "RDS farm deployment using existing active directory",
|
||||
"description": "This template creates a RDS farm deployment using existing active directory in same resource group",
|
||||
"summary": "Creates and deploys fully functional RDS farm deployment using existing active directory in same resource group",
|
||||
"githubUsername": "MahendraAgrawal",
|
||||
"dateUpdated": "2016-10-12"
|
||||
}
|
||||
|
|
Двоичный файл не отображается.
|
@ -0,0 +1,43 @@
|
|||
# Provide High Availability to RD Connection Broker servers in RDS deployment
|
||||
|
||||
This template deploys the following resources:
|
||||
|
||||
* a second RD Connection Broker VM including a NIC and StorageAccount
|
||||
|
||||
The template will
|
||||
|
||||
* Create a new VM and join the new VM to the domain
|
||||
* Prepare the existing RDS Deployment for RDCB HA
|
||||
* Add the RD Connection Broker role to the new VM and join it to the deployment
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Current Template is an extension to the Basic RDS Deployment Template, and it is mandatory to deploy any one of the template as prerequisite:
|
||||
|
||||
* Basic RDS deployment template
|
||||
https://github.com/Azure/azure-quickstart-templates/tree/master/rds-deployment
|
||||
|
||||
* RDS deployment on pre-existing VNET and AD
|
||||
https://github.com/Azure/azure-quickstart-templates/tree/master/rds-deployment-existing-ad
|
||||
|
||||
* An Azure SQL Database, or a VM running SQL Server also needs to be in place to house the RDCB Database
|
||||
|
||||
This template expects the same names of resources from RDS deployment, if resource names are changed in your deployment then please edit the parameters and resources accordingly, example of such resources are below:
|
||||
<ul>
|
||||
<li>storageAccountName: Resource must be exact same to existing RDS deployment.</li>
|
||||
<li>publicIpRef: Resource must be exact same to existing RDS deployment.</li>
|
||||
<li>availabilitySets: Resource must be exact same to existing RDS deployment.</li>
|
||||
<li>Load-balancer: Load balancer name, Backend pool, LB-rules, Nat-Rule and NIC.</li>
|
||||
<li>VM’s – VM name classification which is using copy index function.</li>
|
||||
<li>NIC – NIC naming convention.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
Click the button below to deploy
|
||||
|
||||
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FRDS-Templates%2Fmaster%2Frds-deployment-ha-broker%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://azuredeploy.net/deploybutton.png"/>
|
||||
</a>
|
||||
<a href="http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FRDS-templates%2Fmaster%2Frds-deployment-ha-broker%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://armviz.io/visualizebutton.png"/>
|
||||
</a>
|
|
@ -0,0 +1,374 @@
|
|||
<#
|
||||
.SYNOPSIS
|
||||
HA Broker configuration.
|
||||
|
||||
.DESCRIPTION
|
||||
Script should run on the new RD Connection Broker in the deployment.
|
||||
|
||||
.PARAMETER newBroker
|
||||
Name of the new server to add as secondary broker.
|
||||
|
||||
#>
|
||||
|
||||
param
|
||||
(
|
||||
[String]$existingBroker,
|
||||
[String]$primaryDbConnectionString,
|
||||
[string]$domainName,
|
||||
[String]$username,
|
||||
[String]$password,
|
||||
[string]$clientAccessName,
|
||||
[string]$sqlClientUrl,
|
||||
[string]$dnsServer,
|
||||
[string]$sqlServer
|
||||
)
|
||||
|
||||
$localhost = [System.Net.Dns]::GetHostByName((hostname)).HostName
|
||||
$domainNetbios = (Get-ADDomain -Current LocalComputer).NetBIOSName
|
||||
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($domainNetbios + "\" + $username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
|
||||
|
||||
$ConfigData = @{
|
||||
AllNodes = @(
|
||||
@{
|
||||
NodeName = 'localhost'
|
||||
PSDscAllowPlainTextPassword = $true
|
||||
}
|
||||
)
|
||||
} # End of Config Data
|
||||
|
||||
$Logfile = ".\CB_PostConfig1.1_{0}.log" -f (get-date -Format "yyyyMMddhhmmss")
|
||||
|
||||
function GetServersByRole($roleName)
|
||||
{
|
||||
$RemoteSqlOdbcconn = new-object System.Data.Odbc.OdbcConnection
|
||||
$RemoteSqlOdbcconn.ConnectionString = $primaryDbConnectionString
|
||||
$RemoteSqlOdbcconn.Open()
|
||||
|
||||
$OdbcCmdStr = "SELECT s.Name FROM rds.Server s INNER JOIN rds." + $roleName + " cb ON s.Id = cb.ServerId"
|
||||
$RemoteSqlOdbccmd = new-object System.Data.Odbc.OdbcCommand
|
||||
$RemoteSqlOdbccmd.CommandText = $OdbcCmdStr
|
||||
$RemoteSqlOdbccmd.Connection = $RemoteSqlOdbcconn
|
||||
$SqlRdr = $RemoteSqlOdbccmd.ExecuteReader()
|
||||
while ($SqlRdr.Read() -eq $true)
|
||||
{
|
||||
$ServerArr += @($SqlRdr.GetString(0).Split('.')[0])
|
||||
}
|
||||
|
||||
$SqlRdr.Close()
|
||||
$RemoteSqlOdbccmd.Dispose()
|
||||
$RemoteSqlOdbcconn.Close()
|
||||
return $ServerArr
|
||||
}
|
||||
|
||||
function GetIpAddress([string]$compName, [int]$ipType)
|
||||
{
|
||||
$IPconfigset = Get-WmiObject -ComputerName $compName Win32_NetworkAdapterConfiguration
|
||||
foreach ($IPConfig in $IPconfigset)
|
||||
{
|
||||
if (!$Ipconfig.IPaddress -or
|
||||
($Ipconfig.IPEnabled -eq $FALSE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($addrStr in $Ipconfig.Ipaddress)
|
||||
{
|
||||
$addr = [System.Net.IPAddress]::Parse($addrStr);
|
||||
if (($ipType -eq 4) -and
|
||||
($addr.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork))
|
||||
{
|
||||
return $addr;
|
||||
}
|
||||
elseif (($ipType -eq 6) -and
|
||||
($addr.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetworkV6) -and
|
||||
(!$addrStr.StartsWith("fe80")))
|
||||
{
|
||||
return $addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function AddDomainComputersToRDSMgmtServerGroup()
|
||||
{
|
||||
$rdmsGroupName = "RDS Management Servers";
|
||||
$objOU = [ADSI]("WinNT://" + $env:computername)
|
||||
$objGroup = $objOU.psbase.children.find($rdmsGroupName)
|
||||
|
||||
$machineAcc = "Domain Computers"
|
||||
$membershipExists = $objGroup.psbase.invoke("Members") | %{$_.GetType().InvokeMember("Name",'GetProperty',$null,$_,$null)} | where {$_ -eq $machineAcc}
|
||||
if ( !($membershipExists.length -gt 1) )
|
||||
{
|
||||
$objGroup.Add("WinNT://" + $domainName + "/" + $machineAcc)
|
||||
}
|
||||
}
|
||||
|
||||
function SetupVMHA($compName)
|
||||
{
|
||||
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $compName);
|
||||
|
||||
$regKey = $reg.OpenSubKey('SYSTEM\CurrentControlSet\Services\VMHostAgent\Parameters', 'ReadWriteSubTree', 'SetValue');
|
||||
$regKey.SetValue('tssdis',$brokerMachineList, 'string');
|
||||
|
||||
AddDomainComputersToRDSMgmtServerGroup;
|
||||
}
|
||||
|
||||
function SetupRDSH($compName)
|
||||
{
|
||||
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $compName);
|
||||
|
||||
$regKey = $reg.OpenSubKey('SYSTEM\CurrentControlSet\Control\Terminal Server\ClusterSettings', 'ReadWriteSubTree', 'SetValue');
|
||||
$regKey.SetValue('SessionDirectoryLocation',$brokerMachineList, 'string');
|
||||
|
||||
AddDomainComputersToRDSMgmtServerGroup;
|
||||
}
|
||||
|
||||
function SetupRDWA($compName)
|
||||
{
|
||||
$rdweb = Get-WmiObject -ComputerName $compName AppSettingssection -namespace root\webadministration -Authentication 6
|
||||
$appSection = $rdweb[0]
|
||||
$objAppSettings = $appSection.AppSettings
|
||||
|
||||
foreach ($cfg in $objAppSettings)
|
||||
{
|
||||
if ($cfg.key.CompareTo("radcmserver") -eq 0)
|
||||
{
|
||||
Write-Host "Changing" $cfg.Value "to" $brokerMachineList
|
||||
$cfg.Value = $brokerMachineList
|
||||
}
|
||||
}
|
||||
$appSection.SetPropertyValue("AppSettings", $objAppSettings)
|
||||
$PutOptions = New-Object System.Management.PutOptions
|
||||
$PutOptions.Type = 1 # update only
|
||||
$appSection.Put($PutOptions)
|
||||
Write-Host "Successfully configured RDWeb's Broker name"
|
||||
}
|
||||
|
||||
function SetupGroups($sqlServer, $computerName, $domain)
|
||||
{
|
||||
$computerName = $computerName.ToLower() -replace "." + $domain.ToLower()
|
||||
|
||||
Invoke-Command -ComputerName $sqlServer -ScriptBlock {
|
||||
param( $computerName )
|
||||
$grMembers = net localgroup "RDS Management Servers"
|
||||
$fnd = $false
|
||||
foreach ($gr in $grMembers)
|
||||
{
|
||||
if ( $gr -Like "*$computerName$" ) { $fnd = $true; break }
|
||||
}
|
||||
if ( $fnd -eq $false )
|
||||
{
|
||||
Write-Output ("Adding $($computerName) to the local RDS Management Servers group")
|
||||
net localgroup "RDS Management Servers" /add "$computerName`$"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Output("Computer $($computerName) is already a member of the group")
|
||||
}
|
||||
} -ArgumentList $computerName
|
||||
}
|
||||
|
||||
function SetupCB($compName, $clientURL)
|
||||
{
|
||||
Write-Output("Starting Install of client on broker machine: $compName [end]")
|
||||
Write-Output("Active broker: $activeBroker")
|
||||
Write-Output("Client URL: $clientURL")
|
||||
try
|
||||
{
|
||||
Invoke-Command -ComputerName $compName -ScriptBlock { param($clientURL, $installPath, $domainNetbios)
|
||||
Write-Output("Running Invoke Command")
|
||||
$installPath = "$env:temp\Install-$(Get-Date -format 'yyyy-dd hh-mm-ss').msi"
|
||||
|
||||
if(!(Split-Path -parent $installPath) -or !(Test-Path -PathType Container (Split-Path -parent $installPath))) {
|
||||
$installPath = Join-Path $pwd (Split-Path -leaf $path)
|
||||
}
|
||||
|
||||
Write-Output("Downloading new client from: $($installPath)")
|
||||
Invoke-WebRequest -Uri $clientURL -OutFile $installPath -UserAgent [Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer
|
||||
Write-Output("FinishedDownloading Client and starting install")
|
||||
sleep -Seconds 10
|
||||
$result = (Start-Process -FilePath "msiexec.exe" -ArgumentList "/i ""$installPath"" /passive ADDLOCAL=ALL APPGUID={0CC618CE-F36A-415E-84B4-FB1BFF6967E1} IACCEPTSQLNCLILICENSETERMS=YES" -Wait -PassThru).ExitCode
|
||||
Write-Output("Result from installing client: $($result)")
|
||||
|
||||
#
|
||||
# Add Domain Computers to RDS Endpoint Servers group
|
||||
Write-Output("Checking Domain computer registration")
|
||||
$rdsServersGroupName = "RDS Endpoint Servers"
|
||||
$objOU = [ADSI]("WinNT://" + $env:computername)
|
||||
$objGroup = $objOU.psbase.children.find($rdsServersGroupName)
|
||||
$machineAcc = "Domain Computers"
|
||||
Write-Output("Checking Membership")
|
||||
|
||||
$membershipExists = $objGroup.psbase.invoke("Members") | %{$_.GetType().InvokeMember("Name",'GetProperty',$null,$_,$null)} | where {$_ -eq $machineAcc}
|
||||
if ( !($membershipExists.length -gt 1) )
|
||||
{
|
||||
Write-Output("Attempting to add domain: $domainNetbios and Account: $machineAcc")
|
||||
$objGroup.Add("WinNT://" + $domainNetbios + "/" + $machineAcc)
|
||||
Write-Output("Account added")
|
||||
}
|
||||
Write-Output("Completed setup for broker")
|
||||
} -ArgumentList $clientURL, $installPath, $domainNetbios | Out-File -Append $Logfile
|
||||
}
|
||||
catch [Exception] {
|
||||
WriteLog("Exception installing the client on the localhost: $($_.Exception.Message)")
|
||||
throw
|
||||
}
|
||||
Write-Output "Setting up Group membership for $compName on SQL"
|
||||
if(![string]::IsNullOrEmpty($sqlServer)) # only run if $sqlServer is not null
|
||||
{
|
||||
SetupGroups $sqlServer $compName $domainNetbios
|
||||
}
|
||||
}
|
||||
|
||||
Function WriteLog
|
||||
{
|
||||
Param ([string]$logstring)
|
||||
|
||||
Add-content $Logfile -value $logstring
|
||||
Write-Host $logstring
|
||||
}
|
||||
|
||||
WriteLog("Starting PostConfig on machine $($localhost)")
|
||||
if ($existingBroker.ToLower().EndsWith($domainName) -eq $false)
|
||||
{
|
||||
$existingBroker = $existingBroker + "." + $domainName
|
||||
}
|
||||
|
||||
if ($clientAccessName.ToLower().EndsWith($domainName) -eq $false)
|
||||
{
|
||||
$clientAccessName = $clientAccessName + "." + $domainName
|
||||
}
|
||||
|
||||
#Impersonate user
|
||||
$ImpersonatedUser = @{}
|
||||
WriteLog "impersonating as '$username'..."
|
||||
Add-Type -Namespace Import -Name Win32 -MemberDefinition @'
|
||||
[DllImport("advapi32.dll", SetLastError = true)]
|
||||
public static extern bool LogonUser(string user, string domain, string password, int logonType, int logonProvider, out IntPtr token);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool CloseHandle(IntPtr handle);
|
||||
'@
|
||||
|
||||
$tokenHandle = 0
|
||||
$returnValue = [Import.Win32]::LogonUser($userName, $domainName, $password, 2, 0, [ref]$tokenHandle)
|
||||
|
||||
if (!$returnValue)
|
||||
{
|
||||
$errCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error();
|
||||
WriteLog "failed a call to LogonUser with error code: $errCode"
|
||||
throw [System.ComponentModel.Win32Exception]$errCode
|
||||
}
|
||||
else
|
||||
{
|
||||
$ImpersonatedUser.ImpersonationContext = [System.Security.Principal.WindowsIdentity]::Impersonate($tokenHandle)
|
||||
[void][Import.Win32]::CloseHandle($tokenHandle)
|
||||
WriteLog "impersonating user $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name) returnValue: '$returnValue'"
|
||||
}
|
||||
|
||||
whoami
|
||||
|
||||
SetupCB $localhost $sqlClientUrl
|
||||
SetupCB $existingBroker $sqlClientUrl
|
||||
|
||||
$cb1IP = (Resolve-DnsName -Name $existingBroker -Type A).IPAddress
|
||||
$cb2IP = (Resolve-DnsName -Name $localhost -Type A).IPAddress
|
||||
|
||||
Write-Output("Creating DNS Records")
|
||||
Invoke-Command -ComputerName $dnsServer -ScriptBlock {
|
||||
param($domainName, $cb1IP, $cb2IP, $clientAccessName)
|
||||
$zone = "$domainName"
|
||||
$name = $clientAccessName.Split('.') | select -First 1
|
||||
$res= Get-DnsServerResourceRecord -ZoneName $zone -Name $name -EA SilentlyContinue
|
||||
if ( $res -ne $null ) {
|
||||
Remove-DnsServerResourceRecord -ZoneName $zone -Name $name -RRType "A" -force
|
||||
}
|
||||
$cmd = "Add-DnsServerResourceRecordA -ZoneName $zone -Name $name -AllowUpdateAny -Ipv4Address ""$cb1IP"",""$cb2IP"" -PassThru -TimeToLive 00:00:30"
|
||||
Write-Output($cmd)
|
||||
$rec = Invoke-Expression $cmd
|
||||
if ($rec -eq $null)
|
||||
{
|
||||
throw "Unable to add Dns record for ip address $($cb1IP) and $($cb2IP)"
|
||||
}
|
||||
Write-Output("Successfully added ip address")
|
||||
} -ArgumentList $domainName, $cb1IP, $cb2IP, $clientAccessName | Out-File -Append $Logfile
|
||||
|
||||
Write-Output("Completed writing DNS Records")
|
||||
|
||||
WriteLog("Getting Connection Broker High Availability settings")
|
||||
$res = Get-RDConnectionBrokerHighAvailability -ConnectionBroker $existingBroker
|
||||
WriteLog("Result from Get-RDConnectionBrokerHighAvailability: $($res)")
|
||||
|
||||
if ($null -eq $res )
|
||||
{
|
||||
WriteLog("existingBroker: $($existingBroker)")
|
||||
WriteLog("primaryDbConnectionString: $($primaryDbConnectionString)")
|
||||
WriteLog("clientAccessName: $($clientAccessNames)")
|
||||
Set-RDConnectionBrokerHighAvailability -ConnectionBroker $existingBroker -DatabaseConnectionString $primaryDbConnectionString -ClientAccessName $clientAccessName
|
||||
WriteLog("Returning from Set-RDConnectionBroker, checking high availability")
|
||||
$res = Get-RDConnectionBrokerHighAvailability -ConnectionBroker $existingBroker
|
||||
if ( $null -eq $res )
|
||||
{
|
||||
WriteLog "Unable to set the connection broker as high availability"
|
||||
}
|
||||
WriteLog("Result from Get-RDConnectionBrokerHighAvailability: $($res)")
|
||||
}
|
||||
|
||||
WriteLog("Getting Connection broker to see if $($localhost) is added as a connection broker")
|
||||
$res = get-rdserver -ConnectionBroker $existingBroker -Role RDS-CONNECTION-BROKER | select Server
|
||||
if ( $res.Server.ToLower().StartsWith($localhost.ToLower()) )
|
||||
{
|
||||
WriteLog( "$($localhost) is already added as a server")
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLog("Add-RdServer -Server $($localhost) -Role RDS-CONNECTION-BROKER")
|
||||
Add-RdServer -ConnectionBroker $existingBroker -Server $localhost -Role RDS-CONNECTION-BROKER
|
||||
}
|
||||
|
||||
$brokerMachines = GetServersByRole "RoleRdcb"
|
||||
$rdwaMachines = GetServersByRole "RoleRdwa"
|
||||
$rdshMachines = GetServersByRole "RoleRdsh"
|
||||
$rdvhMachines = GetServersByRole "RoleRdvh"
|
||||
|
||||
$brokerCount = 1;
|
||||
$brokerMachineList = "";
|
||||
foreach ($broker in $brokerMachines)
|
||||
{
|
||||
$brokerMachineList = $brokerMachineList + $broker + "." + $env:USERDNSDOMAIN;
|
||||
if ($brokerCount -lt $brokerMachines.Count)
|
||||
{
|
||||
$brokerMachineList = $brokerMachineList + ";"
|
||||
}
|
||||
$brokerCount++;
|
||||
}
|
||||
|
||||
foreach ($broker in $brokerMachines)
|
||||
{
|
||||
#Write-Host "Setting up Redirector machine : " + $broker
|
||||
#SetupRDSH $broker;
|
||||
}
|
||||
|
||||
foreach ($rdvh in $rdvhMachines)
|
||||
{
|
||||
#Write-Host "Setting up RDVH machine : " + $rdvh
|
||||
#SetupVMHA $rdvh;
|
||||
}
|
||||
|
||||
foreach ($rdsh in $rdshMachines)
|
||||
{
|
||||
#Write-Host "Setting up RDSH machine : " + $rdsh
|
||||
#SetupRDSH $rdsh;
|
||||
}
|
||||
|
||||
foreach ($rdwa in $rdwaMachines)
|
||||
{
|
||||
#Write-Host "Setting up RDWA machine : " + $rdwa
|
||||
#SetupRDWA $rdwa
|
||||
}
|
||||
|
||||
Writelog "remove impersonation..."
|
||||
$ImpersonatedUser.ImpersonationContext.Undo()
|
||||
|
||||
WriteLog("Completed setup")
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"clientAccessName": {
|
||||
"type": "string",
|
||||
"defaultValue": "HARDCB",
|
||||
"metadata": {
|
||||
"description": "The name of the Connection Broker Servers to be added to the DNS."
|
||||
}
|
||||
},
|
||||
"dnsServer": {
|
||||
"type": "string",
|
||||
"defaultValue": "addc-01",
|
||||
"metadata": {
|
||||
"description": "The name of the DNS Server to add the DNS entry to for the Connection Broker Names"
|
||||
}
|
||||
},
|
||||
"existingAdminPassword": {
|
||||
"type": "securestring",
|
||||
"metadata": {
|
||||
"description": "The password of the administrator account"
|
||||
}
|
||||
},
|
||||
"existingAdminUsername": {
|
||||
"type": "string",
|
||||
"defaultValue": "cloudAdmin",
|
||||
"metadata": {
|
||||
"description": "Name of domain user account with administrative priveledges to manage RDS deployment"
|
||||
}
|
||||
},
|
||||
"existingBrokerAvailabilitySet": {
|
||||
"type": "string",
|
||||
"defaultValue": "cb-availabilityset",
|
||||
"metadata": {
|
||||
"description": "Availability set for RD Connection Brokers"
|
||||
}
|
||||
},
|
||||
"existingBrokerHostname": {
|
||||
"type": "string",
|
||||
"defaultValue": "rdcb-01",
|
||||
"metadata": {
|
||||
"description": "The host name of the existing Connection Broker vm"
|
||||
}
|
||||
},
|
||||
"existingDomainName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The domain to join the Connection Broker Machine to"
|
||||
}
|
||||
},
|
||||
"existingSubnetName": {
|
||||
"type": "string",
|
||||
"defaultValue": "Subnet",
|
||||
"metadata": {
|
||||
"description": "Subnet name"
|
||||
}
|
||||
},
|
||||
"existingVnetName": {
|
||||
"type": "string",
|
||||
"defaultValue": "vnet",
|
||||
"metadata": {
|
||||
"description": "Virtual network name"
|
||||
}
|
||||
},
|
||||
"primaryDbConnectionString": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Specifies the database primary connection string. The database connection string supports both high availability configurations: -- Dedicated database server. Uses Windows Authentication to connect to the databse. -- Shared database server. Uses database authentication (such as SQL authentication) with a user name and password to connect to the database."
|
||||
}
|
||||
},
|
||||
"sqlServer": {
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"metadata": {
|
||||
"description": "The name of the SQL server that the database is located on (only required for the Dedicated database server case w/Windows Auth)"
|
||||
}
|
||||
},
|
||||
"windowsServerVersion": {
|
||||
"type": "string",
|
||||
"allowedValues": [
|
||||
"2012-R2-Datacenter",
|
||||
"2016-Datacenter"
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Windows server version for the second Broker; should be same version as the first broker in the deployment"
|
||||
},
|
||||
"defaultValue": "2016-Datacenter"
|
||||
},
|
||||
"_artifactsLocation": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The base URI where artifacts required by this template are located. When the template is deployed using the accompanying scripts, a private location in the subscription will be used and this value will be automatically generated."
|
||||
},
|
||||
"defaultValue": "https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/rds-deployment-ha-broker/"
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"brokerVmName": "[concat(variables('vmPrefix'), 'rdcb-02')]",
|
||||
"brokerNicName": "[concat(variables('brokerVmName'), '-nic')]",
|
||||
"storageAccountName": "[concat(uniquestring(resourceGroup().id), 'rdsstorage2')]",
|
||||
"storageAccountType": "Standard_LRS",
|
||||
"sqlClientUrl": "http://go.microsoft.com/fwlink/?LinkID=239648&clcid=0x409",
|
||||
"vmPrefix": "",
|
||||
"p": {
|
||||
"broker": "[concat(' -existingBroker ', parameters('existingBrokerHostname'))]",
|
||||
"connstr": "[concat(' -primaryDbConnectionString \"', parameters('primaryDbConnectionString'), '\"')]",
|
||||
"domain": "[concat(' -domainName ', parameters('existingDomainName'))]",
|
||||
"user": "[concat(' -username ', parameters('existingAdminUsername'))]",
|
||||
"pwd": "[concat(' -password ', parameters('existingAdminPassword'))]",
|
||||
"can": "[concat(' -clientAccessName \"', parameters('clientAccessName'), '\"')]",
|
||||
"sqlnclient": "[concat(' -sqlClientUrl \"', variables('sqlClientUrl'), '\"')]",
|
||||
"dnsserver": "[concat(' -dnsServer ', parameters('dnsServer'))]",
|
||||
"sqlserver": "[concat(' -sqlServer \"', parameters('sqlServer'), '\"')]"
|
||||
},
|
||||
"scriptParameters": "[concat(variables('p').broker, variables('p').connstr, variables('p').domain, variables('p').user, variables('p').pwd, variables('p').can, variables('p').sqlnclient, variables('p').dnsserver, variables('p').sqlserver)]",
|
||||
"scriptLocation": "[concat(parameters('_artifactsLocation'), '/Scripts')]",
|
||||
"scriptFileName": "RdcbHaPostConfig.ps1"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Storage/storageAccounts",
|
||||
"name": "[variables('storageAccountName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"accountType": "[variables('storageAccountType')]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "[variables('brokerNicName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"subnet": {
|
||||
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('existingVnetName'), parameters('existingSubnetName'))]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines",
|
||||
"name": "[variables('brokerVmName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
|
||||
"[concat('Microsoft.Network/networkInterfaces/', variables('brokerNicName'))]"
|
||||
],
|
||||
"properties": {
|
||||
"hardwareProfile": {
|
||||
"vmSize": "Standard_A2"
|
||||
},
|
||||
"availabilitySet": {
|
||||
"id": "[resourceId('Microsoft.Compute/availabilitySets', parameters('existingBrokerAvailabilitySet'))]"
|
||||
},
|
||||
"osProfile": {
|
||||
"computerName": "[variables('brokerVmName')]",
|
||||
"adminUsername": "[parameters('existingAdminUsername')]",
|
||||
"adminPassword": "[parameters('existingAdminPassword')]"
|
||||
},
|
||||
"storageProfile": {
|
||||
"imageReference": {
|
||||
"publisher": "MicrosoftWindowsServer",
|
||||
"offer": "WindowsServer",
|
||||
"sku": "[parameters('windowsServerVersion')]",
|
||||
"version": "latest"
|
||||
},
|
||||
"osDisk": {
|
||||
"name": "osdisk",
|
||||
"vhd": {
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),'2016-01-01').primaryEndpoints.blob,'vhds/',variables('brokerVmName'),'-osdisk.vhd')]"
|
||||
},
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage"
|
||||
}
|
||||
},
|
||||
"networkProfile": {
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"id": "[resourceId('Microsoft.Network/networkInterfaces',variables('brokerNicName'))]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"name": "[concat(variables('brokerVmName'),'/configuration')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Compute/virtualMachines',variables('brokerVmName'))]"
|
||||
],
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Powershell",
|
||||
"type": "DSC",
|
||||
"typeHandlerVersion": "2.75",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"modulesUrl": "[concat(parameters('_artifactsLocation'),'/DSC/Configuration.zip')]",
|
||||
"configurationFunction": "Configuration.ps1\\DomainJoin",
|
||||
"properties": {
|
||||
"domainName": "[parameters('existingDomainName')]",
|
||||
"adminCreds": {
|
||||
"UserName": "[parameters('existingAdminUsername')]",
|
||||
"Password": "PrivateSettingsRef:adminPassword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"protectedSettings": {
|
||||
"Items": {
|
||||
"adminPassword": "[parameters('existingAdminPassword')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"name": "[concat(variables('brokerVmName'),'/ha-broker-configuration')]",
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Compute/virtualMachines/', variables('brokerVmName'),'/extensions/','configuration')]"
|
||||
],
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Compute",
|
||||
"type": "CustomScriptExtension",
|
||||
"typeHandlerVersion": "1.8",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"fileUris": [
|
||||
"[concat(variables('scriptLocation'), '/', variables('scriptFileName'))]"
|
||||
]
|
||||
},
|
||||
"protectedSettings": {
|
||||
"commandToExecute": "[concat( 'powershell -noninteractive -executionpolicy bypass -file ', variables('scriptFileName'), variables('scriptParameters'), ' >> script.log 2>&1' )]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"_artifactsLocation": {
|
||||
"value": "https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/rds-deployment-ha-broker/"
|
||||
},
|
||||
"clientAccessName": {
|
||||
"value": "HARDCB"
|
||||
},
|
||||
"dnsServer": {
|
||||
"value": "addc-01"
|
||||
},
|
||||
"existingAdminPassword": {
|
||||
"value": "{enter_existing_adminUsername_password_here}"
|
||||
},
|
||||
"existingAdminUsername": {
|
||||
"value": "cloudadmin"
|
||||
},
|
||||
"existingBrokerAvailabilitySet": {
|
||||
"value": "cb-availabilityset"
|
||||
},
|
||||
"existingBrokerHostname": {
|
||||
"value": "rdcb-01"
|
||||
},
|
||||
"existingDomainName": {
|
||||
"value": "contoso.com"
|
||||
},
|
||||
"existingSubnetName": {
|
||||
"value": "subnet"
|
||||
},
|
||||
"existingVnetName": {
|
||||
"value": "vnet"
|
||||
},
|
||||
"primaryDbConnectionString": {
|
||||
"value": "DRIVER=SQL Server Native Client 11.0;Server={enter_sql_server_here},1433;Database={enter_sql_database_here};Uid={enter_sql_admin_here}@{enter_sql_server_here};Pwd={enter_sql_password_here};Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;"
|
||||
},
|
||||
"sqlServer": {
|
||||
"value": "{enter_NON_Azure_sql_server_here_or_leave_blank_for_Azure_SQL}"
|
||||
},
|
||||
"windowsServerVersion": {
|
||||
"value": "2016-Datacenter"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"itemDisplayName": "RDS Broker High Availability deployment",
|
||||
"description": "This template provides high availability to RD Connection Broker in an existing RDS deployment",
|
||||
"summary": "Provide HA to RDCB servers in RDS deployment",
|
||||
"githubUsername": "fberson",
|
||||
"dateUpdated": "2017-07-21"
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,45 @@
|
|||
# Provide High Availability to RD Gateway and RD Web Access servers in RDS deployment
|
||||
|
||||
This template deploys the following resources:
|
||||
|
||||
* a number of RD Gateway/RD Web Access VMs (number defined by 'numberOfWebGwInstances' parameter)
|
||||
|
||||
The template will
|
||||
|
||||
* Join all new VMs to the domain
|
||||
* Deploy RDS roles in the deployment
|
||||
* Join new VM's to the existing web and Gateway farm of basic RDS deployment
|
||||
* Post configurations for web/Gateway VM's such as defining the Machine keys for IIS modules
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Current Template is an extension to the Basic RDS Deployment Template, and it is mandatory to deploy any one of the template as prerequisite:
|
||||
|
||||
* Basic RDS deployment template
|
||||
https://github.com/Azure/azure-quickstart-templates/tree/master/rds-deployment
|
||||
|
||||
* RDS deployment from custom RDSH image
|
||||
https://github.com/Azure/azure-quickstart-templates/tree/master/rds-deployment-custom-image-rdsh
|
||||
|
||||
* RDS deployment on pre-existing VNET and AD
|
||||
https://github.com/Azure/azure-quickstart-templates/tree/master/rds-deployment-existing-ad
|
||||
|
||||
This template expects the same names of resources from RDS deployment, if resource names are changed in your deployment then please edit the parameters and resources accordingly, example of such resources are below:
|
||||
<ul>
|
||||
<li>storageAccountName: Resource must be exact same to existing RDS deployment.</li>
|
||||
<li>publicIpRef: Resource must be exact same to existing RDS deployment.</li>
|
||||
<li>availabilitySets: Resource must be exact same to existing RDS deployment.</li>
|
||||
<li>Load-balancer: Load balancer name, Backend pool, LB-rules, Nat-Rule and NIC.</li>
|
||||
<li>VM’s – VM name classification which is using copy index function.</li>
|
||||
<li>NIC – NIC naming convention.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
Click the button below to deploy
|
||||
|
||||
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2Frds-deployment-ha-gateway%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://azuredeploy.net/deploybutton.png"/>
|
||||
</a>
|
||||
<a href="http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2Frds-deployment-ha-gateway%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://armviz.io/visualizebutton.png"/>
|
||||
</a>
|
|
@ -0,0 +1,312 @@
|
|||
|
||||
param
|
||||
(
|
||||
|
||||
[String]$WebGwServer,
|
||||
[String]$BrokerServer,
|
||||
[String]$WebURL,
|
||||
[String]$Domainname,
|
||||
[String]$DomainNetbios,
|
||||
[String]$username,
|
||||
[String]$password,
|
||||
[string]$ServerName = "gateway",
|
||||
[int]$numberofwebServers,
|
||||
$validationKey64,
|
||||
$decryptionKey24
|
||||
|
||||
)
|
||||
|
||||
$localhost = [System.Net.Dns]::GetHostByName((hostname)).HostName
|
||||
$username = $DomainNetbios + "\" + $Username
|
||||
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
|
||||
|
||||
configuration RDWebAccessdeployment
|
||||
{
|
||||
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory)]
|
||||
[String]$domainName,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[PSCredential]$adminCreds,
|
||||
|
||||
# Connection Broker Node name
|
||||
[String]$connectionBroker,
|
||||
|
||||
# Web Access Node name
|
||||
[String]$webAccessServer,
|
||||
|
||||
# Gateway external FQDN
|
||||
[String]$externalFqdn
|
||||
|
||||
)
|
||||
|
||||
|
||||
Import-DscResource -ModuleName PSDesiredStateConfiguration -ModuleVersion 1.1
|
||||
Import-DscResource -ModuleName xActiveDirectory, xComputerManagement, xRemoteDesktopSessionHost
|
||||
|
||||
$localhost = [System.Net.Dns]::GetHostByName((hostname)).HostName
|
||||
|
||||
if (-not $connectionBroker) { $connectionBroker = $localhost }
|
||||
if (-not $webAccessServer) { $webAccessServer = $localhost }
|
||||
|
||||
if (-not $collectionName) { $collectionName = "Desktop Collection" }
|
||||
if (-not $collectionDescription) { $collectionDescription = "A sample RD Session collection up in cloud." }
|
||||
|
||||
Node localhost
|
||||
{
|
||||
|
||||
LocalConfigurationManager
|
||||
{
|
||||
RebootNodeIfNeeded = $true
|
||||
ConfigurationMode = "ApplyOnly"
|
||||
}
|
||||
|
||||
xRDServer AddWebAccessServer
|
||||
{
|
||||
Role = 'RDS-Web-Access'
|
||||
Server = $webAccessServer
|
||||
GatewayExternalFqdn = $externalFqdn
|
||||
ConnectionBroker = $BrokerServer
|
||||
|
||||
PsDscRunAsCredential = $adminCreds
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}#End of Configuration RDWebAccessdeployment
|
||||
|
||||
$ConfigData = @{
|
||||
AllNodes = @(
|
||||
@{
|
||||
NodeName = 'localhost'
|
||||
PSDscAllowPlainTextPassword = $true
|
||||
}
|
||||
)
|
||||
} # End of Config Data
|
||||
|
||||
# calling the configuration
|
||||
RDWebAccessdeployment -adminCreds $cred -connectionBroker $BrokerServer -webAccessServer $localhost -externalFqdn $WebURL -domainName $Domainname -ConfigurationData $ConfigData -Verbose
|
||||
Start-DscConfiguration -Wait -Force -Path .\RDWebAccessdeployment -Verbose
|
||||
|
||||
|
||||
configuration RDGatewaydeployment
|
||||
{
|
||||
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory)]
|
||||
[String]$domainName,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[PSCredential]$adminCreds,
|
||||
|
||||
# Connection Broker Node name
|
||||
[String]$connectionBroker,
|
||||
|
||||
# Web Access Node name
|
||||
[String]$webAccessServer,
|
||||
|
||||
# Gateway external FQDN
|
||||
[String]$externalFqdn,
|
||||
|
||||
# RD Session Host count and naming prefix
|
||||
[Int]$numberOfRdshInstances = 1,
|
||||
[String]$sessionHostNamingPrefix = "SessionHost-",
|
||||
|
||||
# Collection Name
|
||||
[String]$collectionName,
|
||||
|
||||
# Connection Description
|
||||
[String]$collectionDescription
|
||||
|
||||
)
|
||||
|
||||
|
||||
Import-DscResource -ModuleName PSDesiredStateConfiguration -ModuleVersion 1.1
|
||||
Import-DscResource -ModuleName xActiveDirectory, xComputerManagement, xRemoteDesktopSessionHost
|
||||
|
||||
$localhost = [System.Net.Dns]::GetHostByName((hostname)).HostName
|
||||
|
||||
if (-not $connectionBroker) { $connectionBroker = $localhost }
|
||||
if (-not $webAccessServer) { $webAccessServer = $localhost }
|
||||
|
||||
if (-not $collectionName) { $collectionName = "Desktop Collection" }
|
||||
if (-not $collectionDescription) { $collectionDescription = "A sample RD Session collection up in cloud." }
|
||||
|
||||
Node localhost
|
||||
{
|
||||
|
||||
LocalConfigurationManager
|
||||
{
|
||||
RebootNodeIfNeeded = $true
|
||||
ConfigurationMode = "ApplyOnly"
|
||||
}
|
||||
|
||||
xRDServer AddGatewayServer
|
||||
{
|
||||
Role = 'RDS-Gateway'
|
||||
Server = $webAccessServer
|
||||
GatewayExternalFqdn = $externalFqdn
|
||||
ConnectionBroker = $BrokerServer
|
||||
|
||||
PsDscRunAsCredential = $adminCreds
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}#End of Configuration RDGatewaydeployment
|
||||
|
||||
$ConfigData = @{
|
||||
AllNodes = @(
|
||||
@{
|
||||
NodeName = 'localhost'
|
||||
PSDscAllowPlainTextPassword = $true
|
||||
}
|
||||
)
|
||||
} # End of Config Data
|
||||
|
||||
RDGatewaydeployment -adminCreds $cred -connectionBroker $BrokerServer -webAccessServer $localhost -externalFqdn $WebURL -domainName $Domainname -ConfigurationData $ConfigData -Verbose
|
||||
Start-DscConfiguration -Wait -Force -Path .\RDGatewaydeployment -Verbose
|
||||
|
||||
|
||||
#--Post Configuration for IIS RD web for Machine keys
|
||||
|
||||
Write-Host "Username : $($username), Password: $($password)"
|
||||
#$username = $DomainNetbios + "\" + $username
|
||||
#$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
|
||||
$webServernameArray = New-Object System.Collections.ArrayList
|
||||
|
||||
for ($i = 0; $i -le $numberofwebServers; $i++)
|
||||
{
|
||||
if ($i -eq 0)
|
||||
{
|
||||
$webServername = "Gateway"
|
||||
#Write-Host "For i = 0, srvername = $($webServername)"
|
||||
}
|
||||
else{
|
||||
$servercount = $i - 1
|
||||
$webServername = "gateway" + $servercount.ToString()
|
||||
#Write-Host "For $($i), servername = $($webServername)"
|
||||
}
|
||||
$webServernameArray.Add($webServername) | Out-Null
|
||||
}
|
||||
|
||||
Write-Host "web server Array value $($webServernameArray)"
|
||||
|
||||
# genrate 64 and 24 char keys:
|
||||
[int]$keylen = 64
|
||||
$buff = new-object "System.Byte[]" $keylen
|
||||
$rnd = new-object System.Security.Cryptography.RNGCryptoServiceProvider
|
||||
$rnd.GetBytes($buff)
|
||||
$result =""
|
||||
for($i=0; $i -lt $keylen; $i++) {
|
||||
$result += [System.String]::Format("{0:X2}",$buff[$i])
|
||||
}
|
||||
$validationkey64 = $result
|
||||
# Write-Host $validationkey64
|
||||
# end of Validation Key code
|
||||
|
||||
$keylen = 24
|
||||
$buff1 = new-object "System.Byte[]" $keylen
|
||||
$rnd1 = new-object System.Security.Cryptography.RNGCryptoServiceProvider
|
||||
$rnd1.GetBytes($buff1)
|
||||
$result =""
|
||||
for($i=0; $i -lt $keylen; $i++) {
|
||||
$result += [System.String]::Format("{0:X2}",$buff[$i])
|
||||
}
|
||||
$decryptionKey24 = $result
|
||||
# Write-Host $decryptionKey24
|
||||
|
||||
# logic end for 64 and 24 char keys
|
||||
|
||||
foreach ($item in $webServernameArray)
|
||||
{
|
||||
$WebServer = $item + "." + $DomainName
|
||||
Write-Host "Starting working on webserver name : $($WebServer)"
|
||||
try{
|
||||
$session = New-PSSession -ComputerName $WebServer -Credential $cred
|
||||
}
|
||||
catch{
|
||||
Write-Host $Error
|
||||
}
|
||||
|
||||
|
||||
Invoke-Command -session $session -ScriptBlock {param($validationkey64,$decryptionKey24)
|
||||
|
||||
|
||||
function ValidateWindowsFeature
|
||||
{
|
||||
$localhost = [System.Net.Dns]::GetHostByName((hostname)).HostName
|
||||
$RdsWindowsFeature = Get-WindowsFeature -ComputerName $localhost -Name RDS-Web-Access
|
||||
if ($RdsWindowsFeature.InstallState -eq "Installed")
|
||||
{
|
||||
Return $true
|
||||
}
|
||||
else
|
||||
{
|
||||
Return $false
|
||||
}
|
||||
|
||||
}
|
||||
$Validationheck = $False
|
||||
$Validationheck = ValidateWindowsFeature
|
||||
$localhost = [System.Net.Dns]::GetHostByName((hostname)).HostName
|
||||
if($Validationheck -eq $true)
|
||||
{
|
||||
Write-Host "Windows feature RDS-Web_access present on $($localhost)"
|
||||
$machineConfig = "C:\Windows\Web\RDWeb\Web.config"
|
||||
if (Test-Path $machineConfig)
|
||||
{
|
||||
Write-Host "editing machine config file : $($machineConfig) on server $($localhost) "
|
||||
|
||||
try{
|
||||
$xml = [xml](get-content $machineConfig)
|
||||
$xml.Save($machineConfig + "_")
|
||||
|
||||
$root = $xml.get_DocumentElement()
|
||||
$system_web = $root."system.web"
|
||||
if ($system_web.machineKey -eq $null)
|
||||
{
|
||||
$machineKey = $xml.CreateElement("machineKey")
|
||||
$a = $system_web.AppendChild($machineKey)
|
||||
}
|
||||
$system_web.SelectSingleNode("machineKey").SetAttribute("validationKey","$validationKey64")
|
||||
$system_web.SelectSingleNode("machineKey").SetAttribute("decryptionKey","$decryptionKey24")
|
||||
$a = $xml.Save($machineConfig)
|
||||
|
||||
}
|
||||
Catch{
|
||||
Write-Host $Error
|
||||
}
|
||||
|
||||
} # end of If test-path
|
||||
|
||||
} # End of If($ValidationCheck -eq $True)
|
||||
else
|
||||
{
|
||||
Write-Host "Windows feature RDS-Web_access is not present on $($localhost)"
|
||||
}
|
||||
|
||||
|
||||
|
||||
} -ArgumentList $validationKey64,$decryptionKey24 # end of Script Block
|
||||
|
||||
Remove-PSSession -Session $session
|
||||
|
||||
|
||||
|
||||
} # end of foreach $item in $webServername
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,401 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"dnsLabelPrefix": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Unique public DNS prefix for the deployment. The fqdn will look something like '<dnsname>.westus.cloudapp.azure.com'. Up to 62 chars, digits or dashes, lowercase, should start with a letter: must conform to '^[a-z][a-z0-9-]{1,61}[a-z0-9]$'."
|
||||
}
|
||||
},
|
||||
"loadBalancer": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The Loadbalancer name must match from the RDS deployment. And default value taken by template is loadbalancer."
|
||||
},
|
||||
"defaultValue": "loadBalancer"
|
||||
},
|
||||
"backendAddressPools": {
|
||||
"type": "string",
|
||||
"defaultValue": "LBBAP",
|
||||
"metadata": {
|
||||
"description": "The backendAddressPools name must match from the RDS deployment. And default value taken by template is LBBAP."
|
||||
}
|
||||
},
|
||||
"gw-AvailabilitySet": {
|
||||
"type": "string",
|
||||
"defaultValue": "gw-availabilityset",
|
||||
"metadata": {
|
||||
"description": "The gw-availabilityset name must match from the RDS deployment. And default value taken by template is gw-availabilityset."
|
||||
}
|
||||
},
|
||||
"adDomainName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The FQDN of the AD domain"
|
||||
}
|
||||
},
|
||||
"adminUsername": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of the administrator of the new VM and the domain. Exclusion list: 'administrator"
|
||||
}
|
||||
},
|
||||
"adminPassword": {
|
||||
"type": "securestring",
|
||||
"metadata": {
|
||||
"description": "The password for the administrator account of the new VM and the domain"
|
||||
}
|
||||
},
|
||||
"numberOfWebGwInstances": {
|
||||
"type": "int",
|
||||
"defaultValue": 2,
|
||||
"metadata": {
|
||||
"description": "Number of RD Gateway instances"
|
||||
}
|
||||
},
|
||||
"brokerServer": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "FQDN for Broker Server"
|
||||
}
|
||||
},
|
||||
"WebURL": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "This is RD Gateway external FQDN. This shall be picked from existing basic RDS deploment."
|
||||
}
|
||||
},
|
||||
"domainNetbios": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Netbios Name for Domain"
|
||||
}
|
||||
},
|
||||
"storageAccountName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Storage account name of RDS-Deployment"
|
||||
}
|
||||
},
|
||||
"imageSKU": {
|
||||
"type": "string",
|
||||
"allowedValues": [
|
||||
"2012-R2-Datacenter",
|
||||
"2016-Datacenter"
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Windows server SKU"
|
||||
},
|
||||
"defaultValue": "2016-Datacenter"
|
||||
},
|
||||
"vmSize": {
|
||||
"type": "string",
|
||||
"defaultValue": "Standard_A2",
|
||||
"metadata": {
|
||||
"description": "Size for the new RD Gateway VMs"
|
||||
}
|
||||
},
|
||||
"existingVnet": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The vnet name of AD domain. For example johnvnet1"
|
||||
},
|
||||
"defaultValue": "vnet"
|
||||
},
|
||||
"existingSubnet": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The subnet name of AD domain. For example johnsubnet1"
|
||||
},
|
||||
"defaultValue": "Subnet"
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"imagePublisher": "MicrosoftWindowsServer",
|
||||
"imageOffer": "WindowsServer",
|
||||
"vnetAddressRange": "10.0.0.0/16",
|
||||
"subnetAddressRange": "10.0.0.0/24",
|
||||
"dnsServerPrivateIp": "10.0.0.8",
|
||||
"subnet-id": "[concat(resourceId('Microsoft.Network/virtualNetworks',parameters('existingVnet')),'/subnets/',parameters('existingSubnet'))]",
|
||||
"publicIpRef": "publicIp",
|
||||
"assetLocation": "https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/rds-deployment",
|
||||
"apiVersion": "2015-06-15",
|
||||
"PublicIPLocation": "[concat(parameters('dnsLabelPrefix'),'.','[resourceGroup().location]','.cloudapp.azure.com')]"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Storage/storageAccounts",
|
||||
"name": "[parameters('storageAccountName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"accountType": "Standard_LRS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "[Parameters('gw-availabilityset')]",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"name": "[variables('publicIpRef')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "Dynamic",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[parameters('dnsLabelPrefix')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/loadBalancers",
|
||||
"name": "[Parameters('Loadbalancer')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/publicIPAddresses/',variables('publicIpRef'))]"
|
||||
],
|
||||
"properties": {
|
||||
"frontendIPConfigurations": [
|
||||
{
|
||||
"name": "LBFE",
|
||||
"properties": {
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIpRef'))]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"backendAddressPools": [
|
||||
{
|
||||
"name": "[parameters('backendAddressPools')]"
|
||||
}
|
||||
],
|
||||
"loadBalancingRules": [
|
||||
{
|
||||
"name": "LBRule01",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers',Parameters('loadBalancer')),'/frontendIPConfigurations/LBFE')]"
|
||||
},
|
||||
"backendAddressPool": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers',Parameters('loadBalancer')),'/backendAddressPools/',parameters('backendAddressPools'))]"
|
||||
},
|
||||
"protocol": "Tcp",
|
||||
"frontendPort": 443,
|
||||
"backendPort": 443,
|
||||
"enableFloatingIP": false,
|
||||
"idleTimeoutInMinutes": 5,
|
||||
"loadDistribution": "SourceIPProtocol",
|
||||
"probe": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers',Parameters('loadBalancer')),'/probes/tcpProbe')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "LBRule02",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers',Parameters('loadBalancer')),'/frontendIPConfigurations/LBFE')]"
|
||||
},
|
||||
"backendAddressPool": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers',Parameters('loadBalancer')),'/backendAddressPools/',parameters('backendAddressPools'))]"
|
||||
},
|
||||
"protocol": "Tcp",
|
||||
"frontendPort": 3391,
|
||||
"backendPort": 3391,
|
||||
"enableFloatingIP": false,
|
||||
"idleTimeoutInMinutes": 5,
|
||||
"loadDistribution": "SourceIPProtocol",
|
||||
"probe": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers',Parameters('loadBalancer')),'/probes/tcpProbe')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"name": "tcpProbe",
|
||||
"properties": {
|
||||
"protocol": "Tcp",
|
||||
"port": 443,
|
||||
"intervalInSeconds": 5,
|
||||
"numberOfProbes": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tcpProbe01",
|
||||
"properties": {
|
||||
"protocol": "Tcp",
|
||||
"port": 3391,
|
||||
"intervalInSeconds": 5,
|
||||
"numberOfProbes": 2
|
||||
}
|
||||
}
|
||||
],
|
||||
"inboundNatRules": [
|
||||
{
|
||||
"name": "rdp",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers',Parameters('loadBalancer')),'/frontendIPConfigurations/LBFE')]"
|
||||
},
|
||||
"protocol": "tcp",
|
||||
"frontendPort": 3389,
|
||||
"backendPort": 3389,
|
||||
"enableFloatingIP": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[concat('gw-',copyindex(),'-nic')]",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"location": "[resourceGroup().location]",
|
||||
"apiVersion": "2015-06-15",
|
||||
"copy": {
|
||||
"name": "gw-nic-loop",
|
||||
"count": "[parameters('numberOfWebGwInstances')]"
|
||||
},
|
||||
"dependsOn": [
|
||||
"Microsoft.Network/loadBalancers/loadBalancer"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig1",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"subnet": {
|
||||
"id": "[variables('subnet-id')]"
|
||||
},
|
||||
"loadBalancerBackendAddressPools": [
|
||||
{
|
||||
"id": "[concat(resourceId('Microsoft.Network/loadBalancers','loadBalancer'),'/backendAddressPools/',parameters('backendAddressPools'))]"
|
||||
}
|
||||
],
|
||||
"loadBalancerInboundNatRules": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[concat('gw-vm-',copyindex())]",
|
||||
"type": "Microsoft.Compute/virtualMachines",
|
||||
"location": "[resourceGroup().location]",
|
||||
"apiVersion": "2015-06-15",
|
||||
"copy": {
|
||||
"name": "gw-vm-loop",
|
||||
"count": "[parameters('numberOfWebGwInstances')]"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]",
|
||||
"[resourceId('Microsoft.Compute/availabilitySets', 'gw-availabilityset')]",
|
||||
"[concat('Microsoft.Network/networkInterfaces/gw-',copyindex(),'-nic')]"
|
||||
],
|
||||
"properties": {
|
||||
"hardwareProfile": {
|
||||
"vmSize": "[parameters('vmSize')]"
|
||||
},
|
||||
"availabilitySet": {
|
||||
"id": "[resourceId('Microsoft.Compute/availabilitySets', 'gw-availabilityset')]"
|
||||
},
|
||||
"osProfile": {
|
||||
"computerName": "[concat('gateway',copyindex())]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"adminPassword": "[parameters('adminPassword')]"
|
||||
},
|
||||
"storageProfile": {
|
||||
"imageReference": {
|
||||
"publisher": "[variables('imagePublisher')]",
|
||||
"offer": "[variables('imageOffer')]",
|
||||
"sku": "[parameters('imageSKU')]",
|
||||
"version": "latest"
|
||||
},
|
||||
"osDisk": {
|
||||
"name": "osdisk",
|
||||
"vhd": {
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName')),'2016-01-01').primaryEndpoints.blob,'/vhds/gateway',copyindex(),'-osdisk.vhd')]"
|
||||
},
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage"
|
||||
}
|
||||
},
|
||||
"networkProfile": {
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"id": "[resourceId('Microsoft.Network/networkInterfaces',concat('gw-',copyindex(),'-nic'))]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"name": "[concat('gw-vm-',copyindex(),'/Gateway')]",
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"location": "[resourceGroup().location]",
|
||||
"apiVersion": "2015-06-15",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Compute/virtualMachines', Concat('gw-vm-',copyindex()))]"
|
||||
],
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Powershell",
|
||||
"type": "DSC",
|
||||
"typeHandlerVersion": "2.75",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"ModulesUrl": "[concat(variables('assetLocation'),'/Configuration.zip')]",
|
||||
"ConfigurationFunction": "Configuration.ps1\\Gateway",
|
||||
"properties": {
|
||||
"DomainName": "[parameters('adDomainName')]",
|
||||
"AdminCreds": {
|
||||
"UserName": "[parameters('adminUsername')]",
|
||||
"Password": "PrivateSettingsRef:AdminPassword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"protectedSettings": {
|
||||
"Items": {
|
||||
"AdminPassword": "[parameters('adminPassword')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[concat('gw-vm-',copyindex(),'/WebAndGwFarmAdd_PostConfig1.1')]",
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"location": "[resourceGroup().location]",
|
||||
"apiVersion": "2015-06-15",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Compute/virtualMachines', Concat('gw-vm-',copyindex()))]",
|
||||
"[concat('Microsoft.Compute/virtualMachines/gw-vm-',copyindex(),'/extensions/','Gateway')]"
|
||||
],
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Compute",
|
||||
"type": "CustomScriptExtension",
|
||||
"typeHandlerVersion": "1.8",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"fileUris": [
|
||||
"https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/rds-deployment-ha-gateway/Scripts/WebAndGwFarmAdd_PostConfig1.1.ps1"
|
||||
]
|
||||
},
|
||||
"protectedSettings": {
|
||||
"Items": {
|
||||
"AdminPassword": "[parameters('adminPassword')]"
|
||||
},
|
||||
"storageAccountName": "[parameters('storageaccountname')]",
|
||||
"commandToExecute": "[Concat('powershell.exe -ExecutionPolicy Unrestricted -File', ' ', 'WebAndGwFarmAdd_PostConfig1.1.ps1',' ','-username \"',parameters('adminusername'),'\" ', '-password \"',parameters('adminpassword'),'\" ','-BrokerServer \"',parameters('BrokerServer'),'\" ','-WebURL \"',parameters('WebURL'),'\" ','-Domainname \"',parameters('adDomainName'),'\" ','-DomainNetbios \"',parameters('DomainNetbios'),'\" ','-numberofwebServers ',parameters('numberOfWebGwInstances'))]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"adminPassword": {
|
||||
"value": "GEN-PASSWORD"
|
||||
},
|
||||
"adminUsername": {
|
||||
"value": "GEN-USER"
|
||||
},
|
||||
"adDomainName": {
|
||||
"value": "mydomain.local"
|
||||
},
|
||||
"numberOfWebGwInstances": {
|
||||
"value": 2
|
||||
},
|
||||
"brokerServer": {
|
||||
"value": "Broker.Mydomain.local"
|
||||
},
|
||||
"WebURL": {
|
||||
"value": "RDS-WebURL"
|
||||
},
|
||||
"domainNetbios": {
|
||||
"value": "Mydomain"
|
||||
},
|
||||
"dnsLabelPrefix": {
|
||||
"value": "GEN-UNIQUE"
|
||||
},
|
||||
"storageAccountName": {
|
||||
"value": "GEN-UNIQUE"
|
||||
},
|
||||
"gw-availabilityset": {
|
||||
"value": "gw-availabilityset"
|
||||
},
|
||||
"loadBalancer": {
|
||||
"value": "loadBalancer"
|
||||
},
|
||||
"backendAddressPools": {
|
||||
"value": "LBBAP"
|
||||
},
|
||||
"existingVnet": {
|
||||
"value": "vnet"
|
||||
},
|
||||
"existingSubnet": {
|
||||
"value": "Subnet"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"itemDisplayName": "RDS Gateway High Availability deployment",
|
||||
"description": "This template provides high availability to RD Gateway and RD Web Access servers in an existing RDS deployment",
|
||||
"summary": "Provide HA to RDG and RDWA servers in RDS deployment",
|
||||
"githubUsername": "ashishsharma303",
|
||||
"dateUpdated": "2016-12-21"
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,16 @@
|
|||
# Create Remote Desktop Sesson Collection deployment
|
||||
|
||||
This template deploys the following resources:
|
||||
|
||||
<ul><li>storage account;</li><li>vnet, public ip, load balancer;</li><li>domain controller vm;</li><li>RD Gateway/RD Web Access vm;</li><li>RD Connection Broker/RD Licensing Server vm;</li><li>a number of RD Session hosts (number defined by 'numberOfRdshInstances' parameter)</li></ul>
|
||||
|
||||
The template will deploy DC, join all vms to the domain and configure RDS roles in the deployment.
|
||||
|
||||
Click the button below to deploy
|
||||
|
||||
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2Frds-deployment%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://azuredeploy.net/deploybutton.png"/>
|
||||
</a>
|
||||
<a href="http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2Frds-deployment%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://armviz.io/visualizebutton.png"/>
|
||||
</a>
|
|
@ -0,0 +1,855 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"gwdnsLabelPrefix": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Unique gateway public DNS prefix for the deployment. The fqdn will look something like '<dnsname>.westus.cloudapp.azure.com'. Up to 62 chars, digits or dashes, lowercase, should start with a letter: must conform to '^[a-z][a-z0-9-]{1,61}[a-z0-9]$'. For example johndns1 will result the final RDWEB access url like https://johndns1.westus.cloudapp.azure.com/RDWeb"
|
||||
}
|
||||
},
|
||||
"gwpublicIPAddressName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of gateway PublicIPAddress object"
|
||||
},
|
||||
"defaultValue": "gwpip"
|
||||
},
|
||||
"adDomainName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of the AD domain. For example contoso.com"
|
||||
},
|
||||
"defaultValue": "contoso.com"
|
||||
},
|
||||
"adminUsername": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of the administrator of the new VM and the domain. Exclusion list: 'administrator'. For example johnadmin"
|
||||
},
|
||||
"defaultValue": "vmadmin"
|
||||
},
|
||||
"adminPassword": {
|
||||
"type": "securestring",
|
||||
"metadata": {
|
||||
"description": "The password for the administrator account of the new VM and the domain"
|
||||
},
|
||||
"defaultValue": "[concat('Subscription#',subscription().subscriptionId)]"
|
||||
},
|
||||
"imageSKU": {
|
||||
"type": "string",
|
||||
"allowedValues": [
|
||||
"2012-R2-Datacenter",
|
||||
"2016-Datacenter"
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Windows server SKU"
|
||||
},
|
||||
"defaultValue": "2016-Datacenter"
|
||||
},
|
||||
"numberOfRdshInstances": {
|
||||
"type": "int",
|
||||
"defaultValue": 1,
|
||||
"metadata": {
|
||||
"description": "Number of RemoteDesktopSessionHosts"
|
||||
}
|
||||
},
|
||||
"rdshVmSize": {
|
||||
"type": "string",
|
||||
"allowedValues": [
|
||||
"Standard_A0",
|
||||
"Standard_A1",
|
||||
"Standard_A2",
|
||||
"Standard_A3",
|
||||
"Standard_A4",
|
||||
"Standard_A5",
|
||||
"Standard_A6",
|
||||
"Standard_A7",
|
||||
"Standard_D1",
|
||||
"Standard_D2",
|
||||
"Standard_D3",
|
||||
"Standard_D4",
|
||||
"Standard_D5"
|
||||
],
|
||||
"metadata": {
|
||||
"description": "The size of the RDSH VMs"
|
||||
},
|
||||
"defaultValue": "Standard_A4"
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"adAssetLocation": "https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/ad-non-ha",
|
||||
"adVMSize": "Standard_A1",
|
||||
"adVnetName": "[concat('ADVNET',resourceGroup().name)]",
|
||||
"adSubnetName": "[concat('ADStaticSubnet',resourceGroup().name)]",
|
||||
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks', variables('adVnetName'))]",
|
||||
"staticSubnetID": "[concat(variables('vnetID'),'/subnets/', variables('adSubnetName'))]",
|
||||
"adTemplateURL": "[concat(variables('adAssetLocation'),'/adVmTemplate.json')]",
|
||||
"adStorageName": "[tolower(concat('adsa',uniqueString(resourceGroup().id)))]",
|
||||
"adVmDeployment": "CreateAdVms",
|
||||
"adVmDeploymentId": "[concat('Microsoft.Resources/deployments/', variables('adVmDeployment'))]",
|
||||
"deployPrimaryAdTemplateURL": "[concat(variables('adAssetLocation'),'/deployPrimaryAD.json')]",
|
||||
"deployPrimaryAd": "DeployPrimaryAd",
|
||||
"deployPrimaryAdID": "[concat('Microsoft.Resources/deployments/', variables('deployPrimaryAd'))]",
|
||||
"adPDCVMName": "advm",
|
||||
"vnetwithDNSTemplateURL": "[concat(variables('adAssetLocation'),'/vnet-with-dns-server.json')]",
|
||||
"updateVNetDNS1": "updateVNetDNS",
|
||||
"updateVNetDNS1ID": "[concat('Microsoft.Resources/deployments/', variables('updateVNetDNS1'))]",
|
||||
"nicTemplateURL": "[concat(variables('adAssetLocation'),'/nic.json')]",
|
||||
"publicLBName": "[concat('ADPLB',resourceGroup().name)]",
|
||||
"publicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]",
|
||||
"lbFE": "ADLBFE",
|
||||
"rdpNAT": "ADRDPNAT",
|
||||
"publiclbID": "[resourceId('Microsoft.Network/loadBalancers',variables('publicLBName'))]",
|
||||
"publiclbFEConfigID": "[concat(variables('publiclbID'),'/frontendIPConfigurations/',variables('lbFE'))]",
|
||||
"rdpPort": 3389,
|
||||
"adRDPNATRuleID": "[concat(variables('publiclbID'),'/inboundNatRules/',variables('rdpNAT'))]",
|
||||
"adNICName": "[concat('ADNic',resourceGroup().name)]",
|
||||
"lbBE": "ADLBBE",
|
||||
"publicBEAddressPoolID": "[concat(variables('publiclbID'),'/backendAddressPools/',variables('lbBE'))]",
|
||||
"gwLBName": "[concat('GWPLB',resourceGroup().name)]",
|
||||
"publicIPAddressName": "[tolower(concat('adpip',uniqueString(resourceGroup().Id)))]",
|
||||
"gwIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',parameters('gwpublicIPAddressName'))]",
|
||||
"gwlbFE": "GWLBFE",
|
||||
"gwlbID": "[resourceId('Microsoft.Network/loadBalancers',variables('gwLBName'))]",
|
||||
"gwlbFEConfigID": "[concat(variables('gwlbID'),'/frontendIPConfigurations/',variables('gwlbFE'))]",
|
||||
"gwlbBE": "GWLBBE",
|
||||
"gwBEAddressPoolID": "[concat(variables('gwlbID'),'/backendAddressPools/',variables('gwlbBE'))]",
|
||||
"dnsLabelPrefix": "[tolower(concat('adns', resourceGroup().name))]",
|
||||
"storageAccountName": "[tolower(concat('rdsa',uniqueString(resourceGroup().id)))]",
|
||||
"storageAccountType": "Standard_LRS",
|
||||
"uniqueStorageAccountContainerName": "[tolower(concat('sc', uniqueString(resourceGroup().id)))]",
|
||||
"imagePublisher": "MicrosoftWindowsServer",
|
||||
"imageOffer": "WindowsServer",
|
||||
"vnetAddressRange": "10.0.0.0/16",
|
||||
"subnetAddressRange": "10.0.0.0/24",
|
||||
"dnsServerPrivateIp": "10.0.0.4",
|
||||
"subnet-id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('adVnetName')),'/subnets/', variables('adSubnetName'))]",
|
||||
"assetLocation": "https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/rds-deployment/",
|
||||
"nsgName": "RDSNsg",
|
||||
"nsgID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('nsgName'))]",
|
||||
"subnets": [
|
||||
{
|
||||
"name": "[variables('adSubnetName')]",
|
||||
"properties": {
|
||||
"addressPrefix": "[variables('subnetAddressRange')]",
|
||||
"networkSecurityGroup": {
|
||||
"id": "[variables('nsgID')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"name": "[variables('nsgName')]",
|
||||
"type": "Microsoft.Network/networkSecurityGroups",
|
||||
"location": "[resourceGroup().location]",
|
||||
"apiVersion": "2015-06-15",
|
||||
"properties": {
|
||||
"securityRules": [
|
||||
{
|
||||
"name": "rule1",
|
||||
"properties": {
|
||||
"protocol": "*",
|
||||
"sourcePortRange": "*",
|
||||
"destinationPortRange": "*",
|
||||
"sourceAddressPrefix": "*",
|
||||
"destinationAddressPrefix": "*",
|
||||
"access": "Allow",
|
||||
"priority": 101,
|
||||
"direction": "Inbound"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[variables('adVnetName')]",
|
||||
"type": "Microsoft.Network/virtualNetworks",
|
||||
"location": "[resourceGroup().location]",
|
||||
"apiVersion": "2015-06-15",
|
||||
"dependsOn": [
|
||||
"[variables('nsgID')]"
|
||||
],
|
||||
"properties": {
|
||||
"addressSpace": {
|
||||
"addressPrefixes": [
|
||||
"[variables('vnetAddressRange')]"
|
||||
]
|
||||
},
|
||||
"subnets": [
|
||||
{
|
||||
"name": "[variables('adSubnetName')]",
|
||||
"properties": {
|
||||
"addressPrefix": "[variables('subnetAddressRange')]",
|
||||
"networkSecurityGroup": {
|
||||
"id": "[variables('nsgID')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[variables('publicIPAddressName')]",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"location": "[resourceGroup().location]",
|
||||
"apiVersion": "2015-06-15",
|
||||
"dependsOn": [
|
||||
"[variables('vnetID')]"
|
||||
],
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "Dynamic",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[variables('dnsLabelPrefix')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[parameters('gwpublicIPAddressName')]",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"location": "[resourceGroup().location]",
|
||||
"apiVersion": "2015-06-15",
|
||||
"dependsOn": [
|
||||
"[variables('deployPrimaryAdID')]"
|
||||
],
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "Dynamic",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[parameters('gwdnsLabelPrefix')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "gw-availabilityset",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "cb-availabilityset",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "rdsh-availabilityset",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"name": "[variables('publiclbName')]",
|
||||
"type": "Microsoft.Network/loadBalancers",
|
||||
"apiVersion": "2015-06-15",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[variables('publicIPAddressID')]"
|
||||
],
|
||||
"properties": {
|
||||
"frontendIPConfigurations": [
|
||||
{
|
||||
"name": "[variables('lbFE')]",
|
||||
"properties": {
|
||||
"publicIPAddress": {
|
||||
"id": "[variables('publicIPAddressID')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"backendAddressPools": [
|
||||
{
|
||||
"name": "[variables('lbBE')]"
|
||||
}
|
||||
],
|
||||
"inboundNatRules": [
|
||||
{
|
||||
"name": "[variables('rdpNAT')]",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[variables('publiclbFEConfigID')]"
|
||||
},
|
||||
"protocol": "tcp",
|
||||
"frontendPort": "[variables('rdpPort')]",
|
||||
"backendPort": 3389,
|
||||
"enableFloatingIP": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[variables('gwlbName')]",
|
||||
"type": "Microsoft.Network/loadBalancers",
|
||||
"apiVersion": "2015-06-15",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[variables('gwIPAddressID')]"
|
||||
],
|
||||
"properties": {
|
||||
"frontendIPConfigurations": [
|
||||
{
|
||||
"name": "[variables('gwlbFE')]",
|
||||
"properties": {
|
||||
"publicIPAddress": {
|
||||
"id": "[variables('gwIPAddressID')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"backendAddressPools": [
|
||||
{
|
||||
"name": "[variables('gwlbBE')]"
|
||||
}
|
||||
],
|
||||
"loadBalancingRules": [
|
||||
{
|
||||
"name": "LBRule01",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[variables('gwlbFEConfigID')]"
|
||||
},
|
||||
"backendAddressPool": {
|
||||
"id": "[variables('gwBEAddressPoolID')]"
|
||||
},
|
||||
"protocol": "Tcp",
|
||||
"frontendPort": 443,
|
||||
"backendPort": 443,
|
||||
"enableFloatingIP": false,
|
||||
"idleTimeoutInMinutes": 5,
|
||||
"loadDistribution": "SourceIPProtocol",
|
||||
"probe": {
|
||||
"id": "[concat(variables('gwlbID'),'/probes/tcpProbe')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "LBRule02",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[variables('gwlbFEConfigID')]"
|
||||
},
|
||||
"backendAddressPool": {
|
||||
"id": "[variables('gwBEAddressPoolID')]"
|
||||
},
|
||||
"protocol": "Udp",
|
||||
"frontendPort": 3391,
|
||||
"backendPort": 3391,
|
||||
"enableFloatingIP": false,
|
||||
"idleTimeoutInMinutes": 5,
|
||||
"loadDistribution": "SourceIPProtocol",
|
||||
"probe": {
|
||||
"id": "[concat(variables('gwlbID'),'/probes/tcpProbe01')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"name": "tcpProbe",
|
||||
"properties": {
|
||||
"protocol": "Tcp",
|
||||
"port": 443,
|
||||
"intervalInSeconds": 5,
|
||||
"numberOfProbes": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tcpProbe01",
|
||||
"properties": {
|
||||
"protocol": "Tcp",
|
||||
"port": 3391,
|
||||
"intervalInSeconds": 5,
|
||||
"numberOfProbes": 2
|
||||
}
|
||||
}
|
||||
],
|
||||
"inboundNatRules": [
|
||||
{
|
||||
"name": "rdp",
|
||||
"properties": {
|
||||
"frontendIPConfiguration": {
|
||||
"id": "[variables('gwlbFEConfigID')]"
|
||||
},
|
||||
"protocol": "tcp",
|
||||
"frontendPort": 3389,
|
||||
"backendPort": 3389,
|
||||
"enableFloatingIP": false
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[variables('adVmDeployment')]",
|
||||
"type": "Microsoft.Resources/deployments",
|
||||
"apiVersion": "2016-02-01",
|
||||
"dependsOn": [
|
||||
"[variables('publiclbID')]"
|
||||
],
|
||||
"properties": {
|
||||
"mode": "Incremental",
|
||||
"templateLink": {
|
||||
"uri": "[variables('adTemplateURL')]",
|
||||
"contentVersion": "1.0.0.0"
|
||||
},
|
||||
"parameters": {
|
||||
"adminUsername": {
|
||||
"value": "[parameters('adminUsername')]"
|
||||
},
|
||||
"adminPassword": {
|
||||
"value": "[parameters('adminPassword')]"
|
||||
},
|
||||
"adRDPNATRuleID": {
|
||||
"value": "[variables('adRDPNATRuleID')]"
|
||||
},
|
||||
"storageAccount": {
|
||||
"value": "[variables('adStorageName')]"
|
||||
},
|
||||
"subnetResourceId": {
|
||||
"value": "[variables('staticSubnetID')]"
|
||||
},
|
||||
"primaryAdIpAddress": {
|
||||
"value": "[variables('dnsServerPrivateIp')]"
|
||||
},
|
||||
"storageAccountType": {
|
||||
"value": "[variables('storageAccountType')]"
|
||||
},
|
||||
"vmName": {
|
||||
"value": "[variables('adPDCVMName')]"
|
||||
},
|
||||
"vmSize": {
|
||||
"value": "[variables('adVMSize')]"
|
||||
},
|
||||
"adDNicName": {
|
||||
"value": "[variables('adNICName')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[variables('deployPrimaryAd')]",
|
||||
"type": "Microsoft.Resources/deployments",
|
||||
"apiVersion": "2016-02-01",
|
||||
"dependsOn": [
|
||||
"[variables('adVmDeploymentID')]"
|
||||
],
|
||||
"properties": {
|
||||
"mode": "Incremental",
|
||||
"templateLink": {
|
||||
"uri": "[variables('deployPrimaryAdTemplateURL')]",
|
||||
"contentVersion": "1.0.0.0"
|
||||
},
|
||||
"parameters": {
|
||||
"primaryADName": {
|
||||
"value": "[variables('adPDCVMName')]"
|
||||
},
|
||||
"domainName": {
|
||||
"value": "[parameters('adDomainName')]"
|
||||
},
|
||||
"adminUsername": {
|
||||
"value": "[parameters('adminUsername')]"
|
||||
},
|
||||
"adminPassword": {
|
||||
"value": "[parameters('adminPassword')]"
|
||||
},
|
||||
"assetLocation": {
|
||||
"value": "[variables('adAssetLocation')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[variables('updateVNetDNS1')]",
|
||||
"type": "Microsoft.Resources/deployments",
|
||||
"apiVersion": "2016-02-01",
|
||||
"dependsOn": [
|
||||
"[variables('deployPrimaryAdID')]"
|
||||
],
|
||||
"properties": {
|
||||
"mode": "Incremental",
|
||||
"templateLink": {
|
||||
"uri": "[variables('vnetwithDNSTemplateURL')]",
|
||||
"contentVersion": "1.0.0.0"
|
||||
},
|
||||
"parameters": {
|
||||
"virtualNetworkName": {
|
||||
"value": "[variables('adVnetName')]"
|
||||
},
|
||||
"virtualNetworkAddressRange": {
|
||||
"value": "[variables('vnetAddressRange')]"
|
||||
},
|
||||
"subnets": {
|
||||
"value": "[variables('subnets')]"
|
||||
},
|
||||
"dnsServerAddress": {
|
||||
"value": [
|
||||
"[variables('dnsServerPrivateIp')]"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Storage/storageAccounts",
|
||||
"name": "[variables('storageAccountName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"accountType": "[variables('storageAccountType')]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "gw-nic",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[variables('gwlbID')]",
|
||||
"[variables('adVmDeploymentID')]"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"subnet": {
|
||||
"id": "[variables('subnet-id')]"
|
||||
},
|
||||
"loadBalancerBackendAddressPools": [
|
||||
{
|
||||
"id": "[variables('gwBEAddressPoolID')]"
|
||||
}
|
||||
],
|
||||
"loadBalancerInboundNatRules": [
|
||||
{
|
||||
"id": "[concat(variables('gwlbID'),'/inboundNatRules/rdp')]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"dnsSettings": {
|
||||
"dnsServers": [
|
||||
"[variables('dnsServerPrivateIp')]"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "cb-nic",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[variables('publiclbID')]",
|
||||
"[variables('adVmDeploymentID')]"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"subnet": {
|
||||
"id": "[variables('subnet-id')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"dnsSettings": {
|
||||
"dnsServers": [
|
||||
"[variables('dnsServerPrivateIp')]"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "[concat('rdsh-', copyindex(), '-nic')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"copy": {
|
||||
"name": "rdsh-nic-loop",
|
||||
"count": "[parameters('numberOfRdshInstances')]"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[variables('publiclbID')]",
|
||||
"[variables('adVmDeploymentID')]"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"subnet": {
|
||||
"id": "[variables('subnet-id')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"dnsSettings": {
|
||||
"dnsServers": [
|
||||
"[variables('dnsServerPrivateIp')]"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines",
|
||||
"name": "gw-vm",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[variables('deployPrimaryAdID')]",
|
||||
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
|
||||
"Microsoft.Network/networkInterfaces/gw-nic"
|
||||
],
|
||||
"properties": {
|
||||
"hardwareProfile": {
|
||||
"vmSize": "Standard_A2"
|
||||
},
|
||||
"availabilitySet": {
|
||||
"id": "[resourceId('Microsoft.Compute/availabilitySets', 'gw-availabilityset')]"
|
||||
},
|
||||
"osProfile": {
|
||||
"computerName": "gateway",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"adminPassword": "[parameters('adminPassword')]"
|
||||
},
|
||||
"storageProfile": {
|
||||
"imageReference": {
|
||||
"publisher": "[variables('imagePublisher')]",
|
||||
"offer": "[variables('imageOffer')]",
|
||||
"sku": "[parameters('imageSKU')]",
|
||||
"version": "latest"
|
||||
},
|
||||
"osDisk": {
|
||||
"name": "osdisk",
|
||||
"vhd": {
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),'2016-01-01').primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','gw-vm-os-disk.vhd')]"
|
||||
},
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage"
|
||||
}
|
||||
},
|
||||
"networkProfile": {
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"id": "[resourceId('Microsoft.Network/networkInterfaces','gw-nic')]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"name": "gw-vm/gateway",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Compute/virtualMachines', 'gw-vm')]"
|
||||
],
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Powershell",
|
||||
"type": "DSC",
|
||||
"typeHandlerVersion": "2.11",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"modulesUrl": "[concat(variables('assetLocation'),'/Configuration.zip')]",
|
||||
"configurationFunction": "Configuration.ps1\\Gateway",
|
||||
"Properties": {
|
||||
"DomainName": "[parameters('adDomainName')]",
|
||||
"AdminCreds": {
|
||||
"UserName": "[parameters('adminUsername')]",
|
||||
"Password": "PrivateSettingsRef:AdminPassword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"protectedSettings": {
|
||||
"Items": {
|
||||
"AdminPassword": "[parameters('adminPassword')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines",
|
||||
"name": "[concat('rdsh-', copyindex())]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"copy": {
|
||||
"name": "rdsh-vm-loop",
|
||||
"count": "[parameters('numberOfRdshInstances')]"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[variables('deployPrimaryAdID')]",
|
||||
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
|
||||
"[concat('Microsoft.Network/networkInterfaces/', 'rdsh-', copyindex(), '-nic')]"
|
||||
],
|
||||
"properties": {
|
||||
"hardwareProfile": {
|
||||
"vmSize": "[parameters('rdshVmSize')]"
|
||||
},
|
||||
"availabilitySet": {
|
||||
"id": "[resourceId('Microsoft.Compute/availabilitySets', 'rdsh-availabilityset')]"
|
||||
},
|
||||
"osProfile": {
|
||||
"computerName": "[concat('rdsh-', copyIndex())]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"adminPassword": "[parameters('adminPassword')]"
|
||||
},
|
||||
"storageProfile": {
|
||||
"imageReference": {
|
||||
"publisher": "[variables('imagePublisher')]",
|
||||
"offer": "[variables('imageOffer')]",
|
||||
"sku": "[parameters('imageSKU')]",
|
||||
"version": "latest"
|
||||
},
|
||||
"osDisk": {
|
||||
"name": "osdisk",
|
||||
"vhd": {
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),'2016-01-01').primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','rdsh-',copyindex(),'-os-disk.vhd')]"
|
||||
|
||||
},
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage"
|
||||
}
|
||||
},
|
||||
"networkProfile": {
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"id": "[resourceId('Microsoft.Network/networkInterfaces',concat('rdsh-', copyindex(), '-nic'))]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"name": "[concat('rdsh-', copyindex(),'/sessionhost')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Compute/virtualMachines', concat('rdsh-', copyindex()))]"
|
||||
],
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Powershell",
|
||||
"type": "DSC",
|
||||
"typeHandlerVersion": "2.11",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"ModulesUrl": "[concat(variables('assetLocation'),'/Configuration.zip')]",
|
||||
"ConfigurationFunction": "Configuration.ps1\\SessionHost",
|
||||
"Properties": {
|
||||
"DomainName": "[parameters('adDomainName')]",
|
||||
"AdminCreds": {
|
||||
"UserName": "[parameters('adminUsername')]",
|
||||
"Password": "PrivateSettingsRef:AdminPassword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"protectedSettings": {
|
||||
"Items": {
|
||||
"AdminPassword": "[parameters('adminPassword')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines",
|
||||
"name": "cb-vm",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[variables('deployPrimaryAdID')]",
|
||||
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
|
||||
"Microsoft.Network/networkInterfaces/cb-nic",
|
||||
"rdsh-vm-loop"
|
||||
],
|
||||
"properties": {
|
||||
"hardwareProfile": {
|
||||
"vmSize": "Standard_A2"
|
||||
},
|
||||
"availabilitySet": {
|
||||
"id": "[resourceId('Microsoft.Compute/availabilitySets', 'cb-availabilityset')]"
|
||||
},
|
||||
"osProfile": {
|
||||
"computerName": "broker",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"adminPassword": "[parameters('adminPassword')]"
|
||||
},
|
||||
"storageProfile": {
|
||||
"imageReference": {
|
||||
"publisher": "[variables('imagePublisher')]",
|
||||
"offer": "[variables('imageOffer')]",
|
||||
"sku": "[parameters('imageSKU')]",
|
||||
"version": "latest"
|
||||
},
|
||||
"osDisk": {
|
||||
"name": "osdisk",
|
||||
"vhd": {
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),'2016-01-01').primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','cb-vm-os-disk.vhd')]"
|
||||
},
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage"
|
||||
}
|
||||
},
|
||||
"networkProfile": {
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"id": "[resourceId('Microsoft.Network/networkInterfaces','cb-nic')]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"name": "cb-vm/rdsdeployment",
|
||||
"apiVersion": "2015-06-15",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Compute/virtualMachines', 'cb-vm')]",
|
||||
"Microsoft.Compute/virtualMachines/gw-vm/extensions/gateway",
|
||||
"rdsh-vm-loop"
|
||||
],
|
||||
"properties": {
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"protectedSettings": {
|
||||
"Items": {
|
||||
"adminPassword": "[parameters('adminPassword')]"
|
||||
}
|
||||
},
|
||||
"publisher": "Microsoft.Powershell",
|
||||
"settings": {
|
||||
"modulesUrl": "[concat(variables('assetLocation'),'/Configuration.zip')]",
|
||||
"configurationFunction": "Configuration.ps1\\RDSDeployment",
|
||||
"Properties": {
|
||||
"adminCreds": {
|
||||
"UserName": "[parameters('adminUsername')]",
|
||||
"Password": "PrivateSettingsRef:adminPassword"
|
||||
},
|
||||
"connectionBroker": "[concat('broker.',parameters('adDomainName'))]",
|
||||
"domainName": "[parameters('adDomainName')]",
|
||||
"externalfqdn": "[reference(parameters('gwpublicIPAddressName')).dnsSettings.fqdn]",
|
||||
"numberOfRdshInstances": "[parameters('numberOfRdshInstances')]",
|
||||
"sessionHostNamingPrefix": "rdsh-",
|
||||
"webAccessServer": "[concat('gateway.',parameters('adDomainName'))]"
|
||||
}
|
||||
},
|
||||
"type": "DSC",
|
||||
"typeHandlerVersion": "2.75"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"gwdnsLabelPrefix": {
|
||||
"value": "GEN-UNIQUE"
|
||||
},
|
||||
"adminPassword": {
|
||||
"value": "GEN-PASSWORD"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"itemDisplayName": "Basic RDS farm deployment",
|
||||
"description": "This template creates a basic RDS farm deployment",
|
||||
"summary": "Creates and deploys a fully functional RDS farm",
|
||||
"githubUsername": "MahendraAgrawal",
|
||||
"dateUpdated": "2017-08-05"
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"virtualNetworkName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of the Virtual Network to Create"
|
||||
}
|
||||
},
|
||||
"virtualNetworkAddressRange": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The address range of the new VNET in CIDR format"
|
||||
},
|
||||
"defaultValue": "10.0.0.0/16"
|
||||
},
|
||||
"subnetName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of the subnet created in the new VNET"
|
||||
}
|
||||
},
|
||||
"subnetRange": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The address range of the subnet created in the new VNET"
|
||||
},
|
||||
"defaultValue": "10.0.0.0/24"
|
||||
},
|
||||
"dnsServerAddress": {
|
||||
"type": "array",
|
||||
"metadata": {
|
||||
"description": "The DNS address(es) of the DNS Server(s) used by the VNET"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"name": "[parameters('virtualNetworkName')]",
|
||||
"type": "Microsoft.Network/virtualNetworks",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"addressSpace": {
|
||||
"addressPrefixes": [
|
||||
"[parameters('virtualNetworkAddressRange')]"
|
||||
]
|
||||
},
|
||||
"dhcpOptions": {
|
||||
"dnsServers": "[parameters('dnsServerAddress')]"
|
||||
},
|
||||
"subnets": [
|
||||
{
|
||||
"name": "[parameters('subnetName')]",
|
||||
"properties": {
|
||||
"addressPrefix": "[parameters('subnetRange')]"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
# Configure certificates for RDS deployment
|
||||
|
||||
Click the button below to deploy:
|
||||
|
||||
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fmmarch%2Fazure-quickstart-templates%2Fcerts-template%2Frds-update-certificate%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://azuredeploy.net/deploybutton.png"/>
|
||||
</a>
|
||||
<a href="http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2Fmmarch%2Fazure-quickstart-templates%2Fcerts-template%2Frds-update-certificate%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://armviz.io/visualizebutton.png"/>
|
||||
</a>
|
||||
<br><br>
|
||||
|
||||
This Template allows you configure certificates in an RDS deployment.
|
||||
Remote Desktop Services require certificaties for
|
||||
server authentication, single sign-on (SSO), and to secure RDP connections.
|
||||
For a good overview of certificates use in RDS see
|
||||
[Configuring RDS 2012 Certificates and SSO](https://ryanmangansitblog.com/2013/03/10/configuring-rds-2012-certificates-and-sso/) and
|
||||
[How to Create a (Mostly) Seamless Logon Experience For Your Remote Desktop Services Environment](http://www.rdsgurus.com/windows-2012-r2-how-to-create-a-mostly-seamless-logon-experience-for-your-remote-desktop-services-environment/) by RDS MVP Toby Phipps.
|
||||
|
||||
The Template makes use of a single SSL certificate. The certificate's Subject Name must match external DNS name of RD Gateway server in the deployment.
|
||||
The certificate with the private key (in .PFX format) must be stored in Azure Key Vault.
|
||||
For information on managing certificates with Azure Key Vault see: [Get started with Azure Key Vault certificates](https://blogs.technet.microsoft.com/kv/2016/09/26/get-started-with-azure-key-vault-certificates/) and
|
||||
[Manage certificates via Azure Key Vault](https://blogs.technet.microsoft.com/kv/2016/09/26/manage-certificates-via-azure-key-vault/).
|
||||
|
||||
|
||||
## Pre-Requisites
|
||||
|
||||
0. Template is intended to run against an existing RDS deployment. The deployment can be created using one of RDS QuickStart templates
|
||||
([Basic RDS Deployment Template](https://github.com/Azure/azure-quickstart-templates/tree/master/rds-deployment), or [RDS Deployment using existing VNET and AD](https://github.com/Azure/azure-quickstart-templates/tree/master/rds-deployment-existing-ad), etc.).
|
||||
|
||||
1. A certificate with the private key needs to be created (or acquired from CA) and imported to Azure Key Vault in tenant's subscription
|
||||
(see [Get started with Azure Key Vault](https://azure.microsoft.com/en-us/documentation/articles/key-vault-get-started)).
|
||||
Certificate's Subject Name should match external DNS name of the RDS Gateway server.
|
||||
|
||||
For example, to import an existing certificate stored as a .pfx file on your local hard drive run the following PowerShell:
|
||||
```PowerShell
|
||||
$vaultName = "myVault"
|
||||
$certNameInVault = "certificate" # cert name in vault, has to be '^[0-9a-zA-Z-]+$' pattern (digits, letters or dashes only, no spaces)
|
||||
$pfxFilePath = "c:\certificate.pfx"
|
||||
$password = "B@kedPotat0" # password that was used to secure the pfx file at the time of export
|
||||
|
||||
Import-AzureKeyVaultCertificate -vaultname $vaultName -name $certNameInVault -filepath $pfxFilePath -password ($password | convertto-securestring -asplaintext -force)
|
||||
```
|
||||
Mark down 1) key vault name, and 2) certificate name in vault from this step - these will need to be supplied as input parameters to the Template.
|
||||
|
||||
2. A Service Principal account needs to be created with permissions to access certificates in the Key Vault
|
||||
(see [Use Azure PowerShell to create a service principal to access resources](https://azure.microsoft.com/en-us/documentation/articles/resource-group-authenticate-service-principal/)).
|
||||
|
||||
Sample powershell (alternatively you see Scripts\New-ServicePrincipal.ps1):
|
||||
```PowerShell
|
||||
$appPassword = "R@bberDuck"
|
||||
$uri = "https://www.contoso.com/script" # a valid formatted URL, not validated for single-tenant deployments
|
||||
$vaultName = "myVault" # same key vault name as in step #1 above
|
||||
|
||||
$app = New-AzureRmADApplication -DisplayName "script" -HomePage $uri -IdentifierUris $uri -password $appPassword
|
||||
$sp = New-AzureRmADServicePrincipal -ApplicationId $app.ApplicationId
|
||||
|
||||
Set-AzureRmKeyVaultAccessPolicy -vaultname $vaultName -serviceprincipalname $sp.ApplicationId -permissionstosecrets get
|
||||
```
|
||||
|
||||
Note: Certificates stored in Key Vault as secrets with content type 'application/x-pkcs12', this is why
|
||||
`Set-AzureRmKeyVaultAccessPolivy` cmdlet grants `-PremissionsToSecrets` (rather than `-PermissionsToCertificates`).
|
||||
|
||||
You will need 1) application id (`$app.ApplicationId`), and 2) the password from above step supplied as input parameters to the Template.
|
||||
You will also need your tenant Id. To get tenant Id run the following powershell:
|
||||
```PowerShell
|
||||
$tenantId = (Get-AzureRmSubscription).TenantId | select -Unique
|
||||
```
|
||||
|
||||
## Running the Template
|
||||
|
||||
Template applies same certificate to all 4 roles in the deployment: `{ RDGateway | RDWebAccess | RDRedirector | RDPublishing }`.
|
||||
|
||||
Template performs the following steps:
|
||||
+ downloads certificate from the key vault using Service Principal credentials;
|
||||
+ invokes [Set-RDCertificate](https://technet.microsoft.com/en-us/library/jj215464.aspx) cmdlet to apply the certificate for each of the roles;
|
||||
+ calls [Set-RDClientAccessName](https://technet.microsoft.com/en-us/library/jj215484.aspx) to update Client Access Name on RD Connection Broker to match the certificate.
|
|
@ -0,0 +1,30 @@
|
|||
[cmdletbinding()]
|
||||
param(
|
||||
|
||||
[string]$appName = "rds-update-certificate-script",
|
||||
|
||||
# has to be a valid format URI; URI's not validated for single-tenant application
|
||||
[string]$uri = "https://login.microsoft.com/rds-update-certificate-script",
|
||||
|
||||
[parameter(mandatory=$true)]
|
||||
[string]$password,
|
||||
|
||||
[string]$vaultName
|
||||
)
|
||||
|
||||
$app = New-AzureRmADApplication -DisplayName $appName -HomePage $uri -IdentifierUris $uri -password $pwd
|
||||
|
||||
$sp = New-AzureRmADServicePrincipal -ApplicationId $app.ApplicationId
|
||||
|
||||
if ($vaultName)
|
||||
{
|
||||
set-azurermkeyvaultaccesspolicy -vaultname $vaultName -serviceprincipalname $sp.ApplicationId -permissionstosecrets get
|
||||
}
|
||||
|
||||
$tenantId = (get-azurermsubscription).TenantId | select -Unique
|
||||
|
||||
|
||||
# outputs
|
||||
#
|
||||
"application id: $($app.ApplicationId)"
|
||||
"tenant id: $tenantId"
|
|
@ -0,0 +1,132 @@
|
|||
[cmdletbinding()]
|
||||
param(
|
||||
[parameter(mandatory = $true)][ValidateNotNullOrEmpty()] [string]$appId,
|
||||
[parameter(mandatory = $true)][ValidateNotNullOrEmpty()] [string]$appPassword,
|
||||
[parameter(mandatory = $true)][ValidateNotNullOrEmpty()] [string]$tenantId,
|
||||
|
||||
[parameter(mandatory = $true)][ValidateNotNullOrEmpty()] [string]$vaultName,
|
||||
[parameter(mandatory = $true)][ValidateNotNullOrEmpty()] [string]$secretName,
|
||||
|
||||
[parameter(mandatory = $true)][ValidateNotNullOrEmpty()] [string]$adminUsername,
|
||||
[parameter(mandatory = $true)][ValidateNotNullOrEmpty()] [string]$adminPassword,
|
||||
|
||||
[parameter(mandatory = $true)][ValidateNotNullOrEmpty()] [string]$adDomainName,
|
||||
|
||||
[Parameter(ValueFromRemainingArguments = $true)]
|
||||
$extraParameters
|
||||
)
|
||||
|
||||
function log
|
||||
{
|
||||
param([string]$message)
|
||||
|
||||
"`n`n$(get-date -f o) $message"
|
||||
}
|
||||
|
||||
|
||||
log "script running..."
|
||||
whoami
|
||||
|
||||
# $PSBoundParameters
|
||||
|
||||
if ($extraParameters)
|
||||
{
|
||||
log "any extra parameters:"
|
||||
$extraParameters
|
||||
}
|
||||
|
||||
# requires WMF 5.0
|
||||
|
||||
# verify NuGet package
|
||||
$nuget = get-packageprovider nuget
|
||||
if (-not $nuget -or ($nuget.Version -lt 2.8.5.22))
|
||||
{
|
||||
log "installing nuget package..."
|
||||
install-packageprovider -name NuGet -minimumversion 2.8.5.201 -force
|
||||
}
|
||||
|
||||
# install AzureRM module
|
||||
#
|
||||
if (-not (get-module AzureRM))
|
||||
{
|
||||
log "installing AzureRm powershell module..."
|
||||
install-module AzureRM -force
|
||||
}
|
||||
|
||||
|
||||
# log onto azure account
|
||||
#
|
||||
log "logging onto azure account with app id = $appId ..."
|
||||
|
||||
$creds = new-object System.Management.Automation.PSCredential ($appId, (convertto-securestring $appPassword -asplaintext -force))
|
||||
login-azurermaccount -credential $creds -serviceprincipal -tenantid $tenantId -confirm:$false
|
||||
|
||||
# get the secret from key vault
|
||||
#
|
||||
log "getting secret '$secretName' from keyvault '$vaultName'..."
|
||||
$secret = get-azurekeyvaultsecret -vaultname $vaultName -name $secretName
|
||||
|
||||
$certCollection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
|
||||
|
||||
$bytes = [System.Convert]::FromBase64String($secret.SecretValueText)
|
||||
$certCollection.Import($bytes, $null, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
|
||||
|
||||
add-type -AssemblyName System.Web
|
||||
$password = [System.Web.Security.Membership]::GeneratePassword(38,5)
|
||||
$protectedCertificateBytes = $certCollection.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $password)
|
||||
|
||||
$pfxFilePath = join-path $env:TEMP "$([guid]::NewGuid()).pfx"
|
||||
log "writing the cert as '$pfxFilePath'..."
|
||||
[io.file]::WriteAllBytes($pfxFilePath, $protectedCertificateBytes)
|
||||
|
||||
|
||||
# apply certificate
|
||||
#
|
||||
ipmo remotedesktop -DisableNameChecking
|
||||
|
||||
# impersonate as admin
|
||||
#
|
||||
log "impersonating as '$adminUsername'..."
|
||||
$admincreds = New-Object System.Management.Automation.PSCredential (($adminUsername + "@" + $adDomainName), (ConvertTo-SecureString $adminPassword -AsPlainText -Force))
|
||||
|
||||
.\New-ImpersonateUser.ps1 -Credential $admincreds
|
||||
whoami
|
||||
|
||||
# apply certificate
|
||||
#
|
||||
$roles = @("RDGateway", "RDWebAccess", "RDRedirector", "RDPublishing")
|
||||
|
||||
$roles | % `
|
||||
{
|
||||
log "applying certificate for role: $_..."
|
||||
set-rdcertificate -role $_ -importpath $pfxFilePath -password (convertto-securestring $password -asplaintext -force) -force
|
||||
}
|
||||
|
||||
log "remove impersonation..."
|
||||
Remove-ImpersonateUser
|
||||
whoami
|
||||
|
||||
# set client access name
|
||||
#
|
||||
$gatewayConfig = get-rddeploymentgatewayconfiguration
|
||||
|
||||
if ($gatewayConfig -and $gatewayConfig.GatewayExternalFqdn)
|
||||
{
|
||||
$externalFqdn = $gatewayConfig.GatewayExternalFqdn
|
||||
$externalDomainSuffix = $externalFqdn.substring($externalFqdn.IndexOf('.') + 1)
|
||||
|
||||
$clientAccessName = $env:COMPUTERNAME + '.' + $externalDomainSuffix
|
||||
|
||||
log "setting client access name to '$clientAccessName'..."
|
||||
.\Set-RDPublishedName.ps1 -ClientAccessName $clientAccessName
|
||||
}
|
||||
|
||||
# clean up
|
||||
#
|
||||
if (test-path($pfxFilePath))
|
||||
{
|
||||
log "running cleanup..."
|
||||
remove-item $pfxFilePath
|
||||
}
|
||||
|
||||
log "done."
|
|
@ -0,0 +1,124 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"vaultName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Azure Key Vault name where the certificate is stored."
|
||||
}
|
||||
},
|
||||
"certificateName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Name of the certificate in the Azure Key Vault."
|
||||
}
|
||||
},
|
||||
"applicationId": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "AD application Id used to access the certificate."
|
||||
}
|
||||
},
|
||||
"applicationPassword": {
|
||||
"type": "securestring",
|
||||
"metadata": {
|
||||
"description": "AD application password."
|
||||
}
|
||||
},
|
||||
"tenantId": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Tenant Id for whom the Secure Principal account was created."
|
||||
}
|
||||
},
|
||||
"brokerVmName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Name of the RD Connection Broker VM resource in the deployment (the configure certificates script is executed on this VM)."
|
||||
},
|
||||
"defaultValue": "cb-vm"
|
||||
},
|
||||
"existingDomainName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The FQDN of the AD domain"
|
||||
}
|
||||
},
|
||||
"existingAdminUsername": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Name of the domain account with administrative priviledges in the RDS deployment"
|
||||
}
|
||||
},
|
||||
"existingAdminPassword": {
|
||||
"type": "securestring",
|
||||
"metadata": {
|
||||
"description": "The password for the administrator account of the new VM and the domain"
|
||||
}
|
||||
},
|
||||
"_artifactsLocation": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The base URI where artifacts required by this template are located. When the template is deployed using the accompanying scripts, a private location in the subscription will be used and this value will be automatically generated."
|
||||
},
|
||||
"defaultValue": "https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/rds-update-certificate"
|
||||
},
|
||||
"_artifactsLocationSasToken": {
|
||||
"type": "securestring",
|
||||
"metadata": {
|
||||
"description": "The sasToken required to access _artifactsLocation. When the template is deployed using the accompanying scripts, a sasToken will be automatically generated."
|
||||
},
|
||||
"defaultValue": ""
|
||||
}
|
||||
},
|
||||
|
||||
"variables": {
|
||||
"p": {
|
||||
"appid": "[concat(' -appId ', parameters('applicationId'))]",
|
||||
"apppassword": "[concat(' -appPassword ', parameters('applicationPassword'))]",
|
||||
"tenantid": "[concat(' -tenantId ', parameters('tenantId'))]",
|
||||
"vault": "[concat(' -vaultName ', parameters('vaultName'))]",
|
||||
"secret": "[concat(' -secretName ', parameters('certificateName'))]",
|
||||
"adminUsername": "[concat(' -adminUsername ', parameters('existingAdminUsername'))]",
|
||||
"adminPassword": "[concat(' -adminPassword ', parameters('existingAdminPassword'))]",
|
||||
"adDomainName": "[concat(' -adDomainName ', parameters('existingDomainName'))]"
|
||||
},
|
||||
"scriptParameters": "[concat(variables('p').appid, variables('p').apppassword, variables('p').tenantid, variables('p').vault, variables('p').secret, variables('p').adminUsername, variables('p').adminPassword, variables('p').adDomainName)]",
|
||||
"scriptFolder": "Scripts",
|
||||
"scriptFileName": "Script.ps1",
|
||||
"impersonateScript": "https://gallery.technet.microsoft.com/scriptcenter/Impersonate-a-User-9bfeff82/file/127189/1/New-ImpersonateUser.ps1",
|
||||
"setPublishedNameScript": "https://gallery.technet.microsoft.com/Change-published-FQDN-for-2a029b80/file/103829/2/Set-RDPublishedName.ps1"
|
||||
},
|
||||
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"name": "[concat(parameters('brokerVmName'),'/customscript')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"tags": {
|
||||
"displayName": "script"
|
||||
},
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Compute",
|
||||
"type": "CustomScriptExtension",
|
||||
"typeHandlerVersion": "1.8",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"fileUris": [
|
||||
"[variables('impersonateScript')]",
|
||||
"[variables('setPublishedNameScript')]",
|
||||
"[concat(parameters('_artifactsLocation'), '/', variables('scriptFolder'), '/', variables('scriptFileName'), parameters('_artifactsLocationSasToken'))]"
|
||||
]
|
||||
},
|
||||
"protectedSettings": {
|
||||
"commandToExecute": "[concat( 'powershell -noninteractive -executionpolicy bypass -file ', variables('scriptFileName'), variables('scriptParameters'), ' >> script.log 2>&1' )]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"outputs": {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"vaultName": {
|
||||
"value": "myVault"
|
||||
},
|
||||
"certificateName": {
|
||||
"value": "certificate"
|
||||
},
|
||||
"applicationId": {
|
||||
"value": "GEN-UNIQUE"
|
||||
},
|
||||
"applicationPassword": {
|
||||
"value": "GEN-PASSWORD"
|
||||
},
|
||||
"tenantId": {
|
||||
"value": "GEN-UNIQUE"
|
||||
},
|
||||
"brokerVmName": {
|
||||
"value": "cb-vm"
|
||||
},
|
||||
"existingDomainName": {
|
||||
"value": "mydomain.local"
|
||||
},
|
||||
"existingAdminUsername": {
|
||||
"value": "GEN-USER"
|
||||
},
|
||||
"existingAdminPassword": {
|
||||
"value": "GEN-PASSWORD"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"itemDisplayName": "Update RDS certificates template",
|
||||
"description": "This template configures certificates in RDS deployment",
|
||||
"summary": "Imports a PFX certificate from Azure Key Vault and configures RDS roles to use the certificate",
|
||||
"githubUsername": "mmarch",
|
||||
"dateUpdated": "2016-12-05"
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,23 @@
|
|||
# Update Remote Desktop Sesson Collection to new template image
|
||||
|
||||
This template updates RDSH servers in existing session host collection with new updated template image. The URI for the image is provided as a template parameter.
|
||||
|
||||
This template deploys the following resources:
|
||||
+ `<rdshNumberOfInstances`> new virtual machines as RDSH servers
|
||||
|
||||
Template does the following:
|
||||
+ creates new RDSH instances from given template image and adds them to collection;
|
||||
+ puts old RDSH servers in Drain mode to prevent new user connections;
|
||||
+ notifies any logged on RD users that their sessions will be soon terminated due to collection maintenance;
|
||||
+ logs off existing users from old RDSH instances after given timeout (`<userLogoffTimeoutInMinutes>` parameter).
|
||||
|
||||
Note: Template does **not** delete or deallocate old RDSH instances, so you may still incur compute charges. These virtual machine instances may need to be deleted manually.
|
||||
|
||||
Click the button below to deploy:
|
||||
|
||||
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fmmarch%2Fazure-quickstart-templates%2Fmaster%2Frds-update-rdsh-collection%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://azuredeploy.net/deploybutton.png"/>
|
||||
</a>
|
||||
<a href="http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2Fmmarch%2Fazure-quickstart-templates%2Fmaster%2Frds-update-rdsh-collection%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://armviz.io/visualizebutton.png"/>
|
||||
</a>
|
|
@ -0,0 +1,237 @@
|
|||
[cmdletbinding()]
|
||||
param(
|
||||
[parameter(mandatory = $true)]
|
||||
[string]$domain,
|
||||
[parameter(mandatory = $true)]
|
||||
[string]$username,
|
||||
[parameter(mandatory = $true)]
|
||||
[string]$password,
|
||||
|
||||
[parameter(mandatory = $true)]
|
||||
[string]$collection,
|
||||
[parameter(mandatory = $true)]
|
||||
[string]$iteration,
|
||||
[parameter(mandatory = $true)]
|
||||
[int]$nServers,
|
||||
|
||||
[parameter(mandatory = $true)]
|
||||
[int]$nTimeoutMinutes,
|
||||
|
||||
[Parameter(ValueFromRemainingArguments = $true)]
|
||||
$extraParameters
|
||||
)
|
||||
|
||||
$title = "System Maintenance"
|
||||
$message = "Please save your work. You will be logged off in $nTimeoutInMinutes minute(s)."
|
||||
|
||||
function log
|
||||
{
|
||||
param([string]$message)
|
||||
|
||||
"`n`n$(get-date -f o) $message"
|
||||
}
|
||||
|
||||
|
||||
function add-server
|
||||
{
|
||||
param(
|
||||
[parameter(mandatory=$true)]
|
||||
[string]$server
|
||||
)
|
||||
|
||||
$cs = gwmi win32_computersystem; $broker = "$($cs.dnshostname).$($cs.domain)"
|
||||
|
||||
log "adding server $server to the deployment..."
|
||||
add-rdserver $server -role rds-rd-server -ev e
|
||||
|
||||
if ($e -like '*deployment*not present*')
|
||||
{
|
||||
log "trying to create rds deployment..."
|
||||
new-rdsessiondeployment -connectionbroker $broker -sessionhost $_ -ev e
|
||||
|
||||
if ($e -like "*$server*has reboots pending*")
|
||||
{
|
||||
log "attempting to reboot $server..."
|
||||
restart-computer $server -force -wait
|
||||
|
||||
log "attempting to create deployment with $server one more time..."
|
||||
new-rdsessiondeployment -connectionbroker $broker -sessionhost $_ -ea stop
|
||||
}
|
||||
|
||||
elseif ($e)
|
||||
{
|
||||
throw
|
||||
}
|
||||
|
||||
log "create deployment - success."
|
||||
}
|
||||
|
||||
elseif ($e -like "*$server*has reboots pending*")
|
||||
{
|
||||
log "attempting to reboot $server..."
|
||||
restart-computer $server -force -wait
|
||||
|
||||
log "attempting to add $server to deployment again after reboot..."
|
||||
add-rdserver $server -role rds-rd-server -ea stop
|
||||
}
|
||||
|
||||
elseif ($e)
|
||||
{
|
||||
throw
|
||||
}
|
||||
|
||||
log "successfully added '$server' to the deployment."
|
||||
}
|
||||
|
||||
|
||||
log "script running..."
|
||||
|
||||
whoami
|
||||
|
||||
# $PSBoundParameters
|
||||
|
||||
if ($extraParameters)
|
||||
{
|
||||
log "any extra parameters:"
|
||||
$extraParameters
|
||||
}
|
||||
|
||||
|
||||
log "attempting impersonate as $domain\$username..."
|
||||
.\New-ImpersonateUser.ps1 -Username $username -Domain $domain -Password $password
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
ipmo remotedesktop -DisableNameChecking # 4>$null
|
||||
|
||||
# $domain = (gwmi win32_computersystem).Domain
|
||||
|
||||
$newServers = 0..$($nServers - 1) | % { "rdsh-$_$iteration.$domain" }
|
||||
log "list of new servers:"
|
||||
$newServers | % { " $($_.tolower())" }
|
||||
|
||||
|
||||
# 1. add new servers to the deployment
|
||||
#
|
||||
log "current list of servers in the rds deployment:"
|
||||
$existingServers = (get-rdserver).Server
|
||||
$existingServers | % { " $($_.tolower())" }
|
||||
|
||||
$newServers | ? { -not ($_ -in $existingServers) } | % { add-server $_ }
|
||||
|
||||
|
||||
# 2. add new servers to the rdsh collection
|
||||
#
|
||||
log "current list of rdsh servers in collection '$($collection)':"
|
||||
$existingServers = (get-rdsessionhost -CollectionName $collection).SessionHost
|
||||
if ($existingServers)
|
||||
{
|
||||
$existingServers | % { " $($_.tolower())" }
|
||||
}
|
||||
else
|
||||
{
|
||||
" --- no servers in the collection yet ----"
|
||||
}
|
||||
|
||||
$serversToAdd = $newServers | ? { -not ($_ -in $existingServers) }
|
||||
|
||||
if ($serversToAdd)
|
||||
{
|
||||
log "adding new servers $($serversToAdd -join '; ') to session host collection '$collection'..."
|
||||
add-rdsessionhost -collectionname $collection -sessionhost $serversToAdd -ea stop
|
||||
}
|
||||
|
||||
|
||||
# 3. put old servers in drain mode
|
||||
#
|
||||
$serversToRemove = $existingServers | ? { -not ($_ -in $newServers) }
|
||||
|
||||
if ($serversToRemove)
|
||||
{
|
||||
$serversToRemove | % `
|
||||
{
|
||||
log "putting server $_ in drain mode..."
|
||||
set-rdsessionhost -sessionhost $_ -newconnectionallowed No
|
||||
}
|
||||
}
|
||||
|
||||
# 4. notify users they are going to be logged off in next <n> minutes
|
||||
#
|
||||
log "querying for user sessions in collection '$collection'..."
|
||||
$sessions = get-rdusersession -CollectionName $collection
|
||||
log "found total $($sessions.count) user sessions,"
|
||||
|
||||
$sessionsToLogoff = $sessions | ? { -not( $_.HostServer -in $newServers ) }
|
||||
log "out of those $($sessionsToLogoff.count) sessions on the servers that are to be removed..."
|
||||
|
||||
if ($sessionsToLogoff)
|
||||
{
|
||||
$sessionsToLogoff| % `
|
||||
{
|
||||
log "sending message to user $($_.UserName) at host $($_.HostServer)..."
|
||||
send-rdusermessage -hostserver $_.HostServer -unifiedsessionid $_.UnifiedSessionId -messagetitle $title -messagebody $message
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# 5. log users off
|
||||
#
|
||||
if ($sessionsToLogoff)
|
||||
{
|
||||
log "waiting $nTimeoutMinutes munites before logging users off..."
|
||||
start-sleep -s ($nTimeoutMinutes * 60)
|
||||
|
||||
|
||||
log "querying for user sessions again..."
|
||||
$sessions = get-rdusersession -CollectionName $collection
|
||||
log "found total $($sessions.count) user sessions at this time,"
|
||||
|
||||
$sessionsToLogoff = $sessions | ? { -not( $_.HostServer -in $newServers ) }
|
||||
log "out of those, $($sessionsToLogoff.count) sessions to be logged off..."
|
||||
if ($sessionsToLogoff)
|
||||
{
|
||||
$sessionsToLogoff | % `
|
||||
{
|
||||
log "logging off user $($_.UserName) from host $($_.HostServer)..."
|
||||
invoke-rduserlogoff -hostserver $_.HostServer -unifiedsessionid $_.SessionId -force
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# 6. remove old servers from deployment
|
||||
#
|
||||
if ($serversToRemove)
|
||||
{
|
||||
log "removing servers $($serversToRemove -join '; ') from session host collection '$collection'..."
|
||||
remove-rdsessionhost -sessionhost $serversToRemove -force
|
||||
|
||||
$serversToRemove | % `
|
||||
{
|
||||
log "removing server $_ from the deployment..."
|
||||
remove-rdserver $_ -role rds-rd-server -force
|
||||
}
|
||||
|
||||
log "shutting down servers $($serversToRemove -join '; ')..."
|
||||
$creds = new-object System.Management.Automation.PSCredential ("$domain\$username", (convertto-securestring $password -asplaintext -force))
|
||||
stop-computer -computer $serversToRemove -credential $creds -force
|
||||
}
|
||||
else
|
||||
{
|
||||
log "nothing to do."
|
||||
}
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
log "ERROR: caught exception"
|
||||
throw
|
||||
}
|
||||
finally
|
||||
{
|
||||
log "remove impersonation..."
|
||||
Remove-ImpersonateUser
|
||||
}
|
||||
|
||||
log "done. success."
|
|
@ -0,0 +1,264 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"existingRdshCollectionName": {
|
||||
"type": "string",
|
||||
"defaultValue": "Desktop Collection",
|
||||
"metadata": {
|
||||
"description": "Name of the RDSH collection to update"
|
||||
}
|
||||
},
|
||||
"rdshTemplateImageUri": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "URI for the template VHD to use for RDSH instances. For example, https://rdsstorage.blob.core.windows.net/vhds/MyWindowServerOSImage.vhd"
|
||||
}
|
||||
},
|
||||
"rdshUpdateIteration": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "A unique designator representing update iteration; newly created RDSH instances will have their names in the form: 'rdsh-<index><iteration>"
|
||||
}
|
||||
},
|
||||
"rdshNumberOfInstances": {
|
||||
"type": "int",
|
||||
"defaultValue": 2,
|
||||
"metadata": {
|
||||
"description": "Number of RD Session Hosts"
|
||||
}
|
||||
},
|
||||
"rdshVmSize": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The size of the RDSH virtual machines"
|
||||
},
|
||||
"defaultValue": "Standard_A2"
|
||||
},
|
||||
"userLogoffTimeoutInMinutes": {
|
||||
"type": "int",
|
||||
"defaultValue": 60,
|
||||
"metadata": {
|
||||
"description": "Timeout before forced user logoff from old RDSH instances"
|
||||
}
|
||||
},
|
||||
"existingDomainName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Domain name of the exisiting RDS deployment"
|
||||
}
|
||||
},
|
||||
"existingAdminUsername": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of administrator in the existing RDS deployment"
|
||||
}
|
||||
},
|
||||
"existingAdminPassword": {
|
||||
"type": "securestring",
|
||||
"metadata": {
|
||||
"description": "Domain administrator password"
|
||||
}
|
||||
},
|
||||
"existingVnetName": {
|
||||
"type": "string",
|
||||
"defaultValue": "vnet",
|
||||
"metadata": {
|
||||
"description": "VNET name"
|
||||
}
|
||||
},
|
||||
"existingSubnetName": {
|
||||
"type": "string",
|
||||
"defaultValue": "Subnet",
|
||||
"metadata": {
|
||||
"description": "Subnet name"
|
||||
}
|
||||
},
|
||||
"availabilitySet": {
|
||||
"type": "string",
|
||||
"defaultValue": "rdsh-availabilityset",
|
||||
"metadata": {
|
||||
"description": "Availability set for new RDSH instances"
|
||||
}
|
||||
},
|
||||
"_artifactsLocation": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The base URI where artifacts required by this template are located. When the template is deployed using the accompanying scripts, a private location in the subscription will be used and this value will be automatically generated."
|
||||
},
|
||||
"defaultValue": "https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/rds-update-rdsh-collection/"
|
||||
},
|
||||
"_artifactsLocationSasToken": {
|
||||
"type": "securestring",
|
||||
"metadata": {
|
||||
"description": "The sasToken required to access _artifactsLocation. When the template is deployed using the accompanying scripts, a sasToken will be automatically generated."
|
||||
},
|
||||
"defaultValue": ""
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
"variables": {
|
||||
"iteration": "[toLower(parameters('rdshUpdateIteration'))]",
|
||||
"storageAccountName": "[split( split( parameters('rdshTemplateImageUri'), '/')[2], '.' )[0]]",
|
||||
"impersonateScript": "https://gallery.technet.microsoft.com/scriptcenter/Impersonate-a-User-9bfeff82/file/127189/1/New-ImpersonateUser.ps1",
|
||||
"p": {
|
||||
"domain": "[concat(' -domain ', parameters('existingDomainName'))]",
|
||||
"user": "[concat(' -username ', parameters('existingAdminUsername'))]",
|
||||
"pwd": "[concat(' -password ', parameters('existingAdminPassword'))]",
|
||||
"collection": "[concat(' -collection \"', parameters('existingRdshCollectionName'), '\"')]",
|
||||
"iteration": "[concat(' -iteration ', toLower(parameters('rdshUpdateIteration')))]",
|
||||
"servers": "[concat(' -nServers ', parameters('rdshNumberOfInstances'))]",
|
||||
"timeout": "[concat(' -nTimeoutMinutes ', parameters('userLogoffTimeoutInMinutes'))]"
|
||||
},
|
||||
"scriptParameters": "[concat(variables('p').domain, variables('p').user, variables('p').pwd, variables('p').collection, variables('p').iteration, variables('p').servers, variables('p').timeout)]",
|
||||
"scriptFolder": "Scripts",
|
||||
"scriptFileName": "Script.ps1"
|
||||
},
|
||||
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "[concat('rdsh-', copyindex(),variables('iteration'), '-nic')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"copy": {
|
||||
"name": "rdsh-nic-loop",
|
||||
"count": "[parameters('rdshNumberOfInstances')]"
|
||||
},
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"subnet": {
|
||||
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('existingVnetName'), parameters('existingSubnetName'))]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/availabilitySets",
|
||||
"name": "[parameters('availabilitySet')]",
|
||||
"location": "[resourceGroup().location]"
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines",
|
||||
"name": "[concat('rdsh-', copyindex(),variables('iteration'))]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"copy": {
|
||||
"name": "rdsh-vm-loop",
|
||||
"count": "[parameters('rdshNumberOfInstances')]"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/networkInterfaces/', 'rdsh-', copyindex(),variables('iteration'), '-nic')]"
|
||||
],
|
||||
"properties": {
|
||||
"hardwareProfile": {
|
||||
"vmSize": "[parameters('rdshVmSize')]"
|
||||
},
|
||||
"availabilitySet": {
|
||||
"id": "[resourceId('Microsoft.Compute/availabilitySets', parameters('availabilitySet'))]"
|
||||
},
|
||||
"osProfile": {
|
||||
"computerName": "[concat('rdsh-', copyindex(),variables('iteration'))]",
|
||||
"adminUsername": "[parameters('existingAdminUsername')]",
|
||||
"adminPassword": "[parameters('existingAdminPassword')]"
|
||||
},
|
||||
"storageProfile": {
|
||||
"osDisk": {
|
||||
"name": "[concat('rdsh-', copyindex(),variables('iteration'),'-osDisk')]",
|
||||
"osType": "Windows",
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage",
|
||||
"image": {
|
||||
"uri": "[parameters('rdshTemplateImageUri')]"
|
||||
},
|
||||
"vhd": {
|
||||
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')), '2016-01-01').primaryEndpoints.blob, 'vhds/rdsh-', copyindex(), variables('iteration'), '-osdisk.vhd')]"
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
"networkProfile": {
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"id": "[resourceId('Microsoft.Network/networkInterfaces',concat('rdsh-', copyindex(),variables('iteration'), '-nic'))]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"diagnosticsProfile": {
|
||||
"bootDiagnostics": {
|
||||
"enabled": "true",
|
||||
"storageUri": "[reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')), '2016-01-01').primaryEndpoints.blob]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"name": "[concat('rdsh-',copyindex(),variables('iteration'),'/sessionhost')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Compute/virtualMachines', concat('rdsh-', copyindex(),variables('iteration')))]"
|
||||
],
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Powershell",
|
||||
"type": "DSC",
|
||||
"typeHandlerVersion": "2.75",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"ModulesUrl": "[concat(parameters('_artifactsLocation'),'/DSC/Configuration.zip', parameters('_artifactsLocationSasToken'))]",
|
||||
"ConfigurationFunction": "Configuration.ps1\\SessionHost",
|
||||
"Properties": {
|
||||
"DomainName": "[parameters('existingDomainName')]",
|
||||
"AdminCreds": {
|
||||
"UserName": "[parameters('existingAdminUsername')]",
|
||||
"Password": "PrivateSettingsRef:AdminPassword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"protectedSettings": {
|
||||
"Items": {
|
||||
"AdminPassword": "[parameters('existingAdminPassword')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-06-15",
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"name": "cb-vm/customscript",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"rdsh-vm-loop"
|
||||
],
|
||||
"tags": {
|
||||
"displayName": "script"
|
||||
},
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Compute",
|
||||
"type": "CustomScriptExtension",
|
||||
"typeHandlerVersion": "1.8",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"fileUris": [
|
||||
"[variables('impersonateScript')]",
|
||||
"[concat(parameters('_artifactsLocation'), '/', variables('scriptFolder'), '/', variables('scriptFileName'), parameters('_artifactsLocationSasToken'))]"
|
||||
]
|
||||
},
|
||||
"protectedSettings": {
|
||||
"commandToExecute": "[concat( 'powershell -noninteractive -executionpolicy bypass -file ', variables('scriptFileName'), variables('scriptParameters'), ' >> script.log 2>&1' )]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"existingDomainName": {
|
||||
"value": "mydomain.local"
|
||||
},
|
||||
"existingAdminUsername": {
|
||||
"value": "GEN-USER"
|
||||
},
|
||||
"existingAdminPassword": {
|
||||
"value": "GEN-PASSWORD"
|
||||
},
|
||||
"rdshTemplateImageUri": {
|
||||
"value": "https://rdsstorage.blob.core.windows.net/vhds/MyWindowServerOSImage.vhd"
|
||||
},
|
||||
"rdshUpdateIteration": {
|
||||
"value": "a"
|
||||
},
|
||||
"userLogoffTimeoutInMinutes": {
|
||||
"value": 60
|
||||
},
|
||||
"existingVnetName": {
|
||||
"value": "vnet"
|
||||
},
|
||||
"existingSubnetName": {
|
||||
"value": "subnet"
|
||||
},
|
||||
"availabilitySet": {
|
||||
"value": "rdsh-availabilityset"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"itemDisplayName": "Update RDSH collection",
|
||||
"description": "This template updates servers in an RD Session Host collection",
|
||||
"summary": "Updates existing session collection with new template image",
|
||||
"githubUsername": "mmarch",
|
||||
"dateUpdated": "2016-09-02"
|
||||
}
|
Загрузка…
Ссылка в новой задаче