PowerShell – Comment générer un mot de passe aléatoire ?

I. Présentation

Créer des comptes Active Directory pour les nouveaux collaborateurs arrivant dans l’entreprise, c’est l’une des tâches les plus courantes et les plus répétitives qui soit.

C’est d’ailleurs l’une des premières tâches que vous automatisez.

Et la même question revient à chaque fois : comment faire pour automatiser la création d’un mot de passe aléatoire en PowerShell ?

Je vois souvent dans vos scripts deux cas de figure :

  • Le premier : mettre un mot de passe par défaut en « Password1 », à changer à la première connexion
  • Le second : Générer un mot de passe dans une application telle que Keepass ou motdepasse.xyz, puis le copier/coller dans le terminal PowerShell, pour finaliser la création du compte Active Directory.

Et bien, vous allez maintenant pouvoir utiliser un troisième cas de figure : une fonction vous permettant de générer un mot de passe aléatoire conforme à votre politique de sécurité.

🎥 Disponible au format vidéo :

II. Prérequis

Un seul et unique prérequis à respecter :

  • PowerShell version 5.1 ou +

III. La méthode .NET

La première possibilité (et celle qui demande le moins de lignes de code), c’est d’utiliser une méthode existante en .NET.

Pour cela, ajoutez dans votre script les commandes suivantes :

Add-Type -AssemblyName 'System.Web'
[System.Web.Security.Membership]::GeneratePassword($Length, $SpecialCharacters)

Il vous suffit de remplacer la variable $Length par le nombre de caractères à respecter, et la variable $SpecialCharacters par le nombre minimal de caractères spéciaux à respecter.

Par exemple, pour générer un mot de passe de 10 caractères, avec un minimum de 2 caractères non alphanumériques, il vous faut taper :

[System.Web.Security.Membership]::GeneratePassword(10, 2)

Mais cette méthode comprend un inconvénient majeur : vous pouvez vous retrouver avec des mots de passe à plus de 2 caractères spéciaux, certains avec uniquement des minuscules, etc. Ce qui fait qu’on peut se retrouver avec des mots de passe ne respectant pas la politique de mot de passe de l’entreprise, ou alors qui la respecte, mais qui sont tellement difficile à taper pour l’utilisateur que vous allez vous retrouver très rapidement à le changer dans l’Active Directory.

Voici quelques exemples :

IV. Créer sa propre fonction PowerShell

Du coup face à ces deux problématiques majeures, j’ai créé une fonction PowerShell pour générer un nouveau mot de passe aléatoire pour un utilisateur, tout en :

  • Pouvant choisir la taille du mot de passe, le nombre de majuscules à mettre, le nombre de chiffres ainsi que le nombre de caractères spéciaux
  • Respectant la politique de mot de passe de l’entreprise

Copier un code qui fonctionne c’est top, notamment pour vous dépanner d’un coup dur. Mais comprendre ce qu’on a copié, et pourquoi ça fonctionne, c’est mieux. Décomposons donc ensemble la fonction que l'on va créer.

A. Explications

On commence par déclarer notre fonction.

J’ai nommé la fonction New-RandomPassword afin de respecter la convention de nommage en PowerShell, qui est Verbe-Nom.

function New-RandomPassword {
    [CmdletBinding()]
    Param()
    Begin {}
    Process {}
    End {}
}

Bien, on a maintenant un squelette vide, qu’il va falloir remplir.

Commençons par lui indiquer quels sont les paramètres de la fonction. Autrement dit, quelles sont les options que l’on va pouvoir lui passer lorsqu’on y fera appel.

Nous avons besoin de 4 paramètres, afin de pouvoir générer un mot de passe aléatoire qui colle parfaitement à votre politique de sécurité / à vos besoins spécifiques :

  • La taille du mot de passe en nombre de caractères
  • Le nombre de majuscules
  • Le nombre de chiffres
  • Le nombre de caractères spéciaux (non-alphanumériques)

Ces 4 paramètres sont de type [int] : ils n'accepteront qu’un chiffre comme valeur.

On va également considérer que le premier paramètre, la taille du mot de passe, est obligatoire (mandatory). Sans cela, on ne sait pas quelle taille générer, et donc quel mot de passe générer.

Les autres paramètres sont optionnels, et ont tous une valeur par défaut de 1 (que vous pouvez bien sûr changer).

Donc si vous appelez la fonction avec la commande :

New-RandomPassword -Length 10

Vous générez en fait un mot de passe de 10 caractères, contenant 1 majuscule, 1 chiffre, et 1 caractère non-alphanumérique.

Si vous souhaitez faire varier le nombre de majuscules, de chiffres, ou de caractères spéciaux, vous pouvez alors appeler la fonction comme ceci :

New-RandomPassword -Length 10 -Uppercase 2 -Digits 3 -SpecialCharacters 3

Bien. Si l’on traduit donc maintenant cela en PowerShell, voici comment nous allons déclarer nos paramètres :

function New-RandomPassword {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true)][int]$Length,
        [Parameter(Mandatory=$false)][int]$Uppercase=1,
        [Parameter(Mandatory=$false)][int]$Digits=1,
        [Parameter(Mandatory=$false)][int]$SpecialCharacters=1
    )
}

Note : Il n’est pas obligatoire d’écrire (Mandatory=$false) pour déclarer qu’un paramètre est optionnel, mais je le fais systématiquement pour faciliter la lecture.

À l’intérieur de notre fonction, nous avons déclaré au-dessus trois sections :

Begin {}
Process {}
End {}

Ce n’est pas obligatoire non plus, mais on considère cela comme une bonne pratique.

  • La section Begin{} va vous servir généralement à initialiser les variables nécessaires pour votre fonction, ou à vérifier par exemple que les paramètres saisis correspondent bien à ce que vous attendez.
  • La section Process{} contient le cœur de votre fonction : la majorité de votre code se trouvera donc ici.
  • La section End{} contient généralement les retours utilisateurs, si vous voulez renvoyer à l’utilisateur un mot de passe aléatoirement généré par exemple, ou alors les déconnexions bases de données, etc.

Commençons par la section Begin{}.

Maintenant que nous connaissons la taille du mot de passe ($Length), le nombre de majuscules ($Uppercase), le nombre de chiffres ($Digits), ainsi que le nombre de caractères spéciaux ($SpecialCharacters), on peut donc calculer le nombre de minuscules que le mot de passe devra comporter. Ce qui nous donne :

Begin {
        $Lowercase = $Length - $SpecialCharacters - $Uppercase - $Digits
    }

On va également déclarer 3 tableaux, contenant les caractères minuscules, majuscules et spéciaux que l’on souhaite voir apparaître dans le mot de passe.

Begin {
        $Lowercase = $Length - $SpecialCharacters - $Uppercase - $Digits
        $ArrayLowerCharacters = @('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z')
        $ArrayUpperCharacters = @('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z')
        $ArraySpecialCharacters = @('_','*','$','%','#','?','!','-')
    }

Note : L’avantage de le faire de cette manière est que cela vous laisse toute latitude pour enlever certains caractères, parmi ceux disponibles pour le mot de passe.

Il est maintenant temps de passer à la section Process{} de la fonction, là où la magie opère.

On va créer une nouvelle variable de type [string], $NewPassword, et choisir aléatoirement des lettres minuscules, selon la valeur de $Lowercase. On utilise pour cela la commande Get-Random à laquelle on passe via un pipeline le tableau de lettres minuscules que l’on a précédemment créé : $LowerCharacters.

On répète ensuite cela pour les chiffres, puis les majuscules, puis les caractères spéciaux.

Process {
[string]$NewPassword = $ArrayLowerCharacters | Get-Random -Count $Lowercase
            $NewPassword += 0..9 | Get-Random -Count $Digits
            $NewPassword += $ArrayUpperCharacters | Get-Random -Count $Uppercase
            $NewPassword += $ArraySpecialCharacters | Get-Random -Count $SpecialCharacters
}

Note : 0..9 indique une suite de chiffre continue de 0 à 9. La commande 0..9 | Get-Random -Count $Digits demande donc à PowerShell de choisir aléatoirement X chiffres entre 0 et 9.

Cette méthode a toutefois deux inconvénients :

  • Le premier, c’est qu’entre chaque caractère, on se retrouve avec un espace. Votre mot de passe « Password1 » est donc : « P a s s w o r d 1 ». C’est donc inutilisable en l’état.
  • Le second, c’est que votre mot de passe est actuellement de la forme : abc22ABC%. On a donc choisi aléatoirement des caractères, mais leur placement dans la chaîne de caractères est prévisible : ce n’est pas ce que l’on cherche. Il va donc falloir retravailler cela.

Pour répondre au premier inconvénient, on va utiliser la méthode Replace qui fonctionne très bien pour les chaînes de caractères. Dans notre cas, on cherche à remplacer les espaces par rien, donc à éliminer les espaces.

$NewPassword = $NewPassword.Replace(' ','')

Il nous reste maintenant à traiter le second inconvénient : mélanger de manière aléatoire les caractères que l’on a retenus.

Pour cela, on va transformer la chaîne de caractères en tableau, puis mélanger les caractères entre eux, avant de retransformer le résultat en chaîne de caractères.

$characterArray = $NewPassword.ToCharArray()  
$scrambledStringArray = $characterArray | Get-Random -Count $characterArray.Length     
$NewRandomPassword = -join $scrambledStringArray

Le plus gros est fait, mais si vous vous arrêtez là, votre fonction marche, un mot de passe aléatoire est bien créé, mais à aucun moment vous ne le verrez puisqu’on n’a pas demandé explicitement à la fonction de vous retourner la valeur du mot de passe.

Il nous reste donc à modifier la section End{} pour retourner le mot de passe.

End {
  Return $NewRandomPassword
}

Vous voici maintenant avec une fonction de génération de mot de passe aléatoire, le tout en PowerShell !

Testons enfin notre fonction, en générant un mot de passe de 15 caractères, dont 3 majuscules, 2 chiffres, et 2 caractères spéciaux :

New-RandomPassword -Length 15 -Uppercase 3 -Digits 2 -SpecialCharacters 2

Contrairement à tout à l’heure, on peut voir que les mots de passe ont bien tous 2 caractères spéciaux, et non pas un minimum de 2. Et ça fait toute la différence !

 

B. La fonction en action

Si vous souhaitez tester cette fonction, voici sans plus attendre le code à recopier dans votre script :

function New-RandomPassword {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true)][int]$Length,
        [Parameter(Mandatory=$false)][int]$Uppercase=1,
        [Parameter(Mandatory=$false)][int]$Digits=1,
        [Parameter(Mandatory=$false)][int]$SpecialCharacters=1
    )
    Begin {
        $Lowercase = $Length - $SpecialCharacters - $Uppercase - $Digits
        $ArrayLowerCharacters = @('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z')
        $ArrayUpperCharacters = @('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z')
        $ArraySpecialCharacters = @('_','*','$','%','#','?','!','-')
    }
    Process {
            [string]$NewPassword = $ArrayLowerCharacters | Get-Random -Count $Lowercase
            $NewPassword += 0..9 | Get-Random -Count $Digits
            $NewPassword += $ArrayUpperCharacters | Get-Random -Count $Uppercase
            $NewPassword += $ArraySpecialCharacters | Get-Random -Count $SpecialCharacters

            $NewPassword = $NewPassword.Replace(' ','')

            $characterArray = $NewPassword.ToCharArray()  
            $scrambledStringArray = $characterArray | Get-Random -Count $characterArray.Length    
            $NewRandomPassword = -join $scrambledStringArray
    }
    End {
            Return $NewRandomPassword
    }
}

N’oubliez pas que pour utiliser cette fonction, vous devrez l’appeler dans votre script de la manière suivante :

New-RandomPassword -Length $Length -Uppercase $Uppercase -Digits $Digits -SpecialCharacters $SpecialCharacters
  • $Length correspond à la taille de votre mot de passe
  • $Uppercase correspond au nombre de majuscules
  • $Digits correspond au nombre de chiffres
  • $SpecialCharacters correspond au nombre de caractères non-alphanumériques

En l’état, ce code est fonctionnel, mais si on souhaite bien faire les choses, il faudrait encore ajouter des commentaires, si possible visible via la commande Get-Help, ainsi que des contrôles d'erreur.

Pour voir à quoi cela ressemble, faites un tour sur ma page Github, vous pourrez alors récupérer cette fonction avancée avec les commentaires, ainsi que les contrôles d'erreurs.

Script - New-RandomPassword.ps1

V. Conclusion

Vous savez maintenant ce qu’il vous reste à ajouter dans vos scripts PowerShell pour automatiser la création d’un utilisateur, et générer un mot de passe aléatoire qui respecte la politique de sécurité de l’entreprise, tout en étant relativement simple à saisir pour l’utilisateur.

Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Partager sur Google+ Envoyer par mail

Thibault Baheux

Responsable Infrastructure IT, Geek, Manager de geeks, Je travaille au quotidien sur une infra Cloud privée / Cloud Azure, aussi bien Windows que Linux. Je me passionne pour Azure & AWS, le DevOps, la sécurité & la programmation objet (PowerShell / Python). Si je ne suis pas derrière mon clavier, vous me trouverez dans une salle de blocs ou devant un bon mur d’escalade.

thibault-baheux a publié 14 articlesVoir toutes les publications de cet auteur

Laisser un commentaire

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

 

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.