mardi 24 avril 2012

Migration et réparation des droits des Home Directory AD en NTFS

Ou comment gagner du temps avec la fonction PowerShell Repair-HomeDir.

Repair-HomeDir est une fonction Powershell qui va vous permettre de remettre à plat les Access Control List NTFS des Home Directory de vos utilisateurs Active Directory. Elle peut être utilisée comme secours ou à des fins de migration.

Dans ce billet, je vais vous présenter Repair-HomDir, vous donner ses différents cas d’utilisation et vous montrer comment l’intégrer dans votre infrastructure.

Qu’est-ce qu’une Home Directory ?

Microsoft appelle ça le “Dossier de base”, dans l’onglet Profil des propriétés d’un utilisateur Active Directory :

bwayne

Il s’agit d’un dossier réservé à l’utilisateur (les autres utilisateurs n’ont pas le droit d’y accéder), utilisant les ACL (Access Control List) NTFS et accessible à partir d’un stockage réseau via CIFS.
Dans cette copie d’écran, le champs contenant \\NAS\Home\bwayne est stocké dans l’attribut HomeDirectory d’un utilisateur Active Directory.

Quand utiliser Repair-HomeDir ?

Globalement, Repair-HomeDir peut être utile à partir du moment où vous avez des utilisateurs Active Directory utilisant une HomeDirectory stockée sur un espace réseau.
Mais vous pourrez l’utiliser plus concrètement dans les cas suivants :
  • Vous venez de migrer des Homes Unix vers des Home Directory CIFS/NTFS via Active Directory.
  • Vous venez de migrer d’un domaine Active Directory vers un nouveau domaine Active Directory.
  • Vous venez de changer de politique de sécurité NTFS.
  • Vous venez de casser les droits NTFS des Home Directory suite à une mauvaise manipulation avec héritage.

Que fait Repair-HomeDir ?

La fonction va lire l’attribut HomeDirectory d’un utilisateur Active Directory et va suivre le chemin qui y est stocké.
Sur ce dossier, il peut :
  • Rendre l’utilisateur propriétaire du dossier et de ses sous-objets (dossiers et fichiers)
  • Donner, à l’utilisateur, le contrôle total de ce dossier et de ses sous-objets (dossiers et fichiers)

Comment l’utiliser ?

Repair-HomeDir est une fonction, c’est à dire qu’à l’instar d’une “commandelette” PowerShell, elle doit recevoir des arguments.
Ici nous utiliserons :
  • Source : Peut être un utilisateur, un groupe ou une OU Active Directory, mais également un fichier CSV.
  • Name : le nom ou le chemin de la source
  • Right : pour appliquer le contrôle totale
  • Owner : pour rendre l’utilisateur propriétaire
Pour que Repair-HomeDir fonctionne, il faut lui donner des utilisateurs, voici quelles sont les façons de lui en fournir :


Via un nom d’utilisateur :

C:\PS> Repair-HomeDir -Source User -Name edgarcia -Owner –Right

Cette commande réappliquera les droits de l'utilisateur edgarcia sur sa Home Directory : contrôle total et propriétés.

 

Via un groupe d’utilisateur :

C:\PS> Repair-HomeDir -Source Group -Name AD_Grp –Right

Cette commande réappliquera les droits de tous les utilisateurs se trouvant dans le groupe Active Directory AD_Grp.

 

Via une Unité d’Organisation :

C:\PS> Repair-HomeDir -Source OU -Name "OU=Users,DC=domaine,DC=lan" –Owner

Cette commande rendra tous les utilisateurs se trouvant dans l'OU Active Directory Users propriétaires de leurs Home Directory.


Via un fichier CSV :

C:\PS> Repair-HomeDir -Source CSV -Name c:\match.csv -HomeLetter N:
Cette commande lit le fichier CSV et renomme, remet les droits et remet le propriétaire sur toutes les Home Directory des utilisateurs se trouvant dans une colonne LDAPLogin. Elle peut appliquer en plus une lettre de lecteur (attribut AD HomeDrive), ici N:.

Le CSV doit être conçu de la façon suivante :

DossierSource ; LDAPLogin
\\NAS\home\garcia ; edgarcia
\\NAS\home\jeannot ; jpouet

Format UT8, les séparateurs de champs sont les ; , la première colonne doit contenir les Home Directory sources, la seconde le login de l’utilisateur et la première ligne doit contenir le descripteur : DossierSource;LDAPLogin


Il ne faut pas mettre d'espace entre chaque élément (contrairement à l'exemple !) et éviter les lignes vides.

Repair-HomeDir va :

  • Renommer le dossier de monsieur Jean POUET de \\NAS\home\jeannot en \\NAS\home\jpouet pour être conventionnel (nom du Home = login de l’utilisateur)
  • Le rendre propriétaire
  • Lui donner le contrôle total
  • Renseigner les attributs HomeDrive et HomeDirectory de l’utilisateur Active Directory pour un montage automatique
Il répond tout à fait aux besoins en migration, par exemple d’une architecture Unix vers Active Directory : on lui fournit une liste de Home Directory et de login, il renomme, remet à plat tous les droits et positionne le montage automatique sur l’utilisateur Active Directory.
Le CSV peut être généré automatiquement par la fonction Match-HomeDir, qui permet de comparer des noms non-LDAP avec des identifiants LDAP ; je posterai peut être cette fonction plus tard, en attendant, ci besoin, vous pouvez me contacter pour l’obtenir.

 

Comment l'installer ?

Voici les prérequis de cette fonction :

  • Une machine NT6.x (2008, 2008R2 ou Win7) membre d'un domaine Active Directory
  • La machine doit avoir accès à l'espace de stockage des Home Directory
  • La commande : Import-Module ActiveDirectory doit fonctionner sur cette machine
  • L'utilisateur exécutant Repair-HomeDir doit avoir les droits d'administrateur dans l'espace de stockage des Home Directory
  • La fonction doit être lancée dans une console PowerShell en mode administrateur
  • Régler l’Execution-Policy pour permettre l’exécution de scripts non signés
  • La fonction à télécharger !


Copiez et modifiez la fonction :

Copiez la fonction dans un espace de stockage réseau du type \\NAS\Scripts$

Une fois copiée éditez-la avec un éditeur de bonne qualité (du type Notepad++), recherchez et remplacez les deux inscriptions [DOMAINE] par le nom court de votre domaine Active Directory.

Je n'ai pas trouvé le moyen d'utiliser une variable de domaine dans une commande icacls...


Modifiez votre profil PowerShell :

Pour pouvoir utiliser une fonction PowerShell, vous devez la charger dans votre environnement, plus exactement dans votre profil PowerShell

Modifiez votre profil PowerShell, soit :

- Pour tous les utilisateurs de la machine :

c:\> notepad %windir%\system32\WindowsPowerShell\v1.0\profile.ps1

- Uniquement sur votre profil :

c:\> notepad %UserProfile%\My Documents\WindowsPowerShell\profile.ps1

Ajoutez une ligne contenant le chemin de stockage de votre fonction :

\\NAS\Scripts$\Func.Repair-HomeDir.ps1

Et relancer une commande PowerShell.

Si vous tapez la commande suivante :

PS> Get-Help Repair-HomeDir -Detailed

Vous devriez voir l'aide de la fonction ; comme vous pouvez le constater, Repair-HomeDir a le même comportement qu'une cmdlet native de PowerShell.

Vous devriez dès à présent pouvoir effectuer un essai de la fonction avec un utilisateur de test, sur une Home Directory de test.


Le code :

Voici le code tel qu’il est disponible en pièce jointe :
   1: #########################################################################################
   2: # Fonction Repair-HomeDir                                                                   #
   3: ############################################################Edgarcia#09/16/2011#V2.0#007#
   4:  
   5: #V2.0 Refonte complete de la fonction pour l'orienter migration via CSV
   6:  
   7: Import-Module ActiveDirectory
   8: Function global:Repair-Homedir
   9: {
  10:     #Parametres de la commande :
  11:     param(
  12:         [parameter(Mandatory=$true,ValueFromPipeline=$true,HelpMessage="Indiquez le nom de la source")]$Name,
  13:         [parameter(Mandatory=$true,HelpMessage="Indiquez le type de source : OU, CSV, Group ou User")]$Source,
  14:         [parameter(Mandatory=$false,HelpMessage="Indiquez la lettre de lecteur de la HomeDirectory")]$HomeLetter,
  15:         [switch]$Right,
  16:         [switch]$Owner
  17:     )
  18:             
  19:     Process
  20:     {
  21:     Write-Host $Right $Owner
  22:         Switch ($Source) # Choix de la source
  23:         {
  24:             OU
  25:             { 
  26:                 Write-Host "Traitement de l'OU $Name"
  27:                 $arrUser = (Get-ADUser -Filter * -SearchBase $Name -Properties HomeDirectory, SamAccountName)
  28:                 if (-not $arrUser)
  29:                 {
  30:                     Write-Warning "Il n'y a pas d'utilisateur dans cette OU ou le chemin de l'OU est incorrect (attention à la casse)"
  31:                     BREAK
  32:                 }
  33:                 foreach ($user in $arrUser)
  34:                 {
  35:                     repairhdir # Execution de la fonction de copie / suppression
  36:                 }
  37:             }
  38:             Group
  39:             {
  40:                 Write-Host "Traitement du groupe AD $Name"
  41:                 try
  42:                 {
  43:                     $strGrp = (Get-ADGroup -Identity $Name -Properties members)
  44:                 }
  45:                 #Récupération de l'erreur en cas de groupe inexistant :
  46:                 catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]
  47:                 {
  48:                     Write-warning "Le Groupe $Name n'existe pas."
  49:                     Break
  50:                 }
  51:                 
  52:                 #Traitement des membres du groupe
  53:                 Foreach ($strMember in $($strGrp.Members))
  54:                 {
  55:                     try
  56:                     {                
  57:                         $User = (Get-ADUser -Filter {(DistinguishedName -eq $strMember) -and (ObjectClass -eq "user")} -Properties Name, DistinguishedName, HomeDirectory, SamAccountName, Description, MemberOf)
  58:                     }
  59:                     catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]
  60:                     {
  61:                     }
  62:                     
  63:                     repairhdir # Execution de la fonction de copie / suppression
  64:                 }
  65:             }
  66:             User
  67:             {
  68:                 Write-Host "Traitement de l'utilisateur $Name"
  69:                 try
  70:                 {
  71:                     $User = (Get-ADUser $Name -Properties HomeDirectory, SamAccountName)
  72:                 }
  73:                 #Récupération de l'erreur en cas d'utilisateur inexistant :
  74:                 catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]
  75:                 {
  76:                     Write-warning "L'utilisateur $Name n'existe pas."
  77:                     Break
  78:                 }
  79:                 repairhdir # Execution de la fonction de copie / suppression
  80:             }
  81:             CSV
  82:             {
  83:                 $Right = $true
  84:                 $Owner = $true
  85:                 if ((Test-Path $Name) -eq $false) # Test de la présence du CSV
  86:                 {
  87:                     Write-Warning "Le CSV : $Name n'est pas accessible ou n'existe pas"
  88:                     BREAK
  89:                 }
  90:                 
  91:                 try
  92:                 {
  93:                     #Import du CSV :
  94:                     $arrCsv = (Import-Csv $Name -Delimiter ";")
  95:                 }
  96:                 #Récupération de l'erreur en cas de mauvais format CSV
  97:                 Catch
  98:                 {
  99:                     Write-warning "Il y a un problème avec le fichier CSV, vérifiez son encodage et supprimez les colonnes vides en fin de ligne (du type ;;;;;)"
 100:                     Break
 101:                 }
 102:                 
 103:                 foreach ($Line in $arrCsv)
 104:                 {
 105:                     $User = (Get-ADUser $($Line.LDAPLogin) -Properties HomeDirectory, SamAccountName)
 106:                     repairhdir # Execution de la fonction de copie / suppression
 107:                 }
 108:             }
 109:         }        
 110:     }
 111: <#
 112: .SYNOPSIS 
 113: Permet de réparer les HomeDirectory des utilisateurs AD et peut être exploité dans le cadre d'une migration de donnée grâce à l'utilisation du fichier CSV généré par Match-HomeDir.
 114:  
 115: .DESCRIPTION
 116: Repair-HomeDir est une fonction qui permet de réparer les droits de l'HomeDirectory d'un utilisateur. Il rend la propriete à l'utilisateur et lui ajoute le contrôle total. La fonction réparera les droits sur le dossier indiqué dans la variable HomeDir de son profil Active Directory.
 117:     
 118: .PARAMETER Source
 119: Parametre obligatoire. La source peut être : 
 120: - User : La fonction corrigera le Home de l'utilisateur spécifié dans -Name
 121: - CSV : Permet d'utiliser le fichier CSV généré par la fonction Match-HomeDir. Repair-HomeDir utilise les champs FolderSource, qui contient le chemin complet du Home à migrer et LDAPLogin qui doit contenir le LDAP de l'utilisateur.
 122: - Group : cela signifie que le script cherchera les utilisateurs dans un groupe AD à préciser dans -Name
 123: - OU : La fonction cherchera les utilisateurs dans une Unité d'Organisation Active Directory et corrigera leurs HomeDirectory
 124:  
 125: .PARAMETER Name
 126: Parametre obligatoire. Indiquez le nom de la source, qui peut être un utilisateur (utilisez l'identifiant SamAccountName : edgarcia), un groupe d'utilisateur Active Directory, une Unité d'Organisation.
 127: (il faut respecter scrupuleusement la casse) ou un fichier CSV généré par Match-HomeDir. En utilisant un CSV, Repair-HomeDir renommera également les HomeDir en utilisant le SamAccountName.
 128:  
 129: .PARAMETER HomeLetter
 130: Parametre facultatif qui n'est utile que dans le cadre d'une migration via CSV. Indique la lettre de lecteur qui sera attribuée à la HomeDirectory dans le profil AD de l'utilisateur.
 131:  
 132: .PARAMETER Owner
 133: Parametre facultatif. Corrige le proprietaire NTFS de la HomeDirectory. Implicite lorsque la source est un CSV.
 134:  
 135: .PARAMETER Right
 136: Parametre facultatif. Corrige les droits NTFS de la HomeDirectory. Implicite lorsque la source est un CSV.
 137:  
 138: .INPUTS
 139: None. You cannot pipe objects to Repair-HomeDir.ps1.
 140:  
 141: .OUTPUTS
 142: La sortie peut être redirigée.
 143:  
 144: .EXAMPLE
 145: C:\PS> Repair-HomeDir -Source User -Name edgarcia -Owner -Right
 146: Cette commande reappliquera les droits de l'utilisateur edgarcia sur son HomeDir : contrôle total et proprietés.
 147:  
 148: .EXAMPLE
 149: C:\PS> Repair-HomeDir -Source Group -Name AD_Grp -Owner -Right
 150: Cette commande reappliquera les droits de tous les utilisateurs se trouvant dans le groupe Active Directory AD_Grp.
 151:  
 152: .EXAMPLE
 153: C:\PS> Repair-HomeDir -Source OU -Name "OU=Users,DC=domaine,DC=local" -Owner
 154: Cette commande reappliquera les droits de tous les utilisateurs se trouvant dans l'OU Active Directory Users.
 155:  
 156: .EXAMPLE
 157: C:\PS> Repair-HomeDir -Source CSV -Name c:\match.csv -HomeLetter N:
 158: Cette commande lit le fichier CSV (obtenu avec Match-HomDir) et renomme, remet les droits et remet le proprietaire sur toutes les HomeDirectory présentes dans le CSV.
 159:  
 160: .NOTES
 161: Edouard Garcia, 21/06/2011
 162: #>
 163: }
 164:  
 165: Function global:repairhdir
 166: {
 167:     if ($Source -match "CSV")
 168:     {
 169:         $strOldNasPath = $($Line.DossierSource)
 170:         $position = $strOldNasPath.LastIndexOfAny("\")
 171:         $strNewNasPath = $strOldNasPath.SubString(0,$position)
 172:         $strNewNasPath += "\$($user.SamAccountName)"
 173:         if ($strOldNasPath -ne $strNewNasPath)
 174:         {
 175:                 try
 176:                 {
 177:                 Rename-Item -Path $strOldNasPath -NewName $($User.SamAccountName) -Force
 178:                 }
 179:                 catch [System.Management.Automation.PSInvalidOperationException]
 180:                 {
 181:                     Write-Host "Le dossier source n'existe pas"
 182:                 }
 183:                 
 184:                 
 185:                 Write-Host "dossier identique"
 186:         }
 187:         
 188:         
 189:         $position = $strOldNasPath.LastIndexOfAny("\")
 190:         $strNewNasPath = $strOldNasPath.SubString(0,$position)
 191:         $strNewNasPath += "\$($user.SamAccountName)"
 192:         Set-Aduser -identity $User -Homedir $strNewNasPath -HomeDrive $HomeLetter
 193:         $User = (Get-ADUser $($Line.LDAPLogin) -Properties HomeDirectory, SamAccountName) # On recharge l'utilisateur avec ses nouvelles proprietes
 194:     }    
 195:         
 196:         if ($User.HomeDirectory)
 197:         {
 198:             if ((Test-Path $($User.HomeDirectory)) -eq $true)
 199:             {
 200:                 
 201:                 if ($Owner)
 202:                 {
 203:                     Write-Host "Traitement du proprietaire $($User.Name) sur le dossier $($User.HomeDirectory)" -ForegroundColor Green
 204:                     & C:\Windows\system32\icacls $($User.HomeDirectory) /setowner [DOMAINE]\$($user.SamAccountName) /T /C /Q
 205:                 }
 206:                 
 207:                 if ($Right)
 208:                 {
 209:                     Write-Host "Traitement des droits de l'utilisateur $($User.Name) sur le dossier $($User.HomeDirectory)" -ForegroundColor Green
 210:                     & C:\Windows\system32\icacls $($User.HomeDirectory) /grant [DOMAINE]\$($user.SamAccountName):`(OI`)`(CI`)F /T /C /Q
 211:                 }
 212:                             
 213:             }
 214:             Else
 215:             {
 216:                 Write-Host "Le dossier HomeDir $($User.HomeDirectory) de l'utilisateur $($User.Name) n'existe pas" -ForegroundColor Red
 217:             }
 218:         }
 219:         Else
 220:         {
 221:             Write-Host "L'utilisateur $($User.Name) n'a pas de HomeDir" -ForegroundColor Red
 222:         }
 223:     }

Je vous recommande de télécharger le fichier en pièce jointe plutôt que de copier/coller le texte ci dessus.


Les améliorations possibles :

Concrètement, je n’ai pas prévu de retravailler cette fonction. Ici, elle est en version 2 et est tout à fait fonctionnelle.

La gestion des erreurs se limite principalement à la détection de la source, si elle existe ou non.

Idéalement, s'il était possible de "piper" des utilisateurs, la fonction serait réellement complète.


Aucun commentaire:

Enregistrer un commentaire