+
+### Parameter Usage: `tags`
+
+Tag names and tag values can be provided as needed. A tag can be left without a value.
+
+Parameter JSON format
+
+```json
+"tags": {
+ "value": {
+ "Environment": "Non-Prod",
+ "Contact": "test.user@testcompany.com",
+ "PurchaseOrder": "1234",
+ "CostCenter": "7890",
+ "ServiceName": "DeploymentValidation",
+ "Role": "DeploymentValidation"
+ }
+}
+```
+
+Bicep format
+
+```bicep
+tags: {
+ Environment: 'Non-Prod'
+ Contact: 'test.user@testcompany.com'
+ PurchaseOrder: '1234'
+ CostCenter: '7890'
+ ServiceName: 'DeploymentValidation'
+ Role: 'DeploymentValidation'
+}
+```
+
+
+ +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `applicationRuleCollections` | array | List of Application Rule Collections. | +| `ipConfAzureFirewallSubnet` | object | The Public IP configuration object for the Azure Firewall Subnet. | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the Azure Firewall. | +| `natRuleCollections` | array | Collection of NAT rule collections used by Azure Firewall. | +| `networkRuleCollections` | array | List of Network Rule Collections. | +| `privateIp` | string | The private IP of the Azure firewall. | +| `resourceGroupName` | string | The resource group the Azure firewall was deployed into. | +| `resourceId` | string | The resource ID of the Azure Firewall. | + +## Considerations + +The `applicationRuleCollections` parameter accepts a JSON Array of AzureFirewallApplicationRule objects. +The `networkRuleCollections` parameter accepts a JSON Array of AzureFirewallNetworkRuleCollection objects. + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other CARML modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `Network/publicIPAddresses` | Local reference | + +## Deployment examples + +The following module usage examples are retrieved from the content of the files hosted in the module's `.test` folder. + >**Note**: The name of each example is based on the name of the file from which it is taken. + + >**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +
+
+via JSON Parameter file
+
+```json
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ // Required parameters
+ "name": {
+ "value": "<
+ +
+
+via JSON Parameter file
+
+```json
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ // Required parameters
+ "name": {
+ "value": "<
+ +
+
+via JSON Parameter file
+
+```json
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ // Required parameters
+ "name": {
+ "value": "<
+ +
+
+via JSON Parameter file
+
+```json
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ // Required parameters
+ "name": {
+ "value": "<
+ +
+
+via JSON Parameter file
+
+```json
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ // Required parameters
+ "name": {
+ "value": "<
+ +
+
+via JSON Parameter file
+
+```json
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ // Required parameters
+ "name": {
+ "value": "<
diff --git a/scenarios/shared/bicep/network/azureFirewalls/main.bicep b/scenarios/shared/bicep/network/azureFirewalls/main.bicep
new file mode 100644
index 00000000..dbbb9fcc
--- /dev/null
+++ b/scenarios/shared/bicep/network/azureFirewalls/main.bicep
@@ -0,0 +1,388 @@
+metadata name = 'Azure Firewalls'
+metadata description = 'This module deploys an Azure Firewall.'
+metadata owner = 'Azure/module-maintainers'
+
+@description('Required. Name of the Azure Firewall.')
+param name string
+
+@description('Optional. Tier of an Azure Firewall.')
+@allowed([
+ 'Basic'
+ 'Standard'
+ 'Premium'
+])
+param azureSkuTier string = 'Standard'
+
+@description('Conditional. Shared services Virtual Network resource ID. The virtual network ID containing AzureFirewallSubnet. If a Public IP is not provided, then the Public IP that is created as part of this module will be applied with the subnet provided in this variable. Required if `virtualHubId` is empty.')
+param vNetId string = ''
+
+@description('Optional. The Public IP resource ID to associate to the AzureFirewallSubnet. If empty, then the Public IP that is created as part of this module will be applied to the AzureFirewallSubnet.')
+param publicIPResourceID string = ''
+
+@description('Optional. This is to add any additional Public IP configurations on top of the Public IP with subnet IP configuration.')
+param additionalPublicIpConfigurations array = []
+
+@description('Optional. Specifies the properties of the Public IP to create and be used by the Firewall, if no existing public IP was provided.')
+param publicIPAddressObject object = {
+ name: '${name}-pip'
+}
+
+@description('Optional. The Management Public IP resource ID to associate to the AzureFirewallManagementSubnet. If empty, then the Management Public IP that is created as part of this module will be applied to the AzureFirewallManagementSubnet.')
+param managementIPResourceID string = ''
+
+@description('Optional. Specifies the properties of the Management Public IP to create and be used by Azure Firewall. If it\'s not provided and managementIPResourceID is empty, a \'-mip\' suffix will be appended to the Firewall\'s name.')
+param managementIPAddressObject object = {}
+
+@description('Optional. Collection of application rule collections used by Azure Firewall.')
+param applicationRuleCollections array = []
+
+@description('Optional. Collection of network rule collections used by Azure Firewall.')
+param networkRuleCollections array = []
+
+@description('Optional. Collection of NAT rule collections used by Azure Firewall.')
+param natRuleCollections array = []
+
+@description('Optional. Resource ID of the Firewall Policy that should be attached.')
+param firewallPolicyId string = ''
+
+@description('Conditional. IP addresses associated with AzureFirewall. Required if `virtualHubId` is supplied.')
+param hubIPAddresses object = {}
+
+@description('Conditional. The virtualHub resource ID to which the firewall belongs. Required if `vNetId` is empty.')
+param virtualHubId string = ''
+
+@allowed([
+ 'Alert'
+ 'Deny'
+ 'Off'
+])
+@description('Optional. The operation mode for Threat Intel.')
+param threatIntelMode string = 'Deny'
+
+@description('Optional. Zone numbers e.g. 1,2,3.')
+param zones array = [
+ '1'
+ '2'
+ '3'
+]
+
+@description('Optional. The diagnostic settings of the service.')
+param diagnosticSettings diagnosticSettingType
+
+@description('Optional. Location for all resources.')
+param location string = resourceGroup().location
+
+@description('Optional. The lock settings of the service.')
+param lock lockType
+
+@description('Optional. Array of role assignments to create.')
+param roleAssignments roleAssignmentType
+
+@description('Optional. Tags of the Azure Firewall resource.')
+param tags object?
+
+@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).')
+param enableDefaultTelemetry bool = true
+
+var azureSkuName = empty(vNetId) ? 'AZFW_Hub' : 'AZFW_VNet'
+var requiresManagementIp = azureSkuTier == 'Basic' ? true : false
+var isCreateDefaultManagementIP = empty(managementIPResourceID) && requiresManagementIp
+
+// ----------------------------------------------------------------------------
+// Prep ipConfigurations object AzureFirewallSubnet for different uses cases:
+// 1. Use existing Public IP
+// 2. Use new Public IP created in this module
+// 3. Do not use a Public IP if publicIPAddressObject is empty
+
+var additionalPublicIpConfigurationsVar = [for ipConfiguration in additionalPublicIpConfigurations: {
+ name: ipConfiguration.name
+ properties: {
+ publicIPAddress: contains(ipConfiguration, 'publicIPAddressResourceId') ? {
+ id: ipConfiguration.publicIPAddressResourceId
+ } : null
+ }
+}]
+var ipConfigurations = concat([
+ {
+ name: !empty(publicIPResourceID) ? last(split(publicIPResourceID, '/')) : publicIPAddress.outputs.name
+ properties: union({
+ subnet: {
+ id: '${vNetId}/subnets/AzureFirewallSubnet' // The subnet name must be AzureFirewallSubnet
+ }
+ }, (!empty(publicIPResourceID) || !empty(publicIPAddressObject)) ? {
+ //Use existing Public IP, new Public IP created in this module, or none if neither
+ publicIPAddress: {
+ id: !empty(publicIPResourceID) ? publicIPResourceID : publicIPAddress.outputs.resourceId
+ }
+ } : {})
+ }
+ ], additionalPublicIpConfigurationsVar)
+
+// ----------------------------------------------------------------------------
+// Prep managementIPConfiguration object for different uses cases:
+// 1. Use existing Management Public IP
+// 2. Use new Management Public IP created in this module
+
+// var managementIPConfiguration = {
+// name: !empty(managementIPResourceID) ? last(split(managementIPResourceID, '/')) : managementIPAddress.outputs.name
+// properties: union({
+// subnet: {
+// id: '${vNetId}/subnets/AzureFirewallManagementSubnet' // The subnet name must be AzureFirewallManagementSubnet for a 'Basic' SKU tier firewall
+// }
+// }, (!empty(managementIPResourceID) || !empty(managementIPAddressObject)) ? {
+// // Use existing Management Public IP, new Management Public IP created in this module, or none if neither
+// publicIPAddress: {
+// id: !empty(managementIPResourceID) ? managementIPResourceID : managementIPAddress.outputs.resourceId
+// }
+// } : {})
+// }
+
+var managementIPConfiguration = {
+ name: managementIPAddress.outputs.name
+ properties: {
+ subnet: {
+ id: '${vNetId}/subnets/AzureFirewallManagementSubnet' // The subnet name must be AzureFirewallManagementSubnet for a 'Basic' SKU tier firewall
+ }
+ publicIPAddress: {
+ id: managementIPAddress.outputs.resourceId
+ }
+
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+var builtInRoleNames = {
+ Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')
+ Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')
+ Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')
+ 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')
+ 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')
+}
+
+#disable-next-line no-deployments-resources
+resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) {
+ name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}'
+ properties: {
+ mode: 'Incremental'
+ template: {
+ '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#'
+ contentVersion: '1.0.0.0'
+ resources: []
+ }
+ }
+}
+
+module publicIPAddress '../publicIPAddresses/main.bicep' = if (empty(publicIPResourceID) && azureSkuName == 'AZFW_VNet') {
+ name: '${uniqueString(deployment().name, location)}-Firewall-PIP'
+ params: {
+ name: publicIPAddressObject.name
+ publicIPPrefixResourceId: contains(publicIPAddressObject, 'publicIPPrefixResourceId') ? (!(empty(publicIPAddressObject.publicIPPrefixResourceId)) ? publicIPAddressObject.publicIPPrefixResourceId : '') : ''
+ publicIPAllocationMethod: contains(publicIPAddressObject, 'publicIPAllocationMethod') ? (!(empty(publicIPAddressObject.publicIPAllocationMethod)) ? publicIPAddressObject.publicIPAllocationMethod : 'Static') : 'Static'
+ skuName: contains(publicIPAddressObject, 'skuName') ? (!(empty(publicIPAddressObject.skuName)) ? publicIPAddressObject.skuName : 'Standard') : 'Standard'
+ skuTier: contains(publicIPAddressObject, 'skuTier') ? (!(empty(publicIPAddressObject.skuTier)) ? publicIPAddressObject.skuTier : 'Regional') : 'Regional'
+ roleAssignments: contains(publicIPAddressObject, 'roleAssignments') ? (!empty(publicIPAddressObject.roleAssignments) ? publicIPAddressObject.roleAssignments : []) : []
+ location: location
+ tags: publicIPAddressObject.?tags ?? tags
+ zones: zones
+ }
+}
+
+// create a Management Public IP address if one is not provided and the flag is true
+module managementIPAddress '../publicIPAddresses/main.bicep' = if (isCreateDefaultManagementIP && azureSkuName == 'AZFW_VNet') {
+ name: '${uniqueString(deployment().name, location)}-Firewall-MIP'
+ params: {
+ name: contains(managementIPAddressObject, 'name') ? (!(empty(managementIPAddressObject.name)) ? managementIPAddressObject.name : '${name}-mip') : '${name}-mip'
+ publicIPPrefixResourceId: contains(managementIPAddressObject, 'managementIPPrefixResourceId') ? (!(empty(managementIPAddressObject.publicIPPrefixResourceId)) ? managementIPAddressObject.publicIPPrefixResourceId : '') : ''
+ publicIPAllocationMethod: contains(managementIPAddressObject, 'managementIPAllocationMethod') ? (!(empty(managementIPAddressObject.publicIPAllocationMethod)) ? managementIPAddressObject.publicIPAllocationMethod : 'Static') : 'Static'
+ skuName: contains(managementIPAddressObject, 'skuName') ? (!(empty(managementIPAddressObject.skuName)) ? managementIPAddressObject.skuName : 'Standard') : 'Standard'
+ skuTier: contains(managementIPAddressObject, 'skuTier') ? (!(empty(managementIPAddressObject.skuTier)) ? managementIPAddressObject.skuTier : 'Regional') : 'Regional'
+ roleAssignments: contains(managementIPAddressObject, 'roleAssignments') ? (!empty(managementIPAddressObject.roleAssignments) ? managementIPAddressObject.roleAssignments : []) : []
+ location: location
+ tags: managementIPAddressObject.?tags ?? tags
+ zones: zones
+ }
+}
+
+resource azureFirewall 'Microsoft.Network/azureFirewalls@2023-04-01' = {
+ name: name
+ location: location
+ zones: length(zones) == 0 ? null : zones
+ tags: tags
+ properties: azureSkuName == 'AZFW_VNet' ? {
+ threatIntelMode: threatIntelMode
+ firewallPolicy: !empty(firewallPolicyId) ? {
+ id: firewallPolicyId
+ } : null
+ ipConfigurations: ipConfigurations
+ managementIpConfiguration: requiresManagementIp ? managementIPConfiguration : null
+ sku: {
+ name: azureSkuName
+ tier: azureSkuTier
+ }
+ applicationRuleCollections: applicationRuleCollections
+ natRuleCollections: natRuleCollections
+ networkRuleCollections: networkRuleCollections
+ } : {
+ firewallPolicy: !empty(firewallPolicyId) ? {
+ id: firewallPolicyId
+ } : null
+ sku: {
+ name: azureSkuName
+ tier: azureSkuTier
+ }
+ hubIPAddresses: !empty(hubIPAddresses) ? hubIPAddresses : null
+ virtualHub: !empty(virtualHubId) ? {
+ id: virtualHubId
+ } : null
+ }
+}
+
+resource azureFirewall_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') {
+ name: lock.?name ?? 'lock-${name}'
+ properties: {
+ level: lock.?kind ?? ''
+ notes: lock.?kind == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot delete or modify the resource or child resources.'
+ }
+ scope: azureFirewall
+}
+
+resource azureFirewall_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): {
+ name: diagnosticSetting.?name ?? '${name}-diagnosticSettings'
+ properties: {
+ storageAccountId: diagnosticSetting.?storageAccountResourceId
+ workspaceId: diagnosticSetting.?workspaceResourceId
+ eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId
+ eventHubName: diagnosticSetting.?eventHubName
+ metrics: diagnosticSetting.?metricCategories ?? [
+ {
+ category: 'AllMetrics'
+ timeGrain: null
+ enabled: true
+ }
+ ]
+ logs: diagnosticSetting.?logCategoriesAndGroups ?? [
+ {
+ categoryGroup: 'AllLogs'
+ enabled: true
+ }
+ ]
+ marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId
+ logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType
+ }
+ scope: azureFirewall
+}]
+
+resource azureFirewall_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): {
+ name: guid(azureFirewall.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName)
+ properties: {
+ roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)
+ principalId: roleAssignment.principalId
+ description: roleAssignment.?description
+ principalType: roleAssignment.?principalType
+ condition: roleAssignment.?condition
+ conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set
+ delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId
+ }
+ scope: azureFirewall
+}]
+
+@description('The resource ID of the Azure Firewall.')
+output resourceId string = azureFirewall.id
+
+@description('The name of the Azure Firewall.')
+output name string = azureFirewall.name
+
+@description('The resource group the Azure firewall was deployed into.')
+output resourceGroupName string = resourceGroup().name
+
+@description('The private IP of the Azure firewall.')
+output privateIp string = contains(azureFirewall.properties, 'ipConfigurations') ? azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress : ''
+
+@description('The Public IP configuration object for the Azure Firewall Subnet.')
+output ipConfAzureFirewallSubnet object = contains(azureFirewall.properties, 'ipConfigurations') ? azureFirewall.properties.ipConfigurations[0] : {}
+
+@description('List of Application Rule Collections.')
+output applicationRuleCollections array = applicationRuleCollections
+
+@description('List of Network Rule Collections.')
+output networkRuleCollections array = networkRuleCollections
+
+@description('Collection of NAT rule collections used by Azure Firewall.')
+output natRuleCollections array = natRuleCollections
+
+@description('The location the resource was deployed into.')
+output location string = azureFirewall.location
+
+// =============== //
+// Definitions //
+// =============== //
+
+type lockType = {
+ @description('Optional. Specify the name of lock.')
+ name: string?
+
+ @description('Optional. Specify the type of lock.')
+ kind: ('CanNotDelete' | 'ReadOnly' | 'None')?
+}?
+
+type roleAssignmentType = {
+ @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.')
+ roleDefinitionIdOrName: string
+
+ @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.')
+ principalId: string
+
+ @description('Optional. The principal type of the assigned principal ID.')
+ principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')?
+
+ @description('Optional. The description of the role assignment.')
+ description: string?
+
+ @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"')
+ condition: string?
+
+ @description('Optional. Version of the condition.')
+ conditionVersion: '2.0'?
+
+ @description('Optional. The Resource Id of the delegated managed identity resource.')
+ delegatedManagedIdentityResourceId: string?
+}[]?
+
+type diagnosticSettingType = {
+ @description('Optional. The name of diagnostic setting.')
+ name: string?
+
+ @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.')
+ logCategoriesAndGroups: {
+ @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.')
+ category: string?
+
+ @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to \'AllLogs\' to collect all logs.')
+ categoryGroup: string?
+ }[]?
+
+ @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.')
+ metricCategories: {
+ @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.')
+ category: string
+ }[]?
+
+ @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.')
+ logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')?
+
+ @description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.')
+ workspaceResourceId: string?
+
+ @description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.')
+ storageAccountResourceId: string?
+
+ @description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.')
+ eventHubAuthorizationRuleResourceId: string?
+
+ @description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.')
+ eventHubName: string?
+
+ @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.')
+ marketplacePartnerResourceId: string?
+}[]?
diff --git a/scenarios/shared/bicep/network/bastion.bicep b/scenarios/shared/bicep/network/bastion.bicep
index 20e817a4..fe83007b 100644
--- a/scenarios/shared/bicep/network/bastion.bicep
+++ b/scenarios/shared/bicep/network/bastion.bicep
@@ -23,15 +23,16 @@ var snetBastion = {
id: '${vnetId}/subnets/AzureBastionSubnet'
}
-
-module publicIp 'publicIp.bicep' = {
- name: 'pipBastionHostDeployment'
- params: {
- location: location
- name: 'pip-${bastionNameSantized}'
- skuTier: 'Regional'
- skuName: 'Standard'
- publicIPAllocationMethod: 'Static'
+resource publicIp 'Microsoft.Network/publicIPAddresses@2021-02-01' = {
+ name: 'pip-${bastionNameSantized}'
+ location: location
+ tags: tags
+ sku: {
+ name: 'Standard'
+ tier: 'Regional'
+ }
+ properties: {
+ publicIPAllocationMethod: 'Static'
}
}
@@ -50,7 +51,7 @@ resource bastionHost 'Microsoft.Network/bastionHosts@2022-07-01' = {
properties: {
subnet: snetBastion
publicIPAddress: {
- id: publicIp.outputs.pipResourceId
+ id: publicIp.id
}
}
}
@@ -59,4 +60,4 @@ resource bastionHost 'Microsoft.Network/bastionHosts@2022-07-01' = {
}
@description('The standard public IP assigned to the Bastion Service')
-output bastionPublicIp string = publicIp.outputs.ipAddress
+output bastionPublicIp string = publicIp.properties.ipAddress
diff --git a/scenarios/shared/bicep/network/firewall.bicep b/scenarios/shared/bicep/network/firewall.bicep
deleted file mode 100644
index c7dce4c2..00000000
--- a/scenarios/shared/bicep/network/firewall.bicep
+++ /dev/null
@@ -1,186 +0,0 @@
-@description('Required. Name of the Azure Firewall.')
-param name string
-
-@description('Optional. Location for all resources.')
-param location string = resourceGroup().location
-
-@description('Optional. Tags of the Azure Firewall resource.')
-param tags object = {}
-
-@description('Optional. Tier of an Azure Firewall.')
-@allowed([
- 'Standard'
- 'Premium'
-])
-param azureSkuTier string = 'Standard'
-
-@description('The virtual network ID containing AzureFirewallSubnet. If a public ip is not provided, then the public ip that is created as part of this module will be applied with the subnet provided in this variable.')
-param vnetId string = ''
-
-@description('Optional. Collection of application rule collections used by Azure Firewall.')
-param applicationRuleCollections array = []
-
-@description('Optional. Collection of network rule collections used by Azure Firewall.')
-param networkRuleCollections array = []
-
-@description('Optional. Collection of NAT rule collections used by Azure Firewall.')
-param natRuleCollections array = []
-
-@description('Optional. Resource ID of the Firewall Policy that should be attached.')
-param firewallPolicyId string = ''
-
-@allowed([
- 'Alert'
- 'Deny'
- 'Off'
-])
-@description('Optional. The operation mode for Threat Intel.')
-param threatIntelMode string = 'Deny'
-
-@description('Optional. Zone numbers e.g. 1,2,3.')
-param zones array = []
-// param zones array = [
-// '1'
-// '2'
-// '3'
-// ]
-
-
-@description('Optional. Diagnostic Storage Account resource identifier.')
-param diagnosticStorageAccountId string = ''
-
-@description('Optional. Log Analytics workspace resource identifier.')
-param diagnosticWorkspaceId string = ''
-
-@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.')
-param diagnosticEventHubAuthorizationRuleId string = ''
-
-@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.')
-param diagnosticEventHubName string = ''
-
-@description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource.')
-@allowed([
- 'allLogs'
- 'AzureFirewallApplicationRule'
- 'AzureFirewallNetworkRule'
- 'AzureFirewallDnsProxy'
-])
-param diagnosticLogCategoriesToEnable array = [
- 'allLogs'
-]
-
-@description('Optional. The name of metrics that will be streamed.')
-@allowed([
- 'AllMetrics'
-])
-param diagnosticMetricsToEnable array = [
- 'AllMetrics'
-]
-
-@description('Optional. The name of the diagnostic setting, if deployed.')
-param diagnosticSettingsName string = '${name}-diagnosticSettings'
-
-var azFwNameMaxLength = 56
-var azFwNameSantized = length(name) > azFwNameMaxLength ? substring(name, 0, azFwNameMaxLength) : name
-
-// The default is AZFW_VNet. If you want to attach azure firewall to vhub, you should set sku to AZFW_Hub. accepted values: AZFW_Hub, AZFW_VNet
-var azureSkuName = 'AZFW_VNet'
-
-// ----------------------------------------------------------------------------
-
-var diagnosticsLogsSpecified = [for category in filter(diagnosticLogCategoriesToEnable, item => item != 'allLogs'): {
- category: category
- enabled: true
-}]
-
-var diagnosticsLogs = contains(diagnosticLogCategoriesToEnable, 'allLogs') ? [
- {
- categoryGroup: 'allLogs'
- enabled: true
- }
-] : diagnosticsLogsSpecified
-
-var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: {
- category: metric
- timeGrain: null
- enabled: true
-}]
-
-var ipConfigurations = [{
- name: 'azFwIpConf1'
- properties: {
- subnet: {
- id: '${vnetId}/subnets/AzureFirewallSubnet'
- }
- publicIPAddress: {
- id: publicIp.outputs.pipResourceId
- }
- }
-}]
-
-module publicIp 'publicIp.bicep' = {
- name: 'pipAzFwDeployment'
- params: {
- location: location
- name: 'pip-${azFwNameSantized}'
- skuTier: 'Regional'
- skuName: 'Standard'
- publicIPAllocationMethod: 'Static'
- }
-}
-
-resource azureFirewall_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) {
- name: diagnosticSettingsName
- properties: {
- storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null
- workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null
- eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null
- eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null
- metrics: diagnosticsMetrics
- logs: diagnosticsLogs
- }
- scope: azureFirewall
-}
-
-resource azureFirewall 'Microsoft.Network/azureFirewalls@2022-07-01' = {
- name: azFwNameSantized
- location: location
- zones: length(zones) == 0 ? null : zones
- tags: tags
- properties: {
- threatIntelMode: threatIntelMode
- firewallPolicy: !empty(firewallPolicyId) ? {
- id: firewallPolicyId
- } : null
- ipConfigurations: ipConfigurations
- sku: {
- name: azureSkuName
- tier: azureSkuTier
- }
- applicationRuleCollections: applicationRuleCollections
- natRuleCollections: natRuleCollections
- networkRuleCollections: networkRuleCollections
- }
-}
-
-
-@description('The resource ID of the Azure Firewall.')
-output azureFirewallId string = azureFirewall.id
-
-@description('The name of the Azure Firewall.')
-output azureFirewallName string = azureFirewall.name
-
-@description('The private IP of the Azure firewall.')
-output azFwPrivateIp string = contains(azureFirewall.properties, 'ipConfigurations') ? azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress : ''
-
-@description('The public IP configuration object for the Azure Firewall Subnet.')
-output ipConfAzureFirewallSubnet object = contains(azureFirewall.properties, 'ipConfigurations') ? azureFirewall.properties.ipConfigurations[0] : {}
-
-@description('List of Application Rule Collections.')
-output azFwApplicationRuleCollections array = applicationRuleCollections
-
-@description('List of Network Rule Collections.')
-output azFwANetworkRuleCollections array = networkRuleCollections
-
-@description('Collection of NAT rule collections used by Azure Firewall.')
-output azFwANatRuleCollections array = natRuleCollections
diff --git a/scenarios/shared/bicep/network/publicIPAddresses/.bicep/nested_roleAssignments.bicep b/scenarios/shared/bicep/network/publicIPAddresses/.bicep/nested_roleAssignments.bicep
new file mode 100644
index 00000000..a078fac3
--- /dev/null
+++ b/scenarios/shared/bicep/network/publicIPAddresses/.bicep/nested_roleAssignments.bicep
@@ -0,0 +1,97 @@
+@sys.description('Required. The IDs of the principals to assign the role to.')
+param principalIds array
+
+@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.')
+param roleDefinitionIdOrName string
+
+@sys.description('Required. The resource ID of the resource to apply the role assignment to.')
+param resourceId string
+
+@sys.description('Optional. The principal type of the assigned principal ID.')
+@allowed([
+ 'ServicePrincipal'
+ 'Group'
+ 'User'
+ 'ForeignGroup'
+ 'Device'
+ ''
+])
+param principalType string = ''
+
+@sys.description('Optional. The description of the role assignment.')
+param description string = ''
+
+@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".')
+param condition string = ''
+
+@sys.description('Optional. Version of the condition.')
+@allowed([
+ '2.0'
+])
+param conditionVersion string = '2.0'
+
+@sys.description('Optional. Id of the delegated managed identity resource.')
+param delegatedManagedIdentityResourceId string = ''
+
+var builtInRoleNames = {
+ 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')
+ 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')
+ 'Azure Center for SAP solutions administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b0c7e81-271f-4c71-90bf-e30bdfdbc2f7')
+ 'Azure Center for SAP solutions reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '05352d14-a920-4328-a0de-4cbe7430e26b')
+ 'Azure Center for SAP solutions service role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aabbc5dd-1af0-458b-a942-81af88f9c138')
+ 'Azure Kubernetes Service Policy Add-on Deployment': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18ed5180-3e48-46fd-8541-4ea054d57064')
+ 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')
+ 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')
+ Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')
+ 'Cosmos DB Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')
+ 'Desktop Virtualization Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a959dbd1-f747-45e3-8ba6-dd80f235f97c')
+ 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')
+ 'DNS Resolver Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')
+ 'DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')
+ 'DocumentDB Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')
+ 'Domain Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')
+ 'Domain Services Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')
+ 'LocalNGFirewallAdministrator role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a8835c7d-b5cb-47fa-b6f0-65ea10ce07a2')
+ 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')
+ 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')
+ 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')
+ 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')
+ 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')
+ 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')
+ 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')
+ 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')
+ Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')
+ 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')
+ Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')
+ 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')
+ 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')
+ 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')
+ 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')
+ 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')
+ 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')
+ 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')
+ 'Traffic Manager Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7')
+ 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')
+ 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')
+ 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')
+ 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')
+ 'Windows Admin Center Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a6333a3e-0164-44c3-b281-7a577aff287f')
+}
+
+resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2022-07-01' existing = {
+ name: last(split(resourceId, '/'))!
+}
+
+resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in principalIds: {
+ name: guid(publicIpAddress.id, principalId, roleDefinitionIdOrName)
+ properties: {
+ description: description
+ roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName
+ principalId: principalId
+ principalType: !empty(principalType) ? any(principalType) : null
+ condition: !empty(condition) ? condition : null
+ conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null
+ delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null
+ }
+ scope: publicIpAddress
+}]
diff --git a/scenarios/shared/bicep/network/publicIPAddresses/README.md b/scenarios/shared/bicep/network/publicIPAddresses/README.md
new file mode 100644
index 00000000..887dce7f
--- /dev/null
+++ b/scenarios/shared/bicep/network/publicIPAddresses/README.md
@@ -0,0 +1,338 @@
+# Public IP Addresses `[Microsoft.Network/publicIPAddresses]`
+
+## Navigation
+
+- [Public IP Addresses `[Microsoft.Network/publicIPAddresses]`](#public-ip-addresses-microsoftnetworkpublicipaddresses)
+ - [Navigation](#navigation)
+ - [Resource types](#resource-types)
+ - [Parameters](#parameters)
+ - [Parameter Usage: `tags`](#parameter-usage-tags)
+ - [Parameter Usage: `roleAssignments`](#parameter-usage-roleassignments)
+ - [Outputs](#outputs)
+ - [Cross-referenced modules](#cross-referenced-modules)
+ - [Deployment examples](#deployment-examples)
+
+## Resource types
+
+| Resource Type | API Version |
+| :-- | :-- |
+| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) |
+| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) |
+| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) |
+| `Microsoft.Network/publicIPAddresses` | [2022-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2022-07-01/publicIPAddresses) |
+
+## Parameters
+
+**Required parameters**
+
+| Parameter Name | Type | Description |
+| :-- | :-- | :-- |
+| `name` | string | The name of the Public IP Address. |
+
+**Optional parameters**
+
+| Parameter Name | Type | Default Value | Allowed Values | Description |
+| :-- | :-- | :-- | :-- | :-- |
+| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. |
+| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. |
+| `diagnosticLogCategoriesToEnable` | array | `[allLogs]` | `[allLogs, DDoSMitigationFlowLogs, DDoSMitigationReports, DDoSProtectionNotifications]` | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. |
+| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. |
+| `diagnosticSettingsName` | string | `''` | | The name of the diagnostic setting, if deployed. If left empty, it defaults to "
+
+### Parameter Usage: `roleAssignments`
+
+Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure.
+
+
+
+## Outputs
+
+| Output Name | Type | Description |
+| :-- | :-- | :-- |
+| `ipAddress` | string | The public IP address of the public IP address resource. |
+| `location` | string | The location the resource was deployed into. |
+| `name` | string | The name of the public IP address. |
+| `resourceGroupName` | string | The resource group the public IP address was deployed into. |
+| `resourceId` | string | The resource ID of the public IP address. |
+
+## Cross-referenced modules
+
+_None_
+
+## Deployment examples
+
+The following module usage examples are retrieved from the content of the files hosted in the module's `.test` folder.
+ >**Note**: The name of each example is based on the name of the file from which it is taken.
+
+ >**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order.
+
+
+
+
+
+
+
+
diff --git a/scenarios/shared/bicep/network/publicIPAddresses/main.bicep b/scenarios/shared/bicep/network/publicIPAddresses/main.bicep
new file mode 100644
index 00000000..665d09d4
--- /dev/null
+++ b/scenarios/shared/bicep/network/publicIPAddresses/main.bicep
@@ -0,0 +1,189 @@
+@description('Required. The name of the Public IP Address.')
+param name string
+
+@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.')
+param publicIPPrefixResourceId string = ''
+
+@description('Optional. The public IP address allocation method.')
+@allowed([
+ 'Dynamic'
+ 'Static'
+])
+param publicIPAllocationMethod string = 'Dynamic'
+
+@description('Optional. Name of a public IP address SKU.')
+@allowed([
+ 'Basic'
+ 'Standard'
+])
+param skuName string = 'Basic'
+
+@description('Optional. Tier of a public IP address SKU.')
+@allowed([
+ 'Global'
+ 'Regional'
+])
+param skuTier string = 'Regional'
+
+@description('Optional. A list of availability zones denoting the IP allocated for the resource needs to come from.')
+param zones array = []
+
+@description('Optional. IP address version.')
+@allowed([
+ 'IPv4'
+ 'IPv6'
+])
+param publicIPAddressVersion string = 'IPv4'
+
+@description('Optional. Resource ID of the diagnostic storage account.')
+param diagnosticStorageAccountId string = ''
+
+@description('Optional. Resource ID of the diagnostic log analytics workspace.')
+param diagnosticWorkspaceId string = ''
+
+@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.')
+param diagnosticEventHubAuthorizationRuleId string = ''
+
+@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.')
+param diagnosticEventHubName string = ''
+
+@description('Optional. The domain name label. The concatenation of the domain name label and the regionalized DNS zone make up the fully qualified domain name associated with the public IP address. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system.')
+param domainNameLabel string = ''
+
+@description('Optional. The Fully Qualified Domain Name of the A DNS record associated with the public IP. This is the concatenation of the domainNameLabel and the regionalized DNS zone.')
+param fqdn string = ''
+
+@description('Optional. The reverse FQDN. A user-visible, fully qualified domain name that resolves to this public IP address. If the reverseFqdn is specified, then a PTR DNS record is created pointing from the IP address in the in-addr.arpa domain to the reverse FQDN.')
+param reverseFqdn string = ''
+
+@allowed([
+ ''
+ 'CanNotDelete'
+ 'ReadOnly'
+])
+@description('Optional. Specify the type of lock.')
+param lock string = ''
+
+@description('Optional. Location for all resources.')
+param location string = resourceGroup().location
+
+@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.')
+param roleAssignments array = []
+
+@description('Optional. Tags of the resource.')
+param tags object = {}
+
+@description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource.')
+@allowed([
+ 'allLogs'
+ 'DDoSProtectionNotifications'
+ 'DDoSMitigationFlowLogs'
+ 'DDoSMitigationReports'
+])
+param diagnosticLogCategoriesToEnable array = [
+ 'allLogs'
+]
+
+@description('Optional. The name of metrics that will be streamed.')
+@allowed([
+ 'AllMetrics'
+])
+param diagnosticMetricsToEnable array = [
+ 'AllMetrics'
+]
+
+@description('Optional. The name of the diagnostic setting, if deployed. If left empty, it defaults to "Parameter JSON format
+
+```json
+"tags": {
+ "value": {
+ "Environment": "Non-Prod",
+ "Contact": "test.user@testcompany.com",
+ "PurchaseOrder": "1234",
+ "CostCenter": "7890",
+ "ServiceName": "DeploymentValidation",
+ "Role": "DeploymentValidation"
+ }
+}
+```
+
+Bicep format
+
+```bicep
+tags: {
+ Environment: 'Non-Prod'
+ Contact: 'test.user@testcompany.com'
+ PurchaseOrder: '1234'
+ CostCenter: '7890'
+ ServiceName: 'DeploymentValidation'
+ Role: 'DeploymentValidation'
+}
+```
+
+Parameter JSON format
+
+```json
+"roleAssignments": {
+ "value": [
+ {
+ "roleDefinitionIdOrName": "Reader",
+ "description": "Reader Role Assignment",
+ "principalIds": [
+ "12345678-1234-1234-1234-123456789012", // object 1
+ "78945612-1234-1234-1234-123456789012" // object 2
+ ]
+ },
+ {
+ "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11",
+ "principalIds": [
+ "12345678-1234-1234-1234-123456789012" // object 1
+ ],
+ "principalType": "ServicePrincipal"
+ }
+ ]
+}
+```
+
+Bicep format
+
+```bicep
+roleAssignments: [
+ {
+ roleDefinitionIdOrName: 'Reader'
+ description: 'Reader Role Assignment'
+ principalIds: [
+ '12345678-1234-1234-1234-123456789012' // object 1
+ '78945612-1234-1234-1234-123456789012' // object 2
+ ]
+ }
+ {
+ roleDefinitionIdOrName: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'
+ principalIds: [
+ '12345678-1234-1234-1234-123456789012' // object 1
+ ]
+ principalType: 'ServicePrincipal'
+ }
+]
+```
+
+Example 1: Common
+
+via Bicep module
+
+```bicep
+module publicIPAddresses './Network/publicIPAddresses/main.bicep' = {
+ name: '${uniqueString(deployment().name, location)}-test-npiacom'
+ params: {
+ // Required parameters
+ name: '<via JSON Parameter file
+
+```json
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ // Required parameters
+ "name": {
+ "value": "<Example 2: Min
+
+via Bicep module
+
+```bicep
+module publicIPAddresses './Network/publicIPAddresses/main.bicep' = {
+ name: '${uniqueString(deployment().name, location)}-test-npiamin'
+ params: {
+ // Required parameters
+ name: '<via JSON Parameter file
+
+```json
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ // Required parameters
+ "name": {
+ "value": "<