Hé, vous le scripteur !Approche naïve des utilisateurs et groupes locaux

Les scripteurs Microsoft

Télécharger le code de cet article: HeyScriptingGuy2007_04.exe (151KB)

Comment gérer des descripteurs de sécurité sur les fichiers et les dossiers ?

Croyez-le si vous voulez , il fut un temps (il y a longtemps, bien sûr) où les scripteurs n'étaient pas si intelligents que ça. Nous savons que c'est dur à croire, mais—comment ça, ce n’est pas difficile à croire ? Et qu'est-ce que vous voulez dire par « c'était pas il y a si longtemps que ça » ? Vous avez dû voir l'un des scripteurs essayer de brancher une télévision l'autre jour.

En fait, ce scripteur pourrait de défendre en affirmant que brancher une nouvelle TV, ce n'est pas de la physique quantique : c'est pire que de la physique quantique. Juste pour brancher la télé, il faut trois câbles vidéo et deux câbles audio, et il vous faut rajouter un magnétoscope, un lecteur de DVD et une Xbox®, et je ne parle même pas du fait d'appuyer sur un nombre aléatoire de boutons sur la télécommande dite « universelle » pour essayer de lui faire reconnaître tous ces appareils. En comparaison, placer un satellite en orbite autour de Mars, c'est du gâteau.

Chose incroyable, le scripteur a fini par réussir à tout brancher correctement. Mais lorsqu'il a tout allumé, rien ne s'est produit. Consciencieux qu'il était, il a vérifié deux fois, puis trois fois tous les branchements. Il a lu toutes les notices, et il est même allé vérifier sur le Web s'il ne manquait pas d'informations. Mais rien. Il était prêt à sacrifier un lecteur MP3 au nom du dieu de l'électronique, lorsqu'il a remarqué qu'il avait oublié une étape clé : brancher le câble d'alimentation de la TV à la prise murale.

Remarque : Vous pensez peut-être que s'il est si difficile de brancher tous les appareils de la famille du scripteur, c'est peut-être parce que la famille du scripteur a trop d'appareils. En fait, le scripteur serait d'accord avec vous. Mais à chaque fois que la famille vote sur l'acquisition d'autres d'appareils, le scripteur perde toujours 2-0 au vote. Et non, il ne perd pas 2-1, c'est bien 2-0. Pour une raison obscure, le vote du Papa scripteur n'a jamais l'air de compter dans le vote familial, et il n'existe pas d'archives papier.

En réponse à votre question suivante, oui, il a essayé. Mais jusqu'ici, les Nations-Unies ont refusé d'envoyer des observateurs à la maison du scripteur pour superviser le vote.

Bien sûr, maintenant que nous y réfléchissons, ce n'est pas tant que les scripteurs (enfin, surtout celui de la TV) sont stupides : c'est juste qu'ils sont naïfs. Par exemple, lorsqu'ils préparaient le Guide du script pour Microsoft® Windows® 2000, ils ont sollicité l'aide de plusieurs..., hum, experts...au moment où il fallait finaliser les chapitres du livre. L'un des chapitres qui ont été coupés au montage était celui qui concernait la gestion des utilisateurs et groupes locaux. « Gestion des utilisateurs et des groupes locaux ? !? », ont déclaré les experts. « Je comprends pas qu'on ait pu considérer ça ! Ça intéresse qui, la gestion des utilisateurs et groupes locaux ? »

Eh bien, à notre grand regret, nous avons découvert depuis que tout le monde (à l'exception peut-être de nos « experts » internes) s'intéressait aux utilisateurs et groupes locaux. Nous recevons chaque semaine des tonnes de messages électroniques de personnes qui nous demandent, par exemple, comment faire pour ajouter un utilisateur à un groupe local, supprimer un utilisateur d'un groupe local ou modifier le mot de passe de l'administrateur local sur un ordinateur.

Bien sûr, le Référentiel de scripts du Script Center propose certains modèles de script qui indiquent comment effectuer ces actions, mais la plupart de ces scripts ne fonctionnent que sur un ordinateur à la fois. Ça ne suffit pas, c'est clair : les gens veulent savoir comment le faire sur plusieurs machines, et sur toutes les machines en même temps. Modifier le mot de passe de l'administrateur local sur un seul ordinateur ? Revenez sur Terre, les scripteurs : on veut le faire sur tous nos ordinateurs, ou sur tous les ordinateurs d'une UO, ou sur tous les serveurs de messagerie électronique, ou sur... Enfin, vous avez compris.

Vu que le Guide du script a été publié en 2003, cela veut dire que ça fait pratiquement quatre ans que nous sommes assiégés par ces messages électroniques. « Voici un autre lecteur qui demande comment il peut lire des noms d'ordinateur sur un tableur Excel®, puis changer le mot de passe l'administrateur local sur chacun de ces ordinateurs », remarquait récemment l'un des scripteurs. « Mais que peut-on bien faire à ce sujet ? »

Bon, ça nous a pris quatre ans, mais on a fini par trouver. La figure 1 indique exactement ce que nous pouvons faire.

Figure 1 Nous avons enfin trouvé

On Error Resume Next

Set objExcel = CreateObject(“Excel.Application”)
Set objWorkbook = objExcel.Workbooks.Open(“C:\Scripts\Test.xls”)
objExcel.Visible = True

i = 2

Do Until objExcel.Cells(i, 1).Value = “”
    strComputer = objExcel.Cells(i, 1).Value   
    Set objUser = GetObject(“WinNT://” & strComputer & “/Administrator”)
    If Err = 0 Then
         objUser.SetPassword “egTY634!alK2”
         objExcel.Cells(i, 2).Value = Now
    End If
    Err.Clear
    i = i + 1
Loop

Remarque : Comme vous le voyez, l'écriture de ce script ne nous a pas pris quatre ans parce que c'était difficile : ça nous a pris quatre ans parce que c'est globalement le temps qu'il nous faut pour faire quoi que ce soit. C'est pour ça qu'il ne faut jamais manquer une fête du Jour de l'An des scripteurs : on ne sait jamais quand aura lieu la prochaine fête annuelle, ni s'il y en aura une.

Le résultat, c'est un script qui prend le nom de tous les ordinateurs à partir d'un tableur, puis modifie le mot de passe de l'administrateur local sur chacune de ces machines. Pour ce petit tour de magie, nous commençons tranquillement, en supposant que vous avez un petit tableur très simple, qui ressemble à quelque chose comme la figure 2. (Si ce n'est pas le cas, créez-en un maintenant).

Figure 2 Liste obligatoire des ordinateurs

Figure 2** Liste obligatoire des ordinateurs **(Cliquer sur l'image pour l'agrandir)

Comme vous pouvez voir, il n'y a rien de spécial ici. Dans la colonne 1 (la colonne A), nous énumérons le nom de tous les ordinateurs qui ont un mot de passe que nous devons modifier. Dans la colonne 2 (la colonne B), nous prenons simplement note de la date et de l'heure de la dernière modification du mot de passe de l'administrateur sur chaque ordinateur. Ça facilite le suivi pour savoir si vos mots de passe administrateur sont tous synchronisés.

Quant au script lui-même, nous commençons par l'instruction On Error Resume Next. D'habitude, on ne s'embête pas avec la gestion des erreurs dans nos scripts. Ce n'est pas parce que nous sommes opposés à la gestion des erreurs, mais plutôt parce que nous essayons de garder nos scripts aussi courts et faciles à suivre que possible. Dans ce cas, cependant, la déclaration On Error Resume Next est cruciale. Après tout, notre script va essayer de se connecter à un grand nombre d'ordinateurs différents. Qu'est-ce qui se passe si l'un de ces ordinateurs est éteint ? Eh bien, avec la gestion des erreurs, rien ne se passe. Alors, bien sûr, une erreur se produira, mais le script pourra l'ignorer et continuer son travail. Sans la gestion des erreurs, vous obtiendriez probablement la même chose que notre scripteur quand il a allumé sa télé pour la première fois : rien.

Ensuite, nous utilisons le bloc de code suivant pour créer une instance de l'objet Excel.Application, faire apparaître cette instance d'Excel à l'écran et ouvrir le tableur C:\Scripts\Test.xls :

Set objExcel = CreateObject _
    (“Excel.Application”)
Set objWorkbook = objExcel.Workbooks.Open _
    (“C:\Scripts\Test.xls”)
objExcel.Visible = True

Dernière étape, mais pas des moindres : nous attribuons la valeur 2 à une variable de compteur nommée i. Nous utiliserons cette variable pour faire un suivi de notre colonne actuelle dans le tableur.

Remarque : Alors pourquoi est-ce qu'on attribue une valeur de 2 à i ? Rien de plus simple : Si vous regardez le tableur de près, vous verrez que nos données commencent en fait à la ligne 2. La ligne 1 est simplement une ligne d'en-tête.

Vous voyez ? Nous ne sommes peut-être pas très bons dans le branchement de prises péritel, mais, en script, on s'y connaît.

Enfin, parfois.

Nous sommes maintenant prêts à commencer le travail. Tout d'abord, nous paramétrons une boucle Do Until qui fonctionnera jusqu'à ce que le script rencontre une cellule vide dans la colonne 1. Et oui, ça veut dire que vous ne devez absolument pas laisser de ligne vide dans la colonne 1. Si votre script rencontre une ligne vide, il supposera qu'il a atteint la fin des données, et la boucle (donc le script) s'arrêtera. Et s'il existe des façons de contourner ce problème, il est beaucoup plus simple d'éviter d'avoir des lignes vierges dans votre tableur.

À l'intérieur de la boucle, nous commençons en attribuant la valeur recherchée dans la cellule de la ligne i et de la colonne 1 à une variable nommée strComputer. (Rappelez-vous que la première fois qu'il passe dans la boucle, i est égal à 2 ; donc nous allons travailler avec la valeur contenue dans la cellule de la ligne 2, colonne 1.) Nous utilisons ensuite cette ligne de code pour créer une référence objet (objUser) au compte de l'administrateur local sur l'ordinateur représenté par la variable strComputer :

Set objUser = GetObject(“WinNT://” & _
    strComputer & “/Administrator”)

Si une erreur se produit dans le script, c'est ici que ça sautera. Supposons par exemple qu'il y ait des problèmes de réseau, que l'ordinateur est éteint, ou que l'un des scripteurs ait mal branché son lecteur de DVD, provoquant un black-out dans tout l'Ouest des États-Unis. Si l'un de ces évènements se produisait, il serait impossible de se connecter à l'ordinateur en question. C'est pourquoi on vérifie tout de suite la valeur de l'objet Err de VBScript :

If Err = 0 Then

Si l'objet Err est égal à 0, c'est que nous avons réussi à nous connecter à l'ordinateur (et au compte de l'administrateur) sans aucun problème. Si Err a une autre valeur que 0, cela ne peut vouloir dire qu'une seule chose : notre tentative de connexion a échoué. Dans ce cas, nous n'allons même pas essayer de modifier le mot de passe sur cet ordinateur. Il va sans dire que si nous ne pouvons pas nous y connecter, nous ne pourrons pas modifier le mot de passe.

En supposant que tout se passe bien et qu'aucune erreur ne se produise, nous exécutons ensuite les deux lignes de code suivantes :

objUser.SetPassword “egTY634!alK2”
objExcel.Cells(i, 2).Value = Now

Dans la ligne 1, nous utilisons la méthode SetPassword pour attribuer un nouveau mot de passe (egTY634!alK2) au compte de l'administrateur local. (Et oui, on le sait : on n’est pas censé utiliser le nom de son enfant comme un mot de passe). Dans la ligne 2, nous écrivons ensuite la date et l'heure actuelles (en utilisant la fonction VB­Script Now) dans la cellule de la ligne i, colonne 2. Notez que nous ne mettons à jour la colonne Password Changed (mot de passe modifié) que si nous avons réussi à nous connecter à l'ordinateur distant et à modifier le mot de passe. Si nous ne parvenons pas à nous connecter à un ordinateur, son champ Password Changed ne sera jamais mis à jour ; c'est comme ça que nous pourrons faire la distinction entre les opérations qui ont réussi et celles qui ont échoué.

Qu’est-ce que ça signifie ? Ça veut dire que, pour le premier passage dans la boucle, notre tableur ressemblera à la figure 3.

Figure 3 Liste des ordinateurs après la réinitialisation du premier mot de passe

Figure 3** Liste des ordinateurs après la réinitialisation du premier mot de passe **(Cliquer sur l'image pour l'agrandir)

Voilà, c'est fait pour l'ordinateur 1. Maintenant, il nous faut faire un peu de ménage avant de continuer :

Err.Clear
i = i + 1

Ces lignes de code ont beau être courtes, elles n'en sont pas moins très importantes. (Comme si les scripteurs écrivaient des lignes de code superflues !) La première ligne réinitialise l'objet Err à 0. Si aucune erreur ne s'est produite, c'est redondant : dans ce cas, Err est déjà égal à 0. Mais si une erreur s'est produite, la valeur de Err sera différente de 0. Dans ce cas, il est crucial que nous réinitialisions manuellement l'objet Err. Pourquoi ? Parce que c'est l'objet Erreur : il prend seulement note des erreurs, pas des succès. Prenons un exemple : un problème survient avec l'ordinateur 1 et nous ne parvenons pas à nous connecter. Disons, à titre d'exemple, que ce problème a eu pour conséquence de régler l'objet Err sur 99.

Imaginons maintenant que nous passions à la boucle suivante et que nous réussissions à nous connecter à l'ordinateur 2. A ce moment-là, quelle sera la valeur de Err ? Bingo. Err sera toujours égale à 99, que ça vous plaise ou non, parce que la valeur de l'objet Err n'est modifié que si une erreur se produit. Mais si aucune erreur ne survient, l'objet Err restera indéfiniment à sa valeur actuelle.

Et c'est important ? Eh bien oui. Car, techniquement, nous ne modifions pas le mot de passe sur un ordinateur si nous réussissons à nous connecter : en fait, nous modifions le mot de passe seulement si Err est égal à 0. Et (une seconde, on ouvre la Calculatrice) oui, nous avions raison : 99 n'est pas égal à 0 (sauf, bien sûr, dans les votes de la famille du scripteur, où 99 votes de Papa scripteur comptent pour 0). Et c'est important pour nous parce que, même si nous avons réussi à nous connecter à l'ordinateur 2, Err n'est pas égal à 0. Et puisque Err n'est pas égal à 0, nous n'essayons même pas de modifier le mot de passe de l'administrateur local.

En d'autres termes, si la valeur de Err ne change jamais, vous devrez réinitialiser cette valeur à 0 ; autrement, à partir de ce moment-là, votre script croira qu'une erreur est survenue. Et comment réinitialise-t-on la valeur de l'objet Err à 0 ? Vous l'avez deviné : avec une simple invocation de Err.Clear.

Ensuite, nous incrémentons la valeur de i par 1. Pourquoi ? Eh bien, la première fois qu'elle passe dans la boucle, la variable i était égale à 2 ; c'est parce que nous voulions nous connecter à l'ordinateur listé à la ligne 2, colonne 1. La deuxième fois qu'elle passe dans la boucle, nous voulons nous connecter à l'ordinateur listé à la ligne 3, colonne 1. Comme i est la variable qui indique la ligne avec laquelle nous voulons travailler, nous devons faire en sorte que i soit égale à 3. Et, comme tout le monde sait, 2 + 1 = 3. (Heureusement qu'on n'avait pas fermé la Calculatrice, hein ?) C'est seulement à ce moment-là que nous ferons une nouvelle boucle et que nous répéterons le processus avec l'ordinateur suivant dans le tableur.

Maintenant, c'est sympa, mais comme nous ne sommes plus aussi naïfs que nous l'étions, nous sommes bien conscients que ce script, à lui seul, ne fera pas grand chose pour le problème évoqué dans le message électronique que nous avons reçu. « Bon, c'était bien sympa votre truc avec Excel », dira-t-on, « mais j'ai toujours besoin de modifier le mot de passe de l'administrateur local pour tous les ordinateurs dans une UO, ou pour tous les ordinateurs listés dans un fichier texte. Ou peut-être que j'aimerais pouvoir ouvrir un menu contextuel avec la liste des ordinateurs et pouvoir en sélectionner un à partir d'une zone de liste. Ou peut-être que j'aimerais aussi... »

On se calme. Les scripteurs sont là pour exaucer vos vœux. (En supposant que vous vouliez bien attendre quatre ans...) Il se trouve que nous avons de multiples modèles informatiques publiés sur le Script Center qui permettent d'exécuter facilement un script sur plusieurs machines. Par exemple, supposons que vous vouliez modifier le mot de passe de l'administrateur local pour tous les ordinateurs dans une UO. Aucun problème. Le modèle pour exécuter un script sur tous les ordinateurs d'une UO ressemble à la figure 4.

Figure 4 Exécution d'un script sur une UO

On Error Resume Next

Set objOU = GetObject(“LDAP://OU=Finance,dc=fabrikam,dc=com”)
objOU.Filter = Array(“Computer”)

For Each objComputer in objOU
    strComputer = objComputer.CN

    ‘ 
=====================================================================
    ‘ Insert your code here
    ‘ 
=====================================================================

    Set objComputer = GetObject(“WinNT://” & strComputer & “”)
    objComputer.Filter = Array(“User”)
    For Each objUser in objComputer
        Wscript.Echo objUser.Name
    Next

    ‘ 
=====================================================================
    ‘ End
    ‘ 
=====================================================================

Next

Vous voyez la section dans le modèle appelée « Insert your code here » ? Tout ce que vous avez à faire, c'est supprimer l'exemple de code de cette section et le remplacer par le code servant à modifier le mot de passe de l'administrateur local (que vous pouvez copier à partir de cet article). En d'autres termes, remplacez l'exemple de code par le code suivant :

Set objUser = GetObject(“WinNT://” & _
    strComputer & “/Administrator”)
If Err = 0 Then
    objUser.SetPassword “egTY634!alK2”
End If
Err.Clear

Cet exemple particulier n'enregistrera pas les résultats pour vous, mais vous pouvez facilement ajouter ce code tout seul. Remplacez l'exemple de code, modifiez la chaîne de connexion LDAP://OU=Finance,dc=fabri­kam,dc=com pour qu'elle pointe à l'une de vos UO, et c'est parti.

Pour tout vous dire, en fait nous avons publié ces modèles il y a plus d'un an, en pensant qu'ils feraient partie des éléments qui rencontreraient le plus grand succès parmi tous ceux que nous avons mis sur le Script Center. Nous avions tort : ils ne sont jamais utilisés, même si on nous écrit presque tous les jours en nous demandant grosso modo comment exécuter des scripts sur de multiples machines. Nous supposons que personne ne savait que ces modèles existaient. Mais maintenant, vous êtes au courant. Ou vous le serez si nous vous disons où les trouver : microsoft.com/technet/scriptcenter/scripts/templates. Humm, c'est peut-être pour ça que personne n'a jamais utilisé ces modèles...

Donc maintenant que les scripteurs ne sont plus aussi naïfs qu'avant, est-ce que ça signifie qu'ils ne sont plus aussi stupides et maladroits qu'ils ne l'étaient ? Disons qu'il il n'y a pas si longtemps, l'un des scripteurs avait décidé de passer son week-end à bricoler chez lui. Quand il est revenu au bureau lundi matin, il avait un pouce écrasé qui n'arrêtait pas de saigner et une grande entaille à la jambe.

Ce qui, en fait, n'était pas si mal que ça. Du moins pour un scripteur.

Les scripteurs Microsoft travaillent pour (enfin, sont employés par) Microsoft. Lorsqu'ils ne sont pas en train de jouer au base-ball, d'entraîner une équipe ou de regarder un match (ou de se livrer à de multiples autres activités), ils dirigent le Script Center TechNet. Vous pouvez le vérifier vous-même sur www.scriptingguys.com.

© 2008 Microsoft Corporation et CMP Media, LLC. Tous droits réservés. Toute reproduction, totale ou partielle, est interdite sans autorisation préalable.