Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fixes] Express-route-gateway: Updated RBAC handling & added min test #3927

Merged
merged 5 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}]
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ module nestedDependencies 'dependencies.bicep' = {
params: {
virtualWANName: 'dep-${namePrefix}-vwan-${serviceShort}'
virtualHubName: 'dep-${namePrefix}-hub-${serviceShort}'
managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}'
}
}
// ============== //
Expand All @@ -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'
}
]
}
}
8 changes: 8 additions & 0 deletions modules/network/express-route-gateway/.test/main.test.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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
55 changes: 55 additions & 0 deletions modules/network/express-route-gateway/.test/min/main.test.bicep
Original file line number Diff line number Diff line change
@@ -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

}
}
95 changes: 86 additions & 9 deletions modules/network/express-route-gateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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`
Expand Down Expand Up @@ -208,6 +212,16 @@ module expressRouteGateway './network/express-route-gateway/main.bicep' = {
autoScaleConfigurationBoundsMax: 3
autoScaleConfigurationBoundsMin: 2
enableDefaultTelemetry: '<enableDefaultTelemetry>'
lock: 'CanNotDelete'
roleAssignments: [
{
principalIds: [
'<managedIdentityPrincipalId>'
]
principalType: 'ServicePrincipal'
roleDefinitionIdOrName: 'Reader'
}
]
tags: {
hello: 'world'
'hidden-title': 'This is visible in the resource name'
Expand Down Expand Up @@ -245,6 +259,20 @@ module expressRouteGateway './network/express-route-gateway/main.bicep' = {
"enableDefaultTelemetry": {
"value": "<enableDefaultTelemetry>"
},
"lock": {
"value": "CanNotDelete"
},
"roleAssignments": {
"value": [
{
"principalIds": [
"<managedIdentityPrincipalId>"
],
"principalType": "ServicePrincipal",
"roleDefinitionIdOrName": "Reader"
}
]
},
"tags": {
"value": {
"hello": "world",
Expand All @@ -257,3 +285,52 @@ module expressRouteGateway './network/express-route-gateway/main.bicep' = {

</details>
<p>

<h3>Example 2: Min</h3>

<details>

<summary>via Bicep module</summary>

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

</details>
<p>

<details>

<summary>via JSON Parameter file</summary>

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

</details>
<p>
33 changes: 33 additions & 0 deletions modules/network/express-route-gateway/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -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

Expand Down
Loading