Associez FSLogix avec Azure AD

Microsoft vient tout juste de l’annoncer en préview : vous pouvez maintenant gérer les identités d’un partage de fichiers Azure PaaS directement avec Azure AD !

C’est une excellente nouvelle, attendue depuis plusieurs mois par de nombreux utilisateurs d’Azure Virtual Desktop, notamment pour mettre en place des solutions comme FSLogix, déjà utilisée pour la gestion des profils utilisateurs, sans serveur AD DS. Par contre, il y a encore une petite mauvaise nouvelle :

Cette fonctionnalité nécessite actuellement que les utilisateurs aient des identités hybrides, gérées dans Active Directory.

Documentation Microsoft

Quel est donc l’intérêt ?

Cette contrainte d’avoir un environnement hybride, qui sous-entend donc la présence d’un domaine AD, n’est pas forcément une mauvaise chose. Il s’agit ici d’une avancée technique intermédiaire. Nul doute que ce prérequis ne sera plus nécessaire à moyen terme.

Dans cet article, nous allons donc tester cette nouvelle fonctionnalité. Le but de tester cette préview de gestion des tickets Kerberos par Azure AD est de mesurer les avancées Microsoft. Vous pouvez suivre la documentation leur officielle ici.

Etape 0 : Rappel des prérequis

Comme vous allez travailler avec des tickets Kerberos spécifiques à Azure AD, il est obligatoire que les postes ayant accès au partage de fichiers PaaS disposent de l’un des OS suivants :

  • Windows 11 Enterprise mono ou multisession
  • Windows 10 Enterprise mono ou multisession, en version 2004 ou ultérieure avec la mise à jour KB5007253
  • Windows Server, version 2022 avec la dernière mise à jour KB5007254

Dans mon cas, j’ai utilisé l’environnement suivant :

  • une VM Windows Server 2022 pour jouer le contrôleur de domaine
  • Une environnement AVD composé de VMs en Windows 11 Enterprise multisession

Comme annoncé avant, les postes en accès au partage de fichier doivent donc être joints à Azure AD ou en mode hybride (Active Directory + Azure AD). Néanmoins, les utilisateurs doivent être « hybrides », il est donc nécessaire de passer par Azure AD Connect pour y arriver. Le choix du domaine managé Azure AD DS n’est donc pas possible ici :

  • Azure Active Directory Domain Services (Azure AD DS) : Azure AD DS fournit des services de domaine managé avec un sous-ensemble de fonctionnalités AD DS traditionnelles, comme la jonction de domaine, la stratégie de groupe, le protocole LDAP et l’authentification Kerberos/NTLM.
  • Active Directory Domain Services (AD DS) : serveur LDAP (Lightweight Directory Access Protocol) qui fournit des fonctionnalités clés telles que l’identité et l’authentification, la gestion des objets, la stratégie de groupe et les approbations.

Au final, les prérequis sont donc les suivants :

  • Un tenant Microsoft (Azure AD)
  • Des licences comprenant Windows 10 Entreprise pour vos utilisateurs AVD
  • Une souscription Azure active avec le rôle de propriétaire :
  • Un domaine Active Directory Domain Services (AD DS) :
  • Des utilisateurs AVD présents dans AD DS et synchronisés avec Azure AD :
  • Un environnement Azure Virtual Desktop déployé et lié à votre domaine AD DS :
  • Des machines virtuelles AVD jointes é la fois à votre AD DS et enrôlées dans votre Azure AD :

Une fois cela en place, déroulez les prochaines étapes d’installation depuis votre contrôleur de domaine.

Etape I : Création d’un nouveau compte de stockage

Sur votre portail Azure, commencez par créer votre nouveau compte de stockage :

Une fois créé, stockez l’ID de la souscription Azure, le nom du groupe de ressources et le nom du compte de stockage dans les variables suivantes :

$resourceGroupName = "<MyResourceGroup>"
$storageAccountName = "<MyStorageAccount>"
$Subscription = "<MySubscriptionID>"

Etape II : Configuration de l’authentification Azure AD

Vous allez utiliser plusieurs nouvelles fonctionnalités, il est donc préférable de réinstaller des modules PowerShell sur votre poste. Ouvrez PowerShell ISE en mode administrateur et lancez la commande suivante :

Install-Module -Name Az.Storage -AllowClobber
Install-Module -Name AzureAD -AllowClobber

Validez les messages d’avertissement si besoin :

L’activation de l’authentification via Azure AD passe elle aussi par une commande PowerShell :

Connect-AzAccount
$ApiVersion = '2021-04-01'

$Uri = ('https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Storage/storageAccounts/{2}?api-version={3}' -f $Subscription, $ResourceGroupName, $StorageAccountName, $ApiVersion);

$json = 
   @{properties=@{azureFilesIdentityBasedAuthentication=@{directoryServiceOptions="AADKERB"}}};
$json = $json | ConvertTo-Json -Depth 99

$token = $(Get-AzAccessToken).Token
$headers = @{ Authorization="Bearer $token" }

try {
    Invoke-RestMethod -Uri $Uri -ContentType 'application/json' -Method PATCH -Headers $Headers -Body $json;
} catch {
    Write-Host $_.Exception.ToString()
    Write-Error -Message "Caught exception setting Storage Account directoryServiceOptions=AADKERB: $_" -ErrorAction Stop
}

Le lancement du script PowerShell vous demandera de vous authentifier en utilisant un compte propriétaire de la souscription Azure :

Le lancement réussi du script devrait vous donner le résultat suivant :

Constatez l’activation de la fonctionnalité en préview, directement sur le compte de stockage :

Il ne reste en plus qu’à générer une nouvelle clef pour le protocole Kerberos :

Set-azcontext -Subscription $Subscription
New-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName -KeyName kerb1 -ErrorAction Stop

Cette clef n’est pas contre pas visible sur le portail Azure.

Etape III : Création d’une identité principal de service

L’activation des droits d’Azure AD sur le compte de stockage n’est pas encore possible via le portail Azure. Commencez par générer un mot de passe, basé sur la nouvelle clef Kerberos de votre compte stockage, et stocker le dans une variable grâce à la commande PowerShell suivante :

$kerbKey1 = Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName -ListKerbKey | Where-Object { $_.KeyName -like "kerb1" }
$aadPasswordBuffer = [System.Linq.Enumerable]::Take([System.Convert]::FromBase64String($kerbKey1.Value), 32);
$password = "kk:" + [System.Convert]::ToBase64String($aadPasswordBuffer);

Lors d’une étape précédente, vous vous êtes déjà connecté à Azure. Connectez-vous maintenant à Azure AD :

Connect-AzureAD
$azureAdTenantDetail = Get-AzureADTenantDetail;
$azureAdTenantId = $azureAdTenantDetail.ObjectId
$azureAdPrimaryDomain = ($azureAdTenantDetail.VerifiedDomains | Where-Object {$_._Default -eq $true}).Name

Utilisez ici un compte administrateur global du tenant :

Préparer la génération du principal de sécurité :

$servicePrincipalNames = New-Object string[] 3
$servicePrincipalNames[0] = 'HTTP/{0}.file.core.windows.net' -f $storageAccountName
$servicePrincipalNames[1] = 'CIFS/{0}.file.core.windows.net' -f $storageAccountName
$servicePrincipalNames[2] = 'HOST/{0}.file.core.windows.net' -f $storageAccountName

Créez et chargez dans une variable les éléments nécessaires à la future Enregistrement d’applications :

$application = New-AzureADApplication -DisplayName $storageAccountName -IdentifierUris $servicePrincipalNames -GroupMembershipClaims "All";

Générez alors le principal de sécurité :

$servicePrincipal = New-AzureADServicePrincipal -AccountEnabled $true -AppId $application.AppId -ServicePrincipalType "Application";

Configurez le mot de passe stocké précédement pour celui-ci :

$Token = ([Microsoft.Open.Azure.AD.CommonLibrary.AzureSession]::AccessTokens['AccessToken']).AccessToken
$apiVersion = '1.6'
$Uri = ('https://graph.windows.net/{0}/{1}/{2}?api-version={3}' -f $azureAdPrimaryDomain, 'servicePrincipals', $servicePrincipal.ObjectId, $apiVersion)
$json = @'
{
  "passwordCredentials": [
  {
    "customKeyIdentifier": null,
    "endDate": "<STORAGEACCOUNTENDDATE>",
    "value": "<STORAGEACCOUNTPASSWORD>",
    "startDate": "<STORAGEACCOUNTSTARTDATE>"
  }]
}
'@
$now = [DateTime]::UtcNow
$json = $json -replace "<STORAGEACCOUNTSTARTDATE>", $now.AddDays(-1).ToString("s")
  $json = $json -replace "<STORAGEACCOUNTENDDATE>", $now.AddMonths(12).ToString("s")
$json = $json -replace "<STORAGEACCOUNTPASSWORD>", $password
$Headers = @{'authorization' = "Bearer $($Token)"}
try {
  Invoke-RestMethod -Uri $Uri -ContentType 'application/json' -Method Patch -Headers $Headers -Body $json 
  Write-Host "Success: Password is set for $storageAccountName"
} catch {
  Write-Host $_.Exception.ToString()
  Write-Host "StatusCode: " $_.Exception.Response.StatusCode.value
  Write-Host "StatusDescription: " $_.Exception.Response.StatusDescription
}

Etape IV : Définir les autorisations API sur l’application nouvellement créée

Comme indiqué dans la documentation Microsoft, la suite du processus peut se faire dans le portail Azure. Ouvrez votre portail Azure Active Directory :


Dans vos Enregistrement d’applications, cliquez sur Toutes les applications, puis enfin sélectionnez l’application dont le nom correspond à votre compte de stockage :

Dans les autorisations API dans le volet de gauche, ajoutez une autorisation comme ceci :

Sélectionnez Microsoft Graph, puis choisissez délégation des permissions :

Dans la section OpenID, sélectionnez Profile :

Descendez plus bas dans la liste pour retrouver la section User. Cochez alors User.Read et cliquez sur Ajouter :

Une fois sur retourné sur l’écran des permissions, cliquez ci-dessous pour ajouter le consentement global à tout votre tenant :

Constatez la bonne application de celui-ci grâce au statut à droite :

Etape V : Création du partage de fichier

Retournez sur votre compte de stockage pour créer un nouveau partage de fichier comme ceci :

Etape VI : Jointure du partage de fichier Azure au domaine Active Directory

Pour l’instant, le partage de fichier Azure nécessite encore l’attribution de droits RBAC aux utilisateurs Azure Virtual desktop. Dans votre cas cette fonctionnalité nécessite d’activer l’authentification AD DS sur le compte de stockage.

Commencez par télécharger sur GitHub la version la plus récente du module PowerShell AzFilesHybrid.zip :

Décompressez les fichiers sur le disque C sur une VM, jointe à votre domaine :

Démarrez Windows PowerShell ISE en tant qu’administrateur et exécutez ce qui suit pour supprimer le flux de données alternatif Zone.Identifier, qui a une valeur de 3, indiquant qu’il a été téléchargé à partir d’Internet :

Get-ChildItem -Path C:\AzFilesHybrid -File -Recurse | Unblock-File

Toujours en PowerShell, connectez-vous à Azure :

Connect-AzAccount

Lancez alors le script suivant en modifiant les paramètres, selon votre configuration :

.\CopyToPSPath.ps1
Import-Module -Name AzFilesHybrid
Join-AzStorageAccountForAuth `
  -ResourceGroupName 'aadjoin-rg' `
  -StorageAccountName 'jloaadjoin2' `
  -DomainAccountType 'ComputerAccount' `
  -OrganizationalUnitDistinguishedName 'OU=AVDJOIN-Devices,DC=jloudev,DC=ml'

Constatez le retour de commande suivant :

Vous pouvez aussi contrôler la bonne activation sur le compte de stockage :

Restez sur votre compte de stockage pour assigner le rôle Storage File Data SMB Share Contributor à votre utilisateurs Azure Virtual Desktop :

Dans notre démonstration, nous allons seulement autoriser le groupe d’utilisateurs Azure Virtual Desktop.

Etape VII : Attribution des autorisations

Pour empêcher les utilisateurs d’accéder aux profils utilisateurs d’autres utilisateurs, vous devez également attribuer des autorisations au niveau du répertoire.

Le système que vous utilisez pour configurer les permissions doit répondre aux exigences suivantes :

  • La poste a une version de Windows répond aux exigences des systèmes d’exploitation des prérequis
  • Le poste doit être joint à Azure AD ou à Hybrid Azure AD à Azure AD
  • Le poste est relié au contrôleur de domaine

Installez ou importez si besoin sur le poste le module PowerShell ActiveDirectory. Dans mon cas, je n’ai pas eu à faire cette opération car j’ai tout exécuté depuis mon contrôleur de domaine :

Import-module ActiveDirectory

Azure AD ne prenant pas actuellement en charge la configuration des listes de contrôle d’accès dans Shell, il doit s’appuyer sur Active Directory. Pour configurer Shell sur votre compte de stockage, exécutez la commande suivante dans PowerShell ISE en tant qu’administrateur :

function Set-StorageAccountAadKerberosADProperties {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true, Position=0)]
        [string]$ResourceGroupName,

        [Parameter(Mandatory=$true, Position=1)]
        [string]$StorageAccountName,

        [Parameter(Mandatory=$false, Position=2)]
        [string]$Domain
    )  

    $AzContext = Get-AzContext;
    if ($null -eq $AzContext) {
        Write-Error "No Azure context found.  Please run Connect-AzAccount and then retry." -ErrorAction Stop;
    }

    $AdModule = Get-Module ActiveDirectory;
     if ($null -eq $AdModule) {
        Write-Error "Please install and/or import the ActiveDirectory PowerShell module." -ErrorAction Stop;
    }	

    if ([System.String]::IsNullOrEmpty($Domain)) {
        $domainInformation = Get-ADDomain
        $Domain = $domainInformation.DnsRoot
    } else {
        $domainInformation = Get-ADDomain -Server $Domain
    }

    $domainGuid = $domainInformation.ObjectGUID.ToString()
    $domainName = $domainInformation.DnsRoot
    $domainSid = $domainInformation.DomainSID.Value
    $forestName = $domainInformation.Forest
    $netBiosDomainName = $domainInformation.DnsRoot
    $azureStorageSid = $domainSid + "-123454321";

    Write-Verbose "Setting AD properties on $StorageAccountName in $ResourceGroupName : `
        EnableActiveDirectoryDomainServicesForFile=$true, ActiveDirectoryDomainName=$domainName, `
        ActiveDirectoryNetBiosDomainName=$netBiosDomainName, ActiveDirectoryForestName=$($domainInformation.Forest) `
        ActiveDirectoryDomainGuid=$domainGuid, ActiveDirectoryDomainSid=$domainSid, `
        ActiveDirectoryAzureStorageSid=$azureStorageSid"

    $Subscription =  $AzContext.Subscription.Id;
    $ApiVersion = '2021-04-01'

    $Uri = ('https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Storage/storageAccounts/{2}?api-version={3}' `
        -f $Subscription, $ResourceGroupName, $StorageAccountName, $ApiVersion);

    $json=
        @{
            properties=
                @{azureFilesIdentityBasedAuthentication=
                    @{directoryServiceOptions="AADKERB";
                        activeDirectoryProperties=@{domainName="$($domainName)";
                                                    netBiosDomainName="$($netBiosDomainName)";
                                                    forestName="$($forestName)";
                                                    domainGuid="$($domainGuid)";
                                                    domainSid="$($domainSid)";
                                                    azureStorageSid="$($azureStorageSid)"}
                                                    }
                    }
        };  

    $json = $json | ConvertTo-Json -Depth 99

    $token = $(Get-AzAccessToken).Token
    $headers = @{ Authorization="Bearer $token" }

    try {
        Invoke-RestMethod -Uri $Uri -ContentType 'application/json' -Method PATCH -Headers $Headers -Body $json
    } catch {
        Write-Host $_.Exception.ToString()
        Write-Host "Error setting Storage Account AD properties.  StatusCode:" $_.Exception.Response.StatusCode.value__ 
        Write-Host "Error setting Storage Account AD properties.  StatusDescription:" $_.Exception.Response.StatusDescription
        Write-Error -Message "Caught exception setting Storage Account AD properties: $_" -ErrorAction Stop
    }
}

Lancez alors la fonction précédente grâce à cette commande :

Connect-AzAccount
Set-StorageAccountAadKerberosADProperties -ResourceGroupName $resourceGroupName -StorageAccountName $storageAccountName

Cette commande fait alors rebasculer le statut Active Directory sur compte de stockage comme ceci :

Etape VIII : Création de la GPO

Toujours sur votre contrôleur de domaine, ouvrez le gestionnaire des polices :

Sous votre OU des postes AVD, créez une nouvelle police et éditez là :

Activer la police suivante :

Administrative Templates\System\Kerberos\Allow retrieving the Azure AD Kerberos Ticket Granting Ticket during logon

Ajoutez également une règle de registre sur cette même police :

reg add HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters /v CloudKerberosTicketRetrievalEnabled /t REG_DWORD /d 1

Redémarrez les VMs Azure Virtual Desktop pour la bonne prise en compte de la GPO :

Connectez-vous à une session Azure Virtual Desktop grâce à Windows Remote Desktop :

Utilisez un compte utilisateur d’AVD.

Une fois la session AVD ouverte, ouvrez une ligne de commande et tapez le code suivant :

dsregcmd /RefreshPrt

Verrouillez votre session AVD, puis déverrouillez-là :

Saisissez les deux lignes de commande suivantes :

klist purge
klist get krbtgt

Constatez la présence de :

krbtgt/KERBEROS.MICROSOFTONLINE.COM @ KERBEROS.MICROSOFTONLINE.COM

Lancez enfin la commande net use pour monter le lecteur réseau et vérifiez le bon fonctionnement :

net use Z: \\jloaadjoin2.file.core.windows.net\avdfileshare
Il arrive par moment que la commande échoue la première fois.

On retrouve bien le disque réseau dans l’explorateur Windows :

En retournant sur les tickets Kerberos, un nouveau CIFS a fait son apparition :

Etape IX : Configuration de FSLogix

Une fois l’architecture en place, on peut combiner cette dernière pour la gestion des profils utilisateurs via FSLogix. Pour cela, il nous faut rajouter la configuration FSLogix et une règle de registre en plus pour Azure AD.

#Variables
$storageAccountName = "jloaadjoin2"
$filesharename = "avdfileshare"

#Create Directories
$LabFilesDirectory = "C:\LabFiles"

if(!(Test-path -Path "$LabFilesDirectory")){
New-Item -Path $LabFilesDirectory -ItemType Directory |Out-Null
}
if(!(Test-path -Path "$LabFilesDirectory\FSLogix")){
New-Item -Path "$LabFilesDirectory\FSLogix" -ItemType Directory |Out-Null
}

 #Download FSLogix Installation bundle
  if(!(Test-path -Path "$LabFilesDirectory\FSLogix_Apps_Installation.zip")){
       Invoke-WebRequest -Uri "https://experienceazure.blob.core.windows.net/templates/wvd/FSLogix_Apps_Installation.zip" -OutFile     "$LabFilesDirectory\FSLogix_Apps_Installation.zip"

 #Extract the downloaded FSLogix bundle
 function Expand-ZIPFile($file, $destination){
     $shell = new-object -com shell.application
     $zip = $shell.NameSpace($file)
     foreach($item in $zip.items()){
     $shell.Namespace($destination).copyhere($item)
     }
 }

 Expand-ZIPFile -File "$LabFilesDirectory\FSLogix_Apps_Installation.zip" -Destination "$LabFilesDirectory\FSLogix"

}
   #Install FSLogix
   if(!(Get-WmiObject -Class Win32_Product | where vendor -eq "FSLogix, Inc." | select Name, Version)){
       $pathvargs = {C:\LabFiles\FSLogix\x64\Release\FSLogixAppsSetup.exe /quiet /install }
       Invoke-Command -ScriptBlock $pathvargs
   }
   #Create registry key 'Profiles' under 'HKLM:\SOFTWARE\FSLogix'
   $registryPath = "HKLM:\SOFTWARE\FSLogix\Profiles"
   if(!(Test-path $registryPath)){
       New-Item -Path $registryPath -Force | Out-Null
   }

   #Add registry values to enable FSLogix profiles, add VHD Locations, Delete local profile and FlipFlop Directory name
   New-ItemProperty -Path $registryPath -Name "VHDLocations" -Value "\\$storageAccountName.file.core.windows.net\$filesharename" -PropertyType String -Force | Out-Null
   New-ItemProperty -Path $registryPath -Name "Enabled" -Value 1 -PropertyType DWord -Force | Out-Null
   New-ItemProperty -Path $registryPath -Name "DeleteLocalProfileWhenVHDShouldApply" -Value 1 -PropertyType DWord -Force | Out-Null
   New-ItemProperty -Path $registryPath -Name "FlipFlopProfileDirectoryName" -Value 1 -PropertyType DWord -Force | Out-Null
    
    reg add HKLM\Software\Policies\Microsoft\AzureADAccount /v LoadCredKeyFromProfile /t REG_DWORD /d 1

   #Display script completion in console
Write-Host "Script Executed successfully"

L’ouverture d’une nouvelle session utilisateurs d’AVD vous affiche bien la mention FSLogix :

Un tour dans le partage de fichier du compte de stockage montre bien la présence du dossier du profil utilisateur géré par FSLogix :

Conclusion

La gestion des tickets Kerberos par Azure AD est une belle avancée. Bien évidemment, le processus de prise en charge complète d’un compte de stockage de manière native n’est pas encore là, mais nous y sommes en bonne voie 😎 Comme à chaque fois, n’hésitez pas à utiliser les commentaires pour exprimer de vos retours 😋

2 commentaires sur “Associez FSLogix avec Azure AD

  1. The following line don’t generate token
    $Token = ([Microsoft.Open.Azure.AD.CommonLibrary.AzureSession]::AccessTokens[‘AccessToken’]).AccessToken

    When I put rest of commands I see 401 (Unauthorized) status code

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *