Skip to content

Commit

Permalink
Created AVD workspace bicep module (#63)
Browse files Browse the repository at this point in the history
* first draft

* first end2end traft

* Minor update

* Minor update

* Minor update

* Minor update

* Minor cleanup

* Minor cleanup

* Minor cleanup

* Added version output

* Added  output

* Minor cleanup

* Added  output

* Added  output

* Added  output

* Simplified logic

* Added output

* Added output

* Added output + refactoring

* Added output

* Added output

* Added replacement

* Added replacement v2

* Cleanup

* Reset trigger

* Added output

* Fixed typo

* Added todo.

* Updated docs

* Replaced login with cred

* Replaced cred ref

* added missing func

* Minor update

* Pretest changes

* Updated remaining tests + extended api tests to exclude preview and allows for latest 5

* Added template translation to test-deployment

* Temp add publish condition

* Another try

* Another try

* Another try

* Another try

* Undid temp changes

* Added workaround to acocunt for bicep compile issue [deployments api version]

* Shifted bicep handling to native PS commands with bicep cli support + updated both RG + Gallery pipelines to ref bicep

* Updated remaining pipelines to use creds object

* Fixed schema eval

* Updated readme

* Temp remove arm templates to ensure it runs without

* Updated removal jobs to bicep + added publish workaround to allow for conditions

* Minor updates

* Further updates

* Further updates

* Restored templates

* Moved lock + rg bicep fix

* Fixed path

* Temp disabled template spec publish

* Undo after test

* Aligned bicep templates rbac

* Reduced roles for gallery

* Reduced role ref

* Cleanup

* Created vmss template

* Adjusted api tests

* Added output

* Switched ref for vmss to bicep

* Updated param

* Updated api

* Adjusted output

* Updated error handling

* Updated output

* Updated function input print

* Finishing touches

* Small update

* Fallback scale set to split PRs

* Updated module name

* Added workspace module + added rbac capabilities

* Minor fix

* Cleanup

* Cleanupo

* Added sql server bicep

* Undo previous changes

* Minor updates

Co-authored-by: Alexander Sehr <[email protected]>
  • Loading branch information
AlexanderSehr and Alexander Sehr authored Sep 27, 2021
1 parent 33bf719 commit 922d890
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 12 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ms.desktopvirtualization.workspaces.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
- name: "Test module"
uses: ./.github/actions/templates/validateModuleDeploy
with:
templateFilePath: '${{ env.modulePath }}/deploy.json'
templateFilePath: '${{ env.modulePath }}/deploy.bicep'
parameterFilePath: '${{ env.modulePath }}/parameters/${{ matrix.parameterFilePaths }}'
location: '${{ env.defaultLocation }}'
resourceGroupName: '${{ env.resourceGroupName }}'
Expand Down Expand Up @@ -114,7 +114,7 @@ jobs:
uses: ./.github/actions/templates/deployModule
with:
moduleName: '${{ env.moduleName }}'
templateFilePath: '${{ env.modulePath }}/deploy.json'
templateFilePath: '${{ env.modulePath }}/deploy.bicep'
parameterFilePath: '${{ env.modulePath }}/parameters/${{ matrix.parameterFilePaths }}'
location: '${{ env.defaultLocation }}'
resourceGroupName: '${{ env.resourceGroupName }}'
Expand Down Expand Up @@ -144,7 +144,7 @@ jobs:
- name: "Publish module"
uses: ./.github/actions/templates/publishModule
with:
templateFilePath: '${{ env.modulePath }}/deploy.json'
templateFilePath: '${{ env.modulePath }}/deploy.bicep'
componentTemplateSpecRGName: '${{ env.componentTemplateSpecRGName }}'
componentTemplateSpecRGLocation: '${{ env.componentTemplateSpecRGLocation }}'
componentTemplateSpecName: '${{ env.moduleName }}'
Expand Down Expand Up @@ -176,5 +176,5 @@ jobs:
uses: ./.github/actions/templates/removeModule
with:
moduleName: '${{ env.moduleName }}'
templateFilePath: '${{ env.modulePath }}/deploy.json'
templateFilePath: '${{ env.modulePath }}/deploy.bicep'
resourceGroupName: '${{ env.resourceGroupName }}'
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
param roleAssignment object
param builtInRoleNames object
param workspaceName string

resource nested_rbac 'Microsoft.DesktopVirtualization/workspaces/providers/roleAssignments@2020-04-01-preview' = [for principalId in roleAssignment.principalIds: {
name: '${workspaceName}/Microsoft.Authorization/${guid(workspaceName, principalId, roleAssignment.roleDefinitionIdOrName)}'
properties: {
roleDefinitionId: (contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : roleAssignment.roleDefinitionIdOrName)
principalId: principalId
}
dependsOn: []
}]
153 changes: 153 additions & 0 deletions arm/Microsoft.DesktopVirtualization/workspaces/deploy.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
@description('Required. The name of the workspace to be attach to new Application Group.')
param workSpaceName string

@description('Optional. Location for all resources.')
param location string = resourceGroup().location

@description('Required. Resource IDs fo the existing Application groups this workspace will group together.')
param appGroupResourceIds array = []

@description('Optional. The friendly name of the Workspace to be created.')
param workspaceFriendlyName string = ''

@description('Optional. The description of the Workspace to be created.')
param workspaceDescription string = ''

@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.')
@minValue(0)
@maxValue(365)
param diagnosticLogsRetentionInDays int = 365

@description('Optional. Resource identifier of the Diagnostic Storage Account.')
param diagnosticStorageAccountId string = ''

@description('Optional. Resource identifier of Log Analytics.')
param workspaceId string = ''

@description('Optional. Resource ID of the event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.')
param eventHubAuthorizationRuleId string = ''

@description('Optional. Name of the event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.')
param eventHubName string = ''

@description('Optional. Switch to lock Resource from deletion.')
param lockForDeletion bool = false

@description('Optional. Tags of the resource.')
param tags object = {}

@description('Optional. Customer Usage Attribution id (GUID). This GUID must be previously registered')
param cuaId string = ''

@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or it\'s fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'')
param roleAssignments array = []

var diagnosticsMetrics = []
var diagnosticsLogs = [
{
category: 'Checkpoint'
enabled: true
retentionPolicy: {
enabled: true
days: diagnosticLogsRetentionInDays
}
}
{
category: 'Error'
enabled: true
retentionPolicy: {
enabled: true
days: diagnosticLogsRetentionInDays
}
}
{
category: 'Management'
enabled: true
retentionPolicy: {
enabled: true
days: diagnosticLogsRetentionInDays
}
}
{
category: 'Feed'
enabled: true
retentionPolicy: {
enabled: true
days: diagnosticLogsRetentionInDays
}
}
]

var builtInRoleNames = {
'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','8e3af657-a8ff-443c-a75c-2fe8c4bcb635')
'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','b24988ac-6180-42a0-ab88-20f7382dd24c')
'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','acdd72a7-3385-48ef-bd42-f606fba81ae7')
'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','ca6382a4-1721-4bcf-a114-ff0c70227b6b')
'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','082f0a83-3be5-4ba1-904c-961cca79b387')
'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','49a72310-ab8d-41df-bbb0-79b649203868')
'Desktop Virtualization Workspace Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','21efdde3-836f-432b-bf3d-3e8e734d4b2b')
'Desktop Virtualization Workspace Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','0fa44ee9-7a7d-466b-9bb2-2bf446b1204d')
'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 Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','3913510d-42f4-4e42-8a64-420c390055eb')
'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','43d0d8ad-25c7-4714-9337-8ba259a9fe05')
'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','36243c78-bf99-498c-9df9-86d9f8d28608')
'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')
}

module pid_cuaId './.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) {
name: 'pid-${cuaId}'
params: {}
}

resource workspace 'Microsoft.DesktopVirtualization/workspaces@2020-11-02-preview' = {
name: workSpaceName
location: location
tags: tags
properties: {
applicationGroupReferences: appGroupResourceIds
description: workspaceDescription
friendlyName: workspaceFriendlyName
}
}

resource workspace_lock 'Microsoft.Authorization/locks@2016-09-01' = if (lockForDeletion) {
name: '${workSpaceName}-workspaceDoNotDelete'
properties: {
level: 'CanNotDelete'
}
scope: workspace
}

resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2017-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(workspaceId)) || (!empty(eventHubAuthorizationRuleId)) || (!empty(eventHubName))) {
name: '${workSpaceName}-diagnosticsetting'
properties: {
storageAccountId: (empty(diagnosticStorageAccountId) ? json('null') : diagnosticStorageAccountId)
workspaceId: (empty(workspaceId) ? json('null') : workspaceId)
eventHubAuthorizationRuleId: (empty(eventHubAuthorizationRuleId) ? json('null') : eventHubAuthorizationRuleId)
eventHubName: (empty(eventHubName) ? json('null') : eventHubName)
metrics: ((empty(diagnosticStorageAccountId) && empty(workspaceId) && empty(eventHubAuthorizationRuleId) && empty(eventHubName)) ? json('null') : diagnosticsMetrics)
logs: ((empty(diagnosticStorageAccountId) && empty(workspaceId) && empty(eventHubAuthorizationRuleId) && empty(eventHubName)) ? json('null') : diagnosticsLogs)
}
scope: workspace
}

module workspace_rbac './.bicep/nested_rbac.bicep' = [for (roleassignment, index) in roleAssignments: {
name: '${uniqueString(deployment().name, location)}-Rbac-${index}'
params: {
roleAssignment: roleassignment
builtInRoleNames: builtInRoleNames
workspaceName: workSpaceName
}
dependsOn: [
workspace
]
}]

output workspaceResourceId string = workspace.id
output workspaceResourceGroup string = resourceGroup().name
output workspaceName string = workSpaceName
98 changes: 94 additions & 4 deletions arm/Microsoft.DesktopVirtualization/workspaces/deploy.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@
"metadata": {
"description": "Optional. Customer Usage Attribution id (GUID). This GUID must be previously registered"
}
},
"roleAssignments": {
"defaultValue": [
],
"type": "array",
"metadata": {
"description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or it's fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'"
}
}
},
"variables": {
Expand Down Expand Up @@ -133,7 +141,27 @@
"days": "[parameters('diagnosticLogsRetentionInDays')]"
}
}
]
],
"builtInRoleNames": {
"Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]",
"Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','b24988ac-6180-42a0-ab88-20f7382dd24c')]",
"Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','acdd72a7-3385-48ef-bd42-f606fba81ae7')]",
"Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','ca6382a4-1721-4bcf-a114-ff0c70227b6b')]",
"Desktop Virtualization Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','082f0a83-3be5-4ba1-904c-961cca79b387')]",
"Desktop Virtualization Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','49a72310-ab8d-41df-bbb0-79b649203868')]",
"Desktop Virtualization Workspace Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','21efdde3-836f-432b-bf3d-3e8e734d4b2b')]",
"Desktop Virtualization Workspace Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','0fa44ee9-7a7d-466b-9bb2-2bf446b1204d')]",
"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 Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','3913510d-42f4-4e42-8a64-420c390055eb')]",
"Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','43d0d8ad-25c7-4714-9337-8ba259a9fe05')]",
"Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','36243c78-bf99-498c-9df9-86d9f8d28608')]",
"User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions','18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]"
}
},
"resources": [
{
Expand Down Expand Up @@ -171,7 +199,7 @@
"dependsOn": [
"[concat('Microsoft.DesktopVirtualization/workspaces/', parameters('workSpaceName'))]"
],
"comments": "Resource lock on the WVD Workspace",
"comments": "Resource lock on the AVD Workspace",
"properties": {
"level": "CannotDelete"
}
Expand All @@ -195,6 +223,68 @@
}
}
]
},
{
"name": "[concat('rbac-',deployment().name, copyIndex())]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-01-01",
"condition": "[not(empty(parameters('roleAssignments')))]",
"dependsOn": [
"[parameters('workspaceName')]"
],
"copy": {
"name": "rbacDeplCopy",
"count": "[length(parameters('roleAssignments'))]"
},
"properties": {
"mode": "Incremental",
"expressionEvaluationOptions": {
"scope": "inner"
},
"parameters": {
"roleAssignment": {
"value": "[parameters('roleAssignments')[copyIndex()]]"
},
"builtInRoleNames": {
"value": "[variables('builtInRoleNames')]"
},
"workspaceName": {
"value": "[parameters('workspaceName')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"roleAssignment": {
"type": "object"
},
"builtInRoleNames": {
"type": "object"
},
"workspaceName": {
"type": "string"
}
},
"resources": [
{
"type": "Microsoft.DesktopVirtualization/workspaces/providers/roleAssignments",
"apiVersion": "2018-09-01-preview",
"name": "[concat(parameters('workspaceName'), '/Microsoft.Authorization/', guid(parameters('workspaceName'), array(parameters('roleAssignment').principalIds)[copyIndex('innerRbacCopy')], parameters('roleAssignment').roleDefinitionIdOrName ))]",
"dependsOn": [
],
"copy": {
"name": "innerRbacCopy",
"count": "[length(parameters('roleAssignment').principalIds)]"
},
"properties": {
"roleDefinitionId": "[if(contains(parameters('builtInRoleNames'), parameters('roleAssignment').roleDefinitionIdOrName ), parameters('builtInRoleNames')[parameters('roleAssignment').roleDefinitionIdOrName] , parameters('roleAssignment').roleDefinitionIdOrName )]",
"principalId": "[array(parameters('roleAssignment').principalIds)[copyIndex()]]"
}
}
]
}
}
}
],
"functions": [
Expand All @@ -204,14 +294,14 @@
"type": "string",
"value": "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('workSpaceName'))]",
"metadata": {
"description": "The Resource Id of the WVD Workspace."
"description": "The Resource Id of the AVD Workspace."
}
},
"workspaceResourceGroup": {
"type": "string",
"value": "[resourceGroup().name]",
"metadata": {
"description": "The name of the Resource Group the WVD Workspace was created in."
"description": "The name of the Resource Group the AVD Workspace was created in."
}
},
"workspaceName": {
Expand Down
Loading

0 comments on commit 922d890

Please sign in to comment.