11$parameters = $args [0 ]
2+ $scriptUrlBase = $args [1 ]
23
34$subscriptionId = $parameters [' subscriptionId' ]
45$resourceGroupName = $parameters [' resourceGroupName' ]
56$virtualNetworkName = $parameters [' virtualNetworkName' ]
67$certificateNamePrefix = $parameters [' certificateNamePrefix' ]
7- $force = $parameters [' force ' ]
8+ $clientCertificatePassword = $parameters [' clientCertificatePassword ' ]
89
9- $scriptUrlBase = $args [1 ]
10+ if ($clientCertificatePassword -eq ' ' -or ($null -eq $clientCertificatePassword )) {
11+ $clientCertificatePassword = ' S0m3Str0nGP@ssw0rd'
12+ }
1013
11- function VerifyPSVersion
12- {
13- Write-Host " Verifying PowerShell version, must be 5.0 or higher."
14- if ($PSVersionTable.PSVersion.Major -ge 5 )
15- {
16- Write-Host " PowerShell version verified." - ForegroundColor Green
14+ function VerifyPSVersion {
15+ Write-Host " Verifying PowerShell version."
16+ if ($PSVersionTable.PSEdition -eq " Desktop" ) {
17+ if (($PSVersionTable.PSVersion.Major -ge 6 ) -or
18+ (($PSVersionTable.PSVersion.Major -eq 5 ) -and ($PSVersionTable.PSVersion.Minor -ge 1 ))) {
19+ Write-Host " PowerShell version verified." - ForegroundColor Green
20+ }
21+ else {
22+ Write-Host " You need to install PowerShell version 5.1 or heigher." - ForegroundColor Red
23+ Break ;
24+ }
1725 }
18- else
19- {
20- Write-Host " You need to install PowerShell version 5.0 or heigher." - ForegroundColor Red
21- Break ;
26+ else {
27+ if ($PSVersionTable.PSVersion.Major -ge 6 ) {
28+ Write-Host " PowerShell version verified." - ForegroundColor Green
29+ }
30+ else {
31+ Write-Host " You need to install PowerShell version 6.0 or heigher." - ForegroundColor Red
32+ Break ;
33+ }
2234 }
2335}
2436
25- function Ensure-Login ()
26- {
27- $context = Get-AzureRmContext
28- If ($context.Subscription -eq $null )
29- {
30- Write-Host " Loging in ..."
31- If ((Login- AzureRmAccount - ErrorAction SilentlyContinue - ErrorVariable Errors) -eq $null )
32- {
33- Write-Host (" Login failed: {0}" -f $Errors [0 ].Exception.Message) - ForegroundColor Red
37+ function EnsureAzModule {
38+ Write-Host " Checking if Az module is imported."
39+ $module = Get-Module Az
40+ If ($null -eq $module ) {
41+ try {
42+ Import-Module Az - ErrorAction Stop
43+ Write-Host " Module Az imported." - ForegroundColor Green
44+ }
45+ catch {
46+ Install-Module Az - AllowClobber
47+ Write-Host " Module Az installed." - ForegroundColor Green
48+ }
49+ }
50+ else {
51+ Write-Host " Module Az imported." - ForegroundColor Green
52+ }
53+ }
54+
55+ function EnsureLogin () {
56+ $context = Get-AzContext
57+ If ($null -eq $context.Subscription ) {
58+ Write-Host " Sign-in..."
59+ If ($null -eq (Connect-AzAccount - ErrorAction SilentlyContinue - ErrorVariable Errors)) {
60+ Write-Host (" Sign-in failed: {0}" -f $Errors [0 ].Exception.Message) - ForegroundColor Red
3461 Break
3562 }
3663 }
37- Write-Host " User logedin ." - ForegroundColor Green
64+ Write-Host " Sign-in successful ." - ForegroundColor Green
3865}
3966
40- function Select-SubscriptionId {
67+ function SelectSubscriptionId {
4168 param (
4269 $subscriptionId
4370 )
44- Write-Host " Selecting subscription '$subscriptionId '."
45- $context = Get-AzureRmContext
46- If ($context.Subscription.Id -ne $subscriptionId )
47- {
48- Try
49- {
50- Select-AzureRmSubscription - SubscriptionId $subscriptionId - ErrorAction Stop | Out-null
71+ Write-Host " Selecting subscription '$subscriptionId '... "
72+ $context = Get-AzContext
73+ If ($context.Subscription.Id -ne $subscriptionId ) {
74+ Try {
75+ $currentSubscriptionId = $context .Subscription.Id
76+ Write-Host " Switching subscription $currentSubscriptionId to ' $subscriptionId '. " - ForegroundColor Green
77+ Select-AzSubscription - SubscriptionId $subscriptionId - ErrorAction Stop | Out-null
5178 }
52- Catch
53- {
79+ Catch {
5480 Write-Host " Subscription selection failed: $_ " - ForegroundColor Red
5581 Break
5682 }
5783 }
5884 Write-Host " Subscription selected." - ForegroundColor Green
5985}
6086
61- function Load-VirtualNetwork {
87+ function LoadVirtualNetwork {
6288 param (
6389 $resourceGroupName ,
6490 $virtualNetworkName
6591 )
66- Write-Host (" Loading virtual network '{0}' in resource group '{1}'." -f $virtualNetworkName , $resourceGroupName )
67- $virtualNetwork = Get-AzureRmVirtualNetwork - ResourceGroupName $resourceGroupName - Name $virtualNetworkName - ErrorAction SilentlyContinue
68- If ($virtualNetwork.Id -ne $null )
69- {
70- Write-Host " Virtual network loaded." - ForegroundColor Green
71- return $virtualNetwork
92+ Write-Host (" Loading virtual network '{0}' in resource group '{1}'." -f $virtualNetworkName , $resourceGroupName )
93+ $virtualNetwork = Get-AzVirtualNetwork - ResourceGroupName $resourceGroupName - Name $virtualNetworkName - ErrorAction SilentlyContinue
94+ $id = $virtualNetwork.Id
95+ If ($null -ne $id ) {
96+ Write-Host " Virtual network with id $id is loaded." - ForegroundColor Green
97+ If ($virtualNetwork.VirtualNetworkPeerings.Count -gt 0 ) {
98+ Write-Host " Virtual network is loaded, but it should not have peerings." - ForegroundColor Red
7299 }
73- else
74- {
75- Write-Host " Virtual network not found." - ForegroundColor Red
76- Break
77- }
78- }
79-
80- function Load-ResourceGroup {
81- param (
82- $resourceGroupName
83- )
84- Write-Host (" Loading resource group '{0}'." -f $resourceGroupName )
85- $resourceGroup = Get-AzureRmResourceGroup - Name $resourceGroupName
86- If ($resourceGroup.ResourceId -ne $null )
87- {
88- Write-Host " Resource group loaded." - ForegroundColor Green
89- return $resourceGroup
100+ return $virtualNetwork
90101 }
91- else
92- {
93- Write-Host " Resource group not found." - ForegroundColor Red
102+ else {
103+ Write-Host " Virtual network $virtualNetworkName cannot be found." - ForegroundColor Red
94104 Break
95105 }
96106}
97107
98- function Set-VirtualNetwork
99- {
108+ function SetVirtualNetwork {
100109 param ($virtualNetwork )
101110
102111 Write-Host " Applying changes to the virtual network."
103- Try
104- {
105- Set-AzureRmVirtualNetwork - VirtualNetwork $virtualNetwork - ErrorAction Stop | Out-Null
112+ Try {
113+ Set-AzVirtualNetwork - VirtualNetwork $virtualNetwork - ErrorAction Stop | Out-Null
106114 }
107- Catch
108- {
109- Write-Host " Failed: $_ " - ForegroundColor Red
115+ Catch {
116+ Write-Host " Failed to configure Virtual Network: $_ " - ForegroundColor Red
110117 }
111-
112118}
113119
114- function ConvertCidrToUint32Array
115- {
120+ function ConvertCidrToUint32Array {
116121 param ($cidrRange )
117- $cidrRangeParts = $cidrRange.Split (@ (" ." , " /" ))
118- $ipnum = ([Convert ]::ToUInt32($cidrRangeParts [0 ]) -shl 24 ) -bor `
119- ([Convert ]::ToUInt32($cidrRangeParts [1 ]) -shl 16 ) -bor `
120- ([Convert ]::ToUInt32($cidrRangeParts [2 ]) -shl 8 ) -bor `
121- [Convert ]::ToUInt32($cidrRangeParts [3 ])
122+ $cidrRangeParts = $cidrRange.Split (" /" )
123+ $ipParts = $cidrRangeParts [0 ].Split(" ." )
124+ $ipnum = ([Convert ]::ToUInt32($ipParts [0 ]) -shl 24 ) -bor `
125+ ([Convert ]::ToUInt32($ipParts [1 ]) -shl 16 ) -bor `
126+ ([Convert ]::ToUInt32($ipParts [2 ]) -shl 8 ) -bor `
127+ [Convert ]::ToUInt32($ipParts [3 ])
122128
123- $maskbits = [System.Convert ]::ToInt32($cidrRangeParts [4 ])
129+ $maskbits = [System.Convert ]::ToInt32($cidrRangeParts [1 ])
124130 $mask = 0xffffffff
125- $mask = $mask -shl (32 - $maskbits )
131+ $mask = $mask -shl (32 - $maskbits )
126132 $ipstart = $ipnum -band $mask
127133 $ipend = $ipnum -bor ($mask -bxor 0xffffffff )
128134 return @ ($ipstart , $ipend )
129135}
130136
131- function ConvertUInt32ToIPAddress
132- {
137+ function ConvertUInt32ToIPAddress {
133138 param ($uint32IP )
134139 $v1 = $uint32IP -band 0xff
135140 $v2 = ($uint32IP -shr 8 ) -band 0xff
@@ -138,80 +143,121 @@ function ConvertUInt32ToIPAddress
138143 return " $v4 .$v3 .$v2 .$v1 "
139144}
140145
141- function CalculateNextAddressPrefix
142- {
146+ function CalculateNextAddressPrefix {
143147 param ($virtualNetwork , $prefixLength )
144- Write-Host " Calculating address prefix."
148+ Write-Host " Calculating address prefix with length $prefixLength .. ."
145149 $startIPAddress = 0
146- ForEach ($addressPrefix in $virtualNetwork.AddressSpace.AddressPrefixes )
147- {
150+ ForEach ($addressPrefix in $virtualNetwork.AddressSpace.AddressPrefixes ) {
148151 $endIPAddress = (ConvertCidrToUint32Array $addressPrefix )[1 ]
149- If ($endIPAddress -gt $startIPAddress )
150- {
152+ If ($endIPAddress -gt $startIPAddress ) {
151153 $startIPAddress = $endIPAddress
152154 }
153155 }
154156 $startIPAddress += 1
155- return (ConvertUInt32ToIPAddress $startIPAddress ) + " /" + $prefixLength
157+ $addressPrefixResult = (ConvertUInt32ToIPAddress $startIPAddress ) + " /" + $prefixLength
158+ Write-Host " Using address prefix $addressPrefixResult ." - ForegroundColor Green
159+ return $addressPrefixResult
156160}
157161
158- function CalculateVpnClientAddressPoolPrefix
159- {
162+ function CalculateVpnClientAddressPoolPrefix {
160163 param ($gatewaySubnetPrefix )
161164 Write-Host " Calculating VPN client address pool prefix."
162- If ($gatewaySubnetPrefix.StartsWith (" 10." ))
163- {
165+ If ($gatewaySubnetPrefix.StartsWith (" 10." )) {
164166 return " 192.168.0.0/24"
165167 }
166- else
167- {
168+ else {
168169 return " 172.16.0.0/24"
169170 }
170171
171172}
172173
173- VerifyPSVersion
174- Ensure- Login
175- Select-SubscriptionId - subscriptionId $subscriptionId
174+ function CreateCerificateWindows () {
175+ $certificate = New-SelfSignedCertificate - Type Custom - KeySpec Signature `
176+ - Subject (" CN=$certificateNamePrefix " + " P2SRoot" ) - KeyExportPolicy Exportable `
177+ - HashAlgorithm sha256 - KeyLength 2048 `
178+ - CertStoreLocation " Cert:\CurrentUser\My" - KeyUsageProperty Sign - KeyUsage CertSign
176179
177- $virtualNetwork = Load - VirtualNetwork - resourceGroupName $resourceGroupName - virtualNetworkName $virtualNetworkName
180+ $certificateThumbprint = $certificate .Thumbprint
178181
179- $resourceGroup = Get-AzureRmResourceGroup - Name $resourceGroupName
182+ New-SelfSignedCertificate - Type Custom - DnsName ($certificateNamePrefix + " P2SChild" ) - KeySpec Signature `
183+ - Subject (" CN=$certificateNamePrefix " + " P2SChild" ) - KeyExportPolicy Exportable `
184+ - HashAlgorithm sha256 - KeyLength 2048 `
185+ - CertStoreLocation " Cert:\CurrentUser\My" `
186+ - Signer $certificate - TextExtension @ (" 2.5.29.37={text}1.3.6.1.5.5.7.3.2" ) | Out-null
187+
188+ [Convert ]::ToBase64String((Get-Item cert:\currentuser\my\$certificateThumbprint ).RawData)
189+ }
180190
181- $certificate = New-SelfSignedCertificate - Type Custom - KeySpec Signature `
182- - Subject ( " CN=$certificateNamePrefix " + " P2SRoot" ) - KeyExportPolicy Exportable `
183- - HashAlgorithm sha256 - KeyLength 2048 `
184- - CertStoreLocation " Cert:\CurrentUser\My " - KeyUsageProperty Sign - KeyUsage CertSign
191+ function CreateCerificateOpenSsl () {
192+ $dn = " CN=$certificateNamePrefix " + " P2SRoot"
193+ ipsec pki -- gen -- outform pem > caKey.pem
194+ ipsec pki -- self - -in caKey.pem -- dn $dn -- ca -- outform pem > caCert.pem
185195
186- $certificateThumbprint = $certificate.Thumbprint
196+ $dn = $certificateNamePrefix + " P2SChild"
197+ ipsec pki -- gen -- outform pem > " $ ( $dn ) Key.pem"
198+ ipsec pki -- pub - -in " $ ( $dn ) Key.pem" -- outform pem > " $ ( $dn ) PubKey.pem"
199+ ipsec pki -- issue - -in " $ ( $dn ) PubKey.pem" -- cacert caCert.pem -- cakey caKey.pem -- dn " CN=$ ( $dn ) " -- san $dn -- flag clientAuth -- outform pem > " $ ( $dn ) Cert.pem"
200+ openssl pkcs12 -in " $ ( $dn ) Cert.pem" - inkey " $ ( $dn ) Key.pem" - certfile caCert.pem - export - out " $ ( $dn ) .p12" - password " pass:$ ( $clientCertificatePassword ) "
187201
188- New-SelfSignedCertificate - Type Custom - DnsName ( $certificateNamePrefix + " P2SChild " ) - KeySpec Signature `
189- - Subject ( " CN= $certificateNamePrefix " + " P2SChild " ) - KeyExportPolicy Exportable `
190- - HashAlgorithm sha256 - KeyLength 2048 `
191- - CertStoreLocation " Cert:\CurrentUser\My " `
192- - Signer $certificate - TextExtension @ ( " 2.5.29.37={text}1.3.6.1.5.5.7.3.2 " ) | Out-null
202+ $publicRootCertData = openssl x509 -in caCert.pem - outform pem
203+ $publicRootCertData = $publicRootCertData -replace " -----BEGIN CERTIFICATE----- " , " "
204+ $publicRootCertData = $publicRootCertData -replace " -----END CERTIFICATE----- " , " "
205+ [ string ]::Join( " " , $publicRootCertData .Split ())
206+ }
193207
194- $publicRootCertData = [Convert ]::ToBase64String((Get-Item cert:\currentuser\my\$certificateThumbprint ).RawData)
208+ function CreateCertificate () {
209+ Write-Host " Creating certificate."
210+ if ($PSVersionTable.PSEdition -eq " Desktop" ) {
211+ return CreateCerificateWindows
212+ }
213+ else {
214+ return CreateCerificateOpenSsl
215+ }
216+ }
217+
218+ VerifyPSVersion
219+ EnsureAzModule
220+ EnsureLogin
221+ SelectSubscriptionId - subscriptionId $subscriptionId
195222
196- $gatewaySubnetPrefix = CalculateNextAddressPrefix $virtualNetwork 28
223+ $virtualNetwork = LoadVirtualNetwork - resourceGroupName $resourceGroupName - virtualNetworkName $virtualNetworkName
197224
198- $vpnClientAddressPoolPrefix = CalculateVpnClientAddressPoolPrefix $gatewaySubnetPrefix
225+ $subnets = $virtualNetwork .Subnets.Name
199226
200- $virtualNetwork.AddressSpace.AddressPrefixes.Add ($gatewaySubnetPrefix )
201- Add-AzureRmVirtualNetworkSubnetConfig - Name GatewaySubnet - VirtualNetwork $virtualNetwork - AddressPrefix $gatewaySubnetPrefix | Out-Null
227+ $gatewaySubnetName = " GatewaySubnet"
202228
203- Set-VirtualNetwork $virtualNetwork
229+ If ($false -eq $subnets.Contains ($gatewaySubnetName )) {
230+ Write-Host " $gatewaySubnetName is not one of the subnets in $subnets " - ForegroundColor Yellow
231+ $gatewaySubnetPrefix = CalculateNextAddressPrefix $virtualNetwork 28
232+ Write-Host " Creating subnet $gatewaySubnetName ($gatewaySubnetPrefix ) in the virtual network ..." - ForegroundColor Green
233+
234+ $virtualNetwork.AddressSpace.AddressPrefixes.Add ($gatewaySubnetPrefix )
235+ Add-AzVirtualNetworkSubnetConfig - Name $gatewaySubnetName - VirtualNetwork $virtualNetwork - AddressPrefix $gatewaySubnetPrefix | Out-Null
236+
237+ SetVirtualNetwork $virtualNetwork
238+ Write-Host " Added subnet $gatewaySubnetName into virtual network." - ForegroundColor Green
239+ }
240+ else {
241+ Write-Host " The subnet $gatewaySubnetName exists in the virtual network." - ForegroundColor Green
242+ }
243+
244+ $vpnClientAddressPoolPrefix = CalculateVpnClientAddressPoolPrefix $gatewaySubnetPrefix
245+ $publicRootCertData = CreateCertificate
204246
205247Write-Host
206248
207249# Start the deployment
208250Write-Host " Starting deployment..."
251+ Write-Host " Deployment will take about 1h." - ForegroundColor Yellow
209252
210253$templateParameters = @ {
211- virtualNetworkName = $virtualNetworkName
212- gatewaySubnetPrefix = $gatewaySubnetPrefix
213- vpnClientAddressPoolPrefix = $vpnClientAddressPoolPrefix
214- publicRootCertData = $publicRootCertData
215- }
254+ location = $virtualNetwork.Location
255+ virtualNetworkName = $virtualNetworkName
256+ gatewaySubnetPrefix = $gatewaySubnetPrefix
257+ vpnClientAddressPoolPrefix = $vpnClientAddressPoolPrefix
258+ publicRootCertData = $publicRootCertData
259+ }
260+
261+ New-AzResourceGroupDeployment - ResourceGroupName $resourceGroupName - TemplateUri ($scriptUrlBase + ' /azuredeploy.json?t=' + [DateTime ]::Now.Ticks) - TemplateParameterObject $templateParameters
216262
217- New-AzureRmResourceGroupDeployment - ResourceGroupName $resourceGroupName - TemplateUri ( $scriptUrlBase + ' /azuredeploy.json?t= ' + [ DateTime ]::Now.Ticks) - TemplateParameterObject $templateParameters
263+ Write-Host " Deployment completed. "
0 commit comments