-
Notifications
You must be signed in to change notification settings - Fork 4
/
Program.cs
321 lines (292 loc) · 18.8 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using Azure;
using Azure.Core;
using Azure.Identity;
using Azure.ResourceManager.Resources.Models;
using Azure.ResourceManager.Samples.Common;
using Azure.ResourceManager.Resources;
using Azure.ResourceManager;
using Azure.ResourceManager.Network;
using Azure.ResourceManager.Network.Models;
using Azure.ResourceManager.Storage.Models;
using Azure.ResourceManager.Storage;
using Microsoft.Identity.Client.Extensions.Msal;
using Azure.ResourceManager.Compute.Models;
using Azure.ResourceManager.Compute;
namespace ManageVpnGatewayVNet2VNetConnection
{
public class Program
{
private static ResourceIdentifier? _resourceGroupId = null;
/**
* Azure Network sample for managing virtual network gateway.
* - Create 2 virtual networks with subnets and 2 virtual network gateways corresponding to each network
* - Create VPN VNet-to-VNet connection
* - Troubleshoot the connection
* - Create network watcher in the same region as virtual network gateway
* - Create storage account to store troubleshooting information
* - Run troubleshooting for the connection - result will be 'UnHealthy' as need to create symmetrical connection from second gateway to the first
* - Create virtual network connection from second gateway to the first and run troubleshooting. Result will be 'Healthy'.
* - List VPN Gateway connections for the first gateway
* - Create 2 virtual machines, each one in its network and verify connectivity between them
*/
public static async Task RunSample(ArmClient client)
{
string rgName = Utilities.CreateRandomName("NetworkSampleRG");
string vnetName1 = Utilities.CreateRandomName("vnet1-");
string vnetName2 = Utilities.CreateRandomName("vnet2-");
string vnetGatewayName1 = Utilities.CreateRandomName("vnetGateway1-");
string vnetGatewayName2 = Utilities.CreateRandomName("vnetGateway2-");
string pipName1 = Utilities.CreateRandomName("pip1-");
string pipName2 = Utilities.CreateRandomName("pip2-");
string networkWatcherName = Utilities.CreateRandomName("watcher");
string storageAccountName = Utilities.CreateRandomName("azstorageaccoun");
string containerName = Utilities.CreateRandomName("container");
string vmName1 = Utilities.CreateRandomName("vm1-");
string vmName2 = Utilities.CreateRandomName("vm2-");
string vpnConnectionName1 = "vnet1-to-vnet2-connection";
string vpnConnectionName2 = "vnet2-to-vnet1-connection";
try
{
// Get default subscription
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
// Create a resource group in the EastUS region
Utilities.Log($"Creating resource group...");
ArmOperation<ResourceGroupResource> rgLro = await subscription.GetResourceGroups().CreateOrUpdateAsync(WaitUntil.Completed, rgName, new ResourceGroupData(AzureLocation.EastUS));
ResourceGroupResource resourceGroup = rgLro.Value;
_resourceGroupId = resourceGroup.Id;
Utilities.Log("Created a resource group with name: " + resourceGroup.Data.Name);
//============================================================
// Create virtual network
VirtualNetworkData vnetInput1 = new VirtualNetworkData()
{
Location = resourceGroup.Data.Location,
AddressPrefixes = { "10.11.0.0/16" },
Subnets =
{
new SubnetData() { AddressPrefix = "10.11.255.0/27", Name = "GatewaySubnet" },
new SubnetData() { AddressPrefix = "10.11.0.0/24", Name = "Subnet1" }
},
};
var vnetLro1 = await resourceGroup.GetVirtualNetworks().CreateOrUpdateAsync(WaitUntil.Completed, vnetName1, vnetInput1);
VirtualNetworkResource vnet1 = vnetLro1.Value;
Utilities.Log($"Created a virtual network: {vnet1.Data.Name}");
//============================================================
// Create virtual network gateway
Utilities.Log("Creating virtual network gateway...");
// Create two public ip for virtual network gateway
var pip1 = await Utilities.CreatePublicIP(resourceGroup, pipName1);
var pip2 = await Utilities.CreatePublicIP(resourceGroup, pipName2);
VirtualNetworkGatewayData vpnGatewayInput1 = new VirtualNetworkGatewayData()
{
Location = resourceGroup.Data.Location,
Sku = new VirtualNetworkGatewaySku()
{
Name = VirtualNetworkGatewaySkuName.Basic,
Tier = VirtualNetworkGatewaySkuTier.Basic
},
Tags = { { "key", "value" } },
EnableBgp = false,
GatewayType = VirtualNetworkGatewayType.Vpn,
VpnType = VpnType.RouteBased,
IPConfigurations =
{
new VirtualNetworkGatewayIPConfiguration()
{
Name = Utilities.CreateRandomName("config"),
PrivateIPAllocationMethod = NetworkIPAllocationMethod.Dynamic,
PublicIPAddressId = pip1.Data.Id,
SubnetId = vnet1.Data.Subnets.First(item => item.Name == "GatewaySubnet").Id,
}
}
};
var vpnGatewayLro1 = await resourceGroup.GetVirtualNetworkGateways().CreateOrUpdateAsync(WaitUntil.Completed, vnetGatewayName1, vpnGatewayInput1);
VirtualNetworkGatewayResource vpnGateway1 = vpnGatewayLro1.Value;
Utilities.Log($"Created virtual network gateway: {vpnGateway1.Data.Name}");
//============================================================
// Create second virtual network
VirtualNetworkData vnetInput2 = new VirtualNetworkData()
{
Location = resourceGroup.Data.Location,
AddressPrefixes = { "10.41.0.0/16" },
Subnets =
{
new SubnetData() { AddressPrefix = "10.41.255.0/27", Name = "GatewaySubnet" },
new SubnetData() { AddressPrefix = "10.41.0.0/24", Name = "Subnet2" }
},
};
var vnetLro2 = await resourceGroup.GetVirtualNetworks().CreateOrUpdateAsync(WaitUntil.Completed, vnetName2, vnetInput2);
VirtualNetworkResource vnet2 = vnetLro2.Value;
Utilities.Log($"Created a virtual network: {vnet2.Data.Name}");
//============================================================
// Create second virtual network gateway
Utilities.Log("Creating second virtual network gateway...");
VirtualNetworkGatewayData vpnGatewayInput2 = new VirtualNetworkGatewayData()
{
Location = resourceGroup.Data.Location,
Sku = new VirtualNetworkGatewaySku()
{
Name = VirtualNetworkGatewaySkuName.Basic,
Tier = VirtualNetworkGatewaySkuTier.Basic
},
Tags = { { "key", "value" } },
EnableBgp = false,
GatewayType = VirtualNetworkGatewayType.Vpn,
VpnType = VpnType.RouteBased,
IPConfigurations =
{
new VirtualNetworkGatewayIPConfiguration()
{
Name = Utilities.CreateRandomName("config"),
PrivateIPAllocationMethod = NetworkIPAllocationMethod.Dynamic,
PublicIPAddressId = pip2.Data.Id,
SubnetId = vnet2.Data.Subnets.First(item => item.Name == "GatewaySubnet").Id,
}
}
};
var vpnGatewayLro2 = await resourceGroup.GetVirtualNetworkGateways().CreateOrUpdateAsync(WaitUntil.Completed, vnetGatewayName2, vpnGatewayInput2);
VirtualNetworkGatewayResource vpnGateway2 = vpnGatewayLro2.Value;
Utilities.Log($"Created second virtual network gateway: {vnet2.Data.Name}");
//============================================================
// Create virtual network gateway connection
Utilities.Log("Creating virtual network gateway connection...");
VirtualNetworkGatewayConnectionType connectionType = VirtualNetworkGatewayConnectionType.Vnet2Vnet;
VirtualNetworkGatewayConnectionData gatewayConnectionInput = new VirtualNetworkGatewayConnectionData(vpnGateway1.Data, connectionType)
{
Location = resourceGroup.Data.Location,
VirtualNetworkGateway2 = vpnGateway2.Data,
SharedKey = "MySecretKey"
};
var connectionLro = await resourceGroup.GetVirtualNetworkGatewayConnections().CreateOrUpdateAsync(WaitUntil.Completed, vpnConnectionName1, gatewayConnectionInput);
VirtualNetworkGatewayConnectionResource connection = connectionLro.Value;
Utilities.Log($"Created virtual network gateway connection: {connection.Data.Name}");
//============================================================
// Troubleshoot the connection
// create Network Watcher
NetworkWatcherData networkWatcherInput = new NetworkWatcherData()
{
Location = resourceGroup.Data.Location,
};
//var networkWatcherLro = await resourceGroup.GetNetworkWatchers().CreateOrUpdateAsync(WaitUntil.Completed, networkWatcherName, networkWatcherInput);
//NetworkWatcherResource networkWatcher = networkWatcherLro.Value;
var watcherRG = await subscription.GetResourceGroups().GetAsync("NetworkWatcherRG");
var networkWatcherLro = await watcherRG.Value.GetNetworkWatchers().GetAsync("NetworkWatcher_eastus");
NetworkWatcherResource networkWatcher = networkWatcherLro.Value;
//Create storage account to store troubleshooting information
StorageSku storageSku = new StorageSku(StorageSkuName.StandardGrs);
StorageKind storageKind = StorageKind.Storage;
StorageAccountCreateOrUpdateContent storagedata = new StorageAccountCreateOrUpdateContent(storageSku, storageKind, resourceGroup.Data.Location) { };
var storageAccountLro = await resourceGroup.GetStorageAccounts().CreateOrUpdateAsync(WaitUntil.Completed, storageAccountName, storagedata);
StorageAccountResource storageAccount = storageAccountLro.Value;
// Create storage container to store troubleshooting results
BlobContainerData containerInput = new BlobContainerData() { };
var blobContainerLro = await storageAccount.GetBlobService().GetBlobContainers().CreateOrUpdateAsync(WaitUntil.Completed, containerName, containerInput);
BlobContainerResource container = blobContainerLro.Value;
// Run troubleshooting for the connection - result will be 'UnHealthy' as need to create symmetrical connection from second gateway to the first
TroubleshootingContent troubleshootingContent = new TroubleshootingContent(
targetResourceId: connection.Id,
storageId: storageAccount.Id,
storageUri: new Uri($"https://{storageAccount.Data.Name}.blob.core.windows.net/{container.Data.Name}"));
var troubleshootingResult = await networkWatcher.GetTroubleshootingAsync(WaitUntil.Completed, troubleshootingContent);
Utilities.Log("Troubleshooting status is: " + troubleshootingResult.Value.Code);
//============================================================
// Create virtual network connection from second gateway to the first and run troubleshooting. Result will be 'Healthy'.
var gatewayConnectionInput2 = new VirtualNetworkGatewayConnectionData(vpnGateway2.Data, connectionType)
{
Location = resourceGroup.Data.Location,
VirtualNetworkGateway2 = vpnGateway1.Data,
SharedKey = "MySecretKey"
};
_ = await resourceGroup.GetVirtualNetworkGatewayConnections().CreateOrUpdateAsync(WaitUntil.Completed, vpnConnectionName2, gatewayConnectionInput2);
Utilities.Log("VNet2 to VNet1 gateway connection created");
// Delay before running troubleshooting to wait for connection settings to propagate
Thread.Sleep(250000);
troubleshootingResult = await networkWatcher.GetTroubleshootingAsync(WaitUntil.Completed, troubleshootingContent);
Utilities.Log("Troubleshooting status is: " + troubleshootingResult.Value.Code);
//============================================================
// List VPN Gateway connections for particular gateway
//var connections = vngw1.ListConnections();
await foreach (var conn in vpnGateway1.GetConnectionsAsync())
{
Utilities.Log(conn.Name);
}
//============================================================
// Create 2 virtual machines, each one in its network and verify connectivity between them
// Definate vm extension input data
string extensionName = "AzureNetworkWatcherExtension";
var extensionInput = new VirtualMachineExtensionData(resourceGroup.Data.Location)
{
Publisher = "Microsoft.Azure.NetworkWatcher",
ExtensionType = "NetworkWatcherAgentWindows",
TypeHandlerVersion = "1.4",
AutoUpgradeMinorVersion = true,
};
// Create vm1
Utilities.Log("Creating a vm...");
NetworkInterfaceResource nic1 = await Utilities.CreateNetworkInterface(resourceGroup, vnet1);
VirtualMachineData vmInput1 = Utilities.GetDefaultVMInputData(resourceGroup, vmName1);
vmInput1.NetworkProfile.NetworkInterfaces.Add(new VirtualMachineNetworkInterfaceReference() { Id = nic1.Id, Primary = true });
var vmLro1 = await resourceGroup.GetVirtualMachines().CreateOrUpdateAsync(WaitUntil.Completed, vmName1, vmInput1);
VirtualMachineResource vm1 = vmLro1.Value;
_ = await vm1.GetVirtualMachineExtensions().CreateOrUpdateAsync(WaitUntil.Completed, extensionName, extensionInput);
Utilities.Log($"Created vm: {vm1.Data.Name}");
// Create vm2
Utilities.Log("Creating a vm...");
NetworkInterfaceResource nic2 = await Utilities.CreateNetworkInterface(resourceGroup, vnet2);
VirtualMachineData vmInput2 = Utilities.GetDefaultVMInputData(resourceGroup, vmName2);
vmInput2.NetworkProfile.NetworkInterfaces.Add(new VirtualMachineNetworkInterfaceReference() { Id = nic2.Id, Primary = true });
var vmLro2 = await resourceGroup.GetVirtualMachines().CreateOrUpdateAsync(WaitUntil.Completed, vmName2, vmInput2);
VirtualMachineResource vm2 = vmLro2.Value;
_ = await vm2.GetVirtualMachineExtensions().CreateOrUpdateAsync(WaitUntil.Completed, extensionName, extensionInput);
Utilities.Log($"Created vm: {vm2.Data.Name}");
// Block: https://github.com/Azure/azure-sdk-for-net/pull/38876
// System.ArgumentException: 'Value cannot be an empty string. (Parameter 'resourceId')'
ConnectivityContent content = new ConnectivityContent(
new ConnectivitySource(vm1.Id),
new ConnectivityDestination() { Port = 22, ResourceId = vm2.Id });
var connectivityResult = await networkWatcher.CheckConnectivityAsync(WaitUntil.Completed, content);
Utilities.Log("Connectivity status: " + connectivityResult.Value.NetworkConnectionStatus);
}
finally
{
try
{
if (_resourceGroupId is not null)
{
Utilities.Log($"Deleting Resource Group...");
await client.GetResourceGroupResource(_resourceGroupId).DeleteAsync(WaitUntil.Completed);
Utilities.Log($"Deleted Resource Group: {_resourceGroupId.Name}");
}
}
catch (NullReferenceException)
{
Utilities.Log("Did not create any resources in Azure. No clean up is necessary");
}
catch (Exception ex)
{
Utilities.Log(ex);
}
}
}
public static async Task Main(string[] args)
{
try
{
//=================================================================
// Authenticate
var clientId = Environment.GetEnvironmentVariable("CLIENT_ID");
var clientSecret = Environment.GetEnvironmentVariable("CLIENT_SECRET");
var tenantId = Environment.GetEnvironmentVariable("TENANT_ID");
var subscription = Environment.GetEnvironmentVariable("SUBSCRIPTION_ID");
ClientSecretCredential credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
ArmClient client = new ArmClient(credential, subscription);
await RunSample(client);
}
catch (Exception ex)
{
Utilities.Log(ex);
}
}
}
}