-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathapim.azcli
More file actions
431 lines (387 loc) · 26.8 KB
/
Copy pathapim.azcli
File metadata and controls
431 lines (387 loc) · 26.8 KB
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
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
############################################################################
# Created by Jose Moreno
# February 2024
#
# The script creates APIM in different configurations
#
############################################################################
# Control
create_linux_vm=yes
create_win_vm=no
create_azfw=yes
# Variables
rg=apim
location=eastus2
vnet_name=apimvnet
vnet_prefix=10.13.76.0/24
aci_subnet_name=aci
aci_subnet_prefix=10.13.76.64/27
aci_rt_name=aci-rt
api_image_name=erjosito/yadaapi:1.0
aci_name=aci
apim_nsg=apim-nsg
apim_name=apim$RANDOM
apim_subnet_name=apim
apim_subnet_prefix=10.13.76.0/26
apim_rt_name=apim-rt
apim_sku=Standard
apim_vnet_type=Internal
apim_publisher_email=admin@contoso.com
apim_publisher_name=Contoso
product_name=MyAPIs
api_name=myapi
vm_subnet_name=vm
vm_rt_name=vm-rt
vm_nsg_name=vm-nsg
vm_subnet_prefix=10.13.76.96/27
vm_name=vm
vm_size=Standard_B1s
vm_image=Ubuntu2204
winvm_name=winvm
winvm_size=Standard_B2s
winvm_image=Win2022Datacenter
winvm_user=$(whoami)
winvm_password='Microsoft123!'
azfw_name=azfw
azfw_public_ip_name=azfw-pip
azfw_policy_name=azfwpolicy
azfw_subnet_prefix=10.13.76.128/26
suffix=$RANDOM
######################
# Deploy API in ACI #
######################
# Create RG and vnet
az group create -n $rg -l $location -o none
az network vnet create -n $vnet_name -g $rg --address-prefix $vnet_prefix -o none
az network vnet subnet create -g $rg -n $apim_subnet_name --vnet-name $vnet_name --address-prefix $apim_subnet_prefix -o none
az network vnet subnet create -g $rg -n $aci_subnet_name --vnet-name $vnet_name --address-prefix $aci_subnet_prefix -o none
az container create -g $rg -n $aci_name --os-type Linux --image $api_image_name --cpu 1 --memory 1.5 --vnet $vnet_name --subnet $aci_subnet_name --ports 8080 -o none
aci_private_ip=$(az container show -g $rg -n $aci_name --query 'ipAddress.ip' -o tsv) && echo "ACI Private IP: $aci_private_ip"
###########################
# Log Analytics workspace #
###########################
# Create LA workspace and storage account
logws_name=$(az monitor log-analytics workspace list -g $rg --query '[0].name' -o tsv)
if [[ -z "$logws_name" ]]
then
logws_name=logws${suffix}
echo "Creating Log Analytics workspace ${logws_name}..."
az monitor log-analytics workspace create -g $rg -n $logws_name -o none
else
echo "Log Analytics workspace $logws_name found in resource group $rg"
fi
logws_id=$(az resource list -g $rg -n $logws_name --query '[].id' -o tsv)
logws_customerid=$(az monitor log-analytics workspace show -n $logws_name -g $rg --query customerId -o tsv)
storage_account_name=$(az storage account list -g $rg --query '[0].name' -o tsv)
if [[ -z "$storage_account_name" ]]
then
storage_account_name=logs${suffix}
echo "Creating Storage Account ${storage_account_name}..."
az storage account create -n $storage_account_name -g $rg --sku Standard_LRS --encryption-services blob -o none
else
echo "Storage Account $storage_account_name found in resource group $rg"
fi
# Enable VNet Flow Logs in the APIM subnet
echo "Enabling VNet Flow Logs in the APIM subnet..."
apim_subnet_id=$(az network vnet subnet show --vnet-name $vnet_name -n $apim_subnet_name -g $rg --query id -o tsv)
az network watcher flow-log create -n "${apim_subnet_name}-subnet-${suffix}" -g $rg --enabled true --retention 7 \
--storage-account $storage_account_name --workspace $logws_id \
--subnet $apim_subnet_id \
--log-version 2 --interval 10 --traffic-analytics true -o none
#########################
# Test VMs and APIM NSG #
#########################
# Create NSG for the VM subnet
echo "Creating NSG ${vm_nsg_name} and VM subnet ${vm_subnet_name}..."
az network nsg create -g $rg -n $vm_nsg_name -o none
az network nsg rule create -g $rg --nsg-name $vm_nsg_name -n Allow-SSH-in --priority 100 --access Allow --protocol Tcp --direction Inbound --destination-port-ranges 22 --source-address-prefixes '*' --destination-address-prefixes '*' -o none
az network nsg rule create -g $rg --nsg-name $vm_nsg_name -n Allow-RDP-in --priority 110 --access Allow --protocol Tcp --direction Inbound --destination-port-ranges 3389 --source-address-prefixes '*' --destination-address-prefixes '*' -o none
az network vnet subnet create -g $rg -n $vm_subnet_name --vnet-name $vnet_name --address-prefix $vm_subnet_prefix -o none
# Create the VM subnet
az network vnet subnet create -g $rg -n $vm_subnet_name --vnet-name $vnet_name --address-prefix $vm_subnet_prefix --network-security-group $vm_nsg_name -o none
# Optionally, create a Linux VM in the same vnet to test connectivity
if [[ "$create_linux_vm" == "yes" ]]; then
echo "Creating Linux VM ${vm_name}..."
az vm create -n $vm_name -g $rg -l $location --image $vm_image --size $vm_size --vnet-name $vnet_name --subnet $vm_subnet_name --generate-ssh-keys --public-ip-sku Standard --nsg '' -o none --only-show-errors
vm_nic_id=$(az vm show -n $vm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv --only-show-errors)
vm_private_ip=$(az network nic show --ids $vm_nic_id --query 'ipConfigurations[0].privateIPAddress' -o tsv --only-show-errors) && echo "Linux VM private IP: $vm_private_ip"
vm_public_ip_id=$(az network nic show --ids $vm_nic_id --query 'ipConfigurations[0].publicIPAddress.id' -o tsv --only-show-errors)
vm_public_ip=$(az network public-ip show --ids $vm_public_ip_id --query 'ipAddress' -o tsv --only-show-errors) && echo "Linux VM public IP: $vm_public_ip"
echo "Testing connectivity to VM..."
ssh -o "StrictHostKeyChecking no" $vm_public_ip "ip a"
api_url=http://${aci_private_ip}:8080/api/healthcheck
echo "Testing connectivity to API from VM (${api_url})..."
ssh -o "StrictHostKeyChecking no" $vm_public_ip "curl -s4 $api_url"
fi
# Optionally, create a Windows VM in the same vnet to work as jump host (for example to the dev portal)
if [[ "$create_win_vm" == "yes" ]]; then
echo "Creating Windows VM ${winvm_name}..."
az vm create -n $winvm_name -g $rg -l $location --image $winvm_image --size $winvm_size --vnet-name $vnet_name --subnet $vm_subnet_name --admin-username $winvm_user --admin-password $winvm_password --public-ip-sku Standard --nsg '' -o none --only-show-errors
winvm_nic_id=$(az vm show -n $winvm_name -g $rg --query 'networkProfile.networkInterfaces[0].id' -o tsv --only-show-errors)
winvm_private_ip=$(az network nic show --ids $winvm_nic_id --query 'ipConfigurations[0].privateIPAddress' -o tsv --only-show-errors) && echo "Windows VM private IP: $winvm_private_ip"
winvm_public_ip_id=$(az network nic show --ids $winvm_nic_id --query 'ipConfigurations[0].publicIPAddress.id' -o tsv --only-show-errors)
winvm_public_ip=$(az network public-ip show --ids $winvm_public_ip_id --query 'ipAddress' -o tsv --only-show-errors) && echo "Windows VM public IP: $winvm_public_ip"
fi
# Add an NSG to the APIM subnet
# https://learn.microsoft.com/en-us/azure/api-management/api-management-using-with-vnet#configure-nsg-rules
echo "Creating NSG ${apim_nsg} and associating it to the APIM subnet..."
az network nsg create -g $rg -n $apim_nsg -o none
az network nsg rule create -g $rg --nsg-name $apim_nsg -n Allow-HTTP-in --priority 100 --access Allow --protocol Tcp --direction Inbound --destination-port-ranges 80 443 --source-address-prefixes '*' --destination-address-prefixes '*' -o none
az network nsg rule create -g $rg --nsg-name $apim_nsg -n Allow-APIM-in --priority 110 --access Allow --protocol Tcp --direction Inbound --destination-port-ranges 3443 --source-address-prefixes ApiManagement --destination-address-prefixes '*' -o none
az network nsg rule create -g $rg --nsg-name $apim_nsg -n Allow-ALB-in --priority 120 --access Allow --protocol Tcp --direction Inbound --destination-port-ranges 6390 6391 --source-address-prefixes AzureLoadBalancer --destination-address-prefixes '*' -o none
az network nsg rule create -g $rg --nsg-name $apim_nsg -n Allow-TrafficManager-in --priority 130 --access Allow --protocol Tcp --direction Inbound --destination-port-ranges 443 --source-address-prefixes AzureTrafficManager --destination-address-prefixes '*' -o none
az network nsg rule create -g $rg --nsg-name $apim_nsg -n Allow-CertValidation-out --priority 110 --access Allow --protocol Tcp --direction Outbound --destination-port-ranges 80 443 --source-address-prefixes VirtualNetwork --destination-address-prefixes Internet -o none
az network nsg rule create -g $rg --nsg-name $apim_nsg -n Allow-Storage-out --priority 120 --access Allow --protocol Tcp --direction Outbound --destination-port-ranges 443 445 --source-address-prefixes VirtualNetwork --destination-address-prefixes Storage -o none
az network nsg rule create -g $rg --nsg-name $apim_nsg -n Allow-SQL-out --priority 130 --access Allow --protocol Tcp --direction Outbound --destination-port-ranges 1433 --source-address-prefixes VirtualNetwork --destination-address-prefixes SQL -o none
az network nsg rule create -g $rg --nsg-name $apim_nsg -n Allow-KeyVault-out --priority 140 --access Allow --protocol Tcp --direction Outbound --destination-port-ranges 443 --source-address-prefixes VirtualNetwork --destination-address-prefixes AzureKeyVault -o none
az network nsg rule create -g $rg --nsg-name $apim_nsg -n Allow-Monitor-out --priority 150 --access Allow --protocol Tcp --direction Outbound --destination-port-ranges 1886 443 --source-address-prefixes VirtualNetwork --destination-address-prefixes AzureMonitor -o none
az network nsg rule create -g $rg --nsg-name $apim_nsg -n Allow-EventHub-out --priority 160 --access Allow --protocol Tcp --direction Outbound --destination-port-ranges 5671 5672 443 --source-address-prefixes VirtualNetwork --destination-address-prefixes EventHub -o none
az network vnet subnet update -g $rg --vnet-name $vnet_name -n $apim_subnet_name --network-security-group $apim_nsg -o none
# Enable required service endpoints in the APIM subnet: Storage, SQL, KeyVault, AAD, EventHub, Service Bus
# This is only relevant if applying 0.0.0.0/0 routes to the APIM subnet, but it doesn't hurt
az network vnet subnet update -g $rg --vnet-name $vnet_name -n $apim_subnet_name -o none \
--service-endpoints Microsoft.Storage Microsoft.Sql Microsoft.KeyVault Microsoft.AzureActiveDirectory Microsoft.EventHub Microsoft.ServiceBus
# If v2, you need to delegate the subnet (although the portal would do it for you)
# az network vnet subnet update -g $rg --vnet-name $vnet_name -n $apim_subnet_name --delegations "Microsoft.Web/hostingEnvironments" -o none
########
# APIM #
########
# See https://learn.microsoft.com/en-us/azure/api-management/virtual-network-concepts
# v2:
# - Basic: no advanced networking features
# - Standard: adds private endpoints and outbound vnet-integration
# - Premium: adds "simplified" VNet-injection (using subnet delegations)
# classic:
# - Developer/Premium: VNet-injection (using gateways in the customer's subnet)
# * The "vnet-type" (internal/external) defines whether external traffic is allowed or not, influences the created ALB
# - All SKUs (except Consumption?) support private endpoints.
# Find existing APIM or create one
apim_name=$(az apim list -g $rg --query '[0].name' -o tsv)
if [[ -z "$apim_name" ]]
then
apim_name=apim$RANDOM
echo "Creating APIM ${apim_name}..."
az apim create -n $apim_name -g $rg -l $location --publisher-email $apim_publisher_email --publisher-name $apim_publisher_name --sku-name $apim_sku --virtual-network $apim_vnet_type -o none
else
echo "APIM $apim_name found in resource group $rg"
fi
# Configure logging
apim_id=$(az apim show -n $apim_name -g $rg --query id -o tsv)
az monitor diagnostic-settings create -n apimdiag$RANDOM --resource $apim_id --workspace $logws_id \
--logs '[{"category": "GatewayLogs", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}},
{"category": "WebSocketConnectionLogs", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}},
{"category": "DeveloperPortalAuditLogs", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}},
{"category": "GatewayLlmLogs", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}}]' -o none
# Add the APIM to the vnet. According to https://learn.microsoft.com/en-us/azure/api-management/api-management-using-with-internal-vnet,
# only portal/ARM is supported
apim_subnet_id=$(az network vnet subnet show -n $apim_subnet_name --vnet-name $vnet_name -g $rg --query id -o tsv)
az apim update -n $apim_name -g $rg -o none \
--set virtualNetworkType=$apim_vnet_type \
--set virtualNetworkConfiguration.subnetResourceId=$apim_subnet_id
# Error in the portal: Connection to management endpoint failed with WebException: ConnectFailure: unable to connect to the remote server
# Workaround: https://learn.microsoft.com/en-us/azure/api-management/api-management-using-with-vnet#troubleshoot-connection-issues
# Eventually with this REST API? https://learn.microsoft.com/en-us/rest/api/apimanagement/api-management-service/apply-network-configuration-updates?view=rest-apimanagement-2024-05-01&tabs=HTTP
# body="{\"location\": \"${location}\"}"
# subscription_id=$(az account show --query id -o tsv)
# az rest --method POST \
# --body "$body" \
# --url "https://management.azure.com/subscriptions/${subscription_id}/resourceGroups/${rg}/providers/Microsoft.ApiManagement/service/$apim_name/applyNetworkConfigurationUpdates?api-version=2024-05-01" \
# -o none
# Or Azure CLI:
az apim apply-network-updates -n $apim_name -g $rg -o none
# Create DNS zones and register APIM's private IP address
echo "Creating Private DNS zone azure-api.net and registering APIM private IP..."
dns_zone_name='azure-api.net'
apim_private_ip=$(az apim show -n $apim_name -g $rg --query 'privateIpAddresses[0]' -o tsv)
az network private-dns zone create -g $rg -n $dns_zone_name -o none
az network private-dns record-set a create -g $rg -z $dns_zone_name -n $apim_name -o none
az network private-dns record-set a add-record -g $rg -z $dns_zone_name -n $apim_name -a $apim_private_ip -o none
az network private-dns record-set a create -g $rg -z $dns_zone_name -n "${apim_name}.portal" -o none
az network private-dns record-set a add-record -g $rg -z $dns_zone_name -n "${apim_name}.portal" -a $apim_private_ip -o none
az network private-dns record-set a create -g $rg -z $dns_zone_name -n "${apim_name}.developer" -o none
az network private-dns record-set a add-record -g $rg -z $dns_zone_name -n "${apim_name}.developer" -a $apim_private_ip -o none
az network private-dns record-set a create -g $rg -z $dns_zone_name -n "${apim_name}.management" -o none
az network private-dns record-set a add-record -g $rg -z $dns_zone_name -n "${apim_name}.management" -a $apim_private_ip -o none
az network private-dns record-set a create -g $rg -z $dns_zone_name -n "${apim_name}.scm" -o none
az network private-dns record-set a add-record -g $rg -z $dns_zone_name -n "${apim_name}.scm" -a $apim_private_ip -o none
az network private-dns link vnet create -g $rg -n ${dns_zone_name}-link --virtual-network $vnet_name --zone-name $dns_zone_name --registration-enabled false -o none
# Create product and API
az apim product create -g $rg --service-name $apim_name -o none \
--product-id $product_name --product-name $product_name --description "Test API product" --legal-terms MyTerms \
--subscription-required false --state "published"
az apim api create -g $rg --service-name $apim_name --api-id $api_name --path '/' --display-name 'Demo API' --service-url "http://${aci_private_ip}:8080" -o none
az apim product api add -n $apim_name -g $rg --product-id $product_name --api-id $api_name -o none
az apim api operation create -g $rg --service-name $apim_name --api-id $api_name --display-name 'IP info' --operation-id ip --url-template /api/ip --method GET -o none
az apim api operation create -g $rg --service-name $apim_name --api-id $api_name --display-name 'Healthcheck' --operation-id healthcheck --url-template /api/healthcheck --method GET -o none
az apim api operation create -g $rg --service-name $apim_name --api-id $api_name --display-name 'Headers' --operation-id headers --url-template /api/headers --method GET -o none
# You can test the APIs right now
apim_url=$(az apim show -n $apim_name -g $rg --query gatewayUrl -o tsv)
if [[ "$create_linux_vm" == "yes" ]]; then
echo "Testing connectivity to APIM from Linux test VM (${apim_url})..."
ssh -o "StrictHostKeyChecking no" $vm_public_ip "curl -s4 ${apim_url}/api/healthcheck"
else
echo "Testing connectivity to APIM from local machine (${apim_url})..."
curl -s4 ${apim_url}/api/healthcheck
fi
# Not required, if hard coding the backend in the API with the --service-url parameter
# Create a backend
# url="https://management.azure.com/subscriptions/${subscription_id}/resourceGroups/${rg}/providers/Microsoft.ApiManagement/service/${apim_name}/backends/proxybackend?api-version=2024-05-01"
# body="""
# {
# \"properties\": {
# \"description\": \"Test API backend\",
# \"url\": \"http://${aci_private_ip}:8080/\",
# \"protocol\": \"http\",
# }
# }
# """
# az rest --method PUT --url $url --body "$body" -o none
# Work in progress!
# Check https://github.com/RobertEichenseer/APIM-CreatePolicy/blob/main/src/CreateEnv/CreateEnv.azcli
# Modify the API to use the backend
# policy="""
# {
# \"properties\": {
# \"value\": \"<policies>
# <inbound>
# <base />
# </inbound>
# <backend>
# <base />
# </backend>
# <outbound>
# <base />
# <set-header name=\\\"APIM-APIScopePolicy\\\" exists-action=\\\"append\\\">
# <value>Added on Api level</value>
# </set-header>
# </outbound>
# <on-error>
# <base />
# </on-error>
# </policies>\",
# \"format\": \"xml\"
# }
# }
# """
# Add a Gateway (portal) and get its key and config URL
# gw_key=<copy from portal>
# gw_config_url=<copy from portal>
########
# AzFW #
########
if [[ "$create_azfw" == "yes" ]]; then
# Create a subnet for the Azure Firewall
az network vnet subnet create -g $rg --vnet-name $vnet_name -n AzureFirewallSubnet --address-prefix $azfw_subnet_prefix -o none
# Create a public IP for the Azure Firewall
az network public-ip create -g $rg -n $azfw_public_ip_name --sku Standard --allocation-method Static -o none
# Create an Azure Firewall policy
az network firewall policy create -g $rg -n $azfw_policy_name --sku Standard -o none
# Create the Azure Firewall
az network firewall create -g $rg -n $azfw_name --public-ip $azfw_public_ip_name --firewall-policy $azfw_policy_name --tier Standard --vnet-name $vnet_name -o none
# Create an IP configuration for the firewall and assign the public IP and subnet
az network firewall ip-config create -g $rg --firewall-name $azfw_name -n fwconfig --public-ip-address $azfw_public_ip_name --vnet-name $vnet_name -o none
# Create a rule collection and a rule to allow all traffic to/from the APIM subnet
az network firewall policy rule-collection-group create -n ruleset01 --policy-name $azfw_policy_name -g $rg --priority 100 -o none
az network firewall policy rule-collection-group collection add-filter-collection --policy-name $azfw_policy_name --rule-collection-group-name ruleset01 -g $rg \
--name APIM --collection-priority 101 --action Allow --rule-name AllowAPIM --rule-type NetworkRule --description "Allow all traffic from APIM" \
--destination-addresses '*' --source-addresses $apim_subnet_prefix --ip-protocols TCP UDP --destination-ports '*' -o none
# Create a rule in the same collection to allow intra-vnet traffic
az network firewall policy rule-collection-group collection add-filter-collection --policy-name $azfw_policy_name --rule-collection-group-name ruleset01 -g $rg \
--name IntraVNet --collection-priority 102 --action Allow --rule-name AllowVNet --rule-type NetworkRule --description "Allow all traffic from VNet" \
--destination-addresses $vnet_prefix --source-addresses $vnet_prefix --ip-protocols TCP UDP --destination-ports '*' -o none
# az network firewall network-rule collection create -g $rg --firewall-name $azfw_name -n AllowAPIMSubnet --action Allow --priority 100 -o noneo
# az network firewall network-rule create -g $rg --firewall-name $azfw_name --collection-name AllowAPIMSubnet -n AllowAPIMSubnetRule --protocols Any --source-addresses '*' --destination-addresses $apim_subnet_prefix --destination-ports '*' -o none
# Get the firewall private IP
azfw_private_ip=$(az network firewall show -g $rg -n $azfw_name --query 'ipConfigurations[0].privateIPAddress' -o tsv) && echo "Azure Firewall Private IP: $azfw_private_ip"
# Enable Azure firewall logs
azfw_id=$(az network firewall show -g $rg -n $azfw_name --query id -o tsv)
az monitor diagnostic-settings create -n mydiag$RANDOM --resource $azfw_id --workspace $logws_id \
--logs '[{"category": "AzureFirewallApplicationRule", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}},
{"category": "AzureFirewallNetworkRule", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}}]' -o none
# Create a route table and a route to force traffic from APIM to the firewall
az network route-table create -g $rg -n $apim_rt_name -o none
# az network route-table route create -g $rg --route-table-name $apim_rt_name -n default-route --address-prefix '0.0.0.0/0' --next-hop-type VirtualAppliance --next-hop-ip-address $azfw_private_ip -o none
az network route-table route create -g $rg --route-table-name $apim_rt_name -n aci-to-azfw --address-prefix $aci_subnet_prefix --next-hop-type VirtualAppliance --next-hop-ip-address $azfw_private_ip -o none
az network route-table route create -g $rg --route-table-name $apim_rt_name -n vm-to-azfw --address-prefix $vm_subnet_prefix --next-hop-type VirtualAppliance --next-hop-ip-address $azfw_private_ip -o none
az network route-table route create -g $rg --route-table-name $apim_rt_name -n subnet-to-vnet --address-prefix $apim_subnet_prefix --next-hop-type VnetLocal -o none
# Associate the route table to the APIM subnet
az network vnet subnet update -g $rg --vnet-name $vnet_name -n $apim_subnet_name --route-table $apim_rt_name -o none
# Create a route table and a route to force traffic from VM to the firewall
az network route-table create -g $rg -n $vm_rt_name -o none
az network route-table route create -g $rg --route-table-name $vm_rt_name -n aci-to-azfw --address-prefix $aci_subnet_prefix --next-hop-type VirtualAppliance --next-hop-ip-address $azfw_private_ip -o none
az network route-table route create -g $rg --route-table-name $vm_rt_name -n apim-to-azfw --address-prefix $apim_subnet_prefix --next-hop-type VirtualAppliance --next-hop-ip-address $azfw_private_ip -o none
az network route-table route create -g $rg --route-table-name $vm_rt_name -n subnet-to-vnet --address-prefix $vm_subnet_prefix --next-hop-type VnetLocal -o none
# Associate the route table to the VM subnet
az network vnet subnet update -g $rg --vnet-name $vnet_name -n $vm_subnet_name --route-table $vm_rt_name -o none
# Create a route table and a route to force traffic from the ACI container to the firewall
az network route-table create -g $rg -n $aci_rt_name -o none
az network route-table route create -g $rg --route-table-name $aci_rt_name -n vm-to-azfw --address-prefix $vm_subnet_prefix --next-hop-type VirtualAppliance --next-hop-ip-address $azfw_private_ip -o none
az network route-table route create -g $rg --route-table-name $aci_rt_name -n apim-to-azfw --address-prefix $apim_subnet_prefix --next-hop-type VirtualAppliance --next-hop-ip-address $azfw_private_ip -o none
az network route-table route create -g $rg --route-table-name $aci_rt_name -n subnet-to-vnet --address-prefix $aci_subnet_prefix --next-hop-type VnetLocal -o none
# Associate the route table to the ACI subnet
az network vnet subnet update -g $rg --vnet-name $vnet_name -n $aci_subnet_name --route-table $aci_rt_name -o none
fi
###############
# Diagnostics #
###############
# API running on ACI
az container logs -g $rg -n $aci_name
# APIM
az apim list -g $rg -o table
az network nsg rule list -g $rg --nsg-name $apim_nsg -o table
az network vnet subnet show -g $rg --vnet-name $vnet_name -n $apim_subnet_name --query serviceEndpoints -o jsonc -o table
subscription_id=$(az account show --query id -o tsv)
az rest --method GET --url https://management.azure.com/subscriptions/$subscription_id/resourceGroups/$rg/providers/Microsoft.ApiManagement/service/$apim_name/networkstatus?api-version=2024-05-01
# Query the log analytics workspace for VNet flow logs
query='NTANetAnalytics
| where TimeGenerated > ago(10m)
| where SubType == \"FlowLog\"
//| where SrcIp == \"${src_ip}\"
//| where ipv4_is_in_range(SrcIp, \"${azfw_subnet_prefix}\")
//| where DestIp == \"${dst_ip}\"
//| where DestPort == 8080
//| where FlowStatus == \"Allowed\"
| summarize BytesSrc2Dst=sum(BytesSrcToDest), BytesDst2Src=sum(BytesDestToSrc) by MacAddress, SrcIp, SourceSystem, L4Protocol, DestIp, DestPort, ConnectionType, FlowStatus'
az monitor log-analytics query -w $logws_customerid --analytics-query "$query" -o table
# Query the firewall logs
query='AzureDiagnostics
| where TimeGenerated > ago(10m)
| where ResourceType == \"AZUREFIREWALLS\"
| where Category == \"AzureFirewallNetworkRule\"
//| where src_ip_s == \"${src_ip}\"
//| where ipv4_is_in_range(src_ip_s, \"${azfw_subnet_prefix}\")
//| where dest_ip_s == \"${dst_ip}\"
//| where dest_port_s == \"8080\"
| project TimeGenerated, src_ip_s, dest_ip_s, dest_port_s, action_s, msg_s'
az monitor log-analytics query -w $logws_customerid --analytics-query "$query" -o table
##################
# Start/Stop VMs #
##################
function stop_firewall() {
echo "Stoping Azure Firewall ${azfw_name}..."
az network firewall ip-config delete -f $azfw_name -n azfw-ipconfig -g $rg -o none
az network firewall update -n $azfw_name -g $rg -o none
}
function start_firewall() {
echo "Starting Azure Firewall ${azfw_name}..."
az network firewall ip-config create -f $azfw_name -n azfw-ipconfig -g $rg --public-ip-address $azfw_public_ip_name --vnet-name $vnet_name -o none
az network firewall update -n $azfw_name -g $rg -o none
}
function stop_vms() {
vm_list=$(az vm list -o tsv -g "$rg" --query "[].name")
while IFS= read -r vm_name; do
echo "Deallocating Virtual Machine ${vm_name}..."
az vm deallocate -g $rg -n "$vm_name" --no-wait -o none
done <<< "$vm_list"
}
function start_vms() {
vm_list=$(az vm list -o tsv -g "$rg" --query "[].name")
while IFS= read -r vm_name; do
echo "Starting Virtual Machine ${vm_name}..."
az vm start -g $rg -n "$vm_name" --no-wait -o none
done <<< "$vm_list"
}
###############
# DANGER ZONE #
###############
# az group delete -n $rg -y --no-wait