diff --git a/modules/network/express-route-gateway/.bicep/nested_roleAssignments.bicep b/modules/network/express-route-gateway/.bicep/nested_roleAssignments.bicep index 2bd352a75d..4d458aa3c5 100644 --- a/modules/network/express-route-gateway/.bicep/nested_roleAssignments.bicep +++ b/modules/network/express-route-gateway/.bicep/nested_roleAssignments.bicep @@ -78,12 +78,12 @@ var builtInRoleNames = { 'Windows Admin Center Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a6333a3e-0164-44c3-b281-7a577aff287f') } -resource applicationGateway 'Microsoft.Network/applicationGateways@2023-04-01' existing = { +resource expressRouteGateway 'Microsoft.Network/expressRouteGateways@2023-04-01' existing = { name: last(split(resourceId, '/'))! } resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in principalIds: { - name: guid(applicationGateway.id, principalId, roleDefinitionIdOrName) + name: guid(expressRouteGateway.id, principalId, roleDefinitionIdOrName) properties: { description: description roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName @@ -93,5 +93,5 @@ resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null } - scope: applicationGateway + scope: expressRouteGateway }] diff --git a/modules/network/express-route-gateway/.test/common/dependencies.bicep b/modules/network/express-route-gateway/.test/common/dependencies.bicep index 0ddf2fe3b3..acaa3b4df8 100644 --- a/modules/network/express-route-gateway/.test/common/dependencies.bicep +++ b/modules/network/express-route-gateway/.test/common/dependencies.bicep @@ -3,9 +3,18 @@ param virtualWANName string @description('Required. The name of the virtual Hub to create.') param virtualHubName string + @description('Optional. The location to deploy resources to.') param location string = resourceGroup().location +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + resource virtualWan 'Microsoft.Network/virtualWans@2023-04-01' = { name: virtualWANName location: location @@ -24,3 +33,6 @@ resource virtualHub 'Microsoft.Network/virtualHubs@2023-04-01' = { @description('The resource ID of the created Virtual Hub.') output virtualHubResourceId string = virtualHub.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/modules/network/express-route-gateway/.test/common/main.test.bicep b/modules/network/express-route-gateway/.test/common/main.test.bicep index 084804abeb..264ba8ba7e 100644 --- a/modules/network/express-route-gateway/.test/common/main.test.bicep +++ b/modules/network/express-route-gateway/.test/common/main.test.bicep @@ -37,6 +37,7 @@ module nestedDependencies 'dependencies.bicep' = { params: { virtualWANName: 'dep-${namePrefix}-vwan-${serviceShort}' virtualHubName: 'dep-${namePrefix}-hub-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' } } // ============== // @@ -56,5 +57,15 @@ module testDeployment '../../main.bicep' = { autoScaleConfigurationBoundsMin: 2 autoScaleConfigurationBoundsMax: 3 virtualHubId: nestedDependencies.outputs.virtualHubResourceId + lock: 'CanNotDelete' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalIds: [ + nestedDependencies.outputs.managedIdentityPrincipalId + ] + principalType: 'ServicePrincipal' + } + ] } } diff --git a/modules/network/express-route-gateway/.test/main.test.bicep b/modules/network/express-route-gateway/.test/main.test.bicep index dff85d99b8..ef99b3dc03 100644 --- a/modules/network/express-route-gateway/.test/main.test.bicep +++ b/modules/network/express-route-gateway/.test/main.test.bicep @@ -13,3 +13,11 @@ module common 'common/main.test.bicep' = { namePrefix: namePrefix } } + +// TEST 2 - MIN +module min 'min/main.test.bicep' = { + name: '${uniqueString(deployment().name)}-min-test' + params: { + namePrefix: namePrefix + } +} diff --git a/modules/network/express-route-gateway/.test/min/dependencies.bicep b/modules/network/express-route-gateway/.test/min/dependencies.bicep new file mode 100644 index 0000000000..0e84400a01 --- /dev/null +++ b/modules/network/express-route-gateway/.test/min/dependencies.bicep @@ -0,0 +1,27 @@ +@description('Required. The name of the virtual WAN to create.') +param virtualWANName string + +@description('Required. The name of the virtual Hub to create.') +param virtualHubName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +resource virtualWan 'Microsoft.Network/virtualWans@2023-04-01' = { + name: virtualWANName + location: location +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2023-04-01' = { + name: virtualHubName + location: location + properties: { + addressPrefix: '10.0.0.0/16' + virtualWan: { + id: virtualWan.id + } + } +} + +@description('The resource ID of the created Virtual Hub.') +output virtualHubResourceId string = virtualHub.id diff --git a/modules/network/express-route-gateway/.test/min/main.test.bicep b/modules/network/express-route-gateway/.test/min/main.test.bicep new file mode 100644 index 0000000000..ec61027df0 --- /dev/null +++ b/modules/network/express-route-gateway/.test/min/main.test.bicep @@ -0,0 +1,55 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'ms.network.expressRouteGateway-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nergmin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + virtualWANName: 'dep-${namePrefix}-vwan-${serviceShort}' + virtualHubName: 'dep-${namePrefix}-hub-${serviceShort}' + } +} +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + virtualHubId: nestedDependencies.outputs.virtualHubResourceId + + } +} diff --git a/modules/network/express-route-gateway/README.md b/modules/network/express-route-gateway/README.md index f1dcb31a8d..b6797dc37c 100644 --- a/modules/network/express-route-gateway/README.md +++ b/modules/network/express-route-gateway/README.md @@ -14,6 +14,8 @@ This module deploys an Express Route Gateway. | 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.Network/expressRouteGateways` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/expressRouteGateways) | ## Parameters @@ -27,15 +29,17 @@ This module deploys an Express Route Gateway. **Optional parameters** -| Parameter Name | Type | Default Value | Description | -| :-- | :-- | :-- | :-- | -| `allowNonVirtualWanTraffic` | bool | `False` | Configures this gateway to accept traffic from non Virtual WAN networks. | -| `autoScaleConfigurationBoundsMax` | int | `2` | Maximum number of scale units deployed for ExpressRoute gateway. | -| `autoScaleConfigurationBoundsMin` | int | `2` | Minimum number of scale units deployed for ExpressRoute gateway. | -| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via a Globally Unique Identifier (GUID). | -| `expressRouteConnections` | array | `[]` | List of ExpressRoute connections to the ExpressRoute gateway. | -| `location` | string | `[resourceGroup().location]` | Location for all resources. | -| `tags` | object | `{object}` | Tags of the Firewall policy resource. | +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowNonVirtualWanTraffic` | bool | `False` | | Configures this gateway to accept traffic from non Virtual WAN networks. | +| `autoScaleConfigurationBoundsMax` | int | `2` | | Maximum number of scale units deployed for ExpressRoute gateway. | +| `autoScaleConfigurationBoundsMin` | int | `2` | | Minimum number of scale units deployed for ExpressRoute gateway. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via a Globally Unique Identifier (GUID). | +| `expressRouteConnections` | array | `[]` | | List of ExpressRoute connections to the ExpressRoute gateway. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `''` | `['', CanNotDelete, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | 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'. | +| `tags` | object | `{object}` | | Tags of the Firewall policy resource. | ### Parameter Usage: `roleAssignments` @@ -208,6 +212,16 @@ module expressRouteGateway './network/express-route-gateway/main.bicep' = { autoScaleConfigurationBoundsMax: 3 autoScaleConfigurationBoundsMin: 2 enableDefaultTelemetry: '' + lock: 'CanNotDelete' + roleAssignments: [ + { + principalIds: [ + '' + ] + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] tags: { hello: 'world' 'hidden-title': 'This is visible in the resource name' @@ -245,6 +259,20 @@ module expressRouteGateway './network/express-route-gateway/main.bicep' = { "enableDefaultTelemetry": { "value": "" }, + "lock": { + "value": "CanNotDelete" + }, + "roleAssignments": { + "value": [ + { + "principalIds": [ + "" + ], + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + }, "tags": { "value": { "hello": "world", @@ -257,3 +285,52 @@ module expressRouteGateway './network/express-route-gateway/main.bicep' = {

+ +

Example 2: Min

+ +
+ +via Bicep module + +```bicep +module expressRouteGateway './network/express-route-gateway/main.bicep' = { + name: '${uniqueString(deployment().name, location)}-test-nergmin' + params: { + // Required parameters + name: 'nergmin001' + virtualHubId: '' + // Non-required parameters + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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": "nergmin001" + }, + "virtualHubId": { + "value": "" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

diff --git a/modules/network/express-route-gateway/main.bicep b/modules/network/express-route-gateway/main.bicep index a435dde03f..0858bcf18d 100644 --- a/modules/network/express-route-gateway/main.bicep +++ b/modules/network/express-route-gateway/main.bicep @@ -26,9 +26,20 @@ param expressRouteConnections array = [] @description('Required. Resource ID of the Virtual Wan Hub.') param virtualHubId string +@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. Enable telemetry via a Globally Unique Identifier (GUID).') param enableDefaultTelemetry bool = true +@allowed([ + '' + 'CanNotDelete' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = '' + resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' properties: { @@ -60,6 +71,28 @@ resource expressRouteGateway 'Microsoft.Network/expressRouteGateways@2023-04-01' } } +resource expressRouteGateway_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock)) { + name: '${expressRouteGateway.name}-${lock}-lock' + properties: { + level: any(lock) + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: expressRouteGateway +} + +module expressRouteGateway_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ExpressRouteGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + condition: contains(roleAssignment, 'condition') ? roleAssignment.condition : '' + delegatedManagedIdentityResourceId: contains(roleAssignment, 'delegatedManagedIdentityResourceId') ? roleAssignment.delegatedManagedIdentityResourceId : '' + resourceId: expressRouteGateway.id + } +}] + @description('The resource ID of the ExpressRoute Gateway.') output resourceId string = expressRouteGateway.id diff --git a/modules/network/express-route-gateway/main.json b/modules/network/express-route-gateway/main.json index 7039161434..c7cb48bafe 100644 --- a/modules/network/express-route-gateway/main.json +++ b/modules/network/express-route-gateway/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.20.4.51522", - "templateHash": "10514926371607978717" + "templateHash": "18410461445637867561" }, "name": "Express Route Gateways", "description": "This module deploys an Express Route Gateway.", @@ -66,12 +66,31 @@ "description": "Required. Resource ID of the Virtual Wan Hub." } }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "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'." + } + }, "enableDefaultTelemetry": { "type": "bool", "defaultValue": true, "metadata": { "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." } + }, + "lock": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "CanNotDelete", + "ReadOnly" + ], + "metadata": { + "description": "Optional. Specify the type of lock." + } } }, "resources": [ @@ -108,6 +127,197 @@ "id": "[parameters('virtualHubId')]" } } + }, + { + "condition": "[not(empty(parameters('lock')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/expressRouteGateways/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/expressRouteGateways', parameters('name'))]" + ] + }, + { + "copy": { + "name": "expressRouteGateway_roleAssignments", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-ExpressRouteGateway-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), createObject('value', parameters('roleAssignments')[copyIndex()].description), createObject('value', ''))]", + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), createObject('value', parameters('roleAssignments')[copyIndex()].principalType), createObject('value', ''))]", + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "condition": "[if(contains(parameters('roleAssignments')[copyIndex()], 'condition'), createObject('value', parameters('roleAssignments')[copyIndex()].condition), createObject('value', ''))]", + "delegatedManagedIdentityResourceId": "[if(contains(parameters('roleAssignments')[copyIndex()], 'delegatedManagedIdentityResourceId'), createObject('value', parameters('roleAssignments')[copyIndex()].delegatedManagedIdentityResourceId), createObject('value', ''))]", + "resourceId": { + "value": "[resourceId('Microsoft.Network/expressRouteGateways', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.20.4.51522", + "templateHash": "8621498859031920018" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the principals to assign the role to." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to." + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "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\"." + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Id of the delegated managed identity resource." + } + } + }, + "variables": { + "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')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/expressRouteGateways/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(resourceId('Microsoft.Network/expressRouteGateways', last(split(parameters('resourceId'), '/'))), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/expressRouteGateways', parameters('name'))]" + ] } ], "outputs": {