From 24cf26dae249d5b9fb5ad85b101414124ea1e4ce Mon Sep 17 00:00:00 2001 From: Billy Richardson Date: Tue, 13 Aug 2024 10:58:19 -0700 Subject: [PATCH 1/5] Add `SystemAssigned, UserAssigned` as an allowed identity on TA-000013 --- src/Analyzer.Core/Rules/BuiltInRules.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Analyzer.Core/Rules/BuiltInRules.json b/src/Analyzer.Core/Rules/BuiltInRules.json index ed9af425..8d5b56e2 100644 --- a/src/Analyzer.Core/Rules/BuiltInRules.json +++ b/src/Analyzer.Core/Rules/BuiltInRules.json @@ -394,7 +394,8 @@ "path": "identity.type", "in": [ "UserAssigned", - "SystemAssigned" + "SystemAssigned", + "SystemAssigned, UserAssigned" ] } ] From 42a7bfae6b00bf8dcba56a9d67e1beeb0c20c8cc Mon Sep 17 00:00:00 2001 From: Billy Richardson Date: Tue, 27 Aug 2024 22:27:08 -0700 Subject: [PATCH 2/5] Add tests and support dynamic number of spaces --- .../Tests/TA-000013/FunctionAppServices.bicep | 92 +++++++++++++ .../Tests/TA-000013/FunctionAppServices.json | 128 ++++++++++++++++++ .../Tests/TA-000013/TA-000013.json | 11 ++ src/Analyzer.Core/Rules/BuiltInRules.json | 6 +- 4 files changed, 232 insertions(+), 5 deletions(-) create mode 100644 src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.bicep create mode 100644 src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.json create mode 100644 src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/TA-000013.json diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.bicep b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.bicep new file mode 100644 index 00000000..7185c39b --- /dev/null +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.bicep @@ -0,0 +1,92 @@ +@description('Location for all resources.') +param location string = resourceGroup().location + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: 'managedIdentity' + location: location +} +resource missingIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'functionapp' + name: 'missingIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } +} + +resource systemManagedIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'functionapp' + name: 'systemManagedIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'SystemAssigned' + } +} + +resource userManagedIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'functionapp' + name: 'userManagedIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } +} + +resource systemAndUserManagedIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'functionapp' + name: 'systemAndUserManagedIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'SystemAssigned,UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } +} + +resource systemAndUserManagedWithSpaceIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'functionapp' + name: 'systemAndUserManagedWithSpaceIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'SystemAssigned, UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } +} diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.json b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.json new file mode 100644 index 00000000..b6ad4236 --- /dev/null +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.json @@ -0,0 +1,128 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "11204652936116461480" + } + }, + "parameters": { + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources." + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2018-11-30", + "name": "managedIdentity", + "location": "[parameters('location')]" + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "missingIdentity", + "kind": "functionapp", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + } + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "systemManagedIdentity", + "kind": "functionapp", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "SystemAssigned" + } + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "userManagedIdentity", + "kind": "functionapp", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity'))]": {} + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity')]" + ] + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "systemAndUserManagedIdentity", + "kind": "functionapp", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "SystemAssigned,UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity'))]": {} + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity')]" + ] + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "systemAndUserManagedWithSpaceIdentity", + "kind": "functionapp", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "SystemAssigned, UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity'))]": {} + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity')]" + ] + } + ] +} \ No newline at end of file diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/TA-000013.json b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/TA-000013.json new file mode 100644 index 00000000..52b0ad1f --- /dev/null +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/TA-000013.json @@ -0,0 +1,11 @@ +[ + { + "Template": "FunctionAppServices.json", + "ReportedFailures": [ + { + "LineNumber": 27, + "Description": "Function app is missing an identity declaration" + } + ] + } +] \ No newline at end of file diff --git a/src/Analyzer.Core/Rules/BuiltInRules.json b/src/Analyzer.Core/Rules/BuiltInRules.json index 8d5b56e2..fd364bbd 100644 --- a/src/Analyzer.Core/Rules/BuiltInRules.json +++ b/src/Analyzer.Core/Rules/BuiltInRules.json @@ -392,11 +392,7 @@ "allOf": [ { "path": "identity.type", - "in": [ - "UserAssigned", - "SystemAssigned", - "SystemAssigned, UserAssigned" - ] + "regex": "^(UserAssigned|SystemAssigned|SystemAssigned, *UserAssigned)$" } ] } From bd20d86ec34f8bb7d57753a809077e82075fef21 Mon Sep 17 00:00:00 2001 From: Billy Richardson Date: Tue, 27 Aug 2024 22:41:35 -0700 Subject: [PATCH 3/5] Update docs --- docs/built-in-rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/built-in-rules.md b/docs/built-in-rules.md index fe908cc4..bf60475f 100644 --- a/docs/built-in-rules.md +++ b/docs/built-in-rules.md @@ -83,7 +83,7 @@ Cross-Origin Resource Sharing (CORS) should not allow all domains to access your ### TA-000013: Managed identity should be used in your function app For enhanced authentication security, use a managed identity. On Azure, managed identities eliminate the need for developers to have to manage credentials by providing an identity for the Azure resource in Azure AD and using it to obtain Azure Active Directory (Azure AD) tokens. -**Recommendation**: To [use Managed Identity](https://docs.microsoft.com/azure/app-service/overview-managed-identity?tabs=dotnet), in the [Microsoft.Web/sites resource managed identity property](https://docs.microsoft.com/azure/templates/microsoft.web/sites?tabs=json#ManagedServiceIdentity), add (or update) the *type* property, setting its value to `"SystemAssigned"` or `"UserAssigned"` and providing any necessary identifiers for the identity if required. +**Recommendation**: To [use Managed Identity](https://docs.microsoft.com/azure/app-service/overview-managed-identity?tabs=dotnet), in the [Microsoft.Web/sites resource managed identity property](https://docs.microsoft.com/azure/templates/microsoft.web/sites?tabs=json#ManagedServiceIdentity), add (or update) the *type* property, setting its value to `"SystemAssigned"`, `"UserAssigned"`, or `"SystemAssigned, UserAssigned"` and providing any necessary identifiers for the identity if required. #### Severity: 2 ### TA-000014: Remote debugging should be turned off for web apps From cd99ee7e3a6596abf8c21d39a8507d1a73134a0e Mon Sep 17 00:00:00 2001 From: Billy Richardson Date: Wed, 28 Aug 2024 10:00:00 -0800 Subject: [PATCH 4/5] Update other rules and restrict multiple identity type formatting --- .../Tests/TA-000007/AppServiceAPIApps.bicep | 92 ++++++++++++ .../Tests/TA-000007/AppServiceAPIApps.json | 121 ++++++++++++++++ .../Tests/TA-000007/TA-000007.json | 15 ++ ...ces.bicep => AppServiceFunctionApps.bicep} | 0 ...vices.json => AppServiceFunctionApps.json} | 7 - .../Tests/TA-000013/TA-000013.json | 10 +- .../Tests/TA-000019/AppServiceWebApps.bicep | 104 ++++++++++++++ .../Tests/TA-000019/AppServiceWebApps.json | 134 ++++++++++++++++++ .../Tests/TA-000019/TA-000019.json | 19 +++ src/Analyzer.Core/Rules/BuiltInRules.json | 12 +- 10 files changed, 501 insertions(+), 13 deletions(-) create mode 100644 src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/AppServiceAPIApps.bicep create mode 100644 src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/AppServiceAPIApps.json create mode 100644 src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/TA-000007.json rename src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/{FunctionAppServices.bicep => AppServiceFunctionApps.bicep} (100%) rename src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/{FunctionAppServices.json => AppServiceFunctionApps.json} (96%) create mode 100644 src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/AppServiceWebApps.bicep create mode 100644 src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/AppServiceWebApps.json create mode 100644 src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/TA-000019.json diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/AppServiceAPIApps.bicep b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/AppServiceAPIApps.bicep new file mode 100644 index 00000000..2f782fd5 --- /dev/null +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/AppServiceAPIApps.bicep @@ -0,0 +1,92 @@ +@description('Location for all resources.') +param location string = resourceGroup().location + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: 'managedIdentity' + location: location +} +resource missingIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'api' + name: 'missingIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } +} + +resource systemManagedIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'api' + name: 'systemManagedIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'SystemAssigned' + } +} + +resource userManagedIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'api' + name: 'userManagedIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } +} + +resource systemAndUserManagedIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'api' + name: 'systemAndUserManagedIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'SystemAssigned,UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } +} + +resource systemAndUserManagedWithSpaceIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'api' + name: 'systemAndUserManagedWithSpaceIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'SystemAssigned, UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } +} diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/AppServiceAPIApps.json b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/AppServiceAPIApps.json new file mode 100644 index 00000000..f5e0def0 --- /dev/null +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/AppServiceAPIApps.json @@ -0,0 +1,121 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources." + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2018-11-30", + "name": "managedIdentity", + "location": "[parameters('location')]" + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "missingIdentity", + "kind": "api", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + } + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "systemManagedIdentity", + "kind": "api", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "SystemAssigned" + } + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "userManagedIdentity", + "kind": "api", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity'))]": {} + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity')]" + ] + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "systemAndUserManagedIdentity", + "kind": "api", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "SystemAssigned,UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity'))]": {} + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity')]" + ] + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "systemAndUserManagedWithSpaceIdentity", + "kind": "api", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "SystemAssigned, UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity'))]": {} + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity')]" + ] + } + ] +} \ No newline at end of file diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/TA-000007.json b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/TA-000007.json new file mode 100644 index 00000000..d50b00ea --- /dev/null +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000007/TA-000007.json @@ -0,0 +1,15 @@ +[ + { + "Template": "AppServiceAPIApps.json", + "ReportedFailures": [ + { + "LineNumber": 20, + "Description": "API app is missing an identity declaration." + }, + { + "LineNumber": 88, + "Description": "Multiple identity types should be separated by a comma, followed by a space." + } + ] + } +] \ No newline at end of file diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.bicep b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/AppServiceFunctionApps.bicep similarity index 100% rename from src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.bicep rename to src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/AppServiceFunctionApps.bicep diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.json b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/AppServiceFunctionApps.json similarity index 96% rename from src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.json rename to src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/AppServiceFunctionApps.json index b6ad4236..640e884b 100644 --- a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/FunctionAppServices.json +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/AppServiceFunctionApps.json @@ -1,13 +1,6 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.29.47.4906", - "templateHash": "11204652936116461480" - } - }, "parameters": { "location": { "type": "string", diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/TA-000013.json b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/TA-000013.json index 52b0ad1f..579032e9 100644 --- a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/TA-000013.json +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000013/TA-000013.json @@ -1,10 +1,14 @@ [ { - "Template": "FunctionAppServices.json", + "Template": "AppServiceFunctionApps.json", "ReportedFailures": [ { - "LineNumber": 27, - "Description": "Function app is missing an identity declaration" + "LineNumber": 20, + "Description": "Function app is missing an identity declaration." + }, + { + "LineNumber": 88, + "Description": "Multiple identity types should be separated by a comma, followed by a space." } ] } diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/AppServiceWebApps.bicep b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/AppServiceWebApps.bicep new file mode 100644 index 00000000..a64f5bc5 --- /dev/null +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/AppServiceWebApps.bicep @@ -0,0 +1,104 @@ +@description('Location for all resources.') +param location string = resourceGroup().location + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: 'managedIdentity' + location: location +} +resource missingIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'app' + name: 'missingIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } +} + +resource systemManagedIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'app' + name: 'systemManagedIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'SystemAssigned' + } +} + +resource userManagedIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'app' + name: 'userManagedIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } +} + +resource systemAndUserManagedIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'app' + name: 'systemAndUserManagedIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'SystemAssigned,UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } +} + +resource systemAndUserManagedWithSpaceIdentity 'Microsoft.Web/sites@2019-08-01' = { + kind: 'app' + name: 'systemAndUserManagedWithSpaceIdentity' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } + identity: { + type: 'SystemAssigned, UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } +} + +resource noKindPropertySpecified 'Microsoft.Web/sites@2019-08-01' = { + name: 'noKindPropertySpecified' + location: location + properties: { + siteConfig: { + detailedErrorLoggingEnabled: false + httpLoggingEnabled: false + requestTracingEnabled: false + } + } +} diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/AppServiceWebApps.json b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/AppServiceWebApps.json new file mode 100644 index 00000000..ce3fc8a4 --- /dev/null +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/AppServiceWebApps.json @@ -0,0 +1,134 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources." + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2018-11-30", + "name": "managedIdentity", + "location": "[parameters('location')]" + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "missingIdentity", + "kind": "app", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + } + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "systemManagedIdentity", + "kind": "app", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "SystemAssigned" + } + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "userManagedIdentity", + "kind": "app", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity'))]": {} + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity')]" + ] + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "systemAndUserManagedIdentity", + "kind": "app", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "SystemAssigned,UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity'))]": {} + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity')]" + ] + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "systemAndUserManagedWithSpaceIdentity", + "kind": "app", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + }, + "identity": { + "type": "SystemAssigned, UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity'))]": {} + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'managedIdentity')]" + ] + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "2019-08-01", + "name": "noKindPropertySpecified", + "location": "[parameters('location')]", + "properties": { + "siteConfig": { + "detailedErrorLoggingEnabled": false, + "httpLoggingEnabled": false, + "requestTracingEnabled": false + } + } + } + ] +} \ No newline at end of file diff --git a/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/TA-000019.json b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/TA-000019.json new file mode 100644 index 00000000..ad59fbd4 --- /dev/null +++ b/src/Analyzer.Core.BuiltInRuleTests/Tests/TA-000019/TA-000019.json @@ -0,0 +1,19 @@ +[ + { + "Template": "AppServiceWebApps.json", + "ReportedFailures": [ + { + "LineNumber": 20, + "Description": "Web app is missing an identity declaration." + }, + { + "LineNumber": 88, + "Description": "Multiple identity types should be separated by a comma, followed by a space." + }, + { + "LineNumber": 120, + "Description": "App resources missing the kind property should be treated as a web app, and any missing identities should be flagged." + } + ] + } +] \ No newline at end of file diff --git a/src/Analyzer.Core/Rules/BuiltInRules.json b/src/Analyzer.Core/Rules/BuiltInRules.json index fd364bbd..0af883dd 100644 --- a/src/Analyzer.Core/Rules/BuiltInRules.json +++ b/src/Analyzer.Core/Rules/BuiltInRules.json @@ -223,7 +223,8 @@ "path": "identity.type", "in": [ "UserAssigned", - "SystemAssigned" + "SystemAssigned", + "SystemAssigned, UserAssigned" ] } ] @@ -392,7 +393,11 @@ "allOf": [ { "path": "identity.type", - "regex": "^(UserAssigned|SystemAssigned|SystemAssigned, *UserAssigned)$" + "in": [ + "UserAssigned", + "SystemAssigned", + "SystemAssigned, UserAssigned" + ] } ] } @@ -610,7 +615,8 @@ "path": "identity.type", "in": [ "UserAssigned", - "SystemAssigned" + "SystemAssigned", + "SystemAssigned, UserAssigned" ] } ] From ebbd3296343ca363883779b679c5d608f9d1f5f6 Mon Sep 17 00:00:00 2001 From: Billy Richardson Date: Wed, 28 Aug 2024 10:00:00 -0800 Subject: [PATCH 5/5] Update docs for additional rules with multiple identity info --- docs/built-in-rules.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/built-in-rules.md b/docs/built-in-rules.md index bf60475f..79f724c9 100644 --- a/docs/built-in-rules.md +++ b/docs/built-in-rules.md @@ -47,7 +47,7 @@ Cross-Origin Resource Sharing (CORS) should not allow all domains to access your ### TA-000007: Managed identity should be used in your API app For enhanced authentication security, use a managed identity. On Azure, managed identities eliminate the need for developers to have to manage credentials by providing an identity for the Azure resource in Azure AD and using it to obtain Azure Active Directory (Azure AD) tokens. -**Recommendation**: To [use Managed Identity](https://docs.microsoft.com/azure/app-service/overview-managed-identity?tabs=dotnet), in the [Microsoft.Web/sites resource managed identity property](https://docs.microsoft.com/azure/templates/microsoft.web/sites?tabs=json#ManagedServiceIdentity), add (or update) the *type* property, setting its value to `"SystemAssigned"` or `"UserAssigned"` and providing any necessary identifiers for the identity if required. +**Recommendation**: To [use Managed Identity](https://docs.microsoft.com/azure/app-service/overview-managed-identity?tabs=dotnet), in the [Microsoft.Web/sites resource managed identity property](https://docs.microsoft.com/azure/templates/microsoft.web/sites?tabs=json#ManagedServiceIdentity), add (or update) the *type* property, setting its value to `"SystemAssigned"`, `"UserAssigned"`, or `"SystemAssigned, UserAssigned"` and providing any necessary identifiers for the identity if required. #### Severity: 2 ### TA-000008: Remote debugging should be turned off for function apps @@ -120,7 +120,7 @@ Cross-Origin Resource Sharing (CORS) should not allow all domains to access your ### TA-000019: Managed identity should be used in your web app For enhanced authentication security, use a managed identity. On Azure, managed identities eliminate the need for developers to have to manage credentials by providing an identity for the Azure resource in Azure AD and using it to obtain Azure Active Directory (Azure AD) tokens. -**Recommendation**: To [use Managed Identity](https://docs.microsoft.com/azure/app-service/overview-managed-identity?tabs=dotnet), in the [Microsoft.Web/sites resource managed identity property](https://docs.microsoft.com/azure/templates/microsoft.web/sites?tabs=json#ManagedServiceIdentity), add (or update) the *type* property, setting its value to `"SystemAssigned"` or `"UserAssigned"` and providing any necessary identifiers for the identity if required. +**Recommendation**: To [use Managed Identity](https://docs.microsoft.com/azure/app-service/overview-managed-identity?tabs=dotnet), in the [Microsoft.Web/sites resource managed identity property](https://docs.microsoft.com/azure/templates/microsoft.web/sites?tabs=json#ManagedServiceIdentity), add (or update) the *type* property, setting its value to `"SystemAssigned"`, `"UserAssigned"`, or `"SystemAssigned, UserAssigned"` and providing any necessary identifiers for the identity if required. #### Severity: 2 ### TA-000020: Audit usage of custom RBAC roles