Robocopy KO sur partage Azure Files

Azure Files est une solution proposée par Microsoft via Azure permettant de créer des partages SMB liés à des Storage Account. Ainsi, il est possible de pousser ses répertoires partagés sans avoir de serveur de fichiers en tant que tel.

Je travaille actuellement sur un sujet portant sur le déploiement de plusieurs partages portés par Azure Files. Une fois la solution mise en place, ma tâche aura été de faire un robocopy des données locales vers le partage SMB porté par Azure Files. Cependant, en montant le partage sur le serveur de transfert avec un compte ayant les bons privilèges RBAC et NTFS, Robocopy se heurtait à un manque de permissions, y compris en mode backup :

2021/08/10 15:35:59 ERROR 5 (0x00000005) Copying NTFS Security to Destination Directory \\dundermifflin.inc\shares\iso\
Access is denied.

Voici plus ou moins à quoi ressemblait mon instruction Robocopy exécutée par Powershell.

Start-Process "robocopy.exe" -ArgumentList "$src $dst /S /E /COPY:DATSOU /PURGE /MIR /MT:4 /R:1 /W:1" 

Ce qui cause l’erreur de permissions est l’argument S de /copy, ce qui demande à Robocopy de conserver les permissions NTFS des fichiers lors du transfert.

Il faut savoir que les permissions sont habituellement découpées en 2 couches au niveau d’un partage : les privilèges SMB et NTFS. Les permissions sont indépendantes ; si sur un serveur managé il est possible d’intervenir sur les permissions SMB, ce n’est pas le cas avec Azure Files car l’accès est donné au service portant les partages, pas au serveur en lui-même. Par conséquent, les permissions sont redescendues via RBAC. Il existe des rôles Storage File Data SMB qui permettent de placer des droits en lecture et/ou en écriture sur les partages portés par Azure Files et qui positionnent ensuite au niveau SMB les permissions. Dans ce cas, mon compte ayant le rôle Storage File Data SMB Share Elevated Contributor était celui utilisé.

En fouinant un peu sur le net, je suis tombé sur cette question posée sur la section Q&A du site de Microsoft. Un utilisateur a été très récemment confronté au même problème. Cette erreur de permissions est due au fait que Robocopy a besoin de devenir propriétaire du fichier qu’il vient d’écrire à destination pour lui attribuer les permissions NTFS du fichier d’origine. Or, sur Azure Files, même avec un compte ayant les privilèges RBAC et NTFS au maximum, ce n’est pas possible. Robocopy va donc se heurter à un blocage et va renvoyer le message d’erreur plus haut.

En conséquence, pour contourner le problème qui est reconnu — et pour lequel Microsoft travaille sur une solution qui consisterait à donner à un compte un privilège RBAC permettant d’autoriser de devenir propriétaire d’un fichier — Microsoft conseille de monter le partage distant Azure Files avec un compte local d’administration qui lui, possède tous les droits.

Le partage doit donc être monté en tant que AZURE\NomDuStorageAccount ; le mot de passe est l’Access Key qui est générée et déclarée au niveau du Storage Account.

Au niveau du Storage Account, dans la section Security + networking du blade, il suffit de se rendre dans Access keys pour arriver sur cette page. La première clef est le mot de passe du compte local à utiliser. Ainsi, si le compte de stockage s’appelle storagedundermifflin, le partage doit être monté avec l’utilisateur AZURE\storagedundermifflin.

Ce compte possède tous les droits sur le partage et court-circuite les privilèges RBAC. En utilisant ce compte, Robocopy est donc capable de devenir propriétaire des fichiers copiés et d’y appliquer les permissions NTFS d’origine. En exécutant de nouveau le Robocopy, tout s’est bien déroulé et les permissions NTFS ont pu être conservées entre la source et la destination.

Powershell : alimentation d’un groupe AD à partir des ACL

J’ai développé ce script Powershell afin de séparer les utilisateurs de plusieurs serveurs de fichiers dans des groupes ActiveDirectory liées à une liste de distribution Exchange. Ainsi, en cas de downtime prévu d’un serveur, il suffit d’envoyer une communication au groupe AD.

Ce script récupère les groupes AD placés dans les ACL des répertoires partagés, vide le groupe en question puis le repeuple à partir des utilisateurs qu’il a récupéré dans les groupes. Un filtre est fait sur l’OU contenant les utilisateurs afin de ne pas inclure d’éventuels comptes de service. Naturellement, on adaptera les filtres (ici, on recherche des groupes, mais on peut très bien lister directement les utilisateurs) et la troncature de la chaîne en fonction de ses besoins.

function update {
	param([string] $srv)
	Get-ADGroupMember "_users-$srv" | foreach { Remove-AdGroupMember "_users-$srv" -Member $_ -Confirm:$false }
	$folders = get-childitem "\\$srv.dundermifflin.inc\d$\shares" | get-acl
	foreach($folder in $folders){
		$domacl = $folder.Access | where-object { $_.IdentityReference -like "DUNDERMIFFLIN\*" }
		foreach($acl in $domacl){
		$grpm = Get-ADGroupMember $acl.IdentityReference.Value.SubString(14,($acl.IdentityReference.Value.Length-14)) -Recursive
			foreach($mbr in $grpm) {
				$adu = Get-ADuser $mbr -Properties CanonicalName
				if($adu.CanonicalName -like "dundermifflin.inc/USERS/*") { Add-AdGroupMember -Identity "_users-$srv" -Members $mbr }
			}			
		}
	}
}

update("filesrv01")
update("filesrv02")
update("filesrv03")

Le script l’exécute donc pour 3 serveurs de fichiers différents afin de peupler trois groupes différents. Si des utilisateurs sont placés directement dans les ACL, alors la commande Get-ADGroupMember renverra une erreur mais celle-ci n’est pas fatale. Afin d’être toujours à jour, on pourra appeler ce script via une tâche planifiée toutes les semaines.

Le script est disponible en téléchargement dans une version commentée.

Migration de la définition des shares Windows

C’est ballot, mais Robocopy est incapable de faire une copie d’un répertoire en conservant son statut de répertoire partagé et les détails associés. Lorsqu’on migre un serveur de fichiers avec par exemple des homedirs, il faut donc transférer les dossiers vers le nouveau avec Robocopy, puis ensuite, appliquer les partages. Plutôt contraignant si il y a des centaines de répertoires à refaire.

Heureusement, si le serveur d’origine et de destination ont exactement la même configuration disque et les mêmes chemins, il est possible d’extraire la définition des shares et donc de l’importer sur le nouveau serveur pour que les répertoires soient de nouveau partagés.

La clef HKLM\System\CurrentControlSet\Services\LanmanServer\Shares contient ces définitions :

Ces clés contiennent le nom du partage, ainsi que d’autres informations (chemin, description)… Il est donc important que les chemins concordent ; en effet, ouvrir le fichier .reg contenant la clef et ses valeurs avec un éditeur de texte ne permettra pas une modification directe.

Un redémarrage est nécessaire après l’import de la clef sur le nouveau serveur afin que les partages soient visibles dans la console Computer Management.

Fausse alerte de quota maximal atteint sur un répertoire partagé

J’ai eu le cas aujourd’hui d’un répertoire partagé limité par un quota d’1 Go sur un serveur Windows 2008 R2 qui était considéré comme plein par la station de travail l’ayant monté alors que la taille des fichiers présents n’excède pas 200 Mo. Un démontage et remontage du répertoire ainsi qu’un redémarrage de la station n’ayant rien changé, je me suis connecté sur le serveur pour vérifier l’occupation réelle du répertoire : même résultat que sur la station cliente, et pourtant, dans la console des partages, j’obtiens un espace libre de 670 Ko.

Afin de forcer un rafraîchissement des données du quota, il existe l’outil utilisable en ligne de commande dirquota qui est installé en même temps que le rôle de serveurs de fichiers. Pour rafraîchir le quota du répertoire, en assumant que son chemin local soit C:\sharesengue :

dirquota quota scan /path:C:\sharesengue

Ensuite, un petit tour dans la console permet de voir que le quota a bien été mis à jour et qu’on ne se fera plus jeter par l’OS client pour cause d’espace disque insuffisant :