Skip to content
Estevão França edited this page Jan 25, 2023 · 1 revision

AZURE VIRTUAL DESKTOP - ENVIRONMENT MAINANTENCE

This is a fork of the original source code of the AVD automation and it will be maintained by the author and community contributors.



🛠  Technologies

GitHub  Azure  Pipelines  Azure Resource Manager  PowerShell Core 

Contents:

This solution was developed to help Azure Administrators to automate the mainatence process of AVD Environments where is required to recreate the session hosts due a image change or even for a quick deployment in another region or azure.

This automation may help you with:

  • Creates a deployment pattern to your session hosts.
  • Keep the AVD Organization Unity Clean.
  • Grant Resources Tagging.

The diagram below helps you to have a better understandment of how the automation works and which componentes are used on Azure and Azure DevOps.

solutionDiagram



The automation steps are executed via Azure DevOps Pipelines, this pipeline can be configured to be executed acording to your business requirement, below you may find some examples.

You can combine scheduled and event-based triggers in your pipelines, for example to validate the build every time a push is made (CI trigger), when a pull request is made (PR trigger), and a nightly build (Scheduled trigger). If you want to build your pipeline only on a schedule, and not in response to event-based triggers, ensure that your pipeline doesn't have any other triggers enabled. For example, YAML pipelines in a GitHub repository have CI triggers and PR triggers enabled by default. For information on disabling default triggers, see Triggers in Azure Pipelines and navigate to the section that covers your repository type.

  1. Manual.

After create the pipeline, you'll need to trigger it manually from the Azure DevOps Portal.

    name: "Deploying Azure Virtual Desktop Session Host"
    trigger: none
    jobs: 
    - job: Deployment
      displayName: devOpsTask - Auto Task
  1. Schedulled Trigger.

You can use cron tab to schedule the automation execution.

Scheduled triggers configure a pipeline to run on a schedule defined using cron syntax.

schedules:
- cron: string # cron syntax defining a schedule
  displayName: string # friendly name given to a specific schedule
  branches:
    include: [ string ] # which branches the schedule applies to
    exclude: [ string ] # which branches to exclude from the schedule
  always: boolean # whether to always run the pipeline or only if there have been source code changes since the last successful scheduled run. The default is false.
  1. Branch Trigger

When specifying a branch, tag, or path, you may use an exact name or a wildcard. Wildcards patterns allow * to match zero or more characters and ? to match a single character.

  • If you start your pattern with * in a YAML pipeline, you must wrap the pattern in quotes, like "*-releases".
  • For branches and tags:
    • A wildcard may appear anywhere in the pattern.
  • For paths:
    • In Azure DevOps Server 2022 and higher, including Azure DevOps Services, a wildcard may appear anywhere within a path pattern and you may use * or ?.
    • In Azure DevOps Server 2020 and lower, you may include * as the final character, but it doesn't do anything differently from specifying the directory name by itself. You may not include * in the middle of a path filter, and you may not use ?.
trigger:
  branches:
    include:
    - master
    - releases/*
    - feature/*
    exclude:
    - releases/old*
    - feature/*-working
  paths:
    include:
    - docs/*.md

To get more details about pipeline execution, please refer to the content below:

https://learn.microsoft.com/en-us/azure/devops/pipelines/repos/azure-repos-git?view=azure-devops&tabs=yaml#pr-triggers

https://learn.microsoft.com/en-us/azure/devops/pipelines/repos/github?view=azure-devops&tabs=yaml#pr-triggers

https://learn.microsoft.com/en-us/azure/devops/pipelines/repos/azure-repos-git?view=azure-devops&tabs=yaml#pr-triggers

https://learn.microsoft.com/en-us/azure/devops/pipelines/repos/azure-repos-git?view=azure-devops&tabs=yaml#choose-a-repository-to-build


This automation requires the usage of a service connection to execute the pipeline and succefully perform the required tasks on Azure.

Your Microsoft Azure subscription: Create a service connection with your Microsoft Azure subscription and use the name of the service connection in an Azure Web Site Deployment task in a release pipeline.

To create a service connection you can refer to this article.


The pipeline needs to be executed from a self-host agent that communicates with the domain controllers of the domain where the session hosts are joined.

Requirements:


The automation requires an existant host pool in the Azure Subscription, you can also use the automation to update the hostpool RDP settings.

For more information about host pools, please take a look in the documentation below:

https://learn.microsoft.com/en-us/azure/virtual-desktop/create-host-pools-azure-marketplace?tabs=azure-portal


The automation uses the azure compute gallery image as reference for the session host deployment.

For more information about Azure Compute Gallery, please take a look in the documentation below:

https://learn.microsoft.com/en-us/azure/virtual-machines/azure-compute-gallery


The KeyVault is used to store:

  • Domain User Join Password.
  • Local Admin Password.
  • AVD Registration Token.

For more information about Azure Key Vault, please take a look in the documentation below:

https://learn.microsoft.com/en-us/azure/key-vault/general/overview


It's required to grant access to the Service Connection in the subscription and the Key Vault.

Key Vault Permission:

https://learn.microsoft.com/en-us/azure/key-vault/general/assign-access-policy?tabs=azure-portal

Note: For subscription, the service connection needs at least the contributor permission at the subscription level.

Note: This automation only applies to scenarios where the computer are joined to an Active Directory Domain Services..


Is required to use a specific organizational unity for this automation as the script deleteAdComputerAccount.ps1 deletes all objects in the specified organizational unity.



The userNotification.ps1 is responsible to check if the available session hosts contains any active session and, if the session state is equal "Active", the script sends a notification to the user desktop warning them that the environment will unavailable for a couple of minutes. It also allows the user to end their pending tasks (by default, the script waits 5 minutes)

The message is tottaly customized and you can change it in the variable $messageBody, below you find the parameters used.

#AVD user notification section
Write-Host (Get-Date -Format 'MM/dd/yyyy HH:mm:ss').ToString() " = [WARNING] The user Session is active!"
Write-Host (Get-Date -Format 'MM/dd/yyyy HH:mm:ss').ToString() " = [WARNING] Sending an alert to the user"

logState -state "WARNING" -logMessage "Sending notification to the active users"

#Generating user details variables

$userName = $activeSession.ActiveDirectoryUserName.Split('\')[1]                    
Write-Host (Get-Date -Format 'MM/dd/yyyy HH:mm:ss').ToString() " = [INFO] logged user name" $userName 
logState -state "INFO" -logMessage "Logged user name: " $userName  $logFileName

#Message Section
[string]$messageTitle = "ALERT! Server Mainatence"
[string]$messageBody = "Dear user, " + $userName + " Your session Will be deactivated in 5   minutes, please save your work"

#Sending message to the user

try
  {
    $null = Send-AzWvdUserSessionMessage  `
                                        -ResourceGroupName $avdResourceGroupName `
                                        -HostPoolName $avdHostPoolName `
                                        -SessionHostName $sessionHostName `
                                        -UserSessionId $activeSession.Id.Split('/')[12] `
                                        -MessageTitle $messageTitle `
                                        -MessageBody  $messageBody
                        
      logState -state "INFO" -logMessage "Alert sent!" 
  }
  catch
  {
    #Calling logging function
    powershellLogging -codeSection "Sending message to the user"
  }
#Execution example

./avdUserNotification.ps1   -avdHostPoolName <hostPoolName> `
                            -avdResourceGroupName <avdResourceGroupName> `
                            -avdSubscriptionName <avdSubscriptionName or SubscriptionId>

The deleteSessionHost.ps1 is responsible to delete the VM's and dependencies (Disk and Network Adapter).

WARNING: This automation deletes the session host from the Host Pool and the Virtual Machine Container. This process is irreversible and needs to be wisly used.

#Execution example

./deleteSessionHost.ps1 -avdHostPoolName <hostPoolName> `
                        -avdResourceGroupName <avdResourceGroupName> `
                        -avdSubscriptionName <Subscription name or SubscriptionId>

The generateAvdTokenId.ps1 is responsible to create the AVD Registration Token. To grant that the proccess can happen automatically, I used a Key Vault to store the registration token as a secret.

#Execution Example
./generateAvdTokenId.ps1    `
                            -adSubscriptionName <subscriptionName> `
                            -avdHostPoolName <name of the host pool> `
                            -avdResourceGroupName <name of the resource group> `
                            -keyVaultName <name of the key vault> `
                            -avdTokenSecret <name of the secret that will store the secret>

The deleteAdComputerAccount.ps1 is responsible to delete the computer accounts in an specified organizational unity and, to this we used the parameter called credential to specified a user that has a privilege to manage the OU.

To grant the access for a specific OU, you can use the delegation control.

WARNING: This automation deletes all computer accounts in the specified organizational unity, please, be aware that this proccess may be irreversible.

#Execution Example
./deleteAdComputerAccount   `
                            -ouPath <OU=FSLOGIX,OU=AZURE-VIRTUAL-DESKTOP,OU=COMPUTERS,OU=ORGANIZATION,DC=myDomain,DC=com> `
                            -userName <DOMAINNAME\USER> `
                            -kvName <myKeyVault> `
                            -secretName <mySecretName> `
                            -subscriptionKeyVault <subscriptionKeyVault> `
                            -domainControllerName <domainControllerName> 

The newAzSessionHostDeployment.ps1 is responsible to trigger the deployment of the session hosts.

The base templates are available in this repository but, you can use your own. Microsoft also has a documentation for AVD and automations that you can take a look to improve it to your environment.

WARNING: All parameters are empty, you need to full fille the template parameters file with the keys of your environment.

#Execution Example
./newAzSessionHostDeployment    `
                                -templateFile <sessionHostTemplate/template.json> `
                                  -templateParametersFile <sessionHostTemplate/parameters.json> `
                                  -avdResourceGroupName <avdResourceGroupName> `
                                  -subscription <yourSubscriptionid> 

The addVmToLawsWorkspace.ps1 is used to configure the VM's in a specific logAnalitcs workspace in case your team uses the AVD Insights Preview.

#Execution Example
./deleteAdComputerAccount   `
                            -subscription <"subscription where the vm's  where deployed">  `
                            -workspaceId <Id of the workspace used for AVD/VM Insights> `
                            -workspaceKey <Secret key of the Workspace> `
                            -avdVmsResourceGroup "Resource group used to store the AVD VMs"