-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathaca.azcli
More file actions
379 lines (344 loc) · 23.8 KB
/
Copy pathaca.azcli
File metadata and controls
379 lines (344 loc) · 23.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
#####################################################
# Sample CLI commands to test Azure Container Apps,
# especially to investigate its networking
# components.
#
# Jose Moreno, July 2022
#####################################################
# Control
internal=no
create_azfw=no
custom_dns=no
# Variables
rg=aca
location=eastus
vnet_name=aca
vnet_prefix=10.10.0.0/22
aca_subnet_prefix=10.10.0.0/26
aca_subnet_name=aca
acainfra_subnet_prefix=10.10.2.0/23
acainfra_subnet_name=aca-infra
sql_subnet_name=sql
sql_subnet_prefix=10.10.0.128/27
vm_subnet_prefix=10.10.0.64/26
vm_subnet_name=vm
vm_name=testvm
vm_sku=Standard_B2ms
azfw_subnet_name=AzureFirewallSubnet
azfw_subnet_prefix=10.10.0.192/26
azfw_name=azfw
azfw_pip_name=azfw-pip
azfw_policy_name=azfw-policy
aca_env_name=env1
web_image_name='erjosito/yadaweb:1.0'
api_image_name='erjosito/yadaapi:1.0'
sql_db_name=mydb
sql_username=azure
sql_password='Microsoft123!'
# Create RG and VNet
echo "Creating resource group and VNet..."
az group create -n $rg -l $location -o none
az network vnet create -n $vnet_name -g $rg --address-prefixes $vnet_prefix --subnet-name $aca_subnet_name --subnet-prefixes $aca_subnet_prefix -o none
az network vnet subnet create -n $vm_subnet_name --vnet-name $vnet_name -g $rg --address-prefixes $vm_subnet_prefix -o none
az network vnet subnet create -n $sql_subnet_name --vnet-name $vnet_name -g $rg --address-prefixes $sql_subnet_prefix -o none
az network vnet subnet create -n $acainfra_subnet_name --vnet-name $vnet_name -g $rg --address-prefixes $acainfra_subnet_prefix -o none
az network vnet subnet create -n $azfw_subnet_name --vnet-name $vnet_name -g $rg --address-prefixes $azfw_subnet_prefix -o none
acainfra_subnet_id=$(az network vnet subnet show -n $acainfra_subnet_name -g $rg --vnet-name $vnet_name --query id -o tsv)
# Create Log Analytics Workspace
logws_name=$(az monitor log-analytics workspace list -g $rg --query '[0].name' -o tsv)
if [[ -z "$logws_name" ]]
then
echo "Creating new Log Analytics workspace"
logws_name=log$RANDOM
az monitor log-analytics workspace create -n $logws_name -g $rg -o none
else
echo "Log Analytics workspace $logws_name found"
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)
logws_key=$(az monitor log-analytics workspace get-shared-keys -n $logws_name -g $rg --query primarySharedKey -o tsv)
# If create AzFW
if [[ "$create_azfw" == "yes" ]]; then
# Create PIP
az network public-ip create -g $rg -n $azfw_pip_name --sku standard --allocation-method static -l $location -o none
azfw_ip=$(az network public-ip show -g $rg -n $azfw_pip_name --query ipAddress -o tsv)
# Create policy
azfw_policy_name="${azfw_name}-policy"
az network firewall policy create -n $azfw_policy_name -g $rg -o none
az network firewall policy rule-collection-group create -n ruleset01 --policy-name $azfw_policy_name -g $rg --priority 1000 -o none
echo "Creating rule to allow SSH and HTTP..." # Allows internal connectivity
az network firewall policy rule-collection-group collection add-filter-collection --policy-name $azfw_policy_name --rule-collection-group-name ruleset01 -g $rg \
--name allowall --collection-priority 101 --action Allow --rule-name allowrfc1918 --rule-type NetworkRule --description "Internal connectivity" \
--destination-addresses "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" --source-addresses "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" --ip-protocols Any --destination-ports "1-65535" -o none
echo "Creating rule to allow ICMP..." # Allow ICMP
az network firewall policy rule-collection-group collection add-filter-collection --policy-name $azfw_policy_name --rule-collection-group-name ruleset01 -g $rg \
--name icmp --collection-priority 102 --action Allow --rule-name allowICMP --rule-type NetworkRule --description "ICMP traffic" \
--destination-addresses 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 --source-addresses 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 --ip-protocols ICMP --destination-ports "1-65535" -o none
echo "Creating rule to allow NTP..." # Allow NTP
az network firewall policy rule-collection-group collection add-filter-collection --policy-name $azfw_policy_name --rule-collection-group-name ruleset01 -g $rg \
--name ntp --collection-priority 103 --action Allow --rule-name allowNTP --rule-type NetworkRule --description "Egress NTP traffic" \
--destination-addresses '*' --source-addresses "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" --ip-protocols UDP --destination-ports "123" -o none
echo "Creating rule to allow Outbound Web..." # Allow outbound web
az network firewall policy rule-collection-group collection add-filter-collection --policy-name $azfw_policy_name --rule-collection-group-name ruleset01 -g $rg \
--name outboundweb --collection-priority 104 --action Allow --rule-name allowWeb --rule-type NetworkRule --description "Egress web traffic" \
--destination-addresses '*' --source-addresses "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" --ip-protocols TCP --destination-ports "443" -o none
echo "Creating rule to allow *.ubuntu.com..." # Example application collection with wildcards (*.ubuntu.com)
az network firewall policy rule-collection-group collection add-filter-collection --policy-name $azfw_policy_name --rule-collection-group-name ruleset01 -g $rg \
--name allowallweb --collection-priority 20000 --action Allow --rule-name allowall --rule-type ApplicationRule --description "allowAllWeb" \
--target-fqdns '*' --source-addresses '*' --protocols Http=80 Https=443 -o none
# Create AzFW
echo "Creating Azure Firewall..."
az network firewall create -n $azfw_name -g $rg --policy $azfw_policy_name -l $location -o none
# Configuring IP
echo "Configuring firewall logs and private IP..."
azfw_id=$(az network firewall show -n $azfw_name -g $rg -o tsv --query id)
az monitor diagnostic-settings create -n mydiag --resource $azfw_id --workspace $logws_id \
--metrics '[{"category": "AllMetrics", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false }, "timeGrain": null}]' \
--logs '[{"category": "AzureFirewallApplicationRule", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}},
{"category": "AzureFirewallNetworkRule", "enabled": true, "retentionPolicy": {"days": 0, "enabled": false}}]' -o none
echo "Creating IP configuration for Azure Firewall..."
az network firewall ip-config create -f $azfw_name -n azfw-ipconfig -g $rg --public-ip-address $azfw_pip_name --vnet-name $vnet_name -o none
az network firewall update -n $azfw_name -g $rg -o none
azfw_private_ip=$(az network firewall show -n $azfw_name -g $rg -o tsv --query 'ipConfigurations[0].privateIPAddress') && echo "AzFW's private IP: $azfw_private_ip"
# Configure UDR and default route in ACA infra subnet
az network route-table create -n aca -g $rg -l $location -o none
az network route-table route create -n defaultRoute --route-table-name aca -g $rg --next-hop-type VirtualAppliance --address-prefix "0.0.0.0/0" --next-hop-ip-address $azfw_private_ip -o none
aca_rt_id=$(az network route-table show -n aca -g $rg --query id -o tsv)
az network vnet subnet update -g $rg --vnet-name $vnet_name -n $acainfra_subnet_name --route-table $aca_rt_id -o none
# az network vnet subnet update -g $rg --vnet-name $vnet_name -n $acainfra_subnet_name --route-table '' -o none # Remove RT
fi
# Functions to start/stop the firewall
function stop_firewall() {
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() {
az network firewall ip-config create -f $azfw_name -n azfw-ipconfig -g $rg --public-ip-address $azfw_pip_name --vnet-name $vnet_name -o none
az network firewall update -n $azfw_name -g $rg -o none
}
# Create VM to test from within the VNet
echo "Creating VM to test from within the VNet..."
az vm create -n $vm_name -g $rg --image UbuntuLTS --generate-ssh-keys --size $vm_sku -l $location \
--vnet-name $vnet_name --subnet $vm_subnet_name --nsg "${vm_name}-nsg" --public-ip-address "${vm_name}-pip"
vm_pip=$(az network public-ip show -n "${vm_name}-pip" -g $rg --query ipAddress -o tsv)
vm_nic_id=$(az vm show -n $vm_name -g "$rg" --query 'networkProfile.networkInterfaces[0].id' -o tsv) && echo $vm_nic_id
vm_private_ip=$(az network nic show --ids $vm_nic_id --query 'ipConfigurations[0].privateIPAddress' -o tsv) && echo "VM's private IP: $vm_private_ip"
# Install Azure CLI
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $vm_pip "curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash"
# Install dnsmasq (to act as DNS server) and add a random name to /etc/hosts
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$vm_pip" "sudo apt install -y dnsmasq"
ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no "$vm_pip" "sudo sed -i \"\$ a 1.2.3.4 test.contoso.corp\" /etc/hosts"
# If custom DNS
if [[ "$custom_dns" == "yes" ]]; then
echo "Updating VNet custom DNS servers to $vm_private_ip..."
az network vnet update -n $vnet_name -g $rg --dns-servers $vm_private_ip -o none
fi
# Create ACA environment
az network vnet subnet update -n $acainfra_subnet_name --vnet-name $vnet_name -g $rg --delegations Microsoft.App/environments -o none
if [[ "$internal" == "yes" ]]; then
echo "Creating internal ACA environment..."
az containerapp env create -n $aca_env_name -g $rg -l $location --enable-workload-profiles true -o none \
--logs-destination log-analytics --logs-workspace-id $logws_customerid --logs-workspace-key $logws_key \
--infrastructure-subnet-resource-id $acainfra_subnet_id --internal-only true
else
echo "Creating external ACA environment..."
az containerapp env create -n $aca_env_name -g $rg -l $location --enable-workload-profiles true -o none \
--logs-destination log-analytics --logs-workspace-id $logws_customerid --logs-workspace-key $logws_key \
--infrastructure-subnet-resource-id $acainfra_subnet_id --internal-only false
fi
# Private DNS for ACA
aca_env_domain=$(az containerapp env show -n $aca_env_name -g $rg --query properties.defaultDomain -o tsv)
aca_env_static_ip=$(az containerapp env show -n $aca_env_name -g $rg --query properties.staticIp -o tsv)
vnet_id=$(az network vnet show -n $vnet_name -g $rg --query id --out tsv)
echo "Creating private DNS zone for ${aca_env_domain}..."
az network private-dns zone create -n $aca_env_domain -g $rg -o none
az network private-dns link vnet create -n $vnet_name -g $rg --virtual-network $vnet_id --zone-name $aca_env_domain --registration-enabled false -o none
az network private-dns record-set a add-record --record-set-name "*" -g $rg --ipv4-address $aca_env_static_ip --zone-name $aca_env_domain -o none
# Get the node RG from the default domain
aca_domain_name=$(echo $aca_env_domain | cut -d. -f 1)
aca_domain_region=$(echo $aca_env_domain | cut -d. -f 2)
node_rg="MC_${aca_domain_name}-rg_${aca_domain_name}_${aca_domain_region}"
az resource list -g $node_rg -o table
# Create backend database to test private link
sql_server_name=$(az sql server list -g $rg --query '[0].name' -o tsv)
if [[ -z "$sql_server_name" ]]; then
sql_server_name=sqlserver$RANDOM
echo "Creating SQL server ${sql_server_name}..."
az sql server create -n $sql_server_name -g $rg -l $location --admin-user "$sql_username" --admin-password "$sql_password" -o none
az sql db create -n $sql_db_name -s $sql_server_name -g $rg -e Basic -c 5 --no-wait -o none
else
echo "SQL Server $sql_server_name found in resource group $rg"
fi
sql_server_fqdn=$(az sql server show -n $sql_server_name -g $rg -o tsv --query fullyQualifiedDomainName) && echo "FQDN: $sql_server_fqdn"
# Create private link for SQL Server
sql_endpoint_name=sqlep
sql_server_id=$(az sql server show -n $sql_server_name -g $rg -o tsv --query id)
echo "Disabling private endpoint network policies for SQL subnet..."
az network vnet subnet update -n $sql_subnet_name -g $rg --vnet-name $vnet_name --disable-private-endpoint-network-policies true -o none
echo "Creating private endpoint for SQL server ${sql_server_name}..."
az network private-endpoint create -n $sql_endpoint_name -g $rg --vnet-name $vnet_name --subnet $sql_subnet_name --private-connection-resource-id $sql_server_id --group-id sqlServer --connection-name sqlConnection -o none
sql_nic_id=$(az network private-endpoint show -n $sql_endpoint_name -g $rg --query 'networkInterfaces[0].id' -o tsv)
sql_endpoint_ip=$(az network nic show --ids $sql_nic_id --query 'ipConfigurations[0].privateIPAddress' -o tsv)
echo "Private IP address for SQL server ${sql_server_name}: ${sql_endpoint_ip}"
# nslookup ${sql_server_fqdn}
# nslookup ${sql_server_name}.privatelink.database.windows.net
# Create private DNS zone for private link
echo "Creating private DNS zone for private link..."
dns_zone_name=privatelink.database.windows.net
az network private-dns zone create -n $dns_zone_name -g $rg -o none
az network private-dns link vnet create -g $rg -z $dns_zone_name -n myDnsLink --virtual-network $vnet_name --registration-enabled false -o none
az network private-endpoint dns-zone-group create --endpoint-name $sql_endpoint_name -g $rg -n plinkzonegroup --zone-name zone1 --private-dns-zone $dns_zone_name -o none
# Create key vault with SQL password
akv_name=$(az keyvault list -g $rg --query '[0].name' -o tsv)
akv_secret_name=sqlpassword
if [[ -z "$akv_name" ]]; then
akv_name=akv$RANDOM
echo "Creating Azure Key Vault $akv_name..."
az keyvault create -n $akv_name -g $rg -l $location --sku standard -o none
echo "Assigning RBAC permissions for AKV $akv_name to current user..."
current_user=$(az ad signed-in-user show --query userPrincipalName -o tsv)
akv_id=$(az keyvault show -n $akv_name -g $rg --query id -o tsv)
az role assignment create --assignee $current_user --role "Key Vault Secrets Officer" --scope $akv_id -o none
else
echo "Key Vault $akv_name found in resource group $rg"
fi
echo "Storing SQL password in Key Vault..."
az keyvault secret set --vault-name $akv_name -n $akv_secret_name --value "$sql_password" -o none
# Create managed identity for ACA apps to access Azure Key Vault
echo "Creating managed identity for ACA apps to access Azure Key Vault..."
aca_mi_name=aca-mi
aca_mi_id=$(az identity create -g $rg -n $aca_mi_name --query id -o tsv)
aca_mi_client_id=$(az identity show -g $rg -n $aca_mi_name --query clientId -o tsv)
echo "Assigning Key Vault RBAC permissions to ACA managed identity $aca_mi_name..."
az role assignment create --assignee $aca_mi_client_id --role "Key Vault Secrets User" --scope $akv_id -o none
# Deploy apps (web and API)
web_app_name=web-app
api_app_name=api-app
echo "Deploying API app $api_app_name..."
az containerapp create --image $api_image_name -n $api_app_name -g $rg --environment $aca_env_name -o none \
--user-assigned $aca_mi_id \
--secrets "sqlpassword=keyvaultref:https://${akv_name}.vault.azure.net/secrets/${akv_secret_name},identityref:${aca_mi_id}" \
--env-vars "SQL_SERVER_USERNAME=${sql_username}" "SQL_SERVER_FQDN=${sql_server_fqdn}" "SQL_SERVER_PASSWORD=secretref:sqlpassword" \
--cpu 0.25 --memory 0.5Gi --min-replicas 1 --max-replicas 2 --ingress internal --target-port 8080
api_app_fqdn=$(az containerapp show -n $api_app_name -g $rg --query properties.configuration.ingress.fqdn -o tsv)
echo "Deploying web app $web_app_name..."
az containerapp create --image $web_image_name -n $web_app_name -g $rg --environment $aca_env_name -o none \
--env-vars "API_URL=https://${api_app_fqdn}" \
--cpu 0.25 --memory 0.5Gi --min-replicas 1 --max-replicas 2 --ingress external --target-port 80
# Web app URL
web_app_fqdn=$(az containerapp show -n $web_app_name -g $rg --query properties.configuration.ingress.fqdn -o tsv)
echo "Web app URL: http://${web_app_fqdn}"
#################
# Modifications #
#################
# Publish/unpublish apps
# az containerapp ingress disable -n $api_app_name -g $rg -o none
# az containerapp ingress enable -n $api_app_name -g $rg --type internal --allow-insecure --target-port 8080 -o none
# Modify resource allocation
az containerapp update -n app1 -g $rg --cpu 0.25 --memory 0.5Gi --min-replicas 1 --max-replicas 2 -o none
az containerapp update -n app2 -g $rg --cpu 0.25 --memory 0.5Gi --min-replicas 1 --max-replicas 2 -o none
# Change image
az containerapp update -n $api_app_name -g $rg --image $api_image_name -o none
az containerapp update -n $web_app_name -g $rg --image $web_image_name -o none
# Set environment variables
az containerapp update -n $web_app_name -g $rg --set-env-vars "API_URL=https://${api_app_fqdn}" -o none
az containerapp update -n $api_app_name -g $rg --set-env-vars "SQL_SERVER_USERNAME=${sql_username}" "SQL_SERVER_FQDN=${sql_server_fqdn}" "SQL_SERVER_PASSWORD=secretref:sqlpassword" -o none
###############
# Diagnostics #
###############
# Exec into app
api_replica0_name=$(az containerapp replica list -n $api_app_name -g $rg --query '[0].name' -o tsv)
az containerapp exec -n $api_app_name -g $rg --command bash
# IP scan
# az containerapp exec -n $api_app_name -g $rg --command 'for i in {0..255}; do for j in {0..255}; do dig -x 10.0.$i.$j | grep -e cluster.local ; done ; done'
# ACA env
az containerapp env list -g $rg -o table
az containerapp env show -n $aca_env_name -g $rg
# Workload profiles
az containerapp env workload-profile list -n $aca_env_name -g $rg -o table
# ACA apps
az containerapp list -g $rg -o table
az containerapp show -n app1 -g $rg
az containerapp replica list -n app1 -g $rg -o table
az containerapp logs show -n app1 -g $rg -o table
# LB
az network lb frontend-ip list --lb-name kubernetes -g $node_rg -o table
az network lb outbound-rule list --lb-name kubernetes -g $node_rg -o table
az network lb rule list --lb-name kubernetes -g $node_rg -o table
az network lb frontend-ip list --lb-name kubernetes-internal -g $node_rg -o table
az network lb outbound-rule list --lb-name kubernetes-internal -g $node_rg -o table
az network lb rule list --lb-name kubernetes-internal -g $node_rg -o table
# Query app insights logs
logws_client_id=$(az containerapp env show -n $aca_env_name -g $rg --query properties.appLogsConfiguration.logAnalyticsConfiguration.customerId -o tsv)
az monitor log-analytics query --workspace $logws_client_id --analytics-query "ContainerAppConsoleLogs_CL | where ContainerAppName_s == 'my-container-app' | project ContainerAppName_s, Log_s, TimeGenerated" -o table
# Query firewall logs
# Firewall Network Rules
fw_net_logs_query='AzureDiagnostics
| where Category == "AzureFirewallNetworkRule"
| where TimeGenerated >= ago(5m)
| parse msg_s with Protocol " request from " SourceIP ":" SourcePortInt:int " to " TargetIP ":" TargetPortInt:int *
| parse msg_s with * ". Action: " Action1a
| parse msg_s with * " was " Action1b " to " NatDestination
| parse msg_s with Protocol2 " request from " SourceIP2 " to " TargetIP2 ". Action: " Action2
| extend SourcePort = tostring(SourcePortInt),TargetPort = tostring(TargetPortInt)
| extend Action = case(Action1a == "", case(Action1b == "",Action2,Action1b), Action1a),Protocol = case(Protocol == "", Protocol2, Protocol),SourceIP = case(SourceIP == "", SourceIP2, SourceIP),TargetIP = case(TargetIP == "", TargetIP2, TargetIP),SourcePort = case(SourcePort == "", "N/A", SourcePort),TargetPort = case(TargetPort == "", "N/A", TargetPort),NatDestination = case(NatDestination == "", "N/A", NatDestination)
//| where Action == "Deny"
//| project TimeGenerated, msg_s, Protocol, SourceIP,SourcePort,TargetIP,TargetPort,Action, NatDestination // with msg_s
| project TimeGenerated, Protocol, SourceIP,SourcePort,TargetIP,TargetPort,Action, NatDestination, Resource // without msg_s
| take 20 '
az monitor log-analytics query -w $logws_customerid --analytics-query $fw_net_logs_query -o tsv
# Firewall App Rules
fw_app_logs_query='AzureDiagnostics
| where ResourceType == "AZUREFIREWALLS"
| where Category == "AzureFirewallApplicationRule"
| where TimeGenerated >= ago(5m)
| project Protocol=split(msg_s, " ")[0], From=split(msg_s, " ")[iif(split(msg_s, " ")[0]=="HTTPS",3,4)], To=split(msg_s, " ")[iif(split(msg_s, " ")[0]=="HTTPS",5,6)], Action=trim_end(".", tostring(split(msg_s, " ")[iif(split(msg_s, " ")[0]=="HTTPS",7,8)])), Rule_Collection=iif(split(msg_s, " ")[iif(split(msg_s, " ")[0]=="HTTPS",10,11)]=="traffic.", "AzureInternalTraffic", iif(split(msg_s, " ")[iif(split(msg_s, " ")[0]=="HTTPS",10,11)]=="matched.","NoRuleMatched",trim_end(".",tostring(split(msg_s, " ")[iif(split(msg_s, " ")[0]=="HTTPS",10,11)])))), Rule=iif(split(msg_s, " ")[11]=="Proceeding" or split(msg_s, " ")[12]=="Proceeding","DefaultAction",split(msg_s, " ")[12]), msg_s
| where Rule_Collection != "AzureInternalTraffic"
//| where Action == "Deny"
| take 20'
az monitor log-analytics query -w $logws_customerid --analytics-query $fw_app_logs_query -o tsv
# Firewall logs (all) WORK IN PROGRESS
fw_logs_query='AzureDiagnostics
| where Category == "AzureFirewallNetworkRule" or Category == "AzureFirewallApplicationRule"
| extend msg_original = msg_s
| extend msg_s = replace(@". Action: Deny. Reason: SNI TLS extension was missing.", @" to no_data:no_data. Action: Deny. Rule Collection: default behavior. Rule: SNI TLS extension missing", msg_s)
| extend msg_s = replace(@"No rule matched. Proceeding with default action", @"Rule Collection: default behavior. Rule: no rule matched", msg_s)
| parse msg_s with * " Web Category: " WebCategory
| extend msg_s = replace(@"(. Web Category:).*","", msg_s)
| parse msg_s with * ". Rule Collection: " RuleCollection ". Rule: " Rule
| extend msg_s = replace(@"(. Rule Collection:).*","", msg_s)
| parse msg_s with * ". Rule Collection Group: " RuleCollectionGroup
| extend msg_s = replace(@"(. Rule Collection Group:).*","", msg_s)
| parse msg_s with * ". Policy: " Policy
| extend msg_s = replace(@"(. Policy:).*","", msg_s)
| parse msg_s with * ". Signature: " IDSSignatureIDInt ". IDS: " IDSSignatureDescription ". Priority: " IDSPriorityInt ". Classification: " IDSClassification
| extend msg_s = replace(@"(. Signature:).*","", msg_s)
| parse msg_s with * " was DNAT"ed to " NatDestination
| extend msg_s = replace(@"( was DNAT"ed to ).*",". Action: DNAT", msg_s)
| parse msg_s with * ". ThreatIntel: " ThreatIntel
| extend msg_s = replace(@"(. ThreatIntel:).*","", msg_s)
| extend URL = extract(@"(Url: )(.*)(\. Action)",2,msg_s)
| extend msg_s=replace(@"(Url: .*)(Action)",@"\2",msg_s)
| parse msg_s with Protocol " request from " SourceIP " to " Target ". Action: " Action
| extend
SourceIP = iif(SourceIP contains ":",strcat_array(split(SourceIP,":",0),""),SourceIP),
SourcePort = iif(SourceIP contains ":",strcat_array(split(SourceIP,":",1),""),""),
Target = iif(Target contains ":",strcat_array(split(Target,":",0),""),Target),
TargetPort = iif(SourceIP contains ":",strcat_array(split(Target,":",1),""),""),
Action = iif(Action contains ".",strcat_array(split(Action,".",0),""),Action),
Policy = case(RuleCollection contains ":", split(RuleCollection, ":")[0] ,Policy),
RuleCollectionGroup = case(RuleCollection contains ":", split(RuleCollection, ":")[1], RuleCollectionGroup),
RuleCollection = case(RuleCollection contains ":", split(RuleCollection, ":")[2], RuleCollection),
IDSSignatureID = tostring(IDSSignatureIDInt),
IDSPriority = tostring(IDSPriorityInt)
| project msg_original,TimeGenerated,Protocol,SourceIP,SourcePort,Target,TargetPort,URL,Action, NatDestination, OperationName,ThreatIntel,IDSSignatureID,IDSSignatureDescription,IDSPriority,IDSClassification,Policy,RuleCollectionGroup,RuleCollection,Rule,WebCategory
| order by TimeGenerated
| limit 100'
az monitor log-analytics query -w $logws_customerid --analytics-query $fw_logs_query -o tsv
###############
# Cleanup #
###############
az containerapp delete -n app1 -g $rg -y
az containerapp delete -n app2 -g $rg -y
az containerapp env delete -n $aca_env_name -g $rg -y
az group delete -n $rg -y --no-wait