3 minute read

Anyone that worked with VMware Cloud Foundation (VCF) knows that passwords and valid special characters can be a tricky business.

In summary, the set of special characters allowed by VCF, is a subset of the ones that some of the individual products admit.

When I was developing some automation to deploy VCF Nested Labs there was the need of generation some random passwords on demand instead of using the same passwords for all the nested environments.

After some search and some stumbling around, I found a good base to start from and to implement my own random password generator function.

Code based on New-RandomPassword.ps1

Objective

Having a function that generates random passwords with the necessary complexity and size to use in VCF deployments.

Complexity Requirements

  • Length - 8-20 characters
  • At least one Uppercase, lowercase, number & special character
  • Special characters allowed: @ ! # $ % ? ^

Password validation regular expression

Generating random passwords is easy, the difficulty is in validating that password against our complexity requirements.

An regular expression is probably one of the ways of doing it.

The regexp used by the function and based in New-RandomPassword.ps1

^((?=.*[a-z])(?=.*[A-Z])(?=.*[^A-Za-z0-9]))([A-Za-z\d@!#$%?^]){8,20}$

Some additional randomization by making the order of the characters in seed array random

To remove some of the non-valid characters from ASCII table, we create a seed array to be the source of our characters for the passwords. We shuffle the array just to get some extra randomization (not that it makes an huge difference).

And we created a list of the valid chars for our password generation.

$seedArray = (48..57) + (65..90) + (97..122) + @(33, 36, 37, 94)
$seedArray = $seedArray | Sort-Object Get-Random

$asciiCharsList = @()
foreach ($a in $seedArray){
    $asciiCharsList += , [char][byte]$a 
}

Now we generate passwords based on our character list until we get one valid one

do {
        $password = ""
        $loops = 1..$length
        Foreach ($loop in $loops) {
            $password += $asciiCharsList | Get-Random
        }
    } until ($password -match $regExp )

Entire function

function New-RandomPassword {
    <#
    .SYNOPSIS
        Random Password Generator function

    .DESCRIPTION
        Random Password Generator function

    .PARAMETER length
        Length of the password to generate (defaults to 16)

    .EXAMPLE

    .NOTES
        Original code from https://github.com/PaoloFrigo/scriptinglibrary/blob/master/Blog/PowerShell/New-RandomPassword.ps1
    #>
    Param(
        [ValidateRange(8, 32)]
        [int] $length = 16
    )  

    # Add some extra randomization by creating the "seed array" randomly
    # Remove double quotes and slash and black slash
    $seedArray = (48..57) + (65..90) + (97..122) + @(33, 36, 37, 94)
    $seedArray = $seedArray | Sort-Object Get-Random

    $asciiCharsList = @()
    foreach ($a in $seedArray){
        $asciiCharsList += , [char][byte]$a 
    }
    #regExp allowing only special characters @!#$%?^ as per VCF/VMware
    $regExp = "^((?=.*[a-z])(?=.*[A-Z])(?=.*[^A-Za-z0-9]))([A-Za-z\d@!#$%?^]){8,20}$"

    do {
        $password = ""
        $loops = 1..$length
        Foreach ($loop in $loops) {
            $password += $asciiCharsList | Get-Random
        }
    } until ($password -match $regExp )

    return $password  
}