Forum Discussion

Logan_Silliman's avatar
Jul 02, 2024

Update to Microsoft Desktop Virtualization API v. 2023-09-05 by August 2, 2024 to avoid any impact

[Recommended actions updated on July 29, 2024]

 

WARNING! Be mindful when using secrets in deployment templates and follow Azure best practices when managing secrets. Our examples in this discussion post are to be used for educational purposes only.

 

Older Microsoft Desktop Virtualization API version(s) utilized for your Azure Virtual Desktop host pool resource will no longer support ‘get’ actions for registration token retrieval as of August 2nd, 2024.

 

 The affected API versions are as follows:  

  • 2019-01-23-preview 
  • 2019-09-24-preview 
  • 2019-12-10-preview 
  • 2020-09-21-preview  
  • 2020-11-02-preview  
  • 2020-11-10-preview  
  • 2021-01-14-preview 

 

On August 2nd, 2024, these affected API versions will no longer support the retrieval of the registration token. Users on older versions will not be able to use the 'get' action to retrieve the token. However, with the newer versions, there are two ways for customers to retrieve registration tokens moving forward:

  1. [Recommended] Using list* resource functions: Microsoft.DesktopVirtualization/hostpools resources now expose a listRegistrationTokens() function. This works if you already have valid registration tokens on your host pool and you want to retrieve them from an existing host pool.
  2. Using a  'post' action to securely retrieve the token

 

Action Required 

  1. Review any workflows you may have that rely on readers retrieving access tokens and update them to extract the registration tokens for a host pool in a new way.
  2. Ensure you are using up to date versions of the Microsoft Desktop Virtualization API.  

To take action, here are examples of how to extract the registration tokens for a host pool and update to the 2023-09-05 API version using Bicep and ARM templates. 

 

WARNING! Be mindful when using secrets in deployment templates and follow Azure best practices when managing secrets. Our examples in this discussion post are to be used for educational purposes only.

 

[Recommended] Take action using list* resource functions

This solution works if you already have valid registration tokens on your host pool and you want to retrieve them from an existing host pool. 

 

If you are using Bicep templates in your deployment:

 

 

 

 

 

@sys.description('AVD Host Pool resource ID. (Default: )')
param hostPoolResourceId string

var varHostpoolSubId = split(hostPoolResourceId, '/')[2]
var varHostpoolRgName = split(hostPoolResourceId, '/')[4]
var varHostPoolName = split(hostPoolResourceId, '/')[8]

// GET hostpool
resource hostPoolGet 'Microsoft.DesktopVirtualization/hostPools@2023-09-05' existing = {
  name: varHostPoolName
  scope: resourceGroup('${varHostpoolSubId}', '${varHostpoolRgName}')
}

@sys.description('The registration token of the host pool. This is not secure! Only for educational/testing purposes. Please follow security practices @ https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/scenarios-secrets ')
output registrationToken array = hostPoolGet.listRegistrationTokens()

 

 

 

 

 

If you are using ARM templates in your deployment:

 

 

 

 

 

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.28.1.47646",
      "templateHash": "2750874554099795062"
    }
  },
  "parameters": {
    "hostPoolResourceId": {
      "type": "string",
      "metadata": {
        "description": "AVD Host Pool resource ID. (Default: )"
      }
    }
  },
  "variables": {
    "varHostpoolSubId": "[split(parameters('hostPoolResourceId'), '/')[2]]",
    "varHostpoolRgName": "[split(parameters('hostPoolResourceId'), '/')[4]]",
    "varHostPoolName": "[split(parameters('hostPoolResourceId'), '/')[8]]"
  },
  "resources": [],
  "outputs": {
    "registrationToken": {
      "type": "array",
      "metadata": {
        "description": "The registration token of the host pool. This is not secure! Only for educational/ testing purposes. Please follow security practices @ https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/scenarios-secrets "
      },
      "value": "[listRegistrationTokens(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('varHostpoolSubId')), format('{0}', variables('varHostpoolRgName'))), 'Microsoft.DesktopVirtualization/hostPools', variables('varHostPoolName')), '2023-09-05')]"
    }
  }
}

 

 

 

 

 

 

Other ways to take action

One alternative is to always (re)create your host pool, which in turn will re-generate registration tokens that can then be retrieved using the PUT operation. 

 

If you are using Bicep templates in your deployment...

Use the retrieveToken.bicep module to retrieve the registration token from a host pool by using a PUT operation:

 

 

 

 

 

 

@sys.description('Optional. Host Pool token validity length. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the token will be valid for 8 hours.')
param tokenValidityLength string = 'PT8H'

@sys.description('Generated. Do not provide a value! This date value is used to generate a registration token.')
param baseTime string = utcNow('u')

param vLocation string

param vHostPoolName string

param vHostPoolType string

param vPreferredAppGroupType string

param vMaxSessionLimit int

param vLoadBalancerType string


resource hostPool 'Microsoft.DesktopVirtualization/hostPools@2023-09-05' = {
  name: vHostPoolName
  location: vLocation
    properties: {
    hostPoolType: vHostPoolType
    preferredAppGroupType: vPreferredAppGroupType
    maxSessionLimit: vMaxSessionLimit
    loadBalancerType: vLoadBalancerType
    registrationInfo: {
      expirationTime: dateTimeAdd(baseTime, tokenValidityLength)
      registrationTokenOperation: 'Update'
    }
  }
}

@sys.description('The registration token of the host pool.')
output registrationToken string = reference(hostPool.id).registrationInfo.token

 

 

 

 

 

 

 Here's an example of using the retrieveToken.bicep module to extract the registration token:

 

 

 

 

 

 

@sys.description('AVD Host Pool resource ID. (Default: )')
param hostPoolResourceId string

var varHostpoolSubId = split(hostPoolResourceId, '/')[2]
var varHostpoolRgName = split(hostPoolResourceId, '/')[4]
var varHostPoolName = split(hostPoolResourceId, '/')[8]

// Call on the hostpool
resource hostPoolGet 'Microsoft.DesktopVirtualization/hostPools@2023-09-05' existing = {
  name: varHostPoolName
  scope: resourceGroup('${varHostpoolSubId}', '${varHostpoolRgName}')
}

module hostPool 'retrieveToken.bicep' = {
  name: varHostPoolName
  scope: resourceGroup('${varHostpoolSubId}', '${varHostpoolRgName}')
  params: {
    vHostPoolName: varHostPoolName
    vMaxSessionLimit: hostPoolGet.properties.maxSessionLimit
    vPreferredAppGroupType: hostPoolGet.properties.preferredAppGroupType
    vHostPoolType: hostPoolGet.properties.hostPoolType
    vLoadBalancerType: hostPoolGet.properties.loadBalancerType
    vLocation: hostPoolGet.location
  }
}


@sys.description('The registration token of the host pool.')
output registrationToken string = hostPool.outputs.registrationToken

 

 

 

 

 

 

If you are using ARM templates in your deployment:

 

 

 

 

 

 

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.28.1.47646",
      "templateHash": "15215789985349638425"
    }
  },
  "parameters": {
    "hostPoolName": {
      "type": "string"
    },
    "location": {
      "type": "string"
    },
    "baseTime": {
      "type": "string",
      "defaultValue": "[utcNow('u')]"
    }
  },
  "variables": {
    "expirationTime": "[dateTimeAdd(parameters('baseTime'), 'PT1H1M')]"
  },
  "resources": [
    {
      "type": "Microsoft.DesktopVirtualization/hostPools",
      "apiVersion": "2023-09-05",
      "name": "[parameters('hostPoolName')]",
      "location": "[parameters('location')]",
      "properties": {
        "maxSessionLimit": 2,
        "hostPoolType": "Personal",
        "loadBalancerType": "Persistent",
        "preferredAppGroupType": "Desktop",
        "registrationInfo": {
          "expirationTime": "[variables('expirationTime')]",
          "registrationTokenOperation": "Update"
        }
      }
    }
  ],
  "outputs": {
    "token": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('hostPoolName'))).registrationInfo.token]"
    }
  }
}

 

 

 

 

 

 

WARNING! Be mindful when using secrets in deployment templates and follow Azure best practices when managing secrets. Our examples in this discussion post are to be used for educational purposes only.

 

Additional Support  

If you have any questions, comments, or concerns about this, please feel free to post a comment.

Resources