This commit is contained in:
Tyler Clintworth 2017-10-28 17:09:45 -07:00
Родитель 5079ca14ad
Коммит 4537a77dea
8 изменённых файлов: 711 добавлений и 12 удалений

Просмотреть файл

@ -1,13 +1,13 @@
# Technical Reference Implementation for Enterprise BI and Reporting
Azure offers a rich data and analytics platform for customers and ISVs seeking to build scalable BI and Reporting solutions. However, customers face pragmatic challenges in building the right infrastructure for enterprise-grade, production systems. They have to evaluate the various products for security, scale, performance and geo-availability requirements. They have to understand service features and their interoperability, and plan to address any perceived gaps with custom software. This takes time and effort, and many times, the end to end system architecture they design is sub-optimal. Consequently, the promise and expectations set during proof-of-concept (POC) stages do not translate to robust production systems in the expected time to market.
Azure offers a rich data and analytics platform for customers and ISVs seeking to build scalable BI and reporting solutions. However, customers face pragmatic challenges in building the right infrastructure for enterprise-grade, production systems. They have to evaluate the various products for security, scale, performance and geo-availability requirements. They have to understand service features and their interoperability, and plan to address any perceived gaps with custom software. This takes time and effort, and many times, the end to end system architecture they design is sub-optimal. Consequently, the promise and expectations set during proof-of-concept (POC) stages do not translate to robust production systems in the expected time to market.
This TRI addresses this customer pain by providing a reference implementation that
- is pre-built based on selected, stable Azure components proven to work in enterprise BI and reporting scenarios
- can be easily configured and deployed to an Azure subscription within a few hours,
- is bundled with software to handle all the operational essentials for a full fledged production system, and
- is tested end to end against large workloads.
This TRI addresses this customer pain by providing a reference implementation that is:
- pre-built based on selected, stable Azure components proven to work in enterprise BI and reporting scenarios
- easily configured and deployed to an Azure subscription within a few hours
- bundled with software to handle all the operational essentials for a full fledged production system
- tested end to end against large workloads
Once deployed, the TRI can be used as-is, or customized to fit the application needs using the technical documentation that is provided with the TRI. This enables the customer to build the solution that delivers the business goals based on a robust and functional infrastructure.

Просмотреть файл

@ -1,18 +1,18 @@
# Summary
This page summarizes prerequisites for EDW Reporting TRA deployment.
This page summarizes prerequisites for Technical Reference Implementation for Enterprise BI and Reporting solution.
# VNET
Most of the resources provisioned will be placed in a pre-existing Azure VNET. Therefore, we require an Azure VNET resource and a domain controller to be deployed in the subscription where the EDW Reporting TRA will be deployed. Customers who already have a functioning Azure VNET can skip this section. For customers new to Azure, the guide below will show how to easily deploy prerequisites in their subscription.
Most of the resources provisioned will be placed in a pre-existing Azure VNET. Therefore, we require an Azure VNET resource and a domain controller to be deployed in the subscription where the solution will be deployed. Customers who already have a functioning Azure VNET and domain controller can skip this section. For customers new to Azure, the guide below will show how to easily deploy prerequisites in their subscription.
## Provisioning Azure VNet resource
First, we will create new Azure VNET and VPN Gateway resources. Navigate to <source root>\edw\deployment directory and run the command below. Note that it might take up to 45 minutes to complete.
First, we will create new Azure VNET and VPN Gateway resources. Navigate to the <source root>\scripts directory and run the command below. Note that it might take up to 45 minutes to complete.
```PowerShell
Login-AzureRmAccount
.\DeployVPN.ps1 -SubscriptionName "My Subscription" -Location "westus" -EDWAddressPrefix "10.254.0.0/16" -EDWGatewaySubnetPrefix "10.254.1.0/24" -OnpremiseVPNClientSubnetPrefix "192.168.200.0/24" -ResourceGroupName "ContosoVNetGroup" -VNetName "ContosoVNet" -VNetGatewayName "ContosoGateway" -RootCertificateName "ContosoRootCertificate" -ChildCertificateName "ContosoChildCertificate"
.\DeployVPN.ps1 -SubscriptionName "My Subscription" -ResourceGroupName "ContosoVNetGroup" -Location "westus" -VNetName "ContosoVNet" -VNetGatewayName "ContosoGateway" -AddressPrefix "10.254.0.0/16" -GatewaySubnetPrefix "10.254.1.0/24" -OnpremiseVPNClientSubnetPrefix "192.168.200.0/24" -RootCertificateName "ContosoRootCertificate" -ChildCertificateName "ContosoChildCertificate"
```
In addition to provisioning Azure VNET and VPN Gateway resources, the script above will also create a self-signed root certificate and a client certificate for the VPN gateway. The root certificate is used for generating and signing client certificates on the client side, and for validating those client certificates on the VPN gateway side.
@ -24,7 +24,7 @@ $rootCert = Get-ChildItem -Path cert:\CurrentUser\My | ?{ $_.Subject -eq "CN=Con
$childCert = Get-ChildItem -Path cert:\CurrentUser\My | ?{ $_.Subject -eq "CN=ContosoChildCertificate" }
$type = [System.Security.Cryptography.X509Certificates.X509Certificate]::pfx
$securePassword = ConvertTo-SecureString -String "Welcome1234!" -Force –AsPlainText
$securePassword = ConvertTo-SecureString -String "MyPassword" -Force –AsPlainText
Export-PfxCertificate -Cert $rootCert -FilePath "ContosoRootCertificate.pfx" -Password $securePassword -Verbose
Export-PfxCertificate -Cert $childCert -FilePath "ContosoChildCertificate.pfx" -Password $securePassword -Verbose
@ -35,7 +35,7 @@ Export-PfxCertificate -Cert $childCert -FilePath "ContosoChildCertificate.pfx" -
The next step is to deploy a Domain Controller VM and set up a new domain. All VMs provisioned during the EDW TRA deployment will join the domain managed by the domain controller. To do that, run the PowerShell script below.
```PowerShell
.\DeployDC.ps1 -SubscriptionName "My Subscription" -Location "westus" -ExistingVNETResourceGroupName "ContosoVNetGroup" -ExistingVNETName "ContosoVNet" -DomainName "contosodomain.ms" -DomainUserName "edwadmin" -DomainUserPassword "Welcome1234!"
.\DeployDC.ps1 -SubscriptionName "My Subscription" -Location "westus" -ResourceGroupName "ContosoVNetGroup" -VNetName "ContosoVNet" -DomainName "contosodomain.ms" -DomainUserName "edwadmin" -DomainUserPassword "MyPassword"
```
The script above will provision an Azure VM and promote it to serve as the domain controller for the VNET. In addition, it will reconfigure the VNET to use the newly provisioned VM as its DNS server.

207
armTemplates/dc-deploy.json Normal file
Просмотреть файл

@ -0,0 +1,207 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": {
"type": "string",
"metadata": {
"description": "The name of the Administrator of the new VM and Domain"
},
"defaultValue": "adAdministrator"
},
"adminPassword": {
"type": "securestring",
"metadata": {
"description": "The password for the Administrator account of the new VM and Domain"
}
},
"domainName": {
"type": "string",
"metadata": {
"description": "The FQDN of the AD Domain to be created"
}
},
"existingVirtualNetworkName": {
"type": "string",
"metadata": {
"description": "Name of the existing VNET"
}
},
"existingVirtualNetworkAddressRange": {
"type": "string",
"metadata": {
"description": "Address range of the existing VNET"
}
},
"dcSubnetName": {
"type": "string",
"metadata": {
"description": "Name of the existing subnet for Domain Controller"
}
},
"existingSubnetAddressRange": {
"type": "string",
"metadata": {
"description": "Address range of the existing subnet"
}
},
"_artifactsLocation": {
"type": "string",
"metadata": {
"description": "The location of resources, such as templates and DSC modules, that the template depends on"
},
"defaultValue": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/active-directory-new-domain-ha-2-dc"
},
"_artifactsLocationSasToken": {
"type": "securestring",
"metadata": {
"description": "Auto-generated token to access _artifactsLocation"
},
"defaultValue": ""
}
},
"variables": {
"vhdStorageAccountName": "[concat('vhds', uniqueString(resourceGroup().id))]",
"storageAccountType": "Premium_LRS",
"dcVMName": "adDC",
"imagePublisher": "MicrosoftWindowsServer",
"imageOffer": "WindowsServer",
"imageSKU": "2016-Datacenter",
"dcVMSize": "Standard_DS2_v2",
"dcPDCNicName": "adPDCNic",
"dcSubnetRef": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('existingVirtualNetworkName'), parameters('dcSubnetName'))]",
"dcDataDisk": "DCDataDisk",
"dcDataDiskSize": 1000,
"dcModulesURL": "[concat(parameters('_artifactsLocation'),'/DSC/CreateADPDC.zip', parameters('_artifactsLocationSasToken'))]",
"dcConfigurationFunction": "CreateADPDC.ps1\\CreateADPDC",
"vnetwithDNSTemplateUri": "[concat(parameters('_artifactsLocation'),'/nestedtemplates/vnet-with-dns-server.json', parameters('_artifactsLocationSasToken'))]"
},
"resources": [
{
"name": "[variables('vhdStorageAccountName')]",
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2016-05-01",
"location": "[resourceGroup().location]",
"properties": {
},
"sku": { "name": "[variables('storageAccountType')]" },
"kind": "Storage"
},
{
"name": "[variables('dcPDCNicName')]",
"type": "Microsoft.Network/networkInterfaces",
"apiVersion": "2016-10-01",
"location": "[resourceGroup().location]",
"dependsOn": [
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[variables('dcSubnetRef')]"
}
}
}
]
}
},
{
"name": "[variables('dcVMName')]",
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2016-03-30",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts',variables('vhdStorageAccountName'))]",
"[resourceId('Microsoft.Network/networkInterfaces',variables('dcPDCNicName'))]"
],
"properties": {
"hardwareProfile": {
"vmSize": "[variables('dcVMSize')]"
},
"osProfile": {
"computerName": "[variables('dcVMName')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "[variables('imagePublisher')]",
"offer": "[variables('imageOffer')]",
"sku": "[variables('imageSKU')]",
"version": "latest"
},
"osDisk": {
"name": "osdisk",
"vhd": {
"uri": "[concat(reference(resourceId('Microsoft.Storage/storageAccounts/', variables('vhdStorageAccountName'))).primaryEndpoints.blob,'vhds0/','osdisk.vhd')]"
},
"caching": "ReadWrite",
"createOption": "FromImage"
},
"dataDisks": [
{
"vhd": {
"uri": "[concat(reference(resourceId('Microsoft.Storage/storageAccounts/', variables('vhdStorageAccountName'))).primaryEndpoints.blob,'vhds0/', variables('dcDataDisk'),'.vhd')]"
},
"name": "[concat(variables('dcVMName'),'-data-disk1')]",
"caching": "None",
"diskSizeGB": "[variables('dcDataDiskSize')]",
"lun": 0,
"createOption": "empty"
}
]
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces',variables('dcPDCNicName'))]"
}
]
}
},
"resources": [
{
"name": "CreateADForest",
"type": "extensions",
"apiVersion": "2016-03-30",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', variables('dcVMName'))]"
],
"properties": {
"publisher": "Microsoft.Powershell",
"type": "DSC",
"typeHandlerVersion": "2.19",
"autoUpgradeMinorVersion": true,
"settings": {
"ModulesUrl": "[variables('dcModulesURL')]",
"ConfigurationFunction": "[variables('dcConfigurationFunction')]",
"Properties": {
"DomainName": "[parameters('domainName')]",
"AdminCreds": {
"UserName": "[parameters('adminUserName')]",
"Password": "PrivateSettingsRef:AdminPassword"
}
}
},
"protectedSettings": {
"Items": {
"AdminPassword": "[parameters('adminPassword')]"
}
}
}
}
]
}
],
"outputs": {
"DCIp": {
"type": "string",
"value": "[reference(variables('dcPDCNicName')).ipConfigurations[0].properties.privateIPAddress]"
}
}
}

Просмотреть файл

@ -0,0 +1,98 @@
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
"contentVersion": "1.0.0.0",
"parameters": {
"gatewayName": {
"type": "string",
"metadata": {
"description": "Name of the VPN gateway"
}
},
"virtualNetworkName": {
"type": "string",
"metadata": {
"description": "Name for the Azure Virtual Network"
}
},
"edwAzureVNetAddressPrefix": {
"type": "string",
"metadata": {
"description": "CIDR block representing the address space of the Azure VNet"
}
},
"vpnGatewaySubnetPrefix": {
"type": "string",
"metadata": {
"description": "CIDR block for gateway subnet, subset of edwAzureVNetAddressPrefix address space"
}
}
},
"variables": {
"apiVersion": "2015-06-15",
"gatewaySubnetName": "GatewaySubnet",
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]",
"gatewaySubnetRef": "[concat(variables('vnetID'),'/subnets/', variables('gatewaySubnetName'))]",
"gatewayPublicIPName": "EDWVPNGwPublicIp"
},
"resources": [
{
"apiVersion": "[variables('apiVersion')]",
"type": "Microsoft.Network/virtualNetworks",
"name": "[parameters('virtualNetworkName')]",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('edwAzureVNetAddressPrefix')]"
]
},
"subnets": [
{
"name": "[variables('gatewaySubnetName')]",
"properties": {
"addressPrefix": "[parameters('vpnGatewaySubnetPrefix')]"
}
}
]
}
},
{
"apiVersion": "[variables('apiVersion')]",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('gatewayPublicIPName')]",
"location": "[resourceGroup().location]",
"properties": {
"publicIPAllocationMethod": "Dynamic"
}
},
{
"apiVersion": "[variables('apiVersion')]",
"type": "Microsoft.Network/virtualNetworkGateways",
"name": "[parameters('gatewayName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[concat('Microsoft.Network/publicIPAddresses/', variables('gatewayPublicIPName'))]",
"[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]"
],
"properties": {
"ipConfigurations": [
{
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[variables('gatewaySubnetRef')]"
},
"publicIPAddress": {
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('gatewayPublicIPName'))]"
}
},
"name": "vnetGatewayConfig"
}
],
"gatewayType": "Vpn",
"vpnType": "RouteBased",
"enableBgp": "false"
}
}
]
}

54
scripts/Common.psm1 Normal file
Просмотреть файл

@ -0,0 +1,54 @@
function New-ResourceGroupIfNotExists ($resourceGroupName, $location) {
$resourceGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
if(-not $resourceGroup) {
New-AzureRmResourceGroup -Name $resourceGroupName -Location $location
Write-Output ("Created Resource Group $resourceGroupName in $location.");
return;
}
$isSameLocation = $resourceGroup.Location -eq $location
if(-not $isSameLocation) {
throw "Resource Group $resourceGroup exists in a different location $resourceGroup.Location .. Delete the existing resource group or choose another name." ;
}
Write-Output ("Resource Group $resourceGroupName already exists. Skipping creation.");
}
function New-Session () {
$Error.Clear()
$ErrorActionPreference = "SilentlyContinue"
Get-AzureRmContext -ErrorAction Continue;
foreach ($eacherror in $Error) {
if ($eacherror.Exception.ToString() -like "*Run Login-AzureRmAccount to login.*") {
Add-AzureAccount
}
}
$Error.Clear();
$ErrorActionPreference = "Stop"
}
function Load-Module($name)
{
if(-not(Get-Module -name $name))
{
if(Get-Module -ListAvailable |
Where-Object { $_.name -eq $name })
{
Import-Module -Name $name
Write-Host "Module $name imported successfully"
} #end if module available then import
else
{
Write-Host "Module $name does not exist. Installing.."
Install-Module -Name $name -AllowClobber -Force
Write-Host "Module $name installed successfully"
} #module not available
} # end if not module
else
{
Write-Host "Module $name exists and is already loaded"
} #module already loaded
}

Просмотреть файл

@ -0,0 +1,170 @@
# This module contains network related common functions
# To get virtual network. If not possible to get virtual network, exit as it is a critical requirement
Function Get-VirtualNetworkOrExit(
[Parameter(Mandatory=$true)]
[string] $ResourceGroupName,
[Parameter(Mandatory=$true)]
[string] $VirtualNetworkName
)
{
try {
$virtualNetwork = Get-AzureRmVirtualNetwork -Name $VirtualNetworkName -ResourceGroupName $ResourceGroupName
if (-not $virtualNetwork) {
Write-Host -ForegroundColor DarkRed "Unable to get virtual network $($VirtualNetworkName). Exiting..."
Display-VnetErrorMessage
exit 3
}
return $virtualNetwork
} catch {
Write-Host -ForegroundColor DarkRed "Unable to get virtual network $($VirtualNetworkName). Exiting..."
Write-Host $Error[0]
Display-VnetErrorMessage
exit 3
}
}
# Get uint32 value for given IPv4 network address
Function Get-NetworkValue(
[Parameter(Mandatory=$true)]
[string] $NetworkPrefix
)
{
$strArray = $NetworkPrefix.Split(".")
[uint32] $value = 0
for($i=0; $i -lt 4; $i++) {
$value = ($value -shl 8) + [convert]::ToInt16($strArray[$i])
}
return $value
}
# Get Ipv4 network address for given uint32
Function Get-NetworkAddress(
[Parameter(Mandatory=$true)]
[uint32] $NetworkValue
)
{
[uint32] $mask = (1 -shl 8) - 1
[string] $networkAddress = ""
for($i=0; $i -lt 3; $i++) {
[uint32] $value = $NetworkValue -band $mask
$NetworkValue = $NetworkValue -shr 8
$networkAddress = "." + $value + $networkAddress
}
$networkAddress = "$($NetworkValue)$($networkAddress)"
return $networkAddress
}
# Get free subnet or existing given subnet under given virtual network or exit
# If free subnet is found then it is created under VNET for this deployment to use
Function Get-AvailableSubnetOrExit(
[Parameter(Mandatory=$true)]
[object] $VirtualNetwork,
[Parameter(Mandatory=$true)]
[string] $SubnetName
)
{
$GatewaySubnetName = "GatewaySubnet"
$TotalBits = 32
try {
$vnetAddressPrefix = $VirtualNetwork.AddressSpace.AddressPrefixes[0]
$addressPrefixArray = $vnetAddressPrefix.Split("/")
$networkAddress = $addressPrefixArray[0]
[int]$networkNumBits = $TotalBits - ([convert]::ToInt32($addressPrefixArray[1], 10))
$gatewaySubnet = Get-AzureRmVirtualNetworkSubnetConfig -Name $GatewaySubnetName -VirtualNetwork $VirtualNetwork
if (-not $gatewaySubnet) {
Write-Host -ForegroundColor DarkRed "Unable to get subnet for deployment. Exiting..."
Display-VnetErrorMessage
exit 4
}
# Using GatewaySubnet range size for all subnets to keep things simple
$addressPrefixArray = $gatewaySubnet.AddressPrefix.Split("/")
$gwNetworkAddress = $addressPrefixArray[0]
$gwNetworkAddressSuffix = $addressPrefixArray[1]
[int]$gwNetworkNumBits = $TotalBits - ([convert]::ToInt16($gwNetworkAddressSuffix, 10))
# Track use subnets
$usedSubnets = New-Object 'System.Collections.Generic.HashSet[int]'
for($i=0; $i -lt $VirtualNetwork.Subnets.Count; $i++) {
$subnet = $VirtualNetwork.Subnets[$i]
if ($subnet.Name.Equals($SubnetName)) {
# Found an existing given subnet, return it
return $subnet.AddressPrefix
}
[uint32]$value = Get-NetworkValue ($subnet.AddressPrefix.Split("/"))[0]
$value = $value -shr $gwNetworkNumBits
$mask = (1 -shl ($networkNumBits - $gwNetworkNumBits)) - 1
$value = $value -band $mask
$usedSubnets.Add($value) | Out-Null
}
# Find a free subnet
$numSubnets = 1 -shl ($networkNumBits - $gwNetworkNumBits)
for([uint32]$i=1; $i -lt $numSubnets; $i++) {
if (-not $usedSubnets.Contains($i)) {
# Found a free subnet
[uint32]$value = Get-NetworkValue $networkAddress
$value = $value -bor ($i -shl $gwNetworkNumBits)
$newSubnetAddress = Get-NetworkAddress $value
$newSubnetPrefix = "$($newSubnetAddress)/$($gwNetworkAddressSuffix)"
# Create the new subnet
New-Subnet -VirtualNetwork $VirtualNetwork `
-SubnetName $SubnetName `
-SubnetPrefix $newSubnetPrefix | Out-Null
return $newSubnetPrefix
}
}
Write-Host -ForegroundColor DarkRed "Unable to find free subnet for deployment. Exiting..."
Display-VnetErrorMessage
exit 4
} catch {
Write-Host -ForegroundColor DarkRed "Unable to get subnet for deployment. Exiting..."
Display-VnetErrorMessage
Write-Host $Error[0]
exit 4
}
}
# Creates a subnet under given VNET
Function New-Subnet(
[Parameter(Mandatory=$true)]
[object] $VirtualNetwork,
[Parameter(Mandatory=$true)]
[string] $SubnetName,
[Parameter(Mandatory=$true)]
[string] $SubnetPrefix
)
{
Add-AzureRmVirtualNetworkSubnetConfig -Name $SubnetName -VirtualNetwork $VirtualNetwork -AddressPrefix $SubnetPrefix
Set-AzureRmVirtualNetwork -VirtualNetwork $VirtualNetwork
}
Function Display-VnetErrorMessage()
{
Write-Host -ForegroundColor DarkRed "Unable to determine VNET or subnet used for this deployment."
Write-Host -ForegroundColor DarkRed "If your setup uses point-to-site VPN configuration, please run DeployVPN.ps1 script before running this script."
}

64
scripts/DeployDC.ps1 Normal file
Просмотреть файл

@ -0,0 +1,64 @@
#Requires -RunAsAdministrator
#Requires -Modules AzureRM.Network
#Requires -Modules AzureRM.profile
# This script deploys a Domain Controller on an existing VNET resource group and assigns the DNS address of VNET to the DC IP address
Param(
[Parameter(Mandatory=$true)]
[string]$SubscriptionName,
[Parameter(Mandatory=$true)]
[string]$Location,
[Parameter(Mandatory=$true)]
[string]$ResourceGroupName,
[Parameter(Mandatory=$true)]
[string]$VNetName,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="Domain name to create.")]
[string]$DomainName,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="Domain admin user name.")]
[string]$DomainUserName,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="Domain admin user password.")]
[securestring]$DomainUserPassword
)
$scriptPath = $MyInvocation.MyCommand.Path
$scriptDir = Split-Path $scriptPath
Import-Module (Join-Path $scriptDir CommonNetworking.psm1) -Force
# Name of the subnet in which Domain Controller will be present
$SubnetName = "DCSubnet"
# Select subscription
Select-AzureRmSubscription -SubscriptionName $SubscriptionName
$subscription = Get-AzureRmSubscription -SubscriptionName $SubscriptionName
$SubscriptionId = $subscription.Subscription.SubscriptionId
# Create a subnet for DC deployment
$virtualNetwork = Get-VirtualNetworkOrExit -ResourceGroupName $ResourceGroupName -VirtualNetworkName $VNetName
$subnetAddressPrefix = Get-AvailableSubnetOrExit -VirtualNetwork $virtualNetwork -SubnetName $SubnetName
$templateParameters = @{
adminUsername=$DomainUserName
adminPassword=$DomainUserPassword
domainName=$DomainName
existingVirtualNetworkName=$VNetName
existingVirtualNetworkAddressRange=$virtualNetwork.AddressSpace.AddressPrefixes[0]
dcSubnetName=$SubnetName
existingSubnetAddressRange=$subnetAddressPrefix
}
$templateFilePath = Join-Path (Join-Path (Split-Path -Parent $scriptDir) 'armTemplates') 'dc-deploy.json'
$out = New-AzureRmResourceGroupDeployment -Name DeployDC `
-ResourceGroupName $ResourceGroupName `
-TemplateFile $templateFilePath `
-TemplateParameterObject $templateParameters
# Update the DNS server address for VNET
$virtualNetwork.DhcpOptions.DnsServers = $out.Outputs.dcIp.Value
Set-AzureRmVirtualNetwork -VirtualNetwork $virtualNetwork

106
scripts/DeployVPN.ps1 Normal file
Просмотреть файл

@ -0,0 +1,106 @@
#Requires -RunAsAdministrator
#Requires -Modules AzureRM.Network
#Requires -Modules AzureRM.profile
# This script deploys a Azure Virtual Network, subnet and VPN gateway
# Use this script when connectivity from onpremises to Azure VNET is using point-to-site VPN connection
Param(
[Parameter(Mandatory=$true)]
[string]$SubscriptionName,
# Under this resource group common resources like VPN gateway, Virtual network will be deployed.
[Parameter(Mandatory=$true)]
[string]$ResourceGroupName,
# The name of Azure VNet resource.
[Parameter(Mandatory=$true)]
[string]$VNetName,
[Parameter(Mandatory=$true)]
[string]$Location,
# The name of the Azure VNet Gateway resource.
[Parameter(Mandatory=$true)]
[string]$VNetGatewayName,
[Parameter(Mandatory=$false)]
[string]$AddressPrefix = "10.254.0.0/16",
[Parameter(Mandatory=$false)]
[string]$GatewaySubnetPrefix = "10.254.1.0/24",
[Parameter(Mandatory=$false)]
[string]$OnpremiseVPNClientSubnetPrefix = "192.168.200.0/24",
[Parameter(Mandatory=$false)]
[string]$RootCertificateName = "VPN-RootCert-$($VNetName)",
[Parameter(Mandatory=$false)]
[string]$ChildCertificateName = "VPN-ChildCert-$($VNetName)"
)
# Import the common functions
$scriptPath = $MyInvocation.MyCommand.Path
$scriptDir = Split-Path $scriptPath
Import-Module (Join-Path $scriptDir Common.psm1) -Force
# Select subscription
Select-AzureRmSubscription -SubscriptionName $SubscriptionName
$subscription = Get-AzureRmSubscription -SubscriptionName $SubscriptionName
$SubscriptionId = $subscription.Subscription.SubscriptionId
# Create the resource group if needed
New-ResourceGroupIfNotExists $ResourceGroupName -Location $Location
# Deploy VNET, Gateway Subnet and VPN gateway
$templateParamsVpnGateway = @{
gatewayName=$VNetGatewayName
virtualNetworkName=$VNetName
edwAzureVNetAddressPrefix=$AddressPrefix
vpnGatewaySubnetPrefix=$GatewaySubnetPrefix
}
Write-Host -ForegroundColor Yellow "VPN Gateway deployment could take upto 45 minutes"
$templateFilePath = Join-Path (Join-Path (Split-Path -Parent $scriptDir) 'armTemplates') 'vpn-gateway.json'
$vpnGwDeployment = New-AzureRmResourceGroupDeployment -Name VpnGateway `
-ResourceGroupName $ResourceGroupName `
-TemplateFile $templateFilePath `
-TemplateParameterObject $templateParamsVpnGateway `
-Verbose
Write-Host "Generating certificates for VPN gateway"
# Generate a self signed root certificate
$vpnRootCert = New-SelfSignedCertificate -Type Custom -KeySpec Signature `
-Subject "CN=$($RootCertificateName)" -KeyExportPolicy Exportable `
-HashAlgorithm sha256 -KeyLength 2048 `
-CertStoreLocation "Cert:\CurrentUser\My" -KeyUsageProperty Sign -KeyUsage CertSign
# Add the self signed root certificate to the trusted root certificates store
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store(
[System.Security.Cryptography.X509Certificates.StoreName]::Root,
"currentuser"
)
$store.open("MaxAllowed")
$store.add($vpnRootCert)
$store.close()
# Generate a client certificate
New-SelfSignedCertificate -Type Custom -KeySpec Signature `
-Subject "CN=$($ChildCertificateName)" -KeyExportPolicy Exportable `
-HashAlgorithm sha256 -KeyLength 2048 `
-CertStoreLocation "Cert:\CurrentUser\My" `
-Signer $vpnRootCert -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2")
# Get root certificate public key data to be used by VPN gateway
$certBase64 = [system.convert]::ToBase64String($vpnRootCert.RawData)
$rootCert = New-AzureRmVpnClientRootCertificate -Name $RootCertificateName -PublicCertData $certBase64
$gateway = Get-AzureRmVirtualNetworkGateway -Name $VNetGatewayName -ResourceGroupName $ResourceGroupName
Write-Host "Updating VPN gateway with certificates"
Set-AzureRmVirtualNetworkGateway -VirtualNetworkGateway $gateway `
-VpnClientAddressPool $OnpremiseVPNClientSubnetPrefix `
-VpnClientRootCertificates $rootCert