- Using AWS Lambda functions with Docker containers - Fri, May 12 2023
- A Go AWS SDK example - Fri, Nov 11 2022
- Getting started with Jenkins - Tue, Aug 16 2022
I was working on a project recently that involved adding and moving users to Office 365. They wanted a way to generate and pass a list of random complex passwords for many new users to the admin team. They also required the ability to capture the user and password so they had a record in case the user required these details from first-line support. By using PowerShell, I came up with the New-ComplexPassword function.
I came across the .NET namespace System.Web.Security. Under this namespace is the Membership class. The MSDN documentation states this class "Validates user credentials and manages user settings." I used the GeneratePassword method in the function. This method takes two parameters to generate a random password, requiring the specified length and the number of special characters to use.
I'll describe the two parameters below (taken from MSDN):
length
Type: System.Int32
> The number of characters in the generated password. The length must be between 1 and 128 characters.
numberOfNonAlphanumericCharacters
Type: System.Int32
> The minimum number of non-alphanumeric characters (such as @, #, !, %, &, and so on) in the generated password.
Now that I know how I'm going generate the passwords, let's focus on how I built the function.
I created the function with two parameter sets. A parameter set gives a single cmdlet the ability to perform different actions for different scenarios. The two tasks I wanted to perform with this function were creating a single ad-hoc password and passing a list of usernames from the pipeline.
This is how I constructed the first part:
[Cmdletbinding(DefaultParameterSetName='Single')] Param( [Parameter(ParameterSetName='Single')] [Parameter(ParameterSetName='Multiple')] [Int] $PasswordLength, [Parameter(ParameterSetName='Single')] [Parameter(ParameterSetName='Multiple')] [int] $SpecialCharCount, [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName='Multiple')] [String[]] $GenerateUserPW )
The main two parameters take an integer, and the last parameter, which is in the 'multiple' parameter set, takes an array of strings.
Using the Syntax switch and the Get-Command cmdlet on the function shows the two parameter sets:
Get-Command New-ComplexPassword -Syntax
The Begin block of the function loads the System.Web assembly so we can use the Membership class:
Begin { # The System.Web namespaces contain types that enable browser/server communication Add-Type -AssemblyName System.Web }
The process block uses one of PowerShell's automatic variables, $PsCmdlet, in our switch statement. PowerShell's help system states this "Contains an object that represents the cmdlet or advanced function that is being run." We are using the ParameterSetName property, which gives us the name of the parameter set we're using. (To learn more about PowerShell automatic variables, read the help on about_Automatic_Variables.)
The switch gives us an either-or instance. This is where we'll use the System.Web.Security.Membership class. The static method described earlier takes two parameters. From the function, we pass our two parameters: password length and the special character count. This will generate our password.
Process { switch ($PsCmdlet.ParameterSetName) { 'Single' { # GeneratePassword static method: Generates a random password of the specified length [System.Web.Security.Membership]::GeneratePassword($PasswordLength, $SpecialCharCount) } 'Multiple' { $GenerateUserPW | Foreach { # Custom Object to display results New-Object -TypeName PSObject -Property @{ User = $_ Password = [System.Web.Security.Membership]::GeneratePassword($PasswordLength, $SpecialCharCount) } } } } # End of Switch }
The multiple part of the switch uses a foreach loop to parse each object to a custom object that will output the name with an assigned password.
Let's work with our function and see how we can use it.
Here is the function at its most basic level:
PS D:\> New-ComplexPassword -PasswordLength 16 -SpecialCharCount 1 %f.=vu%:hbANT)l
We can pass some users through the pipeline to the function, providing a password length of 10 characters and containing 2 special characters:
'John','Paul','George','Ringo' | New-ComplexPassword -PasswordLength 10 ‑SpecialCharCount 2
By using the range operator, I can generate many passwords quickly:
1..12 | New-ComplexPassword -PasswordLength 16 -SpecialCharCount 5
Finally, to show the flexibility of the function, I can pass and generate a text file with a list of passwords by typing the following:
(1..5 | New-ComplexPassword -PasswordLength 10 -SpecialCharCount 1).Password | Out-File c:\demo\Passwords.csv -Encoding utf8 -Force
This is a great example of using .NET classes with PowerShell to generate passwords quickly and efficiently.
And this is the function in full:
Subscribe to 4sysops newsletter!
Function New-ComplexPassword { <# .SYNOPSIS Password Generator .DESCRIPTION Password Generator tool to obtain any length and numbers of passwords, adding desired number of special characters, quickly. .PARAMETER PasswordLength Add a integer value for desired password length .PARAMETER SpecialCharCount Add a integer value for desired number of special characters .PARAMETER GenerateUserPW Enter as many named string or integer values .EXAMPLE 'John','Paul','George','Ringo' | New-ComplexPassword -PasswordLength 10 -SpecialCharCount 2 1..5 | New-ComplexPassword -PasswordLength 16 -SpecialCharCount 5 .NOTES By Graham Beer #> [Cmdletbinding(DefaultParameterSetName='Single')] Param( [Parameter(ParameterSetName='Single')] [Parameter(ParameterSetName='Multiple')] [Int] $PasswordLength, [Parameter(ParameterSetName='Single')] [Parameter(ParameterSetName='Multiple')] [int] $SpecialCharCount, [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName='Multiple')] [String[]] $GenerateUserPW ) Begin { # The System.Web namespaces contain types that enable browser/server communication Add-Type -AssemblyName System.Web } Process { switch ($PsCmdlet.ParameterSetName) { 'Single' { # GeneratePassword static method: Generates a random password of the specified length [System.Web.Security.Membership]::GeneratePassword($PasswordLength, $SpecialCharCount) } 'Multiple' { $GenerateUserPW | Foreach { # Custom Object to display results New-Object -TypeName PSObject -Property @{ User = $_ Password = [System.Web.Security.Membership]::GeneratePassword($PasswordLength, $SpecialCharCount) } } } } # End of Switch } End {} } # End of Function
Hi Graham, thanks for this post which I found useful. I wanted to create complex passwords for use with O365 and which would be within the set restrictions, but I also wanted the passwords to be easier for my users to type in. If you’re interested, I wrote about it here.