ADSI et Powershell : un petit challenge

Avant de commencer, je rappellerais simplement que ADSI (Active Directory Standard Interface) est une technologie permettant gérer les bases de comptes. Comme son nom l’indique, ADSI permet de gérer les objets d’un annuaire AD, mais de nos jours, on préfèrera le module spécialisé (“import-module ActiveDirectory”) beaucoup plus riche et simple à exploiter. Toutefois, ce module n’applique pas aux bases de comptes locales (SAM) d’une machine Windows et c’est là que ADSI prend toute son importance.

Présentation succincte d’ADSI

En quelques mot, ADSI utilise des “fournisseurs” (Providers) spécialisés en fonction du type d’accès souhaité et supporté par la base consultée. Ces fournisseurs sont sensibles à la casse et identifiables comme suit :

WinNT://localhost Accès à une base de comptes locale
WinNT://Domain Accès à un domaine à plat (Compatible Active Directory) – tel que les domaines antérieurs à Windows 2000
LDAP://RootDSE Accès à un annuaire Active Directory (arboresence)

 

ADSI peut être utilisé au sein de plusieurs  langages de script tels que VBScript, JavaScript et Powershell Sourire. Petit exemple de code :

domainuser = [ADSI]"LDAP://cn=Admin,ou=IT,dc=labo,dc=local" 
$domainuser = [ADSI]"WinNT://labo.local/Admin" 
$domainuser | Get-Member -Force

$localuser = [ADSI]"WinNT://tof-pc/Admin" 
$localuser.Psbase.Properties

 

Contexte de l’anomalie

 

A l’occasion d’une de mes formations sur Powershell, l’un des participants m’a soumis une remarque sur l’impossibilité d’ajouter un compte dans un groupe local comportant une apostrophe via un script ADSI. (comme par exemple, « Lecteurs des journaux d’évènements », « Utilisateurs de l’Analyseur de performances », « Opérateurs d’impression » …)

Un chalenge plutôt « franco-français » vue que le problème ne se pose pas dans la langue de Shakespeare.

En étudiant la question, je me suis rendu compte que le fournisseur ADSI « WinNT » était plutôt sensible (voir buggé) sur ce point, puisqu’un code équivalent avec le fournisseur ADSI « LDAP » exécuté sur un contrôleur de domaine fonctionnait parfaitement.
En fait, le problème semble provenir du fournisseur ADSI “WinNT” qui interprèterait mal le code de caractère de la chaine, c’est à dire la simple quotte ou l’apostrophe. Avec les fournisseurs LDAP cela fonctionne mais celui-ci ne fonctionne pas sur une base SAM (normal, ce n’est pas son but) Triste. Et “bricoler” le code page via chcp, pour contourner les caractères problématiques, ne me semble pas très sérieux.

 

Solution proposée

 

Le contournement que je vous propose, consiste à récupérer le nom du groupe (sur une partie du nom sans les quottes Sourire ) puis à modifier ces membres via le même fournisseur. Ce qui donnerait, en code Powershell :

$Connexion = [ADSI]"WinNT://localhost"

# --- Enumère tous les groupes locaux 
# $Connexion.psbase.children | where { $_.psbase.schemaClassName -eq 'group' } | % { $_.name }

# --- Chargement du nom du groupe recherché dans une chaine, par exemple "Utilisateurs de l'Analyseur de performances" 
$strGroupName = $Connexion.psbase.children | where { $_.psbase.schemaClassName -eq 'group' -and $_.name -like '*Analyseur*' } | % { $_.path }

# --- Membre (local) à ajouter 
$NewMember = "WinNT://Christophe"

# --- Membre Active Directory à ajouter (user ou global group) 
# !! Il faut utiliser le même provider WinNT pour le membre du domaine, donc ici, pas LDAP 
$NewMember = "WinNT://labo.local/toto"

# --- Ajoute le membre au groupe local via la methode '.Add' de l'objet 'group' 
$Connexion = [ADSI]"$strGroupName,group" 
$Connexion.Add($NewMember)

 

Voilà, j’espère que cette précision vous permettra de sortir de cette impasse, Clignement d'œil.

Powershellement votre

Christophe

Laisser un commentaire

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