From 92f64ea1f21f8c3082d2bbdd60943c9f09201e7b Mon Sep 17 00:00:00 2001 From: Alex Anders <alex@andersconnection.com> Date: Wed, 1 Jan 2025 22:14:03 -0700 Subject: [PATCH] Deployment fixes and updates. --- .../azureDeploy.json | 643 ++++++++++++------ .../main.bicep | 313 +++++---- .../deployLatestFunctionPackage.ps1 | 2 +- .../modules/customDcrTables.bicep | 12 +- .../modules/functionApp.bicep | 59 ++ .../modules/functionAppPE.bicep | 8 +- .../modules/lawCustomTable.bicep | 4 +- .../modules/lawRoleAssignment.bicep | 14 +- .../modules/privateNetwork.bicep | 36 +- .../modules/sentinelWorkbooks.bicep | 4 +- .../readme.md | 2 +- .../releaseNotes.md | 20 +- 12 files changed, 711 insertions(+), 406 deletions(-) create mode 100644 DataConnectors/M365Defender-VulnerabilityManagement/modules/functionApp.bicep diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/azureDeploy.json b/DataConnectors/M365Defender-VulnerabilityManagement/azureDeploy.json index cf415470099..d40db729221 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/azureDeploy.json +++ b/DataConnectors/M365Defender-VulnerabilityManagement/azureDeploy.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "10697487873063493625" + "version": "0.32.4.45862", + "templateHash": "2827659141380388100" } }, "parameters": { @@ -123,22 +123,29 @@ } }, "variables": { - "deploymentVersion": "1.1.1", + "deploymentVersion": "1.1.2", "location": "[resourceGroup().location]", "functionAppPackageUri": "[format('{0}/DataConnectors/M365Defender-VulnerabilityManagement/functionPackage.zip', parameters('RepoUri'))]", "deploymentScriptUri": "[format('{0}/DataConnectors/M365Defender-VulnerabilityManagement/deploymentScript.ps1', parameters('RepoUri'))]", - "roleIdOwner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635" + "roleIdOwner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "roleIdStorageBlobDataOwner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "appSettingsFilesKv": [ + { + "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", + "value": "[format('@Microsoft.KeyVault(VaultName={0};SecretName=StorageAccountConnectionString)', parameters('KeyVaultName'))]" + } + ] }, "resources": [ { "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2022-01-31-preview", + "apiVersion": "2023-01-31", "name": "[format('uami-{0}', parameters('FunctionAppName'))]", "location": "[variables('location')]" }, { "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "2021-08-01", + "apiVersion": "2023-05-01", "name": "[parameters('StorageAccountName')]", "location": "[variables('location')]", "kind": "StorageV2", @@ -152,23 +159,16 @@ "networkAcls": { "defaultAction": "[if(equals(parameters('EnablePrivateNetworking'), true()), 'Deny', 'Allow')]", "bypass": "AzureServices" - } + }, + "allowSharedKeyAccess": "[if(equals(parameters('EnableElasticPremiumPlan'), true()), true(), false())]" }, "dependsOn": [ "[resourceId('Microsoft.Resources/deployments', 'createCustomTables')]" ] }, - { - "type": "Microsoft.Storage/storageAccounts/fileServices/shares", - "apiVersion": "2022-09-01", - "name": "[format('{0}/default/{1}', parameters('StorageAccountName'), toLower(parameters('FunctionAppName')))]", - "dependsOn": [ - "[resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName'))]" - ] - }, { "type": "Microsoft.KeyVault/vaults", - "apiVersion": "2022-07-01", + "apiVersion": "2023-07-01", "name": "[parameters('KeyVaultName')]", "location": "[variables('location')]", "properties": { @@ -179,7 +179,7 @@ "tenantId": "[subscription().tenantId]", "accessPolicies": [ { - "objectId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2022-01-31-preview').principalId]", + "objectId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').principalId]", "permissions": { "secrets": [ "get", @@ -202,11 +202,12 @@ ] }, { + "condition": "[equals(parameters('EnableElasticPremiumPlan'), true())]", "type": "Microsoft.KeyVault/vaults/secrets", - "apiVersion": "2022-07-01", + "apiVersion": "2023-07-01", "name": "[format('{0}/{1}', parameters('KeyVaultName'), 'StorageAccountConnectionString')]", "properties": { - "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};EndpointSuffix={1};AccountKey={2}', parameters('StorageAccountName'), environment().suffixes.storage, listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName')), '2021-08-01').keys[0].value)]" + "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};EndpointSuffix={1};AccountKey={2}', parameters('StorageAccountName'), environment().suffixes.storage, listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName')), '2023-05-01').keys[0].value)]" }, "dependsOn": [ "[resourceId('Microsoft.KeyVault/vaults', parameters('KeyVaultName'))]", @@ -215,7 +216,7 @@ }, { "type": "Microsoft.Web/serverfarms", - "apiVersion": "2021-03-01", + "apiVersion": "2024-04-01", "name": "[parameters('FunctionAppName')]", "location": "[variables('location')]", "sku": { @@ -224,116 +225,16 @@ } }, { - "type": "Microsoft.Web/sites", - "apiVersion": "2022-03-01", - "name": "[parameters('FunctionAppName')]", - "location": "[variables('location')]", - "identity": { - "type": "UserAssigned", - "userAssignedIdentities": { - "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))))]": {} - } - }, - "kind": "functionapp", + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', parameters('StorageAccountName'))]", + "name": "[guid(resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName')), variables('roleIdStorageBlobDataOwner'), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))))]", "properties": { - "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('FunctionAppName'))]", - "keyVaultReferenceIdentity": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName')))]", - "httpsOnly": true, - "clientCertEnabled": true, - "clientCertMode": "OptionalInteractiveUser", - "virtualNetworkSubnetId": "[if(equals(parameters('EnablePrivateNetworking'), true()), reference(resourceId('Microsoft.Resources/deployments', 'privateNetwork'), '2022-09-01').outputs.functionAppSubnetId.value, null())]", - "vnetContentShareEnabled": "[if(equals(parameters('EnablePrivateNetworking'), true()), true(), false())]", - "vnetRouteAllEnabled": "[if(equals(parameters('EnablePrivateNetworking'), true()), true(), false())]", - "siteConfig": { - "appSettings": [ - { - "name": "AzureWebJobsStorage", - "value": "[format('@Microsoft.KeyVault(VaultName={0};SecretName=StorageAccountConnectionString)', parameters('KeyVaultName'))]" - }, - { - "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", - "value": "[format('@Microsoft.KeyVault(VaultName={0};SecretName=StorageAccountConnectionString)', parameters('KeyVaultName'))]" - }, - { - "name": "AzureWebJobsSecretStorageType", - "value": "keyvault" - }, - { - "name": "AzureWebJobsSecretStorageKeyVaultUri", - "value": "[format('https://{0}{1}/', parameters('KeyVaultName'), environment().suffixes.keyvaultDns)]" - }, - { - "name": "AzureWebJobsSecretStorageKeyVaultClientId", - "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2022-01-31-preview').clientId]" - }, - { - "name": "WEBSITE_CONTENTSHARE", - "value": "[toLower(parameters('FunctionAppName'))]" - }, - { - "name": "WEBSITE_SKIP_CONTENTSHARE_VALIDATION", - "value": "1" - }, - { - "name": "FUNCTIONS_EXTENSION_VERSION", - "value": "~4" - }, - { - "name": "APPINSIGHTS_INSTRUMENTATIONKEY", - "value": "[if(equals(parameters('DeployApplicationInsights'), true()), reference(resourceId('Microsoft.Insights/components', format('appInsights-{0}', parameters('FunctionAppName'))), '2020-02-02').InstrumentationKey, '')]" - }, - { - "name": "FUNCTIONS_WORKER_RUNTIME", - "value": "powershell" - }, - { - "name": "WEBSITE_RUN_FROM_PACKAGE", - "value": "1" - }, - { - "name": "WEBSITE_CONTENTOVERVNET", - "value": "[if(equals(parameters('EnablePrivateNetworking'), true()), '1', '0')]" - }, - { - "name": "LawResourceId", - "value": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[2], split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[8])]" - }, - { - "name": "DcrImmutableId", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'createCustomTables'), '2022-09-01').outputs.DcrImmutableId.value]" - }, - { - "name": "DceUri", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'createCustomTables'), '2022-09-01').outputs.DceUri.value]" - }, - { - "name": "UamiClientId", - "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2022-01-31-preview').clientId]" - }, - { - "name": "FullImport", - "value": "0" - }, - { - "name": "DeploymentVersion", - "value": "[variables('deploymentVersion')]" - } - ], - "powerShellVersion": "7.2", - "minTlsVersion": "1.2", - "ftpsState": "Disabled", - "http20Enabled": true, - "alwaysOn": true, - "publicNetworkAccess": "Enabled" - } + "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').principalId]", + "roleDefinitionId": "[variables('roleIdStorageBlobDataOwner')]", + "principalType": "ServicePrincipal" }, "dependsOn": [ - "[resourceId('Microsoft.Insights/components', format('appInsights-{0}', parameters('FunctionAppName')))]", - "[resourceId('Microsoft.Resources/deployments', 'createCustomTables')]", - "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', split(format('{0}/default/{1}', parameters('StorageAccountName'), toLower(parameters('FunctionAppName'))), '/')[0], split(format('{0}/default/{1}', parameters('StorageAccountName'), toLower(parameters('FunctionAppName'))), '/')[1], split(format('{0}/default/{1}', parameters('StorageAccountName'), toLower(parameters('FunctionAppName'))), '/')[2])]", - "[resourceId('Microsoft.Web/serverfarms', parameters('FunctionAppName'))]", - "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('KeyVaultName'), 'StorageAccountConnectionString')]", - "[resourceId('Microsoft.Resources/deployments', 'privateNetwork')]", "[resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName'))]", "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName')))]" ] @@ -351,26 +252,10 @@ "WorkspaceResourceId": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[2], split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[8])]" } }, - { - "condition": "[equals(parameters('DeployFunctionCode'), true())]", - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.Web/sites/{0}', parameters('FunctionAppName'))]", - "name": "[guid(subscription().id, resourceGroup().id, resourceId('Microsoft.Web/sites', parameters('FunctionAppName')))]", - "properties": { - "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2022-01-31-preview').principalId]", - "roleDefinitionId": "[variables('roleIdOwner')]", - "principalType": "ServicePrincipal" - }, - "dependsOn": [ - "[resourceId('Microsoft.Web/sites', parameters('FunctionAppName'))]", - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName')))]" - ] - }, { "condition": "[equals(parameters('DeployFunctionCode'), true())]", "type": "Microsoft.Resources/deploymentScripts", - "apiVersion": "2020-10-01", + "apiVersion": "2023-08-01", "name": "deployCode", "location": "[variables('location')]", "kind": "AzurePowerShell", @@ -381,15 +266,16 @@ } }, "properties": { - "azPowerShellVersion": "11.0", + "azPowerShellVersion": "12.3", "retentionInterval": "PT1H", "timeout": "PT10M", "cleanupPreference": "Always", "primaryScriptUri": "[variables('deploymentScriptUri')]", - "arguments": "[if(equals(parameters('EnablePrivateNetworking'), true()), format('-PackageUri {0} -SubscriptionId {1} -ResourceGroupName {2} -FunctionAppName {3} -FAScope {4} -UAMIPrincipalId {5} -VnetScope {6} -RestrictedIPs \"None\"', variables('functionAppPackageUri'), split(subscription().id, '/')[2], resourceGroup().name, reference(resourceId('Microsoft.Resources/deployments', 'functionAppPe'), '2022-09-01').outputs.functionAppName.value, resourceId('Microsoft.Web/sites', parameters('FunctionAppName')), reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2022-01-31-preview').principalId, reference(resourceId('Microsoft.Resources/deployments', 'privateNetwork'), '2022-09-01').outputs.vnetId.value), format('-PackageUri {0} -SubscriptionId {1} -ResourceGroupName {2} -FunctionAppName {3} -FAScope {4} -UAMIPrincipalId {5}', variables('functionAppPackageUri'), split(subscription().id, '/')[2], resourceGroup().name, parameters('FunctionAppName'), resourceId('Microsoft.Web/sites', parameters('FunctionAppName')), reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2022-01-31-preview').principalId))]" + "arguments": "[if(equals(parameters('EnablePrivateNetworking'), true()), format('-PackageUri {0} -SubscriptionId {1} -ResourceGroupName {2} -FunctionAppName {3} -FAScope {4} -UAMIPrincipalId {5} -VnetScope {6} -RestrictedIPs \"None\"', variables('functionAppPackageUri'), split(subscription().id, '/')[2], resourceGroup().name, reference(resourceId('Microsoft.Resources/deployments', 'functionAppPe'), '2022-09-01').outputs.functionAppName.value, reference(resourceId('Microsoft.Resources/deployments', 'functionAppDeploy'), '2022-09-01').outputs.functionAppId.value, reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').principalId, reference(resourceId('Microsoft.Resources/deployments', 'privateNetwork'), '2022-09-01').outputs.vnetId.value), format('-PackageUri {0} -SubscriptionId {1} -ResourceGroupName {2} -FunctionAppName {3} -FAScope {4} -UAMIPrincipalId {5}', variables('functionAppPackageUri'), split(subscription().id, '/')[2], resourceGroup().name, reference(resourceId('Microsoft.Resources/deployments', 'functionAppDeploy'), '2022-09-01').outputs.functionAppName.value, reference(resourceId('Microsoft.Resources/deployments', 'functionAppDeploy'), '2022-09-01').outputs.functionAppId.value, reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').principalId))]" }, "dependsOn": [ - "[resourceId('Microsoft.Web/sites', parameters('FunctionAppName'))]", + "[resourceId('Microsoft.Resources/deployments', 'functionAppDeploy')]", + "[resourceId('Microsoft.Resources/deployments', 'functionAppDeployFilesKv')]", "[resourceId('Microsoft.Resources/deployments', 'functionAppPe')]", "[resourceId('Microsoft.Resources/deployments', 'privateNetwork')]", "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName')))]" @@ -418,7 +304,7 @@ "value": "[parameters('DataCollectionRuleName')]" }, "ServicePrincipalId": { - "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2022-01-31-preview').principalId]" + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').principalId]" } }, "template": { @@ -427,8 +313,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "9983229875268352637" + "version": "0.32.4.45862", + "templateHash": "13349298757103545815" } }, "parameters": { @@ -466,10 +352,13 @@ } } }, + "variables": { + "roleDefId": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb" + }, "resources": [ { "type": "Microsoft.Insights/dataCollectionEndpoints", - "apiVersion": "2021-09-01-preview", + "apiVersion": "2023-03-11", "name": "[parameters('DataCollectionEndpointName')]", "location": "[parameters('LogAnalyticsWorkspaceLocation')]", "properties": {} @@ -477,11 +366,11 @@ { "condition": "[not(equals(parameters('ServicePrincipalId'), ''))]", "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2020-10-01-preview", + "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Insights/dataCollectionRules/{0}', parameters('DataCollectionRuleName'))]", - "name": "[guid(resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName')), '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb')]", + "name": "[guid(resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName')), variables('roleDefId'), parameters('ServicePrincipalId'))]", "properties": { - "roleDefinitionId": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "roleDefinitionId": "[variables('roleDefId')]", "principalId": "[parameters('ServicePrincipalId')]", "principalType": "ServicePrincipal" }, @@ -491,7 +380,7 @@ }, { "type": "Microsoft.Insights/dataCollectionRules", - "apiVersion": "2022-06-01", + "apiVersion": "2023-03-11", "name": "[parameters('DataCollectionRuleName')]", "location": "[parameters('LogAnalyticsWorkspaceLocation')]", "properties": { @@ -1203,8 +1092,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "2787795770695009804" + "version": "0.32.4.45862", + "templateHash": "3154619017496488402" } }, "parameters": { @@ -1228,7 +1117,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/workspaces/tables", - "apiVersion": "2022-10-01", + "apiVersion": "2023-09-01", "name": "[format('{0}/{1}', parameters('LawName'), parameters('TableName'))]", "properties": { "schema": { @@ -1355,8 +1244,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "2787795770695009804" + "version": "0.32.4.45862", + "templateHash": "3154619017496488402" } }, "parameters": { @@ -1380,7 +1269,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/workspaces/tables", - "apiVersion": "2022-10-01", + "apiVersion": "2023-09-01", "name": "[format('{0}/{1}', parameters('LawName'), parameters('TableName'))]", "properties": { "schema": { @@ -1487,8 +1376,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "2787795770695009804" + "version": "0.32.4.45862", + "templateHash": "3154619017496488402" } }, "parameters": { @@ -1512,7 +1401,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/workspaces/tables", - "apiVersion": "2022-10-01", + "apiVersion": "2023-09-01", "name": "[format('{0}/{1}', parameters('LawName'), parameters('TableName'))]", "properties": { "schema": { @@ -1659,8 +1548,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "2787795770695009804" + "version": "0.32.4.45862", + "templateHash": "3154619017496488402" } }, "parameters": { @@ -1684,7 +1573,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/workspaces/tables", - "apiVersion": "2022-10-01", + "apiVersion": "2023-09-01", "name": "[format('{0}/{1}', parameters('LawName'), parameters('TableName'))]", "properties": { "schema": { @@ -1807,8 +1696,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "2787795770695009804" + "version": "0.32.4.45862", + "templateHash": "3154619017496488402" } }, "parameters": { @@ -1832,7 +1721,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/workspaces/tables", - "apiVersion": "2022-10-01", + "apiVersion": "2023-09-01", "name": "[format('{0}/{1}', parameters('LawName'), parameters('TableName'))]", "properties": { "schema": { @@ -2003,8 +1892,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "2787795770695009804" + "version": "0.32.4.45862", + "templateHash": "3154619017496488402" } }, "parameters": { @@ -2028,7 +1917,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/workspaces/tables", - "apiVersion": "2022-10-01", + "apiVersion": "2023-09-01", "name": "[format('{0}/{1}', parameters('LawName'), parameters('TableName'))]", "properties": { "schema": { @@ -2047,11 +1936,11 @@ "outputs": { "DcrImmutableId": { "type": "string", - "value": "[reference(resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName')), '2022-06-01').immutableId]" + "value": "[reference(resourceId('Microsoft.Insights/dataCollectionRules', parameters('DataCollectionRuleName')), '2023-03-11').immutableId]" }, "DceUri": { "type": "string", - "value": "[reference(resourceId('Microsoft.Insights/dataCollectionEndpoints', parameters('DataCollectionEndpointName')), '2021-09-01-preview').logsIngestion.endpoint]" + "value": "[reference(resourceId('Microsoft.Insights/dataCollectionEndpoints', parameters('DataCollectionEndpointName')), '2023-03-11').logsIngestion.endpoint]" }, "DcrName": { "type": "string", @@ -2064,6 +1953,322 @@ "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName')))]" ] }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "functionAppDeploy", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "AppSettings": { + "value": "[concat(createArray(createObject('name', 'AzureWebJobsStorage__blobServiceUri', 'value', format('https://{0}.blob.{1}', parameters('StorageAccountName'), environment().suffixes.storage)), createObject('name', 'AzureWebJobsStorage__clientId', 'value', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').clientId), createObject('name', 'AzureWebJobsSecretStorageType', 'value', 'keyvault'), createObject('name', 'AzureWebJobsSecretStorageKeyVaultUri', 'value', format('https://{0}{1}/', parameters('KeyVaultName'), environment().suffixes.keyvaultDns)), createObject('name', 'AzureWebJobsSecretStorageKeyVaultClientId', 'value', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').clientId), createObject('name', 'FUNCTIONS_EXTENSION_VERSION', 'value', '~4'), createObject('name', 'APPINSIGHTS_INSTRUMENTATIONKEY', 'value', if(equals(parameters('DeployApplicationInsights'), true()), reference(resourceId('Microsoft.Insights/components', format('appInsights-{0}', parameters('FunctionAppName'))), '2020-02-02').InstrumentationKey, '')), createObject('name', 'FUNCTIONS_WORKER_RUNTIME', 'value', 'powershell'), createObject('name', 'WEBSITE_RUN_FROM_PACKAGE', 'value', '1'), createObject('name', 'LawResourceId', 'value', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[2], split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[8])), createObject('name', 'DcrImmutableId', 'value', reference(resourceId('Microsoft.Resources/deployments', 'createCustomTables'), '2022-09-01').outputs.DcrImmutableId.value), createObject('name', 'DceUri', 'value', reference(resourceId('Microsoft.Resources/deployments', 'createCustomTables'), '2022-09-01').outputs.DceUri.value), createObject('name', 'UamiClientId', 'value', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').clientId), createObject('name', 'FullImport', 'value', '0'), createObject('name', 'DeploymentVersion', 'value', variables('deploymentVersion'))), if(equals(parameters('EnableElasticPremiumPlan'), true()), createArray(createObject('name', 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING', 'value', format('DefaultEndpointsProtocol=https;AccountName={0};EndpointSuffix={1};AccountKey={2}', parameters('StorageAccountName'), environment().suffixes.storage, listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName')), '2023-05-01').keys[0].value))), createArray()))]" + }, + "EnablePrivateNetworking": { + "value": "[parameters('EnablePrivateNetworking')]" + }, + "FunctionAppName": { + "value": "[parameters('FunctionAppName')]" + }, + "FunctionAppSubnetId": "[if(equals(parameters('EnablePrivateNetworking'), true()), createObject('value', reference(resourceId('Microsoft.Resources/deployments', 'privateNetwork'), '2022-09-01').outputs.functionAppSubnetId.value), createObject('value', ''))]", + "HostingPlanId": { + "value": "[resourceId('Microsoft.Web/serverfarms', parameters('FunctionAppName'))]" + }, + "Location": { + "value": "[variables('location')]" + }, + "UserAssignedMiId": { + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName')))]" + }, + "DeployFunctionCode": { + "value": "[parameters('DeployFunctionCode')]" + }, + "UserAssignedMiPrincipalId": { + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').principalId]" + }, + "RoleIdOwner": { + "value": "[variables('roleIdOwner')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "11348593861695904653" + } + }, + "parameters": { + "FunctionAppName": { + "type": "string" + }, + "Location": { + "type": "string" + }, + "UserAssignedMiId": { + "type": "string" + }, + "UserAssignedMiPrincipalId": { + "type": "string" + }, + "HostingPlanId": { + "type": "string" + }, + "EnablePrivateNetworking": { + "type": "bool" + }, + "FunctionAppSubnetId": { + "type": "string", + "defaultValue": "" + }, + "AppSettings": { + "type": "array" + }, + "DeployFunctionCode": { + "type": "bool" + }, + "RoleIdOwner": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.Web/sites", + "apiVersion": "2024-04-01", + "name": "[parameters('FunctionAppName')]", + "location": "[parameters('Location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', parameters('UserAssignedMiId'))]": {} + } + }, + "kind": "functionapp", + "properties": { + "serverFarmId": "[parameters('HostingPlanId')]", + "keyVaultReferenceIdentity": "[parameters('UserAssignedMiId')]", + "httpsOnly": true, + "clientCertEnabled": true, + "clientCertMode": "OptionalInteractiveUser", + "virtualNetworkSubnetId": "[if(equals(parameters('EnablePrivateNetworking'), true()), parameters('FunctionAppSubnetId'), null())]", + "vnetContentShareEnabled": "[if(equals(parameters('EnablePrivateNetworking'), true()), true(), false())]", + "vnetRouteAllEnabled": "[if(equals(parameters('EnablePrivateNetworking'), true()), true(), false())]", + "siteConfig": { + "appSettings": "[parameters('AppSettings')]", + "powerShellVersion": "7.4", + "minTlsVersion": "1.2", + "ftpsState": "Disabled", + "http20Enabled": true, + "alwaysOn": true, + "publicNetworkAccess": "Enabled", + "cors": { + "allowedOrigins": [ + "https://portal.azure.com" + ] + } + } + } + }, + { + "condition": "[equals(parameters('DeployFunctionCode'), true())]", + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Web/sites/{0}', parameters('FunctionAppName'))]", + "name": "[guid(subscription().id, resourceGroup().id, parameters('UserAssignedMiId'))]", + "properties": { + "principalId": "[parameters('UserAssignedMiPrincipalId')]", + "roleDefinitionId": "[parameters('RoleIdOwner')]", + "principalType": "ServicePrincipal" + }, + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', parameters('FunctionAppName'))]" + ] + } + ], + "outputs": { + "functionAppName": { + "type": "string", + "value": "[parameters('FunctionAppName')]" + }, + "functionAppId": { + "type": "string", + "value": "[resourceId('Microsoft.Web/sites', parameters('FunctionAppName'))]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Insights/components', format('appInsights-{0}', parameters('FunctionAppName')))]", + "[resourceId('Microsoft.Resources/deployments', 'createCustomTables')]", + "[resourceId('Microsoft.Web/serverfarms', parameters('FunctionAppName'))]", + "[resourceId('Microsoft.Resources/deployments', 'privateNetwork')]", + "[resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName'))]", + "[extensionResourceId(resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName')), 'Microsoft.Authorization/roleAssignments', guid(resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName')), variables('roleIdStorageBlobDataOwner'), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName')))))]", + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName')))]" + ] + }, + { + "condition": "[equals(parameters('EnableElasticPremiumPlan'), true())]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "functionAppDeployFilesKv", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "AppSettings": { + "value": "[concat(createArray(createObject('name', 'AzureWebJobsStorage__blobServiceUri', 'value', format('https://{0}.blob.{1}', parameters('StorageAccountName'), environment().suffixes.storage)), createObject('name', 'AzureWebJobsStorage__clientId', 'value', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').clientId), createObject('name', 'AzureWebJobsSecretStorageType', 'value', 'keyvault'), createObject('name', 'AzureWebJobsSecretStorageKeyVaultUri', 'value', format('https://{0}{1}/', parameters('KeyVaultName'), environment().suffixes.keyvaultDns)), createObject('name', 'AzureWebJobsSecretStorageKeyVaultClientId', 'value', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').clientId), createObject('name', 'FUNCTIONS_EXTENSION_VERSION', 'value', '~4'), createObject('name', 'APPINSIGHTS_INSTRUMENTATIONKEY', 'value', if(equals(parameters('DeployApplicationInsights'), true()), reference(resourceId('Microsoft.Insights/components', format('appInsights-{0}', parameters('FunctionAppName'))), '2020-02-02').InstrumentationKey, '')), createObject('name', 'FUNCTIONS_WORKER_RUNTIME', 'value', 'powershell'), createObject('name', 'WEBSITE_RUN_FROM_PACKAGE', 'value', '1'), createObject('name', 'LawResourceId', 'value', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[2], split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[8])), createObject('name', 'DcrImmutableId', 'value', reference(resourceId('Microsoft.Resources/deployments', 'createCustomTables'), '2022-09-01').outputs.DcrImmutableId.value), createObject('name', 'DceUri', 'value', reference(resourceId('Microsoft.Resources/deployments', 'createCustomTables'), '2022-09-01').outputs.DceUri.value), createObject('name', 'UamiClientId', 'value', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').clientId), createObject('name', 'FullImport', 'value', '0'), createObject('name', 'DeploymentVersion', 'value', variables('deploymentVersion'))), if(equals(parameters('EnableElasticPremiumPlan'), true()), variables('appSettingsFilesKv'), createArray()))]" + }, + "EnablePrivateNetworking": { + "value": "[parameters('EnablePrivateNetworking')]" + }, + "FunctionAppName": { + "value": "[parameters('FunctionAppName')]" + }, + "FunctionAppSubnetId": "[if(equals(parameters('EnablePrivateNetworking'), true()), createObject('value', reference(resourceId('Microsoft.Resources/deployments', 'privateNetwork'), '2022-09-01').outputs.functionAppSubnetId.value), createObject('value', ''))]", + "HostingPlanId": { + "value": "[resourceId('Microsoft.Web/serverfarms', parameters('FunctionAppName'))]" + }, + "Location": { + "value": "[variables('location')]" + }, + "UserAssignedMiId": { + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName')))]" + }, + "DeployFunctionCode": { + "value": "[parameters('DeployFunctionCode')]" + }, + "UserAssignedMiPrincipalId": { + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').principalId]" + }, + "RoleIdOwner": { + "value": "[variables('roleIdOwner')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "11348593861695904653" + } + }, + "parameters": { + "FunctionAppName": { + "type": "string" + }, + "Location": { + "type": "string" + }, + "UserAssignedMiId": { + "type": "string" + }, + "UserAssignedMiPrincipalId": { + "type": "string" + }, + "HostingPlanId": { + "type": "string" + }, + "EnablePrivateNetworking": { + "type": "bool" + }, + "FunctionAppSubnetId": { + "type": "string", + "defaultValue": "" + }, + "AppSettings": { + "type": "array" + }, + "DeployFunctionCode": { + "type": "bool" + }, + "RoleIdOwner": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.Web/sites", + "apiVersion": "2024-04-01", + "name": "[parameters('FunctionAppName')]", + "location": "[parameters('Location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', parameters('UserAssignedMiId'))]": {} + } + }, + "kind": "functionapp", + "properties": { + "serverFarmId": "[parameters('HostingPlanId')]", + "keyVaultReferenceIdentity": "[parameters('UserAssignedMiId')]", + "httpsOnly": true, + "clientCertEnabled": true, + "clientCertMode": "OptionalInteractiveUser", + "virtualNetworkSubnetId": "[if(equals(parameters('EnablePrivateNetworking'), true()), parameters('FunctionAppSubnetId'), null())]", + "vnetContentShareEnabled": "[if(equals(parameters('EnablePrivateNetworking'), true()), true(), false())]", + "vnetRouteAllEnabled": "[if(equals(parameters('EnablePrivateNetworking'), true()), true(), false())]", + "siteConfig": { + "appSettings": "[parameters('AppSettings')]", + "powerShellVersion": "7.4", + "minTlsVersion": "1.2", + "ftpsState": "Disabled", + "http20Enabled": true, + "alwaysOn": true, + "publicNetworkAccess": "Enabled", + "cors": { + "allowedOrigins": [ + "https://portal.azure.com" + ] + } + } + } + }, + { + "condition": "[equals(parameters('DeployFunctionCode'), true())]", + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Web/sites/{0}', parameters('FunctionAppName'))]", + "name": "[guid(subscription().id, resourceGroup().id, parameters('UserAssignedMiId'))]", + "properties": { + "principalId": "[parameters('UserAssignedMiPrincipalId')]", + "roleDefinitionId": "[parameters('RoleIdOwner')]", + "principalType": "ServicePrincipal" + }, + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', parameters('FunctionAppName'))]" + ] + } + ], + "outputs": { + "functionAppName": { + "type": "string", + "value": "[parameters('FunctionAppName')]" + }, + "functionAppId": { + "type": "string", + "value": "[resourceId('Microsoft.Web/sites', parameters('FunctionAppName'))]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Insights/components', format('appInsights-{0}', parameters('FunctionAppName')))]", + "[resourceId('Microsoft.Resources/deployments', 'createCustomTables')]", + "[resourceId('Microsoft.Resources/deployments', 'functionAppDeploy')]", + "[resourceId('Microsoft.Web/serverfarms', parameters('FunctionAppName'))]", + "[resourceId('Microsoft.Resources/deployments', 'privateNetwork')]", + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName')))]" + ] + }, { "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -2077,7 +2282,7 @@ "mode": "Incremental", "parameters": { "PrincipalId": { - "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2022-01-31-preview').principalId]" + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').principalId]" }, "LawName": { "value": "[split(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[2], split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', split(parameters('LogAnalyticsWorkspaceResourceID'), '/')[8]), '/')[8]]" @@ -2092,8 +2297,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "17635329862361088530" + "version": "0.32.4.45862", + "templateHash": "11232319375925855437" } }, "parameters": { @@ -2267,8 +2472,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "16920742540395135656" + "version": "0.32.4.45862", + "templateHash": "15017717243574337441" } }, "parameters": { @@ -2305,7 +2510,7 @@ "resources": [ { "type": "Microsoft.Insights/workbooks", - "apiVersion": "2021-03-08", + "apiVersion": "2023-06-01", "name": "[parameters('WorkbookIdVulnerabilityManagement')]", "location": "[parameters('Location')]", "kind": "shared", @@ -2322,7 +2527,7 @@ }, { "type": "Microsoft.Insights/workbooks", - "apiVersion": "2021-03-08", + "apiVersion": "2023-06-01", "name": "[parameters('WorkbookIdCVEDetails')]", "location": "[parameters('Location')]", "kind": "shared", @@ -2339,7 +2544,7 @@ }, "dependsOn": [ "[resourceId('Microsoft.Resources/deployments', 'createCustomTables')]", - "[resourceId('Microsoft.Web/sites', parameters('FunctionAppName'))]" + "[resourceId('Microsoft.Resources/deployments', 'functionAppDeploy')]" ] }, { @@ -2381,7 +2586,7 @@ "value": "[parameters('PrivateEndpointsSubnet')]" }, "PrincipalId": { - "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2022-01-31-preview').principalId]" + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').principalId]" }, "DeployCode": { "value": "[parameters('DeployFunctionCode')]" @@ -2393,8 +2598,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "10952522562962288358" + "version": "0.32.4.45862", + "templateHash": "9714520919609121205" } }, "parameters": { @@ -2438,7 +2643,7 @@ "resources": [ { "type": "Microsoft.Network/virtualNetworks", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('vnet-{0}', parameters('FunctionAppName'))]", "location": "[parameters('location')]", "properties": { @@ -2482,12 +2687,12 @@ }, { "type": "Microsoft.Network/privateEndpoints", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('pe-{0}', parameters('KeyVaultName'))]", "location": "[parameters('location')]", "properties": { "subnet": { - "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2022-07-01').subnets[0].id]" + "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2024-05-01').subnets[0].id]" }, "privateLinkServiceConnections": [ { @@ -2507,12 +2712,12 @@ }, { "type": "Microsoft.Network/privateEndpoints", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('pe-blob-{0}', parameters('StorageAccountName'))]", "location": "[parameters('location')]", "properties": { "subnet": { - "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2022-07-01').subnets[0].id]" + "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2024-05-01').subnets[0].id]" }, "privateLinkServiceConnections": [ { @@ -2532,12 +2737,12 @@ }, { "type": "Microsoft.Network/privateEndpoints", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('pe-queue-{0}', parameters('StorageAccountName'))]", "location": "[parameters('location')]", "properties": { "subnet": { - "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2022-07-01').subnets[0].id]" + "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2024-05-01').subnets[0].id]" }, "privateLinkServiceConnections": [ { @@ -2557,12 +2762,12 @@ }, { "type": "Microsoft.Network/privateEndpoints", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('pe-file-{0}', parameters('StorageAccountName'))]", "location": "[parameters('location')]", "properties": { "subnet": { - "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2022-07-01').subnets[0].id]" + "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2024-05-01').subnets[0].id]" }, "privateLinkServiceConnections": [ { @@ -2582,7 +2787,7 @@ }, { "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2020-06-01", + "apiVersion": "2024-06-01", "name": "[format('privatelink.blob.{0}', environment().suffixes.storage)]", "location": "global", "dependsOn": [ @@ -2591,7 +2796,7 @@ }, { "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2020-06-01", + "apiVersion": "2024-06-01", "name": "[format('privatelink.file.{0}', environment().suffixes.storage)]", "location": "global", "dependsOn": [ @@ -2600,7 +2805,7 @@ }, { "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2020-06-01", + "apiVersion": "2024-06-01", "name": "[format('privatelink.queue.{0}', environment().suffixes.storage)]", "location": "global", "dependsOn": [ @@ -2609,7 +2814,7 @@ }, { "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2020-06-01", + "apiVersion": "2024-06-01", "name": "privatelink.vaultcore.azure.net", "location": "global", "dependsOn": [ @@ -2618,7 +2823,7 @@ }, { "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2020-06-01", + "apiVersion": "2024-06-01", "name": "[format('{0}/{1}', format('privatelink.blob.{0}', environment().suffixes.storage), format('{0}-link', format('privatelink.blob.{0}', environment().suffixes.storage)))]", "location": "global", "properties": { @@ -2634,7 +2839,7 @@ }, { "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2020-06-01", + "apiVersion": "2024-06-01", "name": "[format('{0}/{1}', format('privatelink.file.{0}', environment().suffixes.storage), format('{0}-link', format('privatelink.file.{0}', environment().suffixes.storage)))]", "location": "global", "properties": { @@ -2650,7 +2855,7 @@ }, { "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2020-06-01", + "apiVersion": "2024-06-01", "name": "[format('{0}/{1}', format('privatelink.queue.{0}', environment().suffixes.storage), format('{0}-link', format('privatelink.queue.{0}', environment().suffixes.storage)))]", "location": "global", "properties": { @@ -2666,7 +2871,7 @@ }, { "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2020-06-01", + "apiVersion": "2024-06-01", "name": "[format('{0}/{1}', 'privatelink.vaultcore.azure.net', format('{0}-link', 'privatelink.vaultcore.azure.net'))]", "location": "global", "properties": { @@ -2682,7 +2887,7 @@ }, { "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('{0}/{1}', format('pe-blob-{0}', parameters('StorageAccountName')), 'dnsGroup')]", "properties": { "privateDnsZoneConfigs": [ @@ -2701,7 +2906,7 @@ }, { "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('{0}/{1}', format('pe-file-{0}', parameters('StorageAccountName')), 'dnsGroup')]", "properties": { "privateDnsZoneConfigs": [ @@ -2720,7 +2925,7 @@ }, { "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('{0}/{1}', format('pe-queue-{0}', parameters('StorageAccountName')), 'dnsGroup')]", "properties": { "privateDnsZoneConfigs": [ @@ -2739,7 +2944,7 @@ }, { "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('{0}/{1}', format('pe-{0}', parameters('KeyVaultName')), 'dnsGroup')]", "properties": { "privateDnsZoneConfigs": [ @@ -2773,7 +2978,7 @@ }, { "type": "Microsoft.Network/networkSecurityGroups", - "apiVersion": "2023-05-01", + "apiVersion": "2024-05-01", "name": "nsg-sentinelmdvm", "location": "[parameters('location')]" } @@ -2781,11 +2986,11 @@ "outputs": { "functionAppSubnetId": { "type": "string", - "value": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2022-07-01').subnets[1].id]" + "value": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2024-05-01').subnets[1].id]" }, "privateEndpointSubnetId": { "type": "string", - "value": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2022-07-01').subnets[0].id]" + "value": "[reference(resourceId('Microsoft.Network/virtualNetworks', format('vnet-{0}', parameters('FunctionAppName'))), '2024-05-01').subnets[0].id]" }, "vnetId": { "type": "string", @@ -2815,7 +3020,7 @@ "value": "[variables('location')]" }, "FunctionAppId": { - "value": "[resourceId('Microsoft.Web/sites', parameters('FunctionAppName'))]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'functionAppDeploy'), '2022-09-01').outputs.functionAppId.value]" }, "FunctionAppName": { "value": "[parameters('FunctionAppName')]" @@ -2829,8 +3034,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "5223866557968199727" + "version": "0.32.4.45862", + "templateHash": "1284817518269594698" } }, "parameters": { @@ -2853,7 +3058,7 @@ "resources": [ { "type": "Microsoft.Network/privateEndpoints", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('pe-{0}', parameters('FunctionAppName'))]", "location": "[parameters('Location')]", "properties": { @@ -2875,13 +3080,13 @@ }, { "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2020-06-01", + "apiVersion": "2024-06-01", "name": "privatelink.azurewebsites.net", "location": "global" }, { "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2020-06-01", + "apiVersion": "2024-06-01", "name": "[format('{0}/{1}', 'privatelink.azurewebsites.net', format('{0}-link', 'privatelink.azurewebsites.net'))]", "location": "global", "properties": { @@ -2896,7 +3101,7 @@ }, { "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", - "apiVersion": "2022-07-01", + "apiVersion": "2024-05-01", "name": "[format('{0}/{1}', format('pe-{0}', parameters('FunctionAppName')), 'dnsGroup')]", "properties": { "privateDnsZoneConfigs": [ @@ -2923,7 +3128,7 @@ } }, "dependsOn": [ - "[resourceId('Microsoft.Web/sites', parameters('FunctionAppName'))]", + "[resourceId('Microsoft.Resources/deployments', 'functionAppDeploy')]", "[resourceId('Microsoft.Resources/deployments', 'privateNetwork')]" ] } @@ -2931,7 +3136,7 @@ "outputs": { "UserAssignedManagedIdentityPrincipalId": { "type": "string", - "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2022-01-31-preview').principalId]" + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('uami-{0}', parameters('FunctionAppName'))), '2023-01-31').principalId]" }, "UserAssignedManagedIdentityPrincipalName": { "type": "string", diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/main.bicep b/DataConnectors/M365Defender-VulnerabilityManagement/main.bicep index 2d977084778..08ba09b8288 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/main.bicep +++ b/DataConnectors/M365Defender-VulnerabilityManagement/main.bicep @@ -1,4 +1,4 @@ -var deploymentVersion = '1.1.1' +var deploymentVersion = '1.1.2' @description('A globally unique name for the Function App to be created which will run the code to ingest MDVM data into Sentinel.') param FunctionAppName string = 'fa-mdvm-${uniqueString(resourceGroup().id)}' @description('Select to enable Application Insights for the Function App. This will allow you to monitor the status of the Function App for any errors. The Log Analytics Workspace specified in the "Log Analytics Resource Id" Parameter will be used to store the Application Insights data.') @@ -36,13 +36,14 @@ var location = resourceGroup().location var functionAppPackageUri = '${RepoUri}/DataConnectors/M365Defender-VulnerabilityManagement/functionPackage.zip' var deploymentScriptUri = '${RepoUri}/DataConnectors/M365Defender-VulnerabilityManagement/deploymentScript.ps1' var roleIdOwner = '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' +var roleIdStorageBlobDataOwner = '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' resource law 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = { name: split(LogAnalyticsWorkspaceResourceID, '/')[8] scope: resourceGroup(split(LogAnalyticsWorkspaceResourceID, '/')[2], split(LogAnalyticsWorkspaceResourceID, '/')[4]) } -resource userAssignedMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2022-01-31-preview' = { +resource userAssignedMi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { name: 'uami-${FunctionAppName}' location: location } @@ -54,14 +55,14 @@ module createCustomTables 'modules/customDcrTables.bicep' = { LogAnalyticsWorkspaceResourceId: law.id DataCollectionEndpointName: DataCollectionEndpointName DataCollectionRuleName: DataCollectionRuleName - ServicePrincipalId: userAssignedMi.properties.principalId - } + ServicePrincipalId: userAssignedMi.properties.principalId + } } -resource storageAccount 'Microsoft.Storage/storageAccounts@2021-08-01' = { +resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = { name: StorageAccountName dependsOn: [ - createCustomTables + createCustomTables ] location: location kind: 'StorageV2' @@ -71,26 +72,30 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2021-08-01' = { properties: { allowBlobPublicAccess: false publicNetworkAccess: EnablePrivateNetworking == true ? 'Disabled' : 'Enabled' - minimumTlsVersion: 'TLS1_2' + minimumTlsVersion: 'TLS1_2' networkAcls: { defaultAction: EnablePrivateNetworking == true ? 'Deny' : 'Allow' bypass: 'AzureServices' - } + } + allowSharedKeyAccess: EnableElasticPremiumPlan == true ? true : false } } -resource fileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2022-09-01' = { +/* +resource fileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2022-09-01' = if(EnableElasticPremiumPlan == true) { name: '${storageAccount.name}/default/${toLower(FunctionAppName)}' } +*/ + -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { +resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = { name: KeyVaultName location: location properties: { sku: { family: 'A' name: 'premium' - } + } tenantId: subscription().tenantId accessPolicies: [ { @@ -108,13 +113,14 @@ resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { ] publicNetworkAccess: EnablePrivateNetworking == true ? 'Disabled' : 'Enabled' networkAcls: { - defaultAction: EnablePrivateNetworking == true ? 'Deny' :'Allow' - bypass: EnablePrivateNetworking == true ? 'None' : 'AzureServices' + defaultAction: EnablePrivateNetworking == true ? 'Deny' : 'Allow' + bypass: EnablePrivateNetworking == true ? 'None' : 'AzureServices' } } } -resource keyVaultSecretStorageAccountConnectionString 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = { + +resource keyVaultSecretStorageAccountConnectionString 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = if (EnableElasticPremiumPlan == true) { parent: keyVault name: 'StorageAccountConnectionString' properties: { @@ -122,7 +128,7 @@ resource keyVaultSecretStorageAccountConnectionString 'Microsoft.KeyVault/vaults } } -resource hostingPlan 'Microsoft.Web/serverfarms@2021-03-01' = { +resource hostingPlan 'Microsoft.Web/serverfarms@2024-04-01' = { name: FunctionAppName location: location sku: { @@ -131,112 +137,138 @@ resource hostingPlan 'Microsoft.Web/serverfarms@2021-03-01' = { } } -resource functionApp 'Microsoft.Web/sites@2022-03-01' = { - name: FunctionAppName - location: location - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${userAssignedMi.id}': {} - } +var appSettingsDefault = [ + { + name: 'AzureWebJobsStorage__blobServiceUri' + value: 'https://${StorageAccountName}.blob.${environment().suffixes.storage}' + } + { + name: 'AzureWebJobsStorage__clientId' + value: userAssignedMi.properties.clientId + } + { + name: 'AzureWebJobsSecretStorageType' + value: 'keyvault' + } + { + name: 'AzureWebJobsSecretStorageKeyVaultUri' + value: 'https://${KeyVaultName}${environment().suffixes.keyvaultDns}/' + } + { + name: 'AzureWebJobsSecretStorageKeyVaultClientId' + value: userAssignedMi.properties.clientId } - kind: 'functionapp' + { + name: 'FUNCTIONS_EXTENSION_VERSION' + value: '~4' + } + { + name: 'APPINSIGHTS_INSTRUMENTATIONKEY' + value: DeployApplicationInsights == true ? applicationInsights.properties.InstrumentationKey : '' + } + { + name: 'FUNCTIONS_WORKER_RUNTIME' + value: 'powershell' + } + { + name: 'WEBSITE_RUN_FROM_PACKAGE' + value: '1' + } + { + name: 'LawResourceId' + value: law.id + } + { + name: 'DcrImmutableId' + value: createCustomTables.outputs.DcrImmutableId + } + { + name: 'DceUri' + value: createCustomTables.outputs.DceUri + } + { + name: 'UamiClientId' + value: userAssignedMi.properties.clientId + } + { + name: 'FullImport' + value: '0' + } + { + name: 'DeploymentVersion' + value: deploymentVersion + } +] + +var appSettingsFiles = [ + { + name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' + value: 'DefaultEndpointsProtocol=https;AccountName=${StorageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}' + } + /* + { + name: 'WEBSITE_CONTENTSHARE' + value: toLower(FunctionAppName) + } + { + name: 'WEBSITE_SKIP_CONTENTSHARE_VALIDATION' + value: '1' + } + */ +] + +var appSettingsFilesKv = [ + { + name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' + value: '@Microsoft.KeyVault(VaultName=${KeyVaultName};SecretName=StorageAccountConnectionString)' + } +] + +resource storageRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(storageAccount.id, roleIdStorageBlobDataOwner, userAssignedMi.id) + scope: storageAccount properties: { - serverFarmId: hostingPlan.id - keyVaultReferenceIdentity: userAssignedMi.id - httpsOnly: true - clientCertEnabled: true - clientCertMode: 'OptionalInteractiveUser' - virtualNetworkSubnetId: EnablePrivateNetworking == true ? privateNetwork.outputs.functionAppSubnetId : (null) - vnetContentShareEnabled: EnablePrivateNetworking == true ? true : false - vnetRouteAllEnabled: EnablePrivateNetworking == true ? true : false - siteConfig: { - appSettings: [ - { - name: 'AzureWebJobsStorage' - value: '@Microsoft.KeyVault(VaultName=${KeyVaultName};SecretName=StorageAccountConnectionString)' - } - { - name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' - value: '@Microsoft.KeyVault(VaultName=${KeyVaultName};SecretName=StorageAccountConnectionString)' - } - { - name: 'AzureWebJobsSecretStorageType' - value: 'keyvault' - } - { - name: 'AzureWebJobsSecretStorageKeyVaultUri' - value: 'https://${KeyVaultName}${environment().suffixes.keyvaultDns}/' - } - { - name: 'AzureWebJobsSecretStorageKeyVaultClientId' - value: userAssignedMi.properties.clientId - } - { - name: 'WEBSITE_CONTENTSHARE' - value: toLower(FunctionAppName) - } - { - name: 'WEBSITE_SKIP_CONTENTSHARE_VALIDATION' - value: '1' - } - { - name: 'FUNCTIONS_EXTENSION_VERSION' - value: '~4' - } - { - name: 'APPINSIGHTS_INSTRUMENTATIONKEY' - value: DeployApplicationInsights == true ? applicationInsights.properties.InstrumentationKey : '' - } - { - name: 'FUNCTIONS_WORKER_RUNTIME' - value: 'powershell' - } - { - name: 'WEBSITE_RUN_FROM_PACKAGE' - value: '1' - } - { - name: 'WEBSITE_CONTENTOVERVNET' - value: EnablePrivateNetworking == true ? '1' : '0' - } - { - name: 'LawResourceId' - value: law.id - } - { - name: 'DcrImmutableId' - value: createCustomTables.outputs.DcrImmutableId - } - { - name: 'DceUri' - value: createCustomTables.outputs.DceUri - } - { - name: 'UamiClientId' - value: userAssignedMi.properties.clientId - } - { - name: 'FullImport' - value: '0' - } - { - name: 'DeploymentVersion' - value: deploymentVersion - } - ] - powerShellVersion: '7.2' - minTlsVersion: '1.2' - ftpsState: 'Disabled' - http20Enabled: true - alwaysOn: true - publicNetworkAccess: 'Enabled' - } + principalId: userAssignedMi.properties.principalId + roleDefinitionId: roleIdStorageBlobDataOwner + principalType: 'ServicePrincipal' + } +} + +module functionAppDeploy 'modules/functionApp.bicep' = { + name: 'functionAppDeploy' + params: { + AppSettings: concat(appSettingsDefault, EnableElasticPremiumPlan == true ? appSettingsFiles : []) + EnablePrivateNetworking: EnablePrivateNetworking + FunctionAppName: FunctionAppName + FunctionAppSubnetId: EnablePrivateNetworking == true ? privateNetwork.outputs.functionAppSubnetId : '' + HostingPlanId: hostingPlan.id + Location: location + UserAssignedMiId: userAssignedMi.id + DeployFunctionCode: DeployFunctionCode + UserAssignedMiPrincipalId: userAssignedMi.properties.principalId + RoleIdOwner: roleIdOwner + } + dependsOn: [ + storageRoleAssignment + ] +} + +module functionAppDeployFilesKv 'modules/functionApp.bicep' = if(EnableElasticPremiumPlan == true) { + name: 'functionAppDeployFilesKv' + params: { + AppSettings: concat(appSettingsDefault, EnableElasticPremiumPlan == true ? appSettingsFilesKv : []) + EnablePrivateNetworking: EnablePrivateNetworking + FunctionAppName: FunctionAppName + FunctionAppSubnetId: EnablePrivateNetworking == true ? privateNetwork.outputs.functionAppSubnetId : '' + HostingPlanId: hostingPlan.id + Location: location + UserAssignedMiId: userAssignedMi.id + DeployFunctionCode: DeployFunctionCode + UserAssignedMiPrincipalId: userAssignedMi.properties.principalId + RoleIdOwner: roleIdOwner } dependsOn: [ - keyVaultSecretStorageAccountConnectionString - storageAccount - fileShare + functionAppDeploy ] } @@ -264,36 +296,26 @@ module roleAssignmentLaw 'modules/lawRoleAssignment.bicep' = { } } -resource roleAssignmentFa 'Microsoft.Authorization/roleAssignments@2022-04-01' = if(DeployFunctionCode == true) { - name: guid(subscription().id, resourceGroup().id, functionApp.id) - scope: functionApp - properties: { - principalId: userAssignedMi.properties.principalId - roleDefinitionId: roleIdOwner - principalType: 'ServicePrincipal' - } -} - -module sentinelWorkbooks 'modules/sentinelWorkbooks.bicep' = if(DeployWorkbooks == true) { +module sentinelWorkbooks 'modules/sentinelWorkbooks.bicep' = if (DeployWorkbooks == true) { name: 'sentinelWorkbooks' - scope: resourceGroup(split(law.id, '/')[2], split(law.id, '/')[4]) + scope: resourceGroup(split(law.id, '/')[2], split(law.id, '/')[4]) dependsOn: [ createCustomTables - functionApp + functionAppDeploy ] params: { WorkbookSourceId: law.id Location: law.location - } + } } -module privateNetwork 'modules/privateNetwork.bicep' = if(EnablePrivateNetworking == true) { +module privateNetwork 'modules/privateNetwork.bicep' = if (EnablePrivateNetworking == true) { name: 'privateNetwork' params: { FunctionAppName: FunctionAppName - KeyVaultId: keyVault.id - location: location - StorageAccountId: storageAccount.id + KeyVaultId: keyVault.id + location: location + StorageAccountId: storageAccount.id StorageAccountName: StorageAccountName KeyVaultName: KeyVaultName PrivateNetworkAddressSpace: PrivateNetworkAddressSpace @@ -304,18 +326,18 @@ module privateNetwork 'modules/privateNetwork.bicep' = if(EnablePrivateNetworkin } } -module functionAppPe 'modules/functionAppPE.bicep' = if(EnablePrivateNetworking == true) { +module functionAppPe 'modules/functionAppPE.bicep' = if (EnablePrivateNetworking == true) { name: 'functionAppPe' params: { Location: location - FunctionAppId: functionApp.id - FunctionAppName: FunctionAppName + FunctionAppId: functionAppDeploy.outputs.functionAppId + FunctionAppName: FunctionAppName PrivateEndpointSubnetId: EnablePrivateNetworking == true ? privateNetwork.outputs.privateEndpointSubnetId : (null) VnetId: EnablePrivateNetworking == true ? privateNetwork.outputs.vnetId : (null) - } + } } -resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = if(DeployFunctionCode == true) { +resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = if (DeployFunctionCode == true) { name: 'deployCode' location: location kind: 'AzurePowerShell' @@ -326,13 +348,18 @@ resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = i } } properties: { - azPowerShellVersion: '11.0' + azPowerShellVersion: '12.3' retentionInterval: 'PT1H' timeout: 'PT10M' - cleanupPreference: 'Always' + cleanupPreference: 'Always' primaryScriptUri: deploymentScriptUri - arguments: EnablePrivateNetworking == true ? '-PackageUri ${functionAppPackageUri} -SubscriptionId ${split(subscription().id, '/')[2]} -ResourceGroupName ${resourceGroup().name} -FunctionAppName ${functionAppPe.outputs.functionAppName} -FAScope ${functionApp.id} -UAMIPrincipalId ${userAssignedMi.properties.principalId} -VnetScope ${privateNetwork.outputs.vnetId} -RestrictedIPs "None"' : '-PackageUri ${functionAppPackageUri} -SubscriptionId ${split(subscription().id, '/')[2]} -ResourceGroupName ${resourceGroup().name} -FunctionAppName ${functionApp.name} -FAScope ${functionApp.id} -UAMIPrincipalId ${userAssignedMi.properties.principalId}' + arguments: EnablePrivateNetworking == true + ? '-PackageUri ${functionAppPackageUri} -SubscriptionId ${split(subscription().id, '/')[2]} -ResourceGroupName ${resourceGroup().name} -FunctionAppName ${functionAppPe.outputs.functionAppName} -FAScope ${functionAppDeploy.outputs.functionAppId} -UAMIPrincipalId ${userAssignedMi.properties.principalId} -VnetScope ${privateNetwork.outputs.vnetId} -RestrictedIPs "None"' + : '-PackageUri ${functionAppPackageUri} -SubscriptionId ${split(subscription().id, '/')[2]} -ResourceGroupName ${resourceGroup().name} -FunctionAppName ${functionAppDeploy.outputs.functionAppName} -FAScope ${functionAppDeploy.outputs.functionAppId} -UAMIPrincipalId ${userAssignedMi.properties.principalId}' } + dependsOn: EnableElasticPremiumPlan == true ? [ + functionAppDeployFilesKv + ] : [] } output UserAssignedManagedIdentityPrincipalId string = userAssignedMi.properties.principalId diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/maintenance/deployLatestFunctionPackage.ps1 b/DataConnectors/M365Defender-VulnerabilityManagement/maintenance/deployLatestFunctionPackage.ps1 index 79b49b0a610..2714d06ff1a 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/maintenance/deployLatestFunctionPackage.ps1 +++ b/DataConnectors/M365Defender-VulnerabilityManagement/maintenance/deployLatestFunctionPackage.ps1 @@ -1,5 +1,5 @@ param( - [string] $PackageUri = 'https://raw.githubusercontent.com/anders-alex/Azure-Sentinel/DataConnector-M365Defender-VulnerabilityManagement/DataConnectors/M365Defender-VulnerabilityManagement/functionPackage.zip', + [string] $PackageUri = 'https://raw.githubusercontent.com/Azure/Azure-Sentinel/refs/heads/master/DataConnectors/M365Defender-VulnerabilityManagement/functionPackage.zip', [string] $ResourceGroupName, [string] $FunctionAppName ) diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/modules/customDcrTables.bicep b/DataConnectors/M365Defender-VulnerabilityManagement/modules/customDcrTables.bicep index 5f182cb683d..b77fe0cde49 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/modules/customDcrTables.bicep +++ b/DataConnectors/M365Defender-VulnerabilityManagement/modules/customDcrTables.bicep @@ -9,23 +9,25 @@ param LogAnalyticsWorkspaceLocation string @description('Optional: Managed Identity or Service Principal ID to be assigned the Metrics Publisher role on the data collection rule.') param ServicePrincipalId string = '' -resource dce 'Microsoft.Insights/dataCollectionEndpoints@2021-09-01-preview' = { +var roleDefId = '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + +resource dce 'Microsoft.Insights/dataCollectionEndpoints@2023-03-11' = { name: DataCollectionEndpointName location: LogAnalyticsWorkspaceLocation properties: {} } -resource roleAssignmentDcr 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = if (ServicePrincipalId != '') { - name: guid(dcr.id, '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb') +resource roleAssignmentDcr 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (ServicePrincipalId != '') { + name: guid(dcr.id, roleDefId, ServicePrincipalId) scope: dcr properties: { - roleDefinitionId: '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + roleDefinitionId: roleDefId principalId: ServicePrincipalId principalType: 'ServicePrincipal' } } -resource dcr 'Microsoft.Insights/dataCollectionRules@2022-06-01' = { +resource dcr 'Microsoft.Insights/dataCollectionRules@2023-03-11' = { dependsOn: [ tableMDVMCveKb tableMDVMRecommendations diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/modules/functionApp.bicep b/DataConnectors/M365Defender-VulnerabilityManagement/modules/functionApp.bicep new file mode 100644 index 00000000000..c6b4b05dffd --- /dev/null +++ b/DataConnectors/M365Defender-VulnerabilityManagement/modules/functionApp.bicep @@ -0,0 +1,59 @@ +param FunctionAppName string +param Location string +param UserAssignedMiId string +param UserAssignedMiPrincipalId string +param HostingPlanId string +param EnablePrivateNetworking bool +param FunctionAppSubnetId string = '' +param AppSettings array +param DeployFunctionCode bool +param RoleIdOwner string + +resource functionApp 'Microsoft.Web/sites@2024-04-01' = { + name: FunctionAppName + location: Location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${UserAssignedMiId}': {} + } + } + kind: 'functionapp' + properties: { + serverFarmId: HostingPlanId + keyVaultReferenceIdentity: UserAssignedMiId + httpsOnly: true + clientCertEnabled: true + clientCertMode: 'OptionalInteractiveUser' + virtualNetworkSubnetId: EnablePrivateNetworking == true ? FunctionAppSubnetId : (null) + vnetContentShareEnabled: EnablePrivateNetworking == true ? true : false + vnetRouteAllEnabled: EnablePrivateNetworking == true ? true : false + siteConfig: { + appSettings: AppSettings + powerShellVersion: '7.4' + minTlsVersion: '1.2' + ftpsState: 'Disabled' + http20Enabled: true + alwaysOn: true + publicNetworkAccess: 'Enabled' + cors: { + allowedOrigins: [ + 'https://portal.azure.com' + ] + } + } + } +} + +resource roleAssignmentFa 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (DeployFunctionCode == true) { + name: guid(subscription().id, resourceGroup().id, UserAssignedMiId) + scope: functionApp + properties: { + principalId: UserAssignedMiPrincipalId + roleDefinitionId: RoleIdOwner + principalType: 'ServicePrincipal' + } +} + +output functionAppName string = functionApp.name +output functionAppId string = functionApp.id diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/modules/functionAppPE.bicep b/DataConnectors/M365Defender-VulnerabilityManagement/modules/functionAppPE.bicep index 54eda159ea7..dcd9bbd6b67 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/modules/functionAppPE.bicep +++ b/DataConnectors/M365Defender-VulnerabilityManagement/modules/functionAppPE.bicep @@ -4,7 +4,7 @@ param PrivateEndpointSubnetId string param Location string param VnetId string -resource peFunctionApp 'Microsoft.Network/privateEndpoints@2022-07-01' = { +resource peFunctionApp 'Microsoft.Network/privateEndpoints@2024-05-01' = { name: 'pe-${FunctionAppName}' location: Location properties: { @@ -25,12 +25,12 @@ resource peFunctionApp 'Microsoft.Network/privateEndpoints@2022-07-01' = { } } -resource privateDnsZoneFunctionApp 'Microsoft.Network/privateDnsZones@2020-06-01' = { +resource privateDnsZoneFunctionApp 'Microsoft.Network/privateDnsZones@2024-06-01' = { name: 'privatelink.azurewebsites.net' location: 'global' } -resource privateDnsZoneLinkFunctionApp 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { +resource privateDnsZoneLinkFunctionApp 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = { name: '${privateDnsZoneFunctionApp.name}-link' parent: privateDnsZoneFunctionApp location: 'global' @@ -42,7 +42,7 @@ resource privateDnsZoneLinkFunctionApp 'Microsoft.Network/privateDnsZones/virtua } } -resource peDnsGroupFunctionApp 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2022-07-01' = { +resource peDnsGroupFunctionApp 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2024-05-01' = { name: 'dnsGroup' parent: peFunctionApp properties: { diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/modules/lawCustomTable.bicep b/DataConnectors/M365Defender-VulnerabilityManagement/modules/lawCustomTable.bicep index 90cdf63a720..0d46e187887 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/modules/lawCustomTable.bicep +++ b/DataConnectors/M365Defender-VulnerabilityManagement/modules/lawCustomTable.bicep @@ -4,11 +4,11 @@ param Plan string param Columns array param Retention int = -1 -resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = { +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' existing = { name: LawName } -resource table 'Microsoft.OperationalInsights/workspaces/tables@2022-10-01' = { +resource table 'Microsoft.OperationalInsights/workspaces/tables@2023-09-01' = { parent: logAnalyticsWorkspace name: TableName properties: { diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/modules/lawRoleAssignment.bicep b/DataConnectors/M365Defender-VulnerabilityManagement/modules/lawRoleAssignment.bicep index a5def4747b5..8f92fa76f71 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/modules/lawRoleAssignment.bicep +++ b/DataConnectors/M365Defender-VulnerabilityManagement/modules/lawRoleAssignment.bicep @@ -18,36 +18,36 @@ var roleDescription = 'Provides access to query Sentinel Watchlists and alert ru var roleDefName = guid(resourceGroup().id, string(Actions), string(NotActions)) -resource law 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = { +resource law 'Microsoft.OperationalInsights/workspaces@2023-09-01' existing = { name: LawName } - resource tableMDVMCveKb 'Microsoft.OperationalInsights/workspaces/tables@2022-10-01' existing = { + resource tableMDVMCveKb 'Microsoft.OperationalInsights/workspaces/tables@2023-09-01' existing = { parent: law name: 'MDVMCVEKB_CL' } - resource tableMDVMRecommendations 'Microsoft.OperationalInsights/workspaces/tables@2022-10-01' existing = { + resource tableMDVMRecommendations 'Microsoft.OperationalInsights/workspaces/tables@2023-09-01' existing = { parent: law name: 'MDVMRecommendations_CL' } - resource tableMDVMVulnerabilitiesByDevice 'Microsoft.OperationalInsights/workspaces/tables@2022-10-01' existing = { + resource tableMDVMVulnerabilitiesByDevice 'Microsoft.OperationalInsights/workspaces/tables@2023-09-01' existing = { parent: law name: 'MDVMVulnerabilitiesByDevice_CL' } - resource tableMDVMNistCveKb 'Microsoft.OperationalInsights/workspaces/tables@2022-10-01' existing = { + resource tableMDVMNistCveKb 'Microsoft.OperationalInsights/workspaces/tables@2023-09-01' existing = { parent: law name: 'MDVMNistCveKb_CL' } - resource tableMDVMNISTConfigurations 'Microsoft.OperationalInsights/workspaces/tables@2022-10-01' existing = { + resource tableMDVMNISTConfigurations 'Microsoft.OperationalInsights/workspaces/tables@2023-09-01' existing = { parent: law name: 'MDVMNISTConfigurations_CL' } - resource tableMDVMSecureConfigurationsByDevice'Microsoft.OperationalInsights/workspaces/tables@2022-10-01' existing = { + resource tableMDVMSecureConfigurationsByDevice'Microsoft.OperationalInsights/workspaces/tables@2023-09-01' existing = { parent: law name: 'MDVMSecureConfigurationsByDevice_CL' } diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/modules/privateNetwork.bicep b/DataConnectors/M365Defender-VulnerabilityManagement/modules/privateNetwork.bicep index 13dab504391..3af2a4ad7e5 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/modules/privateNetwork.bicep +++ b/DataConnectors/M365Defender-VulnerabilityManagement/modules/privateNetwork.bicep @@ -10,7 +10,7 @@ param location string param PrincipalId string param DeployCode bool -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-07-01' = { +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-05-01' = { name: 'vnet-${FunctionAppName}' location: location properties: { @@ -50,7 +50,7 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-07-01' = { } } -resource peKeyVault 'Microsoft.Network/privateEndpoints@2022-07-01' = { +resource peKeyVault 'Microsoft.Network/privateEndpoints@2024-05-01' = { name: 'pe-${KeyVaultName}' location: location properties: { @@ -71,7 +71,7 @@ resource peKeyVault 'Microsoft.Network/privateEndpoints@2022-07-01' = { } } -resource peBlob 'Microsoft.Network/privateEndpoints@2022-07-01' = { +resource peBlob 'Microsoft.Network/privateEndpoints@2024-05-01' = { name: 'pe-blob-${StorageAccountName}' location: location properties: { @@ -92,7 +92,7 @@ resource peBlob 'Microsoft.Network/privateEndpoints@2022-07-01' = { } } -resource peQueue 'Microsoft.Network/privateEndpoints@2022-07-01' = { +resource peQueue 'Microsoft.Network/privateEndpoints@2024-05-01' = { name: 'pe-queue-${StorageAccountName}' location: location properties: { @@ -113,7 +113,7 @@ resource peQueue 'Microsoft.Network/privateEndpoints@2022-07-01' = { } } -resource peFile 'Microsoft.Network/privateEndpoints@2022-07-01' = { +resource peFile 'Microsoft.Network/privateEndpoints@2024-05-01' = { name: 'pe-file-${StorageAccountName}' location: location properties: { @@ -134,7 +134,7 @@ resource peFile 'Microsoft.Network/privateEndpoints@2022-07-01' = { } } -resource privateDnsZoneBlob 'Microsoft.Network/privateDnsZones@2020-06-01' = { +resource privateDnsZoneBlob 'Microsoft.Network/privateDnsZones@2024-06-01' = { name: 'privatelink.blob.${environment().suffixes.storage}' location: 'global' dependsOn: [ @@ -143,7 +143,7 @@ resource privateDnsZoneBlob 'Microsoft.Network/privateDnsZones@2020-06-01' = { } -resource privateDnsZoneFile 'Microsoft.Network/privateDnsZones@2020-06-01' = { +resource privateDnsZoneFile 'Microsoft.Network/privateDnsZones@2024-06-01' = { name: 'privatelink.file.${environment().suffixes.storage}' location: 'global' dependsOn: [ @@ -151,7 +151,7 @@ resource privateDnsZoneFile 'Microsoft.Network/privateDnsZones@2020-06-01' = { ] } -resource privateDnsZoneQueue 'Microsoft.Network/privateDnsZones@2020-06-01' = { +resource privateDnsZoneQueue 'Microsoft.Network/privateDnsZones@2024-06-01' = { name: 'privatelink.queue.${environment().suffixes.storage}' location: 'global' dependsOn: [ @@ -159,7 +159,7 @@ resource privateDnsZoneQueue 'Microsoft.Network/privateDnsZones@2020-06-01' = { ] } -resource privateDnsZoneKeyVault 'Microsoft.Network/privateDnsZones@2020-06-01' = { +resource privateDnsZoneKeyVault 'Microsoft.Network/privateDnsZones@2024-06-01' = { name: 'privatelink.vaultcore.azure.net' location: 'global' dependsOn: [ @@ -167,7 +167,7 @@ resource privateDnsZoneKeyVault 'Microsoft.Network/privateDnsZones@2020-06-01' = ] } -resource privateDnsZoneLinkBlob 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { +resource privateDnsZoneLinkBlob 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = { name: '${privateDnsZoneBlob.name}-link' parent: privateDnsZoneBlob location: 'global' @@ -179,7 +179,7 @@ resource privateDnsZoneLinkBlob 'Microsoft.Network/privateDnsZones/virtualNetwor } } -resource privateDnsZoneLinkFile 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { +resource privateDnsZoneLinkFile 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = { name: '${privateDnsZoneFile.name}-link' parent: privateDnsZoneFile location: 'global' @@ -191,7 +191,7 @@ resource privateDnsZoneLinkFile 'Microsoft.Network/privateDnsZones/virtualNetwor } } -resource privateDnsZoneLinkQueue 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { +resource privateDnsZoneLinkQueue 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = { name: '${privateDnsZoneQueue.name}-link' parent: privateDnsZoneQueue location: 'global' @@ -203,7 +203,7 @@ resource privateDnsZoneLinkQueue 'Microsoft.Network/privateDnsZones/virtualNetwo } } -resource privateDnsZoneLinkKeyVault 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { +resource privateDnsZoneLinkKeyVault 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = { name: '${privateDnsZoneKeyVault.name}-link' parent: privateDnsZoneKeyVault location: 'global' @@ -215,7 +215,7 @@ resource privateDnsZoneLinkKeyVault 'Microsoft.Network/privateDnsZones/virtualNe } } -resource peDnsGroupBlob 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2022-07-01' = { +resource peDnsGroupBlob 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2024-05-01' = { name: 'dnsGroup' parent: peBlob properties: { @@ -230,7 +230,7 @@ resource peDnsGroupBlob 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups } } -resource peDnsGroupFile 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2022-07-01' = { +resource peDnsGroupFile 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2024-05-01' = { name: 'dnsGroup' parent: peFile properties: { @@ -245,7 +245,7 @@ resource peDnsGroupFile 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups } } -resource peDnsGroupQueue 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2022-07-01' = { +resource peDnsGroupQueue 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2024-05-01' = { name: 'dnsGroup' parent: peQueue properties: { @@ -260,7 +260,7 @@ resource peDnsGroupQueue 'Microsoft.Network/privateEndpoints/privateDnsZoneGroup } } -resource peDnsGroupKeyVault 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2022-07-01' = { +resource peDnsGroupKeyVault 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2024-05-01' = { name: 'dnsGroup' parent: peKeyVault properties: { @@ -287,7 +287,7 @@ resource roleAssignmentVnet 'Microsoft.Authorization/roleAssignments@2022-04-01' } } -resource nsg 'Microsoft.Network/networkSecurityGroups@2023-05-01' = { +resource nsg 'Microsoft.Network/networkSecurityGroups@2024-05-01' = { name: 'nsg-sentinelmdvm' location: location /* diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/modules/sentinelWorkbooks.bicep b/DataConnectors/M365Defender-VulnerabilityManagement/modules/sentinelWorkbooks.bicep index 1012151879b..1471c04a218 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/modules/sentinelWorkbooks.bicep +++ b/DataConnectors/M365Defender-VulnerabilityManagement/modules/sentinelWorkbooks.bicep @@ -11,7 +11,7 @@ param WorkbookIdCVEDetails string = guid(WorkbookSourceId, '79ac946b-2986-4274-a param Location string -resource workbookId_resource 'microsoft.insights/workbooks@2021-03-08' = { +resource workbookId_resource 'Microsoft.Insights/workbooks@2023-06-01' = { name: WorkbookIdVulnerabilityManagement location: Location kind: 'shared' @@ -24,7 +24,7 @@ resource workbookId_resource 'microsoft.insights/workbooks@2021-03-08' = { } } -resource cveDetailsWorkbook 'microsoft.insights/workbooks@2021-03-08' = { +resource cveDetailsWorkbook 'Microsoft.Insights/workbooks@2023-06-01' = { name: WorkbookIdCVEDetails location: Location kind: 'shared' diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/readme.md b/DataConnectors/M365Defender-VulnerabilityManagement/readme.md index 6a10406f8be..c47cb810661 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/readme.md +++ b/DataConnectors/M365Defender-VulnerabilityManagement/readme.md @@ -62,7 +62,7 @@ The Function App is configured to run daily at 12:00 AM UTC. You can either wait 1. Open the newly deployed Function App in the Azure Portal. 2. Select the **GetMDVMData** Function in the Overview section. 3. Select **Code and Test**. -4. Select **Test/Run**. Note: You will have to add https://portal.azure.com as an allowed [CORS](https://learn.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-rest-api) origin via the main Function App menu option (Under the API section). Also, if you deployed using private networking, you will either need to have connectivity to the private endpoint (and add the additional CORS origins as mentioned [here](https://learn.microsoft.com/en-us/azure/azure-functions/functions-networking-options?tabs=azure-cli#testing-considerations)), or temporarily remove [network access restrictions](https://learn.microsoft.com/en-us/azure/app-service/overview-access-restrictions). +4. Select **Test/Run**. Note: If you deployed using private networking, you will either need to have connectivity to the private endpoint or, temporarily remove [network access restrictions](https://learn.microsoft.com/en-us/azure/app-service/overview-access-restrictions). 5. Select **Run**. After a successful run, you should see data populated in the MDVM* custom tables. diff --git a/DataConnectors/M365Defender-VulnerabilityManagement/releaseNotes.md b/DataConnectors/M365Defender-VulnerabilityManagement/releaseNotes.md index d15f00d39ac..0773193cd31 100644 --- a/DataConnectors/M365Defender-VulnerabilityManagement/releaseNotes.md +++ b/DataConnectors/M365Defender-VulnerabilityManagement/releaseNotes.md @@ -1,14 +1,26 @@ # Release Notes +## 1.1.2 (1/1/2025) +### Changes/Fixes +- Deployment + - Fixed issue where previous method to deploy Azure Files Share (required for Consumption and Elastic Premium plans) no longer worked and was causing depoyments to fail. + - Removed key-based authentication between Function App and Storage Account where supported for additional security. + - Updated Function App PowerShell to version 7.4. + - Updated post deployment script to use Az module 12.4. + - Removed hard-coded GUID for Log Analytics role assignment so it doesn't error out in the event of a redeployment. + - Updated resource provider API versions to latest. + ## 1.1.2 (7/9/2024) ### Changes/Fixes -- Updated Azure resource ID enrichment logic to pull this informaton directly from the Defender API vs. trying to do a lookup via ARG based on hostname. -- Updated libraries and PowerShell modules to recent versions. +- Function App Code + - Updated Azure resource ID enrichment logic to pull this informaton directly from the Defender API vs. trying to do a lookup via ARG based on hostname. + - Updated libraries and PowerShell modules to recent versions. ## 1.1.1 (3/13/2024) ### Changes/Fixes -- Fixed bug in calculating full vs. incremental import. -- Added new fullImport column to MDVMCVEKB and MDVMNISTCVEKB tables to support above bug fix. +- Function App Code + - Fixed bug in calculating full vs. incremental import. + - Added new fullImport column to MDVMCVEKB and MDVMNISTCVEKB tables to support above bug fix. ## 1.1.0 (2/19/2024) ### Changes/Fixes