/
appservice.sp
1896 lines (1760 loc) · 70.2 KB
/
appservice.sp
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
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
locals {
regulatory_compliance_appservice_common_tags = {
service = "Azure/AppService"
}
}
control "appservice_web_app_use_https" {
title = "Web Application should only be accessible over HTTPS"
description = "Use of HTTPS ensures server/service authentication and protects data in transit from network layer eavesdropping attacks."
query = query.appservice_web_app_use_https
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
pci_dss_v321 = "true"
})
}
control "appservice_web_app_remote_debugging_disabled" {
title = "Remote debugging should be turned off for Web Applications"
description = "Remote debugging requires inbound ports to be opened on a web application. Remote debugging should be turned off."
query = query.appservice_web_app_remote_debugging_disabled
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_function_app_remote_debugging_disabled" {
title = "Function apps should have remote debugging turned off"
description = "Remote debugging requires inbound ports to be opened on function apps. Remote debugging should be turned off."
query = query.appservice_function_app_remote_debugging_disabled
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_function_app_latest_tls_version" {
title = "Function apps should use the latest TLS version"
description = "Periodically, newer versions are released for TLS either due to security flaws, include additional functionality, and enhance speed. Upgrade to the latest TLS version for Function apps to take advantage of security fixes, if any, and/or new functionalities of the latest version."
query = query.appservice_function_app_latest_tls_version
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_web_app_latest_tls_version" {
title = "Latest TLS version should be used in your Web App"
description = "Upgrade to the latest TLS version."
query = query.appservice_web_app_latest_tls_version
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_function_app_only_https_accessible" {
title = "Function apps should only be accessible over HTTPS"
description = "Use of HTTPS ensures server/service authentication and protects data in transit from network layer eavesdropping attacks."
query = query.appservice_function_app_only_https_accessible
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
pci_dss_v321 = "true"
})
}
control "appservice_web_app_use_virtual_service_endpoint" {
title = "App Service apps should use a virtual network service endpoint"
description = "Use virtual network service endpoints to restrict access to your app from selected subnets from an Azure virtual network. To learn more about App Service service endpoints, visit https://aks.ms/appservice-vnet-service-endpoint."
query = query.appservice_web_app_use_virtual_service_endpoint
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
})
}
control "appservice_api_app_use_https" {
title = "App Service API apps should only be accessible over HTTPS"
description = "Use of HTTPS ensures server/service authentication and protects data in transit from network layer eavesdropping attacks."
query = query.appservice_api_app_use_https
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
pci_dss_v321 = "true"
})
}
control "appservice_api_app_remote_debugging_disabled" {
title = "App Service apps should have remote debugging turned off"
description = "Remote debugging requires inbound ports to be opened on an App Service app. Remote debugging should be turned off."
query = query.appservice_api_app_remote_debugging_disabled
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_api_app_latest_tls_version" {
title = "App Service apps should use the latest TLS version"
description = "Periodically, newer versions are released for TLS either due to security flaws, include additional functionality, and enhance speed. Upgrade to the latest TLS version for App Service apps to take advantage of security fixes, if any, and/or new functionalities of the latest version."
query = query.appservice_api_app_latest_tls_version
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_web_app_diagnostic_logs_enabled" {
title = "App Service apps should have resource logs enabled"
description = "Audit enabling of resource logs on the app. This enables you to recreate activity trails for investigation purposes if a security incident occurs or your network is compromised."
query = query.appservice_web_app_diagnostic_logs_enabled
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_web_app_cors_no_star" {
title = "App Service apps should not have CORS configured to allow every resource to access your apps"
description = "Cross-Origin Resource Sharing (CORS) should not allow all domains to access your web application. Allow only required domains to interact with your web app."
query = query.appservice_web_app_cors_no_star
tags = merge(local.regulatory_compliance_appservice_common_tags, {
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_function_app_cors_no_star" {
title = "Function apps should not have CORS configured to allow every resource to access your apps"
description = "Cross-Origin Resource Sharing (CORS) should not allow all domains to access your Function app. Allow only required domains to interact with your Function app."
query = query.appservice_function_app_cors_no_star
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_api_app_uses_managed_identity" {
title = "Managed identity should be used in your API App"
description = "Use a managed identity for enhanced authentication security."
query = query.appservice_api_app_uses_managed_identity
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_api_app_cors_no_star" {
title = "App Service apps should not have CORS configured to allow every resource to access your apps"
description = "Cross-Origin Resource Sharing (CORS) should not allow all domains to access your app. Allow only required domains to interact with your app."
query = query.appservice_api_app_cors_no_star
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_web_app_uses_managed_identity" {
title = "App Service apps should use managed identity"
description = "Use a managed identity for enhanced authentication security."
query = query.appservice_web_app_uses_managed_identity
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_function_app_uses_managed_identity" {
title = "Function apps should use managed identity"
description = "Use a managed identity for enhanced authentication security."
query = query.appservice_function_app_uses_managed_identity
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_api_app_client_certificates_on" {
title = "App Service apps should have 'Client Certificates (Incoming client certificates)' enabled"
description = "Client certificates allow for the app to request a certificate for incoming requests. Only clients that have a valid certificate will be able to reach the app."
query = query.appservice_api_app_client_certificates_on
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_web_app_client_certificates_on" {
title = "App Service apps should have 'Client Certificates (Incoming client certificates)' enabled"
description = "Client certificates allow for the app to request a certificate for incoming requests. Only clients that have a valid certificate will be able to reach the app."
query = query.appservice_web_app_client_certificates_on
tags = merge(local.regulatory_compliance_appservice_common_tags, {
hipaa_hitrust_v92 = "true"
})
}
control "appservice_web_app_ftps_enabled" {
title = "FTPS should be required in your Web App"
description = "Enable FTPS enforcement for enhanced security."
query = query.appservice_web_app_ftps_enabled
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_function_app_client_certificates_on" {
title = "Function apps should have 'Client Certificates (Incoming client certificates)' enabled"
description = "Client certificates allow for the app to request a certificate for incoming requests. Only clients with valid certificates will be able to reach the app."
query = query.appservice_function_app_client_certificates_on
tags = merge(local.regulatory_compliance_appservice_common_tags, {
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_api_app_ftps_enabled" {
title = "FTPS only should be required in your API App"
description = "Enable FTPS enforcement for enhanced security."
query = query.appservice_api_app_ftps_enabled
tags = merge(local.regulatory_compliance_appservice_common_tags, {
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_function_app_ftps_enabled" {
title = "FTPS only should be required in your Function App"
description = "Enable FTPS enforcement for enhanced security."
query = query.appservice_function_app_ftps_enabled
tags = merge(local.regulatory_compliance_appservice_common_tags, {
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_function_app_latest_http_version" {
title = "Ensure that 'HTTP Version' is the latest, if used to run the Function app"
description = "Periodically, newer versions are released for HTTP either due to security flaws or to include additional functionality. Using the latest HTTP version for web apps to take advantage of security fixes, if any, and/or new functionalities of the newer version. Currently, this policy only applies to Linux web apps."
query = query.appservice_function_app_latest_http_version
tags = merge(local.regulatory_compliance_appservice_common_tags, {
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_web_app_latest_http_version" {
title = "Ensure that 'HTTP Version' is the latest, if used to run the Web app"
description = "Periodically, newer versions are released for HTTP either due to security flaws or to include additional functionality. Using the latest HTTP version for web apps to take advantage of security fixes, if any, and/or new functionalities of the newer version. Currently, this policy only applies to Linux web apps."
query = query.appservice_web_app_latest_http_version
tags = merge(local.regulatory_compliance_appservice_common_tags, {
nist_sp_800_53_rev_5 = "true"
})
}
control "app_service_environment_internal_encryption_enabled" {
title = "App Service Environment should enable internal encryption"
description = "Setting InternalEncryption to true encrypts the pagefile, worker disks, and internal network traffic between the front ends and workers in an App Service Environment."
query = query.app_service_environment_internal_encryption_enabled
tags = merge(local.regulatory_compliance_appservice_common_tags, {
nist_sp_800_53_rev_5 = "true"
})
}
control "appservice_function_app_latest_java_version" {
title = "Ensure that 'Java version' is the latest, if used as a part of the Function app"
description = "Periodically, newer versions are released for Java software either due to security flaws or to include additional functionality. Using the latest Java version for Function apps is recommended in order to take advantage of security fixes, if any, and/or new functionalities of the latest version. Currently, this policy only applies to Linux web apps."
query = query.appservice_function_app_latest_java_version
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_latest_java_version" {
title = "Ensure that 'Java version' is the latest, if used as a part of the Web app"
description = "Periodically, newer versions are released for Java software either due to security flaws or to include additional functionality. Using the latest Java version for web apps is recommended in order to take advantage of security fixes, if any, and/or new functionalities of the latest version. Currently, this policy only applies to Linux web apps."
query = query.appservice_web_app_latest_java_version
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_latest_php_version" {
title = "Ensure that 'PHP version' is the latest, if used as a part of the WEB app"
description = "Periodically, newer versions are released for PHP software either due to security flaws or to include additional functionality. Using the latest PHP version for web apps is recommended in order to take advantage of security fixes, if any, and/or new functionalities of the latest version. Currently, this policy only applies to Linux web apps."
query = query.appservice_web_app_latest_php_version
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_function_app_latest_python_version" {
title = "Ensure that 'Python version' is the latest, if used as a part of the Function app"
description = "Periodically, newer versions are released for Python software either due to security flaws or to include additional functionality. Using the latest Python version for Function apps is recommended in order to take advantage of security fixes, if any, and/or new functionalities of the latest version. Currently, this policy only applies to Linux web apps."
query = query.appservice_function_app_latest_python_version
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_latest_python_version" {
title = "Ensure that 'Python version' is the latest, if used as a part of the Web app"
description = "Periodically, newer versions are released for Python software either due to security flaws or to include additional functionality. Using the latest Python version for web apps is recommended in order to take advantage of security fixes, if any, and/or new functionalities of the latest version. Currently, this policy only applies to Linux web apps."
query = query.appservice_web_app_latest_python_version
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_latest_dotnet_framework_version" {
title = "Web app should use the latest 'Net Framework' version"
description = "Periodically, newer versions are released for Net Framework software either due to security flaws or to include additional functionality. Using the latest Net Framework for web apps is recommended in order to take advantage of security fixes, if any, and/or new functionalities of the latest version."
query = query.appservice_web_app_latest_dotnet_framework_version
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_failed_request_tracing_enabled" {
title = "Web app failed request tracing should be enabled"
description = "Ensure that Web app enables failed request tracing. This control is non-compliant if Web app failed request tracing is disabled."
query = query.appservice_web_app_failed_request_tracing_enabled
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_http_logs_enabled" {
title = "Web app HTTP logs should be enabled"
description = "Ensure that Web app HTTP logs is enabled. This control is non-compliant if Web app HTTP logs is disabled."
query = query.appservice_web_app_http_logs_enabled
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_worker_more_than_one" {
title = "Web app should have more than one worker"
description = "It is recommended to have more than one worker for failover. This control is non-compliant if Web apps have one or less than one worker."
query = query.appservice_web_app_worker_more_than_one
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_slot_use_https" {
title = "Web app slot should only be accessible over HTTPS"
description = "Use of HTTPS ensures server/service authentication and protects data in transit from network layer eavesdropping attacks."
query = query.appservice_web_app_slot_use_https
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_always_on" {
title = "Web apps should be configured to always be on"
description = "This control ensures that a web app is configured with settings to keep it consistently active. Always On feature of Azure App Service, keeps the host process running. This allows your site to be more responsive to requests after significant idle periods."
query = query.appservice_web_app_always_on
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_plan_minimum_sku" {
title = "Appservice plan should not use free, shared or basic SKU"
description = "The Free, Shared, and Basic plans are suitable for constrained testing and development purposes. This control is considered non-compliant when free, shared, or basic SKUs are utilized."
query = query.appservice_plan_minimum_sku
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_health_check_enabled" {
title = "Web apps should have health check enabled"
description = "Health check increases your application's availability by rerouting requests away from unhealthy instances and replacing instances if they remain unhealthy."
query = query.appservice_web_app_health_check_enabled
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_incoming_client_cert_on" {
title = "Ensure the web app has 'Client Certificates (Incoming client certificates)' set to 'On'"
description = "Client certificates allow for the app to request a certificate for incoming requests. Only clients that have a valid certificate will be able to reach the app."
query = query.appservice_web_app_incoming_client_cert_on
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_authentication_enabled" {
title = "Ensure App Service authentication is set up for apps in Azure App Service"
description = "Azure App Service authentication is a feature that can prevent anonymous HTTP requests from reaching a Web Application or authenticate those with tokens before they reach the app. If an anonymous request is received from a browser, App Service will redirect to a logon page. To handle the logon process, a choice from a set of identity providers can be made, or a custom authentication mechanism can be implemented."
query = query.appservice_authentication_enabled
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_ftp_deployment_disabled" {
title = "Ensure FTP deployments are Disabled"
description = "By default, Azure Functions, Web, and API Services can be deployed over FTP. If FTP is required for an essential deployment workflow, FTPS should be required for FTP login for all App Service Apps and Functions."
query = query.appservice_ftp_deployment_disabled
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_web_app_register_with_active_directory_enabled" {
title = "Ensure that Register with Azure Active Directory is enabled on App Service"
description = "Managed service identity in App Service provides more security by eliminating secrets from the app, such as credentials in the connection strings. When registering with Azure Active Directory in App Service, the app will connect to other Azure services securely without the need for usernames and passwords."
query = query.appservice_web_app_register_with_active_directory_enabled
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_function_app_authentication_on" {
title = "Ensure App Service authentication is set up for function apps in Azure App Service"
description = "Azure App Service authentication is a feature that can prevent anonymous HTTP requests from reaching a Web Application or authenticate those with tokens before they reach the app. If an anonymous request is received from a browser, App Service will redirect to a logon page. To handle the logon process, a choice from a set of identity providers can be made, or a custom authentication mechanism can be implemented."
query = query.appservice_function_app_authentication_on
tags = local.regulatory_compliance_appservice_common_tags
}
control "appservice_function_app_restrict_public_acces" {
title = "App Service function apps public access should be restricted"
description = "Anonymous public read access to function app in Azure App Service is a convenient way to share data but might present security risks. To prevent data breaches caused by undesired anonymous access, Microsoft recommends preventing public access to a function app unless your scenario requires it."
query = query.appservice_function_app_restrict_public_acces
tags = local.regulatory_compliance_appservice_common_tags
}
query "appservice_web_app_use_https" {
sql = <<-EOQ
select
app.id as resource,
case
when not https_only then 'alarm'
else 'ok'
end as status,
case
when not https_only then name || ' does not redirect all HTTP traffic to HTTPS.'
else name || ' redirects all HTTP traffic to HTTPS.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as app,
azure_subscription as sub
where
sub.subscription_id = app.subscription_id;
EOQ
}
query "appservice_web_app_incoming_client_cert_on" {
sql = <<-EOQ
select
app.id as resource,
case
when not client_cert_enabled then 'alarm'
else 'ok'
end as status,
case
when not client_cert_enabled then name || ' incoming client certificates set to off.'
else name || ' incoming client certificates set to on.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as app,
azure_subscription as sub
where
sub.subscription_id = app.subscription_id;
EOQ
}
query "appservice_web_app_remote_debugging_disabled" {
sql = <<-EOQ
select
app.id as resource,
case
when kind = 'api' then 'skip'
when configuration -> 'properties' ->> 'remoteDebuggingEnabled' = 'false' then 'ok'
else 'alarm'
end as status,
case
when kind = 'api' then name || ' is of ' || kind || ' type.'
when configuration -> 'properties' ->> 'remoteDebuggingEnabled' = 'false' then name || ' remote debugging disabled.'
else name || ' remote debugging enabled.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as app,
azure_subscription as sub
where
sub.subscription_id = app.subscription_id;
EOQ
}
query "appservice_function_app_remote_debugging_disabled" {
sql = <<-EOQ
select
app.id as resource,
case
when configuration -> 'properties' ->> 'remoteDebuggingEnabled' = 'false' then 'ok'
else 'alarm'
end as status,
case
when configuration -> 'properties' ->> 'remoteDebuggingEnabled' = 'false' then name || ' remote debugging disabled.'
else name || ' remote debugging enabled.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_function_app as app,
azure_subscription as sub
where
sub.subscription_id = app.subscription_id;
EOQ
}
query "appservice_function_app_latest_tls_version" {
sql = <<-EOQ
select
app.id as resource,
case
when configuration -> 'properties' ->> 'minTlsVersion' < '1.2' then 'alarm'
else 'ok'
end as status,
case
when configuration -> 'properties' ->> 'minTlsVersion' < '1.2' then name || ' not using the latest version of TLS encryption.'
else name || ' using the latest version of TLS encryption.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_function_app as app,
azure_subscription as sub
where
sub.subscription_id = app.subscription_id;
EOQ
}
query "appservice_web_app_latest_tls_version" {
sql = <<-EOQ
select
app.id as resource,
case
when configuration -> 'properties' ->> 'minTlsVersion' < '1.2' then 'alarm'
else 'ok'
end as status,
case
when configuration -> 'properties' ->> 'minTlsVersion' < '1.2' then name || ' not using the latest version of TLS encryption.'
else name || ' using the latest version of TLS encryption.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as app,
azure_subscription as sub
where
sub.subscription_id = app.subscription_id;
EOQ
}
query "appservice_function_app_only_https_accessible" {
sql = <<-EOQ
select
app.id as resource,
case
when https_only then 'ok'
else 'alarm'
end as status,
case
when https_only then name || ' https-only accessible enabled.'
else name || ' https-only accessible disabled.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_function_app as app,
azure_subscription as sub
where
sub.subscription_id = app.subscription_id;
EOQ
}
query "appservice_web_app_use_virtual_service_endpoint" {
sql = <<-EOQ
select
a.id as resource,
case
when vnet_connection -> 'properties' -> 'vnetResourceId' is not null then 'ok'
else 'alarm'
end as status,
case
when vnet_connection -> 'properties' -> 'vnetResourceId' is not null then a.name || ' configured with virtual network service endpoint.'
else a.name || ' not configured with virtual network service endpoint.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as a,
azure_subscription as sub
where
sub.subscription_id = a.subscription_id;
EOQ
}
query "appservice_api_app_use_https" {
sql = <<-EOQ
with all_api_app as (
select
id
from
azure_app_service_web_app
where
exists (
select
from
unnest(regexp_split_to_array(kind, ',')) elem
where
elem like '%api'
)
)
select
a.id as resource,
case
when b.id is null then 'skip'
when not https_only then 'alarm'
else 'ok'
end as status,
case
when b.id is null then a.title || ' is ' || a.kind || ' kind.'
when not https_only then a.name || ' does not redirect all HTTP traffic to HTTPS.'
else a.name || ' redirects all HTTP traffic to HTTPS.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as a
left join all_api_app as b on a.id = b.id,
azure_subscription as sub
where
sub.subscription_id = a.subscription_id;
EOQ
}
query "appservice_api_app_remote_debugging_disabled" {
sql = <<-EOQ
select
app.id as resource,
case
when kind <> 'api' then 'skip'
when configuration -> 'properties' ->> 'remoteDebuggingEnabled' = 'false' then 'ok'
else 'alarm'
end as status,
case
when kind <> 'api' then name || ' is of ' || kind || ' type.'
when configuration -> 'properties' ->> 'remoteDebuggingEnabled' = 'false' then name || ' remote debugging disabled.'
else name || ' remote debugging enabled.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as app,
azure_subscription as sub
where
sub.subscription_id = app.subscription_id;
EOQ
}
query "appservice_api_app_latest_tls_version" {
sql = <<-EOQ
with all_api_app as (
select
id
from
azure_app_service_web_app
where
exists (
select
from
unnest(regexp_split_to_array(kind, ',')) elem
where
elem like '%api'
)
)
select
a.id as resource,
case
when b.id is null then 'skip'
when configuration -> 'properties' ->> 'minTlsVersion' < '1.2' then 'alarm'
else 'ok'
end as status,
case
when b.id is null then a.title || ' is ' || a.kind || ' kind.'
when configuration -> 'properties' ->> 'minTlsVersion' < '1.2' then a.name || ' not using the latest version of TLS encryption.'
else a.name || ' using the latest version of TLS encryption.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as a
left join all_api_app as b on a.id = b.id,
azure_subscription as sub
where
sub.subscription_id = a.subscription_id;
EOQ
}
query "appservice_web_app_diagnostic_logs_enabled" {
sql = <<-EOQ
select
a.id as resource,
case
when (a.configuration-> 'properties' -> 'detailedErrorLoggingEnabled')::bool
and (a.configuration -> 'properties' -> 'httpLoggingEnabled')::bool
and (a.configuration-> 'properties' -> 'requestTracingEnabled')::bool
then 'ok'
else 'alarm'
end as status,
case
when (a.configuration-> 'properties' -> 'detailedErrorLoggingEnabled')::bool
and (a.configuration -> 'properties' -> 'httpLoggingEnabled')::bool
and (a.configuration-> 'properties' -> 'requestTracingEnabled')::bool
then a.name || ' diagnostic logs enabled.'
else a.title || ' diagnostic logs disabled.'
-- concat_ws(', ',
-- case when not ((a.configuration-> 'properties' -> 'detailedErrorLoggingEnabled')::bool) then 'detailed_Error_Logging_Enabled' end,
-- case when not ((a.configuration -> 'properties' -> 'httpLoggingEnabled')::bool) then 'http_logging_enabled' end,
-- case when not ((a.configuration-> 'properties' -> 'requestTracingEnabled')::bool) then 'request_tracing_enabled' end
-- ) || '.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as a,
azure_subscription as sub
where
sub.subscription_id = a.subscription_id;
EOQ
}
query "appservice_web_app_cors_no_star" {
sql = <<-EOQ
select
a.id as resource,
case
when configuration -> 'properties' -> 'cors' -> 'allowedOrigins' @> '["*"]' then 'alarm'
else 'ok'
end as status,
case
when configuration -> 'properties' -> 'cors' -> 'allowedOrigins' @> '["*"]'
then a.name || ' CORS allow all domains to access the application.'
else a.name || ' CORS does not all domains to access the application.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as a,
azure_subscription as sub
where
sub.subscription_id = a.subscription_id;
EOQ
}
query "appservice_function_app_cors_no_star" {
sql = <<-EOQ
select
b.id as resource,
case
when configuration -> 'properties' -> 'cors' -> 'allowedOrigins' @> '["*"]' then 'alarm'
else 'ok'
end as status,
case
when configuration -> 'properties' -> 'cors' -> 'allowedOrigins' @> '["*"]'
then b.name || ' CORS allow all domains to access the application.'
else b.name || ' CORS does not all domains to access the application.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "b.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_function_app as b,
azure_subscription as sub
where
sub.subscription_id = b.subscription_id;
EOQ
}
query "appservice_api_app_cors_no_star" {
sql = <<-EOQ
with all_api_app as (
select
id
from
azure_app_service_web_app
where
exists (
select
from
unnest(regexp_split_to_array(kind, ',')) elem
where
elem like '%api'
)
)
select
a.id as resource,
case
when b.id is null then 'skip'
when configuration -> 'properties' -> 'cors' -> 'allowedOrigins' @> '["*"]' then 'alarm'
else 'ok'
end as status,
case
when b.id is null then a.title || ' is ' || a.kind || ' kind.'
when configuration -> 'properties' -> 'cors' -> 'allowedOrigins' @> '["*"]' then a.name || ' CORS allow all domains to access the application.'
else a.name || ' CORS does not all domains to access the application.'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as a
left join all_api_app as b on a.id = b.id,
azure_subscription as sub
where
sub.subscription_id = a.subscription_id;
EOQ
}
query "appservice_web_app_uses_managed_identity" {
sql = <<-EOQ
with all_web_app as (
select
id
from
azure_app_service_web_app
where
exists (
select
from
unnest(regexp_split_to_array(kind, ',')) elem
where
elem like 'app%'
)
)
select
a.id as resource,
case
when b.id is null then 'skip'
when
configuration -> 'properties' ->> 'xManagedServiceIdentityId' is not null
or configuration -> 'properties' ->> 'managedServiceIdentityId' is not null then 'ok'
else 'alarm'
end as status,
case
when b.id is null then a.title || ' is ' || a.kind || ' kind.'
when
configuration -> 'properties' ->> 'xManagedServiceIdentityId' is not null
or configuration -> 'properties' ->> 'managedServiceIdentityId' is not null
then a.name || ' uses managed identity.'
else a.name || ' not uses managed identity'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as a
left join all_web_app as b on a.id = b.id,
azure_subscription as sub
where
sub.subscription_id = a.subscription_id;
EOQ
}
query "appservice_api_app_uses_managed_identity" {
sql = <<-EOQ
with all_api_app as (
select
id
from
azure_app_service_web_app
where
exists (
select
from
unnest(regexp_split_to_array(kind, ',')) elem
where
elem like '%api'
)
)
select
a.id as resource,
case
when b.id is null then 'skip'
when
configuration -> 'properties' ->> 'xManagedServiceIdentityId' is not null
or configuration -> 'properties' ->> 'managedServiceIdentityId' is not null then 'ok'
else 'alarm'
end as status,
case
when b.id is null then a.title || ' is ' || a.kind || ' kind.'
when
configuration -> 'properties' ->> 'xManagedServiceIdentityId' is not null
or configuration -> 'properties' ->> 'managedServiceIdentityId' is not null
then a.name || ' uses managed identity.'
else a.name || ' not uses managed identity'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_web_app as a
left join all_api_app as b on a.id = b.id,
azure_subscription as sub
where
sub.subscription_id = a.subscription_id;
EOQ
}
query "appservice_function_app_uses_managed_identity" {
sql = <<-EOQ
with all_function_app as (
select
id
from
azure_app_service_function_app
where
exists (
select
from
unnest(regexp_split_to_array(kind, ',')) elem
where
elem like 'functionapp%'
)
)
select
a.id as resource,
case
when b.id is null then 'skip'
when
configuration -> 'properties' ->> 'xManagedServiceIdentityId' is not null
or configuration -> 'properties' ->> 'managedServiceIdentityId' is not null then 'ok'
else 'alarm'
end as status,
case
when b.id is null then a.title || ' is ' || a.kind || ' kind.'
when
configuration -> 'properties' ->> 'xManagedServiceIdentityId' is not null
or configuration -> 'properties' ->> 'managedServiceIdentityId' is not null
then a.name || ' uses managed identity.'
else a.name || ' not uses managed identity'
end as reason
${local.tag_dimensions_sql}
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
from
azure_app_service_function_app as a
left join all_function_app as b on a.id = b.id,
azure_subscription as sub
where
sub.subscription_id = a.subscription_id;
EOQ
}
query "appservice_api_app_client_certificates_on" {
sql = <<-EOQ
with all_api_app as (
select
id
from
azure_app_service_web_app
where
exists (
select
from
unnest(regexp_split_to_array(kind, ',')) elem
where
elem like '%api'
)
)
select
a.id as resource,
case
when b.id is null then 'skip'
when client_cert_enabled then 'ok'
else 'alarm'
end as status,
case
when b.id is null then a.title || ' is ' || a.kind || ' kind.'
when client_cert_enabled then a.name || ' client certificate enabled.'
else a.name || ' client certificate disabled.'