@@ -65,6 +65,371 @@ Once you have enabled Kerberos on your Bastion resource, you can verify that it'
65
65
1 . End the VM session.
66
66
1 . Connect to the target VM again using Bastion. Sign-in should succeed, indicating that Bastion used Kerberos (and not NTLM) for authentication.
67
67
68
+ ## Quickstart: Setup Bastion with Kerberos - Resource Manager template
69
+
70
+ ### Review the template
71
+
72
+ ```
73
+ {
74
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
75
+ "contentVersion": "1.0.0.0",
76
+ "parameters": {
77
+ "location": {
78
+ "defaultValue": "[resourceGroup().location]",
79
+ "type": "string"
80
+ },
81
+ "defaultNsgName": {
82
+ "type": "string",
83
+ "defaultValue": "Default-nsg"
84
+ },
85
+ "VnetName": {
86
+ "type": "string",
87
+ "defaultValue": "myVnet"
88
+ },
89
+ "ClientVMName": {
90
+ "defaultValue": "Client-vm",
91
+ "type": "string"
92
+ },
93
+ "ServerVMName": {
94
+ "defaultValue": "Server-vm",
95
+ "type": "string"
96
+ },
97
+ "vmsize": {
98
+ "defaultValue": "Standard_DS1_v2",
99
+ "type": "string",
100
+ "metadata": {
101
+ "description": "VM SKU to deploy"
102
+ }
103
+ },
104
+ "ServerVMUsername": {
105
+ "type": "string",
106
+ "defaultValue": "serveruser",
107
+ "metadata": {
108
+ "description": "Admin username on all VMs."
109
+ }
110
+ },
111
+ "ServerVMPassword": {
112
+ "type": "securestring",
113
+ "metadata": {
114
+ "description": "Admin password on all VMs."
115
+ }
116
+ },
117
+ "SafeModeAdministratorPassword": {
118
+ "type": "securestring",
119
+ "metadata": {
120
+ "description": "See https://learn.microsoft.com/en-us/powershell/module/addsdeployment/install-addsdomaincontroller?view=windowsserver2022-ps#-safemodeadministratorpassword"
121
+ }
122
+ },
123
+ "ClientVMUsername": {
124
+ "type": "string",
125
+ "defaultValue": "clientuser",
126
+ "metadata": {
127
+ "description": "username on ClientVM."
128
+ }
129
+ },
130
+ "ClientVMPassword": {
131
+ "type": "securestring",
132
+ "metadata": {
133
+ "description": "password on ClientVM."
134
+ }
135
+ },
136
+ "ServerVmImage": {
137
+ "type": "object",
138
+ "defaultValue": {
139
+ "offer": "WindowsServer",
140
+ "publisher": "MicrosoftWindowsServer",
141
+ "sku": "2019-Datacenter",
142
+ "version": "latest"
143
+ }
144
+ },
145
+ "ClientVmImage": {
146
+ "type": "object",
147
+ "defaultValue": {
148
+ "offer": "Windows",
149
+ "publisher": "microsoftvisualstudio",
150
+ "sku": "Windows-10-N-x64",
151
+ "version": "latest"
152
+ }
153
+ },
154
+ "publicIPAllocationMethod": {
155
+ "type": "string",
156
+ "defaultValue": "Static"
157
+ },
158
+ "BastionName": {
159
+ "defaultValue": "Bastion",
160
+ "type": "string"
161
+ },
162
+ "BastionPublicIPName": {
163
+ "defaultValue": "Bastion-ip",
164
+ "type": "string"
165
+ }
166
+ },
167
+ "variables": {
168
+ "DefaultSubnetId": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('VnetName')), '/subnets/default')]",
169
+ "ClientVMSubnetId": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('VnetName')), '/subnets/clientvm-subnet')]",
170
+ "DNSServerIpAddress": "10.16.0.4",
171
+ "ClientVMPrivateIpAddress": "10.16.1.4"
172
+ },
173
+ "resources": [
174
+ {
175
+ "apiVersion": "2020-03-01",
176
+ "name": "[parameters('VnetName')]",
177
+ "type": "Microsoft.Network/virtualNetworks",
178
+ "location": "[parameters('location')]",
179
+ "properties": {
180
+ "dhcpOptions": {
181
+ "dnsServers": [ "[variables('DNSServerIpAddress')]" ]
182
+ },
183
+ "subnets": [
184
+ {
185
+ "name": "default",
186
+ "properties": {
187
+ "addressPrefix": "10.16.0.0/24"
188
+ }
189
+ },
190
+ {
191
+ "name": "clientvm-subnet",
192
+ "properties": {
193
+ "addressPrefix": "10.16.1.0/24"
194
+ }
195
+ },
196
+ {
197
+ "name": "AzureBastionSubnet",
198
+ "properties": {
199
+ "addressPrefix": "10.16.2.0/24"
200
+ }
201
+ }
202
+ ],
203
+ "addressSpace": {
204
+ "addressPrefixes": [
205
+ "10.16.0.0/16"
206
+ ]
207
+ }
208
+ }
209
+ },
210
+ {
211
+ "type": "Microsoft.Network/networkInterfaces",
212
+ "apiVersion": "2018-10-01",
213
+ "name": "[concat(parameters('ServerVMName'), 'Nic')]",
214
+ "location": "[parameters('location')]",
215
+ "dependsOn": [
216
+ "[concat('Microsoft.Network/virtualNetworks/', parameters('VnetName'))]"
217
+ ],
218
+ "properties": {
219
+ "ipConfigurations": [
220
+ {
221
+ "name": "[concat(parameters('ServerVMName'), 'NicIpConfig')]",
222
+ "properties": {
223
+ "privateIPAllocationMethod": "Static",
224
+ "privateIPAddress": "[variables('DNSServerIpAddress')]",
225
+ "subnet": {
226
+ "id": "[variables('DefaultSubnetId')]"
227
+ }
228
+ }
229
+ }
230
+ ]
231
+ }
232
+ },
233
+ {
234
+ "type": "Microsoft.Compute/virtualMachines",
235
+ "apiVersion": "2020-06-01",
236
+ "name": "[parameters('ServerVMName')]",
237
+ "location": "[parameters('location')]",
238
+ "dependsOn": [
239
+ "[concat('Microsoft.Network/networkInterfaces/', parameters('ServerVMName'), 'Nic')]"
240
+ ],
241
+ "properties": {
242
+ "hardwareProfile": {
243
+ "vmSize": "[parameters('vmSize')]"
244
+ },
245
+ "osProfile": {
246
+ "AdminUsername": "[parameters('ServerVMUsername')]",
247
+ "AdminPassword": "[parameters('ServerVMPassword')]",
248
+ "computerName": "[parameters('ServerVMName')]"
249
+ },
250
+ "storageProfile": {
251
+ "imageReference": "[parameters('ServerVmImage')]",
252
+ "osDisk": {
253
+ "createOption": "FromImage",
254
+ "managedDisk": {
255
+ "storageAccountType": "Standard_LRS"
256
+ }
257
+ }
258
+ },
259
+ "networkProfile": {
260
+ "networkInterfaces": [
261
+ {
262
+ "id": "[ResourceId('Microsoft.Network/networkInterfaces/', concat(parameters('ServerVMName'), 'Nic'))]"
263
+ }
264
+ ]
265
+ }
266
+ }
267
+ },
268
+ {
269
+ "type": "Microsoft.Compute/virtualMachines/extensions",
270
+ "apiVersion": "2021-04-01",
271
+ "name": "[concat(parameters('ServerVMName'),'/', 'PromoteToDomainController')]",
272
+ "location": "[parameters('location')]",
273
+ "dependsOn": [
274
+ "[concat('Microsoft.Compute/virtualMachines/',parameters('ServerVMName'))]"
275
+ ],
276
+ "properties": {
277
+ "publisher": "Microsoft.Compute",
278
+ "type": "CustomScriptExtension",
279
+ "typeHandlerVersion": "1.7",
280
+ "autoUpgradeMinorVersion": true,
281
+ "settings": {
282
+ "commandToExecute": "[concat('powershell.exe -Command \"Install-windowsfeature AD-domain-services; Import-Module ADDSDeployment;$Secure_String_Pwd = ConvertTo-SecureString ',parameters('SafeModeAdministratorPassword'),' -AsPlainText -Force; Install-ADDSForest -DomainName \"bastionkrb.test\" -SafeModeAdministratorPassword $Secure_String_Pwd -Force:$true')]"
283
+ }
284
+ }
285
+ },
286
+ {
287
+ "type": "Microsoft.Network/networkInterfaces",
288
+ "apiVersion": "2018-10-01",
289
+ "name": "[concat(parameters('ClientVMName'), 'Nic')]",
290
+ "location": "[parameters('location')]",
291
+ "dependsOn": [
292
+ "[concat('Microsoft.Network/virtualNetworks/', parameters('VnetName'))]",
293
+ "[concat('Microsoft.Compute/virtualMachines/', parameters('ServerVMName'))]"
294
+ ],
295
+ "properties": {
296
+ "ipConfigurations": [
297
+ {
298
+ "name": "[concat(parameters('ClientVMName'), 'NicIpConfig')]",
299
+ "properties": {
300
+ "privateIPAllocationMethod": "Static",
301
+ "privateIPAddress": "[variables('ClientVMPrivateIpAddress')]",
302
+ "subnet": {
303
+ "id": "[variables('ClientVMSubnetId')]"
304
+ }
305
+ }
306
+ }
307
+ ]
308
+ }
309
+ },
310
+ {
311
+ "type": "Microsoft.Compute/virtualMachines",
312
+ "apiVersion": "2020-06-01",
313
+ "name": "[parameters('ClientVMName')]",
314
+ "location": "[parameters('location')]",
315
+ "dependsOn": [
316
+ "[concat('Microsoft.Network/networkInterfaces/', parameters('ClientVMName'), 'Nic')]"
317
+ ],
318
+ "properties": {
319
+ "hardwareProfile": {
320
+ "vmSize": "[parameters('vmSize')]"
321
+ },
322
+ "osProfile": {
323
+ "AdminUsername": "[parameters('ClientVMUsername')]",
324
+ "AdminPassword": "[parameters('ClientVMPassword')]",
325
+ "computerName": "[parameters('ClientVMName')]"
326
+ },
327
+ "storageProfile": {
328
+ "imageReference": "[parameters('ClientVmImage')]",
329
+ "osDisk": {
330
+ "createOption": "FromImage",
331
+ "managedDisk": {
332
+ "storageAccountType": "Standard_LRS"
333
+ }
334
+ }
335
+ },
336
+ "networkProfile": {
337
+ "networkInterfaces": [
338
+ {
339
+ "id": "[ResourceId('Microsoft.Network/networkInterfaces/', concat(parameters('ClientVMName'), 'Nic'))]"
340
+ }
341
+ ]
342
+ }
343
+ }
344
+ },
345
+ {
346
+ "type": "Microsoft.Compute/virtualMachines/extensions",
347
+ "apiVersion": "2021-04-01",
348
+ "name": "[concat(parameters('ClientVMName'),'/', 'DomainJoin')]",
349
+ "location": "[parameters('location')]",
350
+ "dependsOn": [
351
+ "[concat('Microsoft.Compute/virtualMachines/',parameters('ClientVMName'))]",
352
+ "[concat('Microsoft.Compute/virtualMachines/', parameters('ServerVMName'),'/extensions/', 'PromoteToDomainController')]",
353
+ "[concat('Microsoft.Network/bastionHosts/', parameters('BastionName'))]"
354
+ ],
355
+ "properties": {
356
+ "publisher": "Microsoft.Compute",
357
+ "type": "CustomScriptExtension",
358
+ "typeHandlerVersion": "1.7",
359
+ "autoUpgradeMinorVersion": true,
360
+ "settings": {
361
+ "commandToExecute": "[concat('powershell.exe -Command Set-ItemProperty -Path HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\MSV1_0\\ -Name RestrictReceivingNTLMTraffic -Value 1; $Pass= ConvertTo-SecureString -String ',parameters('ServerVMPassword'),' -AsPlainText -Force; $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList \"AD\\serveruser\", $Pass; do { try { $joined = add-computer -computername Client-vm -domainname bastionkrb.test –credential $Credential -passthru -restart –force; } catch {}} while ($joined.HasSucceeded -ne $true)')]"
362
+ }
363
+ }
364
+ },
365
+ {
366
+ "apiVersion": "2020-11-01",
367
+ "type": "Microsoft.Network/publicIPAddresses",
368
+ "name": "[parameters('BastionPublicIPName')]",
369
+ "location": "[resourceGroup().location]",
370
+ "sku": {
371
+ "name": "Standard"
372
+ },
373
+ "properties": {
374
+ "publicIPAllocationMethod": "Static"
375
+ },
376
+ "tags": {}
377
+ },
378
+ {
379
+ "type": "Microsoft.Network/bastionHosts",
380
+ "apiVersion": "2020-11-01",
381
+ "name": "[parameters('BastionName')]",
382
+ "location": "[resourceGroup().location]",
383
+ "dependsOn": [
384
+ "[concat('Microsoft.Network/virtualNetworks/', parameters('VnetName'))]",
385
+ "[concat('Microsoft.Network/publicIpAddresses/', parameters('BastionPublicIPName'))]"
386
+ ],
387
+ "sku": {
388
+ "name": "Standard"
389
+ },
390
+ "properties": {
391
+ "enableKerberos": "true",
392
+ "ipConfigurations": [
393
+ {
394
+ "name": "IpConf",
395
+ "properties": {
396
+ "privateIPAllocationMethod": "Dynamic",
397
+ "publicIPAddress": {
398
+ "id": "[resourceId('Microsoft.Network/publicIpAddresses', parameters('BastionPublicIPName'))]"
399
+ },
400
+ "subnet": {
401
+ "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('VnetName')), '/subnets/AzureBastionSubnet')]"
402
+ }
403
+ }
404
+ }
405
+ ]
406
+ }
407
+ }
408
+ ]
409
+ }
410
+ ```
411
+
412
+ The following resources have been defined in the template:
413
+ - Deploys the following Azure resources:
414
+ - [ ** Microsoft.Network/virtualNetworks** ] ( /azure/templates/microsoft.network/virtualnetworks ) : create an Azure virtual network.
415
+ - [ ** Microsoft.Network/bastionHosts** ] ( /azure/templates/microsoft.network/bastionHosts ) : create a Standard SKU Bastion with a public IP and Kerberos feature enabled
416
+ - Create a Windows 10 ClientVM and a Windows Server 2019 ServerVM
417
+ - Have the DNS Server of the VNET point to the private IP address of the ServerVM (domain controller).
418
+ - Runs a Custom Script Extension on the ServerVM to promote it to a domain controller with domain name: ` bastionkrb.test ` .
419
+ - Runs a Custom Script Extension on the ClientVM to have it:
420
+ - ** Restrict NTLM: Incoming NTLM traffic** = Deny all domain accounts (this is to ensure Kerberos is used for authentication).
421
+ - Domain-join the ` bastionkrb.test ` domain.
422
+
423
+ ## Deploy the template
424
+ To setup Kerberos, deploy the ARM template above by running the following PS cmd:
425
+ ```
426
+ New-AzResourceGroupDeployment -ResourceGroupName <your-rg-name> -TemplateFile "<path-to-template>\KerberosDeployment.json"`
427
+ ```
428
+ ## Review deployed resources
429
+ Now, login to ClientVM using Bastion with Kerberos authentication:
430
+ - credentials: username =
` [email protected] ` and password =
` <password-entered-during-deployment> ` .
431
+
432
+
68
433
## Next steps
69
434
70
435
For more information about Azure Bastion, see [ What is Azure Bastion?] ( bastion-overview.md )
0 commit comments