SampleScripts/ppm/passwordPolicyManager.ps1
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. <# .SYNOPSIS Generate Password Policy Report and Configure Password Policies .DESCRIPTION The passwordPolicyManager.ps1 provides a single script to generate a Password Policy Report for audit purposes and to configure password policies based on a standard common policies configuration. .EXAMPLE passwordPolicyManager.ps1 -sddcFqdn sfo-vcf01.sfo.rainpole.io -sddcUser administrator@vsphere.local -sddcPass VMw@re1! -sddcDomain sfo-m01 -wsaFqdn sfo-wsa01.sfo.rainpole.io -wsaUser admin -wsaPass VMw@re1! -outputFile ".\sfo-m01_domain_pp_report.json" -commonPolicyFile ".\standardConfigure.json" -publishJSON Generates a Password Policy Report to a JSON file based on the -outputFile parameter for the provided Workload Domain containing all ESXi hosts, vCenter Server, vCenter Single Sign-On, NSX Manager, NSX Edge, and Workspace ONE Access nodes and the highlights the differences between the policies collected against a common policy file based on the -commonPolicyFile parameter. .EXAMPLE passwordPolicyManager.ps1 -sddcFqdn sfo-vcf01.sfo.rainpole.io -sddcUser administrator@vsphere.local -sddcPass VMw@re1! -sddcDomain sfo-m01 -wsaFqdn sfo-wsa01.sfo.rainpole.io -wsaUser admin -wsaPass VMw@re1! -outputFile ".\sfo-m01_domain_pp_report.html" -publishHTML Generates a Password Policy Report to a HTML file based on the -outputFile parameter for the provided Workload Domain containing all ESXi hosts, vCenter Server, vCenter Single Sign-On, NSX Manager, NSX Edge, and Workspace ONE Access nodes. .EXAMPLE passwordPolicyManager.ps1 -sddcFqdn sfo-vcf01.sfo.rainpole.io -sddcUser administrator@vsphere.local -sddcPass VMw@re1! -sddcDomain sfo-m01 -wsaFqdn sfo-wsa01.sfo.rainpole.io -wsaUser admin -wsaPass VMw@re1! -outputFile ".\sfo-m01_domain_pp_report.html" -commonPolicyFile ".\standardConfigure.json" -publishHTML Generates a Password Policy Report to a HTML file based on the -outputFile parameter for the provided Workload Domain containing all ESXi hosts, vCenter Server, vCenter Single Sign-On, NSX Manager, NSX Edge. and Workspace ONE Access nodes as well as highlights the differences between the policies collected against a common policy file based on the -commonPolicyFile parameter. .EXAMPLE passwordPolicyManager.ps1 -sddcFqdn sfo-vcf01.sfo.rainpole.io -sddcUser administrator@vsphere.local -sddcPass VMw@re1! -sddcDomain sfo-m01 -wsaFqdn sfo-wsa01.sfo.rainpole.io -wsaUser admin -wsaPass VMw@re1! -commonPolicyFile ".\standardConfigure.json" -applyPasswordPolicy Configures password policies as defined by the common policy file based on the -commonPolicyFile parameter for all ESXi hosts, vCenter Server, vCenter Single Sign-On, NSX Manager, NSX Edge, and Workspace ONE Access nodes for a given Workload Domain. .EXAMPLE passwordPolicyManager.ps1 -sddcFqdn sfo-vcf01.sfo.rainpole.io -sddcUser administrator@vsphere.local -sddcPass VMw@re1! -sddcDomain sfo-w01 -ssoFqdn sfo-m01-vc01.sfo.rainpole.io -ssoUser administrator@vsphere.local -ssoPass VMw@re1! -wsaFqdn sfo-wsa01.sfo.rainpole.io -wsaUser admin -wsaAdminPass VMw@re1! -outputFile ".\sfo-m01_domain_pp_report.html" -publishHTML Generates a Password Policy Report to a HTML file based on the -outputFile parameter for the provided Workload Domain containing all ESXi hosts, vCenter Server, NSX Manager, NSX Edge, Workspace ONE Access nodes, and a vCenter Single Sign-On external to the provided Workload Domain. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcFqdn, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcUser, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcPass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcDomain, [Parameter (mandatory = $false)] [String]$ssoFqdn, [Parameter (mandatory = $false)] [String]$ssoUser, [Parameter (mandatory = $false)] [String]$ssoPass, [Parameter (mandatory = $false)] [String]$wsaFqdn, [Parameter (mandatory = $false)] [String]$wsaUser, [Parameter (mandatory = $false)] [String]$wsaPass, [Parameter (mandatory = $false)] [String]$commonPolicyFile, [Parameter (mandatory = $false)] [String]$outputFilePath, [Parameter (mandatory = $false)] [Switch]$publishHTML = $false, [Parameter (mandatory = $false)] [Switch]$publishJSON = $false, [Parameter (mandatory = $false)] [Switch]$driftOnly = $false, [Parameter (mandatory = $false)] [Switch]$applyPasswordPolicy = $false ) Clear-Host; Write-Host "" ################ Perform Prerequisite Check #################### Function Test-PasswordPolicyManagerPrereq { <# .SYNOPSIS Validate prerequisites to run the PowerShell module. .DESCRIPTION The Test-PasswordPolicyManagerPrereq cmdlet checks that all the prerequisites have been met to run the PowerShell module. .EXAMPLE Test-PasswordPolicyManagerPrereq This example runs the prerequisite validation. #> Try { $modules = @( @{ Name=("PowerVCF"); Version=("2.2.0")} @{ Name=("PowerValidatedSolutions"); Version=("1.8.0")} @{ Name=("VMware.PowerCLI"); Version=("12.4.1")} @{ Name=("VMware.vSphere.SsoAdmin"); Version=("1.3.8")} ) foreach ($module in $modules ) { if ($PSEdition -eq "Desktop") { if ((Get-InstalledModule -Name $module.Name).Version -lt $module.Version) { $message = "PowerShell Module: $($module.Name) Version: $($module.Version) Not Installed, Please update before proceeding." Write-Warning $message; Write-Host "" Exit } else { $message = "PowerShell Module: $($module.Name) Version: $($module.Version) Found, Supports the minimum required version." $message } } else { if (!$module -eq "VMware.PowerCLI") { if ((Get-Module -Name $module.Name).Version -lt $module.Version) { $message = "PowerShell Module: $($module.Name) Version: $($module.Version) Not Installed, Please update before proceeding." Write-Warning $message; Write-Host "" Exit } else { $message = "PowerShell Module: $($module.Name) Version: $($module.Version) Found, Supports the minimum required version." $message } } } } } Catch { Write-Error $_.Exception.Message } } ################################################################################## #### Parsing through standard configuration files to extract common values ##### #### *importStandardConfigurations function will take in commonvalue file ##### #### check values ranges and parse through each product and produce ##### #### $ppmStandardConfigValues (which contains all standard password ##### #### setting values. ##### ################################################################################## Function parseProductTypeESXiConfiguration { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$productConfiguration, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmStandardConfigValues ) $esxiConfigTypeValues = New-Object -TypeName psobject $esxiConfigTypeValues | Add-Member -notepropertyname "passwdExpInDays" -notepropertyvalue "Default" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMaxFailAttempts" -notepropertyvalue "Default" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLengthFor1CharClass" -notepropertyvalue "disabled" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLengthFor2CharClass" -notepropertyvalue "disabled" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLengthFor3CharClass" -notepropertyvalue "disabled" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLengthFor4CharClass" -notepropertyvalue "Default" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMinimumCharLengthForPhrase" -notepropertyvalue "disabled" foreach ($configuration in $productConfiguration.ESXi.PSObject.Properties) { if ($configuration.Name -eq "passwdMinimumLength") { $esxiConfigTypeValues.passwdMinimumLengthFor4CharClass = $configuration.Value } elseif ($esxiConfigTypeValues.psobject.properties.match($configuration.Name).Count) { $esxiConfigTypeValues.$($configuration.Name) = $configuration.Value } else { Write-LogMessage -Type ERROR -Message "Parameter $($configuration.Name) not found (ESXi)." -Colour Red } } foreach ($configuration in $productConfiguration.Default.PSObject.Properties) { if ($esxiConfigTypeValues.psobject.properties.match($configuration.Name).Count) { if ($esxiConfigTypeValues.$($configuration.Name) -eq "Default") { $esxiConfigTypeValues.$($configuration.Name) = $configuration.Value } } if ($configuration.Name -eq "passwdMinimumLength") { if ($esxiConfigTypeValues.passwdMinimumLengthFor4CharClass -eq "Default") { $esxiConfigTypeValues.passwdMinimumLengthFor4CharClass = $configuration.Value } } } $standardConfigValue = New-Object -TypeName psobject $standardConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "ESXi" $standardConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue $esxiConfigTypeValues $ppmStandardConfigValues.Add($standardConfigValue) } Function parseProductTypeVCConfiguration{ Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$productConfiguration, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmStandardConfigValues ) $VCConfigTypeValues = New-Object -TypeName psobject $VCConfigTypeValues | Add-Member -notepropertyname "passwdExpInDays" -notepropertyvalue "Default" $VCConfigTypeValues | Add-Member -notepropertyname "passwdNotifyEmail" -notepropertyvalue "Default" foreach ($configuration in $productConfiguration.VC.PSObject.Properties) { if ($VCConfigTypeValues.psobject.properties.match($configuration.Name).Count) { $VCConfigTypeValues.$($configuration.Name) = $configuration.Value } else { Write-LogMessage -Type ERROR -Message "Parameter ("$configuration.Name") not found (VC)." -Colour Red } } foreach ($configuration in $productConfiguration.Default.PSObject.Properties) { if ($VCConfigTypeValues.psobject.properties.match($configuration.Name).Count) { if ($VCConfigTypeValues.$($configuration.Name) -eq "Default") { $VCConfigTypeValues.$($configuration.Name) = $configuration.Value } } } $standardConfigValue = New-Object -TypeName psobject $standardConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "VC" $standardConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue $VCConfigTypeValues $ppmStandardConfigValues.Add($standardConfigValue) } Function parseProductTypeSSOConfiguration{ Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$productConfiguration, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmStandardConfigValues ) $SSOConfigTypeValues = New-Object -TypeName psobject $SSOConfigTypeValues | Add-Member -notepropertyname "passwdExpInDays" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdHistoryRestriction" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLength" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdMaximumLength" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdMinUppercase" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdMinLowercase" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdMinAlphabetic" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdMinNumeric" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdMinSpecial" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdMaxConsecutiveIdenticalChar" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdMaxFailAttempts" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdAttemptsIntervalInSec" -notepropertyvalue "Default" $SSOConfigTypeValues | Add-Member -notepropertyname "passwdUnlockIntervalInSec" -notepropertyvalue "Default" foreach ($configuration in $productConfiguration.SSO.PSObject.Properties) { if ($SSOConfigTypeValues.psobject.properties.match($configuration.Name).Count) { $SSOConfigTypeValues.$($configuration.Name) = $configuration.Value } else { Write-LogMessage -Type ERROR -Message "Parameter ("$configuration.Name") not found (SSO)." -Colour Red } } foreach ($configuration in $productConfiguration.Default.PSObject.Properties) { if ($SSOConfigTypeValues.psobject.properties.match($configuration.Name).Count) { if ($SSOConfigTypeValues.$($configuration.Name) -eq "Default") { $SSOConfigTypeValues.$($configuration.Name) = $configuration.Value } } } $standardConfigValue = New-Object -TypeName psobject $standardConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "SSO" $standardConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue $SSOConfigTypeValues $ppmStandardConfigValues.Add($standardConfigValue) } Function parseProductTypeNSXMgrConfiguration { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$productConfiguration, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmStandardConfigValues ) $NSXMgrConfigTypeValues = New-Object -TypeName psobject $NSXMgrConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLength" -notepropertyvalue "Default" $NSXMgrConfigTypeValues | Add-Member -notepropertyname "apiPasswdMaxFailAttempts" -notepropertyvalue "Default" $NSXMgrConfigTypeValues | Add-Member -notepropertyname "apiPasswdMaxFailIntervalInSec" -notepropertyvalue "Default" $NSXMgrConfigTypeValues | Add-Member -notepropertyname "apiPasswdUnlockIntervalInSec" -notepropertyvalue "Default" $NSXMgrConfigTypeValues | Add-Member -notepropertyname "cliPasswdMaxFailAttempts" -notepropertyvalue "Default" $NSXMgrConfigTypeValues | Add-Member -notepropertyname "cliPasswdMaxFailIntervalInSec" -notepropertyvalue "Default" foreach ($configuration in $productConfiguration.NSXMgr.PSObject.Properties) { if ($NSXMgrConfigTypeValues.psobject.properties.match($configuration.Name).Count) { $NSXMgrConfigTypeValues.$($configuration.Name) = $configuration.Value } else { Write-LogMessage -Type ERROR -Message "Parameter ("$configuration.Name") not found (NSXEdge)." -Colour Red } } foreach ($configuration in $productConfiguration.Default.PSObject.Properties) { if ($NSXMgrConfigTypeValues.psobject.properties.match($configuration.Name).Count) { if ($NSXMgrConfigTypeValues.$($configuration.Name) -eq "Default") { $NSXMgrConfigTypeValues.$($configuration.Name) = $configuration.Value } } if ($NSXMgrConfigTypeValues.psobject.properties.match($("api"+$($configuration.Name))).Count) { if ($NSXMgrConfigTypeValues.$($("api"+$($configuration.Name))) -eq "Default") { $NSXMgrConfigTypeValues.$($("api"+$($configuration.Name))) = $configuration.Value } } if ($NSXMgrConfigTypeValues.psobject.properties.match($("cli"+$($configuration.Name))).Count) { if ($NSXMgrConfigTypeValues.$($("cli"+$($configuration.Name))) -eq "Default") { $NSXMgrConfigTypeValues.$($("cli"+$($configuration.Name))) = $configuration.Value } } } $standardConfigValue = New-Object -TypeName psobject $standardConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "NSXMgr" $standardConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue $NSXMgrConfigTypeValues $ppmStandardConfigValues.Add($standardConfigValue) } Function parseProductTypeNSXEdgeConfiguration { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$productConfiguration, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmStandardConfigValues ) $NSXEdgeConfigTypeValues = New-Object -TypeName psobject $NSXEdgeConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLength" -notepropertyvalue "Default" $NSXEdgeConfigTypeValues | Add-Member -notepropertyname "cliPasswdMaxFailAttempts" -notepropertyvalue "Default" $NSXEdgeConfigTypeValues | Add-Member -notepropertyname "cliPasswdMaxFailIntervalInSec" -notepropertyvalue "Default" foreach ($configuration in $productConfiguration.NSXEdge.PSObject.Properties) { if ($NSXEdgeConfigTypeValues.psobject.properties.match($configuration.Name).Count) { $NSXEdgeConfigTypeValues.$($configuration.Name) = $configuration.Value } else { Write-LogMessage -Type ERROR -Message "Parameter ("$configuration.Name") not found (NSXEdge)." -Colour Red } } foreach ($configuration in $productConfiguration.Default.PSObject.Properties) { if ($NSXEdgeConfigTypeValues.psobject.properties.match($configuration.Name).Count) { if ($NSXEdgeConfigTypeValues.$($configuration.Name) -eq "Default") { $NSXEdgeConfigTypeValues.$($configuration.Name) = $configuration.Value } } if ($NSXEdgeConfigTypeValues.psobject.properties.match($("cli"+$($configuration.Name))).Count) { if ($NSXEdgeConfigTypeValues.$($("cli"+$($configuration.Name))) -eq "Default") { $NSXEdgeConfigTypeValues.$($("cli"+$($configuration.Name))) = $configuration.Value } } } $standardConfigValue = New-Object -TypeName psobject $standardConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "NSXEdge" $standardConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue $NSXEdgeConfigTypeValues $ppmStandardConfigValues.Add($standardConfigValue) } Function parseProductTypeWSAConfiguration { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$productConfiguration, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmStandardConfigValues ) $WSAConfigTypeValues = New-Object -TypeName psobject $WSAConfigTypeValues | Add-Member -notepropertyname "passwdExpInDays" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdHistoryRestriction" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLength" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdMinUppercase" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdMinLowercase" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdMinNumeric" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdMinSpecial" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdMaxConsecutiveIdenticalChar" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdMaxPreviousCharactersReused" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdMaxFailAttempts" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdAttemptsIntervalInMins" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdUnlockIntervalInMins" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "tempPasswdLifetimeInHour" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdExpReminderInDay" -notepropertyvalue "Default" $WSAConfigTypeValues | Add-Member -notepropertyname "passwdExpReminderNotificationFrequencyInDay" -notepropertyvalue "Default" foreach ($configuration in $productConfiguration.WSA.PSObject.Properties) { if ($WSAConfigTypeValues.psobject.properties.match($configuration.Name).Count) { $WSAConfigTypeValues.$($configuration.Name) = $configuration.Value } else { Write-LogMessage -Type ERROR -Message "Parameter ("$configuration.Name") not found (WSA)." -Colour Red } } foreach ($configuration in $productConfiguration.Default.PSObject.Properties) { if ($WSAConfigTypeValues.psobject.properties.match($configuration.Name).Count) { if ($WSAConfigTypeValues.$($configuration.Name) -eq "Default") { $WSAConfigTypeValues.$($configuration.Name) = $configuration.Value } } } $standardConfigValue = New-Object -TypeName psobject $standardConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "WSA" $standardConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue $WSAConfigTypeValues $ppmStandardConfigValues.Add($standardConfigValue) } Function checkRange() { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$name, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$value, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$minRange, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$maxRange, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Bool]$required ) if (($value -eq "Null") -and ($required -eq $true)) { Write-LogMessage -Type ERROR -Message "$name variable has not been configured. Please check the standard configuration JSON configuration file." -Colour Red return $false } elseif (($value -lt $minRange) -or ($value -gt $maxRange)) { Write-LogMessage -Type ERROR -Message "The recommended range for $name should be between $minRange and $maxRange.(current value is $value)" -Colour Red return $false } else { return $true } } Function checkEmailString() { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$name, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$address, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Bool]$required ) if (($address -eq "Null") -and ($required -eq $true)) { Write-LogMessage -type ERROR -Message "$name variable has not been configured. Please check the standard configuration JSON configuration file." -Colour Red return $false } $checkStatement = $address -match "^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$" if ($checkStatement -eq $true) { return $true } else { Write-LogMessage -Type ERROR -Message "Please input a validate email address for" $name "in the standard configuration JSON configuration file." -Colour Red return $false } } Function importStandardConfigurations { <# .SYNOPSIS Imports the standard configuration JSON into a consumable array to feed into various functions. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$ppmVariables, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmStandardConfigValues, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmEnvironmentalDetails ) # Checking if file exists if (Test-Path $ppmVariables.commonPolicyFilePath) { $ppmStandardConfiguration = Get-Content -Path $ppmVariables.commonPolicyFilePath -Raw | ConvertFrom-Json } else { Write-LogMessage -Type ERROR -Message $ppmVariables.commonPolicyFilePath+" file not found." -Colour Red Exit } $errorCount = 0; # Validating values $CommonValues = New-Object -TypeName psobject $CommonValues | Add-Member -notepropertyname "passwdExpInDays" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMinimumLength" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMinUppercase" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMinLowercase" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMinNumeric" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMinSpecial" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMaxConsecutiveIdenticalChar" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdHistoryRestriction" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdUnlockIntervalInSec" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMaxFailAttempts" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdAttemptsIntervalInSec" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMaxFailIntervalInSec" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdNotifyEmail" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMaximumLength" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMinAlphabetic" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdMaxPreviousCharactersReused" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdAttemptsIntervalInMins" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdUnlockIntervalInMins" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "tempPasswdLifetimeInHour" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdExpReminderInDay" -notepropertyvalue "Null" $CommonValues | Add-Member -notepropertyname "passwdExpReminderNotificationFrequencyInDay" -notepropertyvalue "Null" foreach ($configuration in $ppmStandardConfiguration.Default.PSObject.Properties) { if ($CommonValues.psobject.properties.match($configuration.Name).Count) { $CommonValues.$($configuration.Name) = $configuration.Value } } $checkReturn = checkRange -name "passwdExpInDays" -value $CommonValues."passwdExpInDays" -minRange 30 -maxRange 99999 -required $true if (!$checkReturn) { $errorCount += 1 } $checkReturn = checkRange -name "passwdMinimumLength" -value $CommonValues."passwdMinimumLength" -minRange 12 -maxRange 9999 -required $true if (!$checkReturn) { $passwdMinLen = 12 $errorCount += 1 } else { $passwdMinLen = $CommonValues."passwdMinimumLength" } $checkReturn = checkRange -name "passwdMinUppercase" -value $CommonValues."passwdMinUppercase" -minRange 1 -maxRange 9000 -required $true if (!$checkReturn) { $passwdUpper = 1 $errorCount += 1 } else { $passwdUpper = $CommonValues."passwdMinUppercase" } $checkReturn = checkRange -name "passwdMinLowercase" -value $CommonValues."passwdMinLowercase" -minRange 1 -maxRange 9000 -required $true if (!$checkReturn) { $passwdLower = $errorCount += 1 } else { $passwdLower = $CommonValues."passwdMinLowercase" } $checkReturn = checkRange -name "passwdMinNumeric" -value $CommonValues."passwdMinNumeric" -minRange 1 -maxRange 9000 -required $true if (!$checkReturn) { $errorCount += 1 } $checkReturn = checkRange -name "passwdMinSpecial" -value $CommonValues."passwdMinSpecial" -minRange 1 -maxRange 9000 -required $true if (!$checkReturn) { $errorCount += 1 } $checkReturn = checkRange -name "passwdMaxConsecutiveIdenticalChar" -value $CommonValues."passwdMaxConsecutiveIdenticalChar" -minRange 1 -maxRange 9000 -required $true if (!$checkReturn) { $errorCount += 1 } $checkReturn = checkRange -name "passwdHistoryRestriction" -value $CommonValues."passwdHistoryRestriction" -minRange 5 -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1 } $checkReturn = checkRange -name "passwdUnlockIntervalInSec" -value $CommonValues."passwdUnlockIntervalInSec" -minRange 0 -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1 } $checkReturn = checkRange -name "passwdMaxFailAttempts" -value $CommonValues."passwdMaxFailAttempts" -minRange 1 -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1 } $checkReturn = checkRange -name "passwdAttemptsIntervalInSec" -value $CommonValues."passwdAttemptsIntervalInSec" -minRange 0 -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1 } $checkReturn = checkEmailString -name "passwdNotifyEmail" -address $CommonValues."passwdNotifyEmail" -required $true if (!$checkReturn) { $errorCount += 1 } $checkReturn = checkRange -name "passwdMaximumLength" -value $CommonValues."passwdMaximumLength" -minRange $passwdMinLen -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1 } $maxValue = [int]$passwdUpper + [int]$passwdLower $checkReturn = checkRange -name "passwdMinAlphabetic" -value $CommonValues."passwdMinAlphabetic" -minRange $maxValue -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1 } $checkReturn = checkRange -name "passwdMaxPreviousCharactersReused" -value $CommonValues."passwdMaxPreviousCharactersReused" -minRange 0 -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1; } $checkReturn = checkRange -name "passwdAttemptsIntervalInMins" -value $CommonValues."passwdAttemptsIntervalInMins" -minRange 0 -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1; } $checkReturn = checkRange -name "passwdUnlockIntervalInMins" -value $CommonValues."passwdUnlockIntervalInMins" -minRange 0 -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1; } $checkReturn = checkRange -name "tempPasswdLifetimeInHour" -value $CommonValues."tempPasswdLifetimeInHour" -minRange 1 -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1; } $checkReturn = checkRange -name "passwdExpReminderInDay" -value $CommonValues."passwdExpReminderInDay" -minRange 1 -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1; } $checkReturn = checkRange -name "passwdExpReminderNotificationFrequencyInDay" -value $CommonValues."passwdExpReminderNotificationFrequencyInDay" -minRange 1 -maxRange 9999 -required $true if (!$checkReturn) { $errorCount += 1; } if ($errorCount -gt 0) { Write-LogMessage -Type ERROR -Message "There are errors in standard configuration JSON. Please see above for more details." -Colour Red Write-LogMessage -Type ERROR -Message "Total error count = $errorCount" -Colour Red Exit } Write-LogMessage -type INFO -Message "Importing standard configuration setting from $($ppmVariables.commonPolicyFilePath)..." parseProductTypeESXiConfiguration -productConfiguration $ppmStandardConfiguration -ppmStandardConfigValues $ppmStandardConfigValues parseProductTypeVCConfiguration -productConfiguration $ppmStandardConfiguration -ppmStandardConfigValues $ppmStandardConfigValues parseProductTypeSSOConfiguration -productConfiguration $ppmStandardConfiguration -ppmStandardConfigValues $ppmStandardConfigValues parseProductTypeNSXMgrConfiguration -productConfiguration $ppmStandardConfiguration -ppmStandardConfigValues $ppmStandardConfigValues parseProductTypeNSXEdgeConfiguration -productConfiguration $ppmStandardConfiguration -ppmStandardConfigValues $ppmStandardConfigValues parseProductTypeWSAConfiguration -productConfiguration $ppmStandardConfiguration -ppmStandardConfigValues $ppmStandardConfigValues Write-LogMessage -type INFO -Message "Importing standard configuration setting from $($ppmVariables.commonPolicyFilePath) completed." } ############################################################################# #### Get-EnvironmentPasswordPolicyDetail will retrieve password policy ##### #### of each components under a workload domain. ##### ############################################################################# Function getEsxiPasswordPolicy { <# .SYNOPSIS Retrieves ESXi host password policy #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$cluster ) # Construct Environment Object $passwordPolicyNodes = New-Object System.Collections.Generic.List[System.Object] $results = Get-EsxiPasswordPolicy -server $server -user $user -pass $pass -domain $domain -cluster $cluster foreach ($result in $results) { $esxiConfigTypeValues = New-Object -TypeName psobject $esxiConfigTypeValues | Add-Member -notepropertyname "passwdExpInDays" -notepropertyvalue "Empty" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMaxFailAttempts" -notepropertyvalue "Empty" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLengthFor1CharClass" -notepropertyvalue "Empty" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLengthFor2CharClass" -notepropertyvalue "Empty" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLengthFor3CharClass" -notepropertyvalue "Empty" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLengthFor4CharClass" -notepropertyvalue "Empty" $esxiConfigTypeValues | Add-Member -notepropertyname "passwdMinimumCharLengthForPhrase" -notepropertyvalue "Empty" # Parsing ESXi password policy string $result.PasswordQualityControl | Select-String -Pattern "^retry=(\d+)\s+min=(.+),(.+),(.+),(.+),(.+)" | Foreach-Object {$PasswdPolicyRetryValue, $PasswdPolicyMinValue1, $PasswdPolicyMinValue2, $PasswdPolicyMinValue3, $PasswdPolicyMinValue4, $PasswdPolicyMinValue5 = $_.Matches[0].Groups[1..6].Value} $esxiConfigTypeValues.passwdExpInDays = $result.PaswordMaxDays $esxiConfigTypeValues.passwdMaxFailAttempts = $PasswdPolicyRetryValue $esxiConfigTypeValues.passwdMinimumLengthFor1CharClass = $PasswdPolicyMinValue1 $esxiConfigTypeValues.passwdMinimumLengthFor2CharClass = $PasswdPolicyMinValue2 $esxiConfigTypeValues.passwdMinimumLengthFor3CharClass = $PasswdPolicyMinValue4 $esxiConfigTypeValues.passwdMinimumLengthFor4CharClass = $PasswdPolicyMinValue5 $esxiConfigTypeValues.passwdMinimumCharLengthForPhrase = $PasswdPolicyMinValue3 $nodeConfigValue = New-Object -TypeName psobject $nodeConfigValue | Add-Member -notepropertyname "FQDN" -notepropertyvalue $result.fqdn $nodeConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "ESXi" $nodeConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue $esxiConfigTypeValues $passwordPolicyNodes.Add($nodeConfigValue) Remove-Variable -Name nodeConfigValue Remove-Variable -Name esxiConfigTypeValues } return $passwordPolicyNodes } Function getVCServerPasswordPolicy { <# .SYNOPSIS Retrieve vCenter Server password policy #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain ) # Construct Environment Object $passwordPolicyNodes = New-Object System.Collections.Generic.List[System.Object] $VCConfigTypeValues = New-Object -TypeName psobject $VCConfigTypeValues | Add-Member -notepropertyname "passwdExpInDays" -notepropertyvalue "Empty" $VCConfigTypeValues | Add-Member -notepropertyname "passwdNotifyEmail" -notepropertyvalue "Empty" $result = Get-VCServerPasswordPolicy -server $server -user $user -pass $pass -domain $domain $VCConfigTypeValues.passwdNotifyEmail = $result.email $VCConfigTypeValues.passwdExpInDays = $result.max_days_between_password_change $nodeConfigValue = New-Object -TypeName psobject $nodeConfigValue | Add-Member -notepropertyname "FQDN" -notepropertyvalue $result.fqdn $nodeConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "VC" $nodeConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue $VCConfigTypeValues $passwordPolicyNodes.Add($nodeConfigValue) return $passwordPolicyNodes } Function getSingleSignOnPasswordPolicy { <# .SYNOPSIS Retrieves vCenter Single Sign-On password policy #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass ) # Construct Environment Object $passwordPolicyNodes = New-Object System.Collections.Generic.List[System.Object] Try { Write-LogMessage -Type INFO -Message "Retrieving vCenter Single Sign-On domain password policies." $checkServer = Test-Connection -ComputerName $server -Quiet -Count 1 if ($checkServer -eq "True") { Write-LogMessage -Type INFO -Message "Attempting to connect to vCenter Single Sign-On domain server '$server'" $mySSOConnection = Connect-SsoAdminServer -Server $server -User $user -Password $pass if ($mySSOConnection.Name -eq $server) { $configurationString = Get-SSOPasswordPolicy $configurationString2 = Get-SsoLockoutPolicy if ($configurationString -and $configurationString2) { $SSOTmpObject = @() $SSOTmpObject += [pscustomobject]@{ "passwdExpInDays" = $configurationString.PasswordLifetimeDays "passwdHistoryRestriction" = $configurationString.ProhibitedPreviousPasswordsCount "passwdMinimumLength" = $configurationString.MinLength "passwdMaximumLength" = $configurationString.MaxLength "passwdMinUppercase" = $configurationString.MinUppercaseCount "passwdMinLowercase" = $configurationString.MinLowercaseCount "passwdMinAlphabetic" = $configurationString.MinAlphabeticCount "passwdMinNumeric" = $configurationString.MinNumericCount "passwdMinSpecial" = $configurationString.MinSpecialCharCount "passwdMaxConsecutiveIdenticalChar" = $configurationString.MaxIdenticalAdjacentCharacters "passwdMaxFailAttempts" = $configurationString2.MaxFailedAttempts "passwdAttemptsIntervalInSec" = $configurationString2.FailedAttemptIntervalSec "passwdUnlockIntervalInSec" = $configurationString2.AutoUnlockIntervalSec } $nodeConfigValue = New-Object -TypeName psobject $nodeConfigValue | Add-Member -notepropertyname "FQDN" -notepropertyvalue $server $nodeConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "SSO" $nodeConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue ($SSOTmpObject | Select-Object -Skip 0) $passwordPolicyNodes.Add($nodeConfigValue) Write-LogMessage -Type INFO -Message "Disconnecting from server '$server'" Disconnect-SsoAdminServer -Server $mySSOConnection | Out-Null return $passwordPolicyNodes } else { Write-LogMessage -Type INFO -Message "Disconnecting from server '$server'" Disconnect-SsoAdminServer -Server $mySSOConnection | Out-Null Write-LogMessage -Type ERROR -Message "Unable to retrieve password policy." -Colour Red Exit } } else { Write-LogMessage -Type ERROR -Message "Not connected to server $server due to an incorrect user name or password. Verify your credentials and try again." -Colour Red Exit } } else { Write-LogMessage -Type ERROR -Message "Testing a connection to server $server failed. Please check your details and try again." -Colour Red Exit } } Catch { Debug-ExceptionWriter -object $_ } } Function getNsxtManagerPasswordPolicy { <# .SYNOPSIS Retrieves NSX Manager password policy #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass ) $passwordPolicyNodes = New-Object System.Collections.Generic.List[System.Object] $nsxtConfigTypeValues = New-Object -TypeName psobject $nsxtConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLength" -notepropertyvalue "Empty" $nsxtConfigTypeValues | Add-Member -notepropertyname "apiPasswdMaxFailAttempts" -notepropertyvalue "Empty" $nsxtConfigTypeValues | Add-Member -notepropertyname "apiPasswdMaxFailIntervalInSec" -notepropertyvalue "Empty" $nsxtConfigTypeValues | Add-Member -notepropertyname "apiPasswdUnlockIntervalInSec" -notepropertyvalue "Empty" $nsxtConfigTypeValues | Add-Member -notepropertyname "cliPasswdMaxFailAttempts" -notepropertyvalue "Empty" $nsxtConfigTypeValues | Add-Member -notepropertyname "cliPasswdMaxFailIntervalInSec" -notepropertyvalue "Empty" $count = 0 Try { $checkServer = Test-Connection -ComputerName $server -Quiet -Count 1 if ($checkServer -eq "True") { while ($checkServer -le 2) { Write-LogMessage -Type INFO -Message "Attempting to connect to NSX Manager '$server'." $NSXToken = Request-NsxToken -fqdn $server -username $user -password $pass if ($NSXToken) { Write-LogMessage -Type INFO -Message "Connected to NSX Manager '$server'" Write-LogMessage -Type INFO -Message "Retrieving password policy from NSX Manager '$server'." $response = Get-NsxtManagerAuthPolicy -nsxtManagerNode $server $nsxtConfigTypeValues.passwdMinimumLength = $response.minimum_password_length $nsxtConfigTypeValues.apiPasswdMaxFailAttempts = $response.api_max_auth_failures $nsxtConfigTypeValues.apiPasswdMaxFailIntervalInSec = $response.api_failed_auth_reset_period $nsxtConfigTypeValues.apiPasswdUnlockIntervalInSec = $response.api_failed_auth_lockout_period $nsxtConfigTypeValues.cliPasswdMaxFailAttempts = $response.cli_max_auth_failures $nsxtConfigTypeValues.cliPasswdMaxFailIntervalInSec = $response.cli_failed_auth_lockout_period $nodeConfigValue = New-Object -TypeName psobject $nodeConfigValue | Add-Member -notepropertyname "FQDN" -notepropertyvalue $server $nodeConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "NSXMgr" $nodeConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue $nsxtConfigTypeValues $passwordPolicyNodes.Add($nodeConfigValue) return $passwordPolicyNodes } else { if ($ErrorLog -match '"error_code":404') { $count += 1 Write-LogMessage -Type WARNING -Message "Unable to submit request. Retry again in 20 secs (Try $count/3)." -Colour Yellow Start-Sleep -s 20 } else { Write-LogMessage -Type ERROR -Message "Failed to obtain access token from NSX Manager '$server'. Please verify your credentials and try again." -Colour Red Exit } } } Write-LogMessage -Type ERROR -Message "Testing a connection to server $server failed. Please check your details and try again." -Colour Red Exit } else { Write-LogMessage -Type ERROR -Message "Testing a connection to server $server failed. Please check your details and try again." -Colour Red Exit } } Catch { Debug-ExceptionWriter -object $_ } Finally { Write-LogMessage -Type INFO -Message "Retrieving NSX Manager '$server' password policies completed." } } Function getNsxtEdgeNodePasswordPolicy { <# .SYNOPSIS Retrieve NSX Edge Node password policy #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass ) $passwordPolicyNodes = New-Object System.Collections.Generic.List[System.Object] $count = 0 Try { $checkServer = Test-Connection -ComputerName $server -Quiet -Count 1 if ($checkServer -eq "True") { while ($checkServer -le 2) { Write-LogMessage -Type INFO -Message "Attempting to connect to NSX Edge '$server'." $NSXToken = Request-NsxToken -fqdn $server -username $user -password $pass if ($NSXToken) { $nsxtEdgeNodes = (Get-NsxtEdgeCluster | Where-Object {$_.member_node_type -eq "EDGE_NODE"}) foreach ($nsxtEdgeNode in $nsxtEdgeNodes.members) { $nsxtConfigTypeValues = New-Object -TypeName psobject $nsxtConfigTypeValues | Add-Member -notepropertyname "transportNodeID" -notepropertyvalue "Empty" $nsxtConfigTypeValues | Add-Member -notepropertyname "passwdMinimumLength" -notepropertyvalue "Empty" $nsxtConfigTypeValues | Add-Member -notepropertyname "cliPasswdMaxFailAttempts" -notepropertyvalue "Empty" $nsxtConfigTypeValues | Add-Member -notepropertyname "cliPasswdMaxFailIntervalInSec" -notepropertyvalue "Empty" $response = Get-NsxtEdgeNodeAuthPolicy -nsxtManager $server -nsxtEdgeNodeID $nsxtEdgeNode.transport_node_id $nsxtConfigTypeValues.transportNodeID = $nsxtEdgeNode.transport_node_id $nsxtConfigTypeValues.passwdMinimumLength = $response.minimum_password_length $nsxtConfigTypeValues.cliPasswdMaxFailAttempts = $response.cli_max_auth_failures $nsxtConfigTypeValues.cliPasswdMaxFailIntervalInSec = $response.cli_failed_auth_lockout_period $nsxtEdgeNodeAdds = Get-NsxtEdgeNode -transportNodeID $nsxtEdgeNode.transport_node_id $nodeConfigValue = New-Object -TypeName psobject $nodeConfigValue | Add-Member -notepropertyname "FQDN" -notepropertyvalue $nsxtEdgeNodeAdds.node_deployment_info.node_settings.hostname $nodeConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "NSXEdge" $nodeConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue $nsxtConfigTypeValues $passwordPolicyNodes.Add($nodeConfigValue) Remove-Variable -Name nodeConfigValue Remove-Variable -Name nsxtConfigTypeValues } return $passwordPolicyNodes } else { if ($ErrorLog -match '"error_code":404') { $count += 1 Write-LogMessage -Type WARNING -Message "Unable to submit request. Retry again in 20 secs (Try $count/3)." -Colour Yellow Start-Sleep -s 20 } else { Write-LogMessage -Type ERROR -Message "Failed to obtain access token from NSX Edge '$server'. Please verify your credentials and try again." -Colour Red Exit } } } Write-LogMessage -Type ERROR -Message "Failed to obtain access token from NSX Edge '$server'. Please verify your credentials and try again." -Colour Red Exit } else { Write-LogMessage -Type ERROR -Message "Testing a connection to NSX Edge $server failed. Please check your details and try again." -Colour Red Exit } } Catch { Debug-ExceptionWriter -object $_ } Finally { Write-LogMessage -Type INFO -Message "Retrieving NSX Edge password policy completed." } } Function getWSAPasswordPolicyAll { <# .SYNOPSIS Retrieve Workspace ONE Access password policy .DESCRIPTION The Get-WSAPasswordPolicyAll cmdlet returns an custom object contains the current configured password policy for a Workpace ONE Access appliance. - Validates that network connectivity is possible to the Workspace ONE Access appliance - Retrieve Workspace ONE Access password policy #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass ) $passwordPolicyNodes = New-Object System.Collections.Generic.List[System.Object] Try { if (Test-WSAConnection -server $server) { $WSAToken = Request-WSAToken -fqdn $server -user $user -pass $pass if ($WSAToken) { $wsaPasswordPolicy = Get-WSAPasswordPolicy | Select-Object * -ExcludeProperty _links $wsaPasswordLockout = Get-WSAPasswordLockout | Select-Object * -ExcludeProperty _links $wsaTmpObject = @() $wsaTmpObject += [pscustomobject]@{ "passwdExpInDays" = [int]$wsaPasswordPolicy.passwordTtlInHours / 24 "passwdHistoryRestriction" = $wsaPasswordPolicy.history "passwdMinimumLength" = $wsaPasswordPolicy.minLen "passwdMinUppercase" = $wsaPasswordPolicy.minUpper "passwdMinLowercase" = $wsaPasswordPolicy.minLower "passwdMinNumeric" = $wsaPasswordPolicy.minDigit "passwdMinSpecial" = $wsaPasswordPolicy.minSpecial "passwdMaxConsecutiveIdenticalChar" = $wsaPasswordPolicy.maxConsecutiveIdenticalCharacters "passwdMaxPreviousCharactersReused" = $wsaPasswordPolicy.maxPreviousPasswordCharactersReused "passwdMaxFailAttempts" = $wsaPasswordLockout.numAttempts "passwdAttemptsIntervalInMins" = $wsaPasswordLockout.attemptInterval "passwdUnlockIntervalInMins" = $wsaPasswordLockout.unlockInterval "tempPasswdLifetimeInHour" = $wsaPasswordPolicy.tempPasswordTtl "passwdExpReminderInDay" = [int64]$wsaPasswordPolicy.notificationThreshold / 86400000 "passwdExpReminderNotificationFrequencyInDay" = [int64]$wsaPasswordPolicy.notificationInterval / 86400000 } $nodeConfigValue = New-Object -TypeName psobject $nodeConfigValue | Add-Member -notepropertyname "FQDN" -notepropertyvalue $server $nodeConfigValue | Add-Member -notepropertyname "productType" -notepropertyvalue "WSA" $nodeConfigValue | Add-Member -notepropertyname "productAttributes" -notepropertyvalue ($wsaTmpObject | Select-Object -Skip 0) $passwordPolicyNodes.Add($nodeConfigValue) return $passwordPolicyNodes } else { Write-LogMessage -Type ERROR -Message "Failed to obtain access token from Workspace ONE Access server '$server'. Please verify your credentials and try again." -Colour Red } } else { Write-LogMessage -Type ERROR -Message "Testing a connection to Workspace ONE Access server $server failed. Please check your details and try again." -Colour Red } } Catch { Debug-ExceptionWriter -object $_ } } Function getEnvironmentPasswordPolicyDetail { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$ppmVariables, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmEnvironmentalDetails ) if ($ppmVariables.isEnvDetailSet -eq $false) { Write-LogMessage -type INFO -Message "Retrieving environment details... (this may take a while depending on the number of ESXi hosts)." -Colour Yellow # Retrieve ESXi host password policy details Write-LogMessage -type INFO -Message "Retrieving ESXi host password policies..." $vcenter = Get-vCenterServerDetail -server $ppmVariables.sddcManagerFqdn -user $ppmVariables.sddcManagerUser -pass $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName $clusterID = Get-VCFWorkloadDomain -name $ppmVariables.sddcDomainName $ppmVariables.esxiCluster = $clusterID foreach ($cid in $ppmVariables.esxiCluster.clusters.id) { $cluster = Get-VCFCluster -id $cid $results = getEsxiPasswordPolicy -server $ppmVariables.sddcManagerFqdn -user $ppmVariables.sddcManagerUser -pass $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName -cluster $cluster.name foreach ($result in $results) { $result.productAttributes | Add-Member -notepropertyname "driftAlarm" -notepropertyvalue "" $result.productAttributes | Add-Member -notepropertyname "driftMessage" -notepropertyvalue "" $ppmEnvironmentalDetails.Add($result) } } Write-LogMessage -type INFO -Message "Retrieving ESXi Hosts password policies completed." # Retrieve vCenter Server password policy details Write-LogMessage -type INFO -Message "Retrieving vCenter Server instance..." $result = getVCServerPasswordPolicy -server $ppmVariables.sddcManagerFqdn -user $ppmVariables.sddcManagerUser -pass $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName $result.productAttributes | Add-Member -notepropertyname "driftAlarm" -notepropertyvalue "" $result.productAttributes | Add-Member -notepropertyname "driftMessage" -notepropertyvalue "" $ppmEnvironmentalDetails.Add($result) Write-LogMessage -type INFO -Message "Retrieving vCenter Server instance completed." # Retrieve vCenter SSO password policy details $result = getSingleSignOnPasswordPolicy -server $ppmVariables.ssoServerFqdn -user $ppmVariables.ssoServerUser -pass $ppmVariables.ssoServerPass $result.productAttributes | Add-Member -notepropertyname "driftAlarm" -notepropertyvalue "" $result.productAttributes | Add-Member -notepropertyname "driftMessage" -notepropertyvalue "" $ppmEnvironmentalDetails.Add($result) # Retrieve NSX Manager password policy details $nsxtManagerDetails = Get-NsxtServerDetail -fqdn $ppmVariables.sddcManagerFqdn -username $ppmVariables.sddcManagerUser -password $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName -listNodes foreach ($nsxtManagerNode in $nsxtManagerDetails.nodes) { $result = getNsxtManagerPasswordPolicy -server $nsxtManagerNode.fqdn -user $nsxtManagerDetails.adminUser -pass $nsxtManagerDetails.AdminPass $result.productAttributes | Add-Member -notepropertyname "driftAlarm" -notepropertyvalue "" $result.productAttributes | Add-Member -notepropertyname "driftMessage" -notepropertyvalue "" $ppmEnvironmentalDetails.Add($result) } # Retrieve NSX Edge password policy details $results = getNsxtEdgeNodePasswordPolicy -server $nsxtManagerDetails.fqdn -user $nsxtManagerDetails.adminUser -pass $nsxtManagerDetails.AdminPass foreach ($result in $results) { $result.productAttributes | Add-Member -notepropertyname "driftAlarm" -notepropertyvalue "" $result.productAttributes | Add-Member -notepropertyname "driftMessage" -notepropertyvalue "" $ppmEnvironmentalDetails.Add($result) } # Retrieve WSA password policy details if ($ppmVariables.wsaFqdn -and $ppmVariables.wsaAdminUser -and $ppmVariables.wsaAdminPass) { Write-LogMessage -type INFO -Message "Retrieving Workspace ONE Access appliance password policy..." $result = getWSAPasswordPolicyAll -server $ppmVariables.wsaFqdn -user $ppmVariables.wsaAdminUser -pass $ppmVariables.wsaAdminPass $result.productAttributes | Add-Member -notepropertyname "driftAlarm" -notepropertyvalue "" $result.productAttributes | Add-Member -notepropertyname "driftMessage" -notepropertyvalue "" $ppmEnvironmentalDetails.Add($result) Write-LogMessage -type INFO -Message "Retrieving Workspace ONE Access appliance password policy completed." } else { Write-LogMessage -Type WARNING -Message "Workspace ONE Access appliance skipped. Login details are not provided." -Colour Yellow } $ppmVariables.isEnvDetailSet = $true Write-LogMessage -type INFO -Message "Retrieving environment details completed." -Colour Green } } ################################################################################ #### Print current environment password policies settings as HTML file #### ################################################################################ Function exportReportHTML { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$ppmVariables, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmStandardConfigValues, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmEnvironmentalDetails, [Parameter (mandatory = $false)] [Switch]$docCompare = $false ) # Retrieving environmental details getEnvironmentPasswordPolicyDetail -ppmVariables $ppmVariables -ppmEnvironmentalDetails $ppmEnvironmentalDetails $count = 0 # Addressing comparison reports if ($docCompare -eq $true) { foreach ($eachNode in $ppmEnvironmentalDetails) { foreach ($eachAttribute in $eachNode.productAttributes.PSObject.Properties){ foreach ($product in $ppmStandardConfigValues) { if ($product.productType -eq $eachNode.productType) { if ($eachAttribute.Value -ne $null) { if ($eachAttribute.Value -ne $product.productAttributes.$($eachAttribute.Name)) { $eachAttribute.Value = "<font color=#DC143C><b>" + $eachAttribute.Value + "</b></font>["+$product.productAttributes.$($eachAttribute.Name)+"]" $count += 1 } } else { $eachAttribute.Value = "<font color=#DC143C><b>NULL</b></font>["+$product.productAttributes.$($eachAttribute.Name)+"]" $count += 1 } } } } } } # Prepare HTML header $htmlOutput = "<html><title>Password Policy Report</title><style type=" + '"text/css"' + ">.myTable { border-collapse:collapse; }.myTable td, .myTable th {text-align:center;padding:5px;border:1px solid #000;}</style><head><H1>Password Policy Report for the Workload domain <font color=#6495ED>$($ppmVariables.sddcDomainName)</font> </H1></head><body><br><H4><p>-Report Ran on <font color=#6495ED>" + (Get-Date).tostring("dd-MM-yyyy-hh-mm-ss") + "</font> for the Workload domain <font color=#6495ED>$($ppmVariables.sddcDomainName)</font>" if ($docCompare -eq $false) { $htmlOutput = $htmlOutput + "</p></H4><br><H4><p><font color=#FFA500>Common Password Policy file path was not provided. Drift data not available.</font></p></H4>" } else { $htmlOutput = $htmlOutput + "</p></H4><br><p>Legend: drift data format <font color=#DC143C><i>Current Environment Value</i></font>[<i>standard Password Policy value</i>]</p>" } # Prepare ESXi section $htmlOutput = $htmlOutput + '<H3>ESXi Host Password Policy</h3><table class="myTable">' $tmpHtmlOutput = $ppmEnvironmentalDetails | Where-Object { $_.productType -match "ESXi" } | select-object -Property FQDN -ExpandProperty productAttributes | select-object FQDN,passwdExpInDays,passwdMaxFailAttempts,passwdMinimumLengthFor1CharClass,passwdMinimumLengthFor2CharClass,passwdMinimumLengthFor3CharClass,passwdMinimumLengthFor4CharClass,passwdMinimumCharLengthForPhrase | sort-object -Property FQDN | ConvertTo-Html -Fragment -As Table $htmlOutput += $tmpHtmlOutput # Prepare vCenter Server section $htmlOutput = $htmlOutput + '<H3>vCenter Server Password Policy</h3><table class="myTable">' $tmpHtmlOutput = $ppmEnvironmentalDetails | Where-Object { $_.productType -match "VC" } | select-object -Property FQDN -ExpandProperty productAttributes | select-object FQDN,passwdExpInDays,passwdNotifyEmail | sort-object -Property FQDN | ConvertTo-Html -Fragment -As Table $htmlOutput += $tmpHtmlOutput # Prepare vCenter SSO section $htmlOutput = $htmlOutput + '<H3>vCenter Single Sign-On Password Policy</H3><p><font color=#6495ED>SSO FQDN: ' + $ppmVariables.ssoServerFqdn + '</font></p><table class="myTable">' $tmpHtmlOutput = $ppmEnvironmentalDetails | Where-Object { $_.productType -match "SSO" } | select-object -ExpandProperty productAttributes | select-object -property * -ExcludeProperty FQDN,productType,driftAlarm,driftMessage | ConvertTo-Html -Fragment -As Table $htmlOutput += $tmpHtmlOutput # Prepare NSX Manager section $htmlOutput = $htmlOutput + '<H3>NSX Manager Password Policy</h3><table class="myTable">' $tmpHtmlOutput = $ppmEnvironmentalDetails | Where-Object { $_.productType -match "NSXMgr" } | select-object -Property FQDN -ExpandProperty productAttributes | select-object FQDN,passwdMinimumLength,apiPasswdMaxFailAttempts,apiPasswdMaxFailIntervalInSec,apiPasswdUnlockIntervalInSec,cliPasswdMaxFailAttempts,cliPasswdMaxFailIntervalInSec | sort-object -Property FQDN | ConvertTo-Html -Fragment -As Table $htmlOutput += $tmpHtmlOutput # Prepare NSX Edge section $htmlOutput = $htmlOutput + '<H3>NSX Edge Password Policy</h3><table class="myTable">' $tmpHtmlOutput = $ppmEnvironmentalDetails | Where-Object { $_.productType -match "NSXEdge" } | select-object -Property FQDN -ExpandProperty productAttributes | select-object FQDN,passwdMinimumLength,cliPasswdMaxFailAttempts,cliPasswdMaxFailIntervalInSec | sort-object -Property FQDN | ConvertTo-Html -Fragment -As Table $htmlOutput += $tmpHtmlOutput # Prepare Workspace ONE Access section if ($ppmVariables.skipWSA -eq $false){ $htmlOutput = $htmlOutput + '<H3>Workspace ONE Access Password Policy</H3><p><font color=#6495ED>WSA FQDN: ' + $ppmVariables.wsaFqdn + '</font></p><table class="myTable">' $tmpHtmlOutput = $ppmEnvironmentalDetails | Where-Object { $_.productType -match "WSA" } | select-object -ExpandProperty productAttributes | select-object -property * -ExcludeProperty FQDN,productType,driftAlarm,driftMessage | ConvertTo-Html -Fragment -As Table $htmlOutput += $tmpHtmlOutput } else { $htmlOutput = $htmlOutput + '<H3>Workspace ONE Access Password Policy</h3><p><br><font color=>Workspace ONE Access skipped; no environmental details provided.</p>' } $htmlOutput = $htmlOutput.replace("<table>", "") $htmlOutput = $htmlOutput.replace("passwd", "passwd ") $htmlOutput = $htmlOutput.replace(">", ">") $htmlOutput = $htmlOutput.replace("<", "<") $htmlOutput = $htmlOutput.replace("<colgroup><col/><col/><col/></colgroup> ","") $htmlOutput = $htmlOutput + "</body></html>" $htmlOutput | out-File $ppmVariables.outputFilePath Write-LogMessage -type INFO -Message "$($ppmVariables.outputFilePath) report generated." -Colour Yellow } ################################################################################ #### Print current environment password policies settings as JSON file #### ################################################################################ Function exportReportJSON { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$ppmVariables, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmStandardConfigValues, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmEnvironmentalDetails, [Parameter (mandatory = $false)] [Switch]$docCompare = $false, [Parameter (mandatory = $false)] [Switch]$onlyDrift = $false ) $count = 0 # Addressing comparison reports if ($docCompare -eq $true) { foreach ($eachNode in $ppmEnvironmentalDetails){ $eachNode.productAttributes.driftAlarm = "Green" $eachNode.productAttributes.driftMessage = "" foreach ($eachAttribute in $eachNode.productAttributes.PSObject.Properties) { foreach ($product in $ppmStandardConfigValues) { if ($product.productType -eq $eachNode.productType) { if ($eachAttribute.Value -ne $null) { if (($eachAttribute.Value -ne $product.productAttributes.$($eachAttribute.Name)) -and ($eachAttribute.Name -ne "driftAlarm") -and ($eachAttribute.Name -ne "driftMessage") -and ($eachAttribute.Name -ne "transportNodeID")) { $eachNode.productAttributes.driftAlarm = "Red" if ($eachNode.productAttributes.driftMessage -eq "") { $eachNode.productAttributes.driftMessage = $eachAttribute.Name + "("+ $product.productAttributes.$($eachAttribute.Name) + ")" } else { $eachNode.productAttributes.driftMessage = $eachNode.productAttributes.driftMessage + ", " + $eachAttribute.Name + "("+ $product.productAttributes.$($eachAttribute.Name) + ")" } $count += 1 } } else { $eachAttribute.Value = "NULL" $eachNode.productAttributes.driftAlarm = "Red" if ($eachNode.productAttributes.driftMessage -eq "") { $eachNode.productAttributes.driftMessage = $eachAttribute.Name + "("+ $product.productAttributes.$($eachAttribute.Name) + ")" } else { $eachNode.productAttributes.driftMessage = $eachNode.productAttributes.driftMessage + ", " + $eachAttribute.Name + "("+ $product.productAttributes.$($eachAttribute.Name) + ")" } $count += 1 } } } } } if ($onlyDrift -eq $true) { $ppmEnvironmentalDetails | Where-Object { $_.productAttributes.driftAlarm -match "Red" } | ConvertTo-Json -depth 100 | Out-File $ppmVariables.outputFilePath } else { $ppmEnvironmentalDetails | ConvertTo-Json -depth 100 | Out-File $ppmVariables.outputFilePath } } else { $ppmEnvironmentalDetails | ConvertTo-Json -depth 100 | Out-File $ppmVariables.outputFilePath } Write-LogMessage -type INFO -Message "$($ppmVariables.outputFilePath) report generated." -Colour Yellow } ################################################################################ #### Configure environment password policies settings from the #### #### standard configuration file. #### ################################################################################ Function setEnvironmentPasswordPolicy { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [psobject]$ppmVariables, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmStandardConfigValues, [Parameter (Mandatory = $true)] [AllowEmptyCollection()][System.Collections.Generic.List[System.Object]]$ppmEnvironmentalDetails ) $count = 0 foreach ($eachNode in $ppmEnvironmentalDetails){ $eachNode.productAttributes.driftAlarm = "Green" $eachNode.productAttributes.driftMessage = "" foreach ($eachAttribute in $eachNode.productAttributes.PSObject.Properties) { foreach ($product in $ppmStandardConfigValues) { if ($product.productType -eq $eachNode.productType) { if ($eachAttribute.Value -ne $null) { if (($eachAttribute.Value -ne $product.productAttributes.$($eachAttribute.Name)) -and ($eachAttribute.Name -ne "driftAlarm") -and ($eachAttribute.Name -ne "driftMessage") -and ($eachAttribute.Name -ne "transportNodeID")){ $eachNode.productAttributes.driftAlarm = "Red" $count += 1 } } else { $eachAttribute.Value = "NULL" $eachNode.productAttributes.driftAlarm = "Red" $count += 1 } } } } } # Getting vCenter Server details $vcenter = Get-vCenterServerDetail -server $ppmVariables.sddcManagerFqdn -user $ppmVariables.sddcManagerUser -pass $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName if (!$ppmVariables.esxiCluster) { $clusterID = Get-VCFWorkloadDomain -name $ppmVariables.sddcDomainName $ppmVariables.esxiCluster = $clusterID } # Start setting the password policy # vCenter Server if ($ppmEnvironmentalDetails | Where-Object { ($_.productType -match "VC") -and ($_.productAttributes.driftAlarm -match "Red") } ) { $products = $ppmStandardConfigValues | Select-Object -Skip 0 | Where-Object -FilterScript { $_.productType -eq "VC" } $passwordTtlInDays = $products.productAttributes.passwdExpInDays $emailNotification = $products.productAttributes.passwdNotifyEmail Write-LogMessage -type INFO -Message "vCenter Server Appliance: Setting the password policy." Set-vCenterPasswordExpiration -server $ppmVariables.sddcManagerFqdn -user $ppmVariables.sddcManagerUser -pass $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName -passwordExpires $true -email $emailNotification -maxDaysBetweenPasswordChange $passwordTtlInDays | Out-Null Write-LogMessage -type INFO -Message "vCenter Server Appliance: Completed setting the password policy." } # vCenter Single Sign-On if ($ppmEnvironmentalDetails | Where-Object { ($_.productType -match "SSO") -and ($_.productAttributes.driftAlarm -match "Red") } ) { $products = $ppmStandardConfigValues | Select-Object -Skip 0 | Where-Object -FilterScript {$_.productType -eq "SSO"} $passHistory = $products.productAttributes.passwdHistoryRestriction $minCharacterLength = $products.productAttributes.passwdMinimumLength $maxCharacterLength = $products.productAttributes.passwdMaximumLength $minNumericChar = $products.productAttributes.passwdMinNumeric $minSpecialChar = $products.productAttributes.passwdMinSpecial $minUppercaseChar = $products.productAttributes.passwdMinUppercase $minLowercaseChar = $products.productAttributes.passwdMinLowercase $maxConsecutiveIdenticalChar = $products.productAttributes.passwdMaxConsecutiveIdenticalChar if ([int]$products.productAttributes.passwdMinAlphabetic -lt [int]([int]$minUppercaseChar + [int]$minLowercaseChar)) { $minAlphabeticCount = [int]$minUppercaseChar + [int]$minLowercaseChar } else { $minAlphabeticCount = $products.productAttributes.passwdMinAlphabetic } $passwordTtlInDays = $products.productAttributes.passwdExpInDays $autoUnlockIntervalSec = $products.productAttributes.passwdUnlockIntervalInSec $failedAttemptIntervalSec = $products.productAttributes.passwdAttemptsIntervalInSec $numAttempts = $products.productAttributes.passwdMaxFailAttempts Write-LogMessage -type INFO -Message "vCenter Single Sign-On: Setting the password policy." Start-Sleep -s 5 if ($ppmVariables.ssoServerFqdn -and $ppmVariables.ssoServerUser -and $ppmVariables.ssoServerPass) { Connect-SsoAdminServer -Server $ppmVariables.ssoServerFqdn -User $ppmVariables.ssoServerUser -Password $ppmVariables.ssoServerPass | Out-Null } else { Connect-SsoAdminServer -server $vcenter.fqdn -user $vcenter.ssoAdmin -pass $vcenter.ssoAdminPass } Get-SsoPasswordPolicy | Set-SsoPasswordPolicy -ProhibitedPreviousPasswordsCount $passHistory -MinLength $minCharacterLength -MaxLength $maxCharacterLength -MinNumericCount $minNumericChar -MinSpecialCharCount $minSpecialChar -MaxIdenticalAdjacentCharacters $maxConsecutiveIdenticalChar -MinAlphabeticCount $minAlphabeticCount -MinUppercaseCount $minUppercaseChar -MinLowercaseCount $minLowercaseChar -PasswordLifetimeDays $passwordTtlInDays | Out-Null Get-SsoLockoutPolicy | Set-SsoLockoutPolicy -AutoUnlockIntervalSec $autoUnlockIntervalSec -FailedAttemptIntervalSec $failedAttemptIntervalSec -MaxFailedAttempts $numAttempts | Out-Null if ($ppmVariables.ssoServerFqdn) { Disconnect-SsoAdminServer -Server $ppmVariables.ssoServerFqdn | Out-Null } else { Disconnect-SsoAdminServer -Server $vcenter.fqdn | Out-Null } Write-LogMessage -type INFO -Message "vCenter Single Sign-On: Completed setting the password policy." } # ESXi Hosts if ($ppmEnvironmentalDetails | Where-Object { ($_.productType -match "ESXi") -and ($_.productAttributes.driftAlarm -match "Red") } ) { $products = $ppmStandardConfigValues | Select-Object -Skip 0 | Where-Object -FilterScript { $_.productType -eq "ESXi" } $passwdExpInDays = $products.productAttributes.passwdExpInDays $numAttempts = $products.productAttributes.passwdMaxFailAttempts $for1CharClass = $products.productAttributes.passwdMinimumLengthFor1CharClass $for2CharClass = $products.productAttributes.passwdMinimumLengthFor2CharClass $for3CharClass = $products.productAttributes.passwdMinimumLengthFor3CharClass $for4CharClass = $products.productAttributes.passwdMinimumLengthFor4CharClass $forPhrases = $products.productAttributes.passwdMinimumCharLengthForPhrase $policy = "retry=" + $numAttempts + " min=" + $for1CharClass + "," + $for2CharClass + "," + $forPhrases + "," + $for3CharClass + "," + $for4CharClass Write-LogMessage -type INFO -Message "ESXi Hosts: Setting the password policy." Start-Sleep -s 5 foreach ($cid in $ppmVariables.esxiCluster.clusters.id) { $cluster = Get-VCFCluster -id $cid Set-EsxiPasswordPolicy -server $ppmVariables.sddcManagerFqdn -user $ppmVariables.sddcManagerUser -pass $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName -cluster $cluster.name -policy $policy | Out-Null Set-EsxiPasswordExpirationPeriod -server $ppmVariables.sddcManagerFqdn -user $ppmVariables.sddcManagerUser -pass $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName -cluster $cluster.name -ExpirationInDays $passwdExpInDays | Out-Null } Write-LogMessage -type INFO -Message "ESXi Hosts: Completed setting the password policy." } # NSX $products = $ppmStandardConfigValues | Select-Object -Skip 0 | Where-Object -FilterScript {$_.productType -eq "NSXMgr"} $apiPasswdMaxFailAttempts = $products.productAttributes.apiPasswdMaxFailAttempts $apiPasswdMaxFailIntervalInSec = $products.productAttributes.apiPasswdMaxFailIntervalInSec $apiPasswdUnlockIntervalInSec = $products.productAttributes.apiPasswdUnlockIntervalInSec $cliPasswdMaxFailAttempts = $products.productAttributes.cliPasswdMaxFailAttempts $cliPasswdMaxFailIntervalInSec = $products.productAttributes.cliPasswdMaxFailIntervalInSec $minCharacterLength = $products.productAttributes.passwdMinimumLength if ($ppmEnvironmentalDetails | Where-Object { ($_.productType -match "NSXMgr") -and ($_.productAttributes.driftAlarm -match "Red") } ) { Write-LogMessage -type INFO -Message "NSX Manager: Setting the password policy." Set-NsxtManagerAuthenticationPolicy -server $ppmVariables.sddcManagerFqdn -user $ppmVariables.sddcManagerUser -pass $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName -apiLockoutPeriod $apiPasswdUnlockIntervalInSec -apiResetPeriod $apiPasswdMaxFailIntervalInSec -apiMaxAttempt $apiPasswdMaxFailAttempts -cliLockoutPeriod $cliPasswdMaxFailIntervalInSec -cliMaxAttempt $cliPasswdMaxFailAttempts -minPasswdLength $minCharacterLength | Out-Null Start-Sleep -s 15 Write-LogMessage -type INFO -Message "NSX Manager: Completed setting the password policy." } if ($ppmEnvironmentalDetails | Where-Object { ($_.productType -match "NSXEdge") -and ($_.productAttributes.driftAlarm -match "Red") } ) { Write-LogMessage -type INFO -Message "NSX Edge: Setting the password policy." Start-Sleep -s 15 $products = $ppmStandardConfigValues | Select-Object -Skip 0 | Where-Object -FilterScript { $_.productType -eq "NSXEdge" } $autoUnlockIntervalSec = $products.productAttributes.cliPasswdMaxFailIntervalInSec $numAttempts = $products.productAttributes.clipasswdMaxFailAttempts $minCharacterLength = $products.productAttributes.passwdMinimumLength Set-NsxtEdgeNodeAuthenticationPolicy -server $ppmVariables.sddcManagerFqdn -user $ppmVariables.sddcManagerUser -pass $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName -cliLockoutPeriod $autoUnlockIntervalSec -cliMaxAttempt $numAttempts -minPasswdLength $minCharacterLength | Out-Null Write-LogMessage -type INFO -Message "NSX Edge: Completed setting the password policy." } # Workspace ONE Access if ($ppmVariables.wsaFqdn -and $ppmVariables.wsaAdminUser -and $ppmVariables.wsaAdminPass) { if($ppmEnvironmentalDetails | Where-Object { ($_.productType -match "WSA") -and ($_.productAttributes.driftAlarm -match "Red") } ) { $products = $ppmStandardConfigValues | Select-Object -Skip 0 | Where-Object -FilterScript { $_.productType -eq "WSA" } $minCharacterLength = $products.productAttributes.passwdMinimumLength $minLowercaseChar = $products.productAttributes.passwdMinLowercase $minUppercaseChar = $products.productAttributes.passwdMinUppercase $minNumericChar = $products.productAttributes.passwdMinNumeric $minSpecialChar = $products.productAttributes.passwdMinSpecial $passwdHistory = $products.productAttributes.passwdHistoryRestriction $maxConsecutiveIdenticalChar = $products.productAttributes.passwdMaxConsecutiveIdenticalChar $maxPreviousPasswordCharactersReused = $products.productAttributes.passwdMaxPreviousCharactersReused $tempPasswordTtlInHrs = $products.productAttributes.tempPasswdLifetimeInHour $passwordTtlInDays = $products.productAttributes.passwdExpInDays $notificationThresholdInDays = $products.productAttributes.passwdExpReminderInDay $notificationIntervalInDays = $products.productAttributes.passwdExpReminderNotificationFrequencyInDay $numAttempts = $products.productAttributes.passwdMaxFailAttempts $attemptIntervalInMins = $products.productAttributes.passwdAttemptsIntervalInMins $unlockIntervalInMins = $products.productAttributes.passwdUnlockIntervalInMins Write-LogMessage -type INFO -Message "Workspace ONE Access: Setting the password policy." Start-Sleep -s 10 Request-WSAToken -fqdn $ppmVariables.wsaFqdn -user $ppmVariables.wsaAdminUser -pass $ppmVariables.wsaAdminPass | Out-Null Set-WSAPasswordPolicy -minLen $minCharacterLength -minLower $minLowercaseChar -minUpper $minUppercaseChar -minDigit $minNumericChar -minSpecial $minSpecialChar -history $passwdHistory -maxConsecutiveIdenticalCharacters $maxConsecutiveIdenticalChar -maxPreviousPasswordCharactersReused $maxPreviousPasswordCharactersReused -tempPasswordTtlInHrs $tempPasswordTtlInHrs -passwordTtlInDays $passwordTtlInDays -notificationThresholdInDays $notificationThresholdInDays -notificationIntervalInDays $notificationIntervalInDays | Out-Null Set-WSAPasswordLockout -numAttempts $numAttempts -attemptInterval $attemptIntervalInMins -unlockInterval $unlockIntervalInMins | Out-Null Write-LogMessage -type INFO -Message "Workspace ONE Access: Completed setting the password policy." } } else { Write-LogMessage -Type INFO -Message "Workspace ONE Access skipped; login details not provided." } } Try { ################ Perform Initialization #################### # Initialize Script Variables $ppmVariables = New-Object -TypeName psobject $ppmVariables | Add-Member -notepropertyname "sddcManagerFqdn" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "sddcManagerUser" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "sddcManagerPass" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "sddcDomainName" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "esxiCluster" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "ssoServerFqdn" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "ssoServerUser" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "ssoServerPass" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "skipWSA" -notepropertyvalue $false $ppmVariables | Add-Member -notepropertyname "wsaFqdn" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "wsaAdminUser" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "wsaAdminPass" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "skipDocComparison" -notepropertyvalue $false $ppmVariables | Add-Member -notepropertyname "commonPolicyFilePath" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "outputFilePath" -notepropertyvalue "" $ppmVariables | Add-Member -notepropertyname "standardConfiguration" -notepropertyvalue "null" $ppmVariables | Add-Member -notepropertyname "isEnvDetailSet" -notepropertyvalue $false $ppmStandardConfigValues = New-Object System.Collections.Generic.List[System.Object] $ppmEnvironmentalDetails = New-Object System.Collections.Generic.List[System.Object] # Initialize Script Log File Test-PasswordPolicyManagerPrereq Start-SetupLogFile -Path $PSScriptRoot -ScriptName $MyInvocation.MyCommand.Name ################ Perform Parameters variable Check #################### if (Test-VCFConnection -server $sddcFqdn) { if (Test-VCFAuthentication -server $sddcFqdn -user $sddcUser -pass $sddcPass) { if (Get-VCFWorkloadDomain | Where-Object {$_.name -eq $sddcDomain}) { # Setting variable $ppmVariables.sddcManagerFqdn = $sddcFqdn $ppmVariables.sddcManagerUser = $sddcUser $ppmVariables.sddcManagerPass = $sddcPass $ppmVariables.sddcDomainName = $sddcDomain # Retrieving vCenter SSO details if ($ssoFqdn -and $ssoUser -and $ssoPass) { $ppmVariables.ssoServerFqdn = $ssoFqdn $ppmVariables.ssoServerUser = $ssoUser $ppmVariables.ssoServerPass = $ssoPass } else { # Retrieving vCenter SSO details from SDDC Manager $vcenter = Get-vCenterServerDetail -server $ppmVariables.sddcManagerFqdn -user $ppmVariables.sddcManagerUser -pass $ppmVariables.sddcManagerPass -domain $ppmVariables.sddcDomainName $ppmVariables.ssoServerFqdn = $vcenter.fqdn $ppmVariables.ssoServerUser = $vcenter.ssoAdmin $ppmVariables.ssoServerPass = $vcenter.ssoAdminPass } # Retrieving Workspace ONE Access details if ($wsaFqdn -and $wsaUser -and $wsaPass) { $ppmVariables.wsaFqdn = $wsaFqdn $ppmVariables.wsaAdminUser = $wsaUser $ppmVariables.wsaAdminPass = $wsaPass } else { Write-LogMessage -Type INFO -Message "Workspace ONE Access server details not provided. Workspace ONE Access will be skipped." -Colour Cyan $ppmVariables.skipWSA = $true } if ($commonPolicyFile) { $commonPolicyFile = Resolve-Path $commonPolicyFile if (Test-Path $commonPolicyFile) { Write-LogMessage -Type INFO -Message "$commonPolicyFile file found" -Colour Yellow $ppmVariables.commonPolicyFilePath = $commonPolicyFile } else { Write-LogMessage -Type ERROR -Message "$commonPolicyFile file not found" -Colour Red Exit } } else { Write-LogMessage -Type INFO -Message "Standard Configuration file not provided. Comparison reporting will be skipped." -Colour Cyan $ppmVariables.skipDocComparison = $true } if ($outputFilePath) { if ($driftOnly) { if (Split-Path -Path $outputFilePath -eq "") { $outputFilePathTimeStampDir = "." } else { $outputFilePathTimeStampDir = Split-Path -Path $outputFilePath } $outputFilePathTimeStampFile = Split-Path -Path $outputFilePath -Leaf if ((([System.IO.Path]::GetExtension($outputFilePathTimeStampFile)) -eq "") -and ($publishHTML -eq $true)) { Write-LogMessage -Type INFO -Message "The file extension was not provided; save output file as a .html file." -Colour Yellow $outputFileExtension = ".html" } elseif (-Not((([System.IO.Path]::GetExtension($outputFilePathTimeStampFile)) -eq ".html") -or (([System.IO.Path]::GetExtension($outputFilePathTimeStampFile)) -eq ".htm")) -and ($publishHTML -eq $true)) { $outputFileExtension = [System.IO.Path]::GetExtension($outputFilePathTimeStampFile) Write-LogMessage -Type INFO -Message "The file extension ($outputFileExtension) does not match HTML file type; save output file as a .html file." -Colour Yellow $outputFileExtension = ".html" } elseif ((([System.IO.Path]::GetExtension($outputFilePathTimeStampFile)) -eq "") -and ($publishJSON -eq $true)) { Write-LogMessage -Type INFO -Message "The file extension was not provided; save output file as a .json file." -Colour Yellow $outputFileExtension = ".json" } elseif (-Not(([System.IO.Path]::GetExtension($outputFilePathTimeStampFile)) -eq ".json") -and ($publishJSON -eq $true)) { $outputFileExtension = [System.IO.Path]::GetExtension($outputFilePathTimeStampFile) Write-LogMessage -Type INFO -Message "The file extension ($outputFileExtension) does not match JSON file type; save output file as a .json file." -Colour Yellow $outputFileExtension = ".json" } else { $outputFileExtension = [System.IO.Path]::GetExtension($outputFilePathTimeStampFile) } $outputFilePathTimeStampFile = ([System.IO.Path]::GetFileNameWithoutExtension($outputFilePathTimeStampFile)) + "_" + (Get-Date -format yyyyMMdd_HHmmss) + "driftOnly" + $outputFileExtension $outputFilePathTimeStamp = Join-Path -Path $outputFilePathTimeStampDir -ChildPath $outputFilePathTimeStampFile } else { if ({ Split-Path -Path $outputFilePath } -eq "") { $outputFilePathTimeStampDir = "." } else { $outputFilePathTimeStampDir = Split-Path -Path $outputFilePath } $outputFilePathTimeStampFile = Split-Path -Path $outputFilePath -Leaf if ((([System.IO.Path]::GetExtension($outputFilePathTimeStampFile)) -eq "") -and ($publishHTML -eq $true)) { Write-LogMessage -Type INFO -Message "The file extension was not provided; save output file as a .html file." -Colour Yellow $outputFileExtension = ".html" } elseif (-Not((([System.IO.Path]::GetExtension($outputFilePathTimeStampFile)) -eq ".html") -or (([System.IO.Path]::GetExtension($outputFilePathTimeStampFile)) -eq ".htm")) -and ($publishHTML -eq $true)) { $outputFileExtension = [System.IO.Path]::GetExtension($outputFilePathTimeStampFile) Write-LogMessage -Type INFO -Message "The file extension ($outputFileExtension) does not match HTML file type; save output file as a .html file." -Colour Yellow $outputFileExtension = ".html" } elseif ((([System.IO.Path]::GetExtension($outputFilePathTimeStampFile)) -eq "") -and ($publishJSON -eq $true)) { Write-LogMessage -Type INFO -Message "The file extension was not provided; save output file as a .json file." -Colour Yellow $outputFileExtension = ".json" } elseif (-Not(([System.IO.Path]::GetExtension($outputFilePathTimeStampFile)) -eq ".json") -and ($publishJSON -eq $true)) { $outputFileExtension = [System.IO.Path]::GetExtension($outputFilePathTimeStampFile) Write-LogMessage -Type INFO -Message "The file extension ($outputFileExtension) does not match JSON file type; save output file as a .json file." -Colour Yellow $outputFileExtension = ".json" } else { $outputFileExtension = [System.IO.Path]::GetExtension($outputFilePathTimeStampFile) } $outputFilePathTimeStampFile = ([System.IO.Path]::GetFileNameWithoutExtension($outputFilePathTimeStampFile)) + "_" + (Get-Date -format yyyyMMdd_HHmmss) + $outputFileExtension $outputFilePathTimeStamp = Join-Path -Path $outputFilePathTimeStampDir -ChildPath $outputFilePathTimeStampFile } if (Test-Path $outputFilePathTimeStamp) { Write-LogMessage -Type ERROR -Message "$outputFilePathTimeStamp file exists." -Colour Red Exit } else { $ppmVariables.outputFilePath = $outputFilePathTimeStamp } # MAIN FUNCTION Try { if ((($publishHTML -or $publishJSON) -and $applyPasswordPolicy) -or ($publishHTML -and $publishJSON)) { Write-LogMessage -Type ERROR -Message "Error multiple options triggered. Please request only one option -publishJSON, -publishHTML or -applyPasswordPolicy." -Colour Red Exit } elseif ($publishJSON -and $ppmVariables.skipDocComparison -eq $false -and $driftOnly) { importStandardConfigurations -ppmVariables $ppmVariables -ppmStandardConfigValues $ppmStandardConfigValues -ppmEnvironmentalDetails $ppmEnvironmentalDetails getEnvironmentPasswordPolicyDetail -ppmVariables $ppmVariables -ppmEnvironmentalDetails $ppmEnvironmentalDetails exportReportJSON -ppmVariables $ppmVariables -ppmStandardConfigValues $ppmStandardConfigValues -ppmEnvironmentalDetails $ppmEnvironmentalDetails Exit } elseif ($publishJSON -and $ppmVariables.skipDocComparison -eq $false -and $driftOnly -eq $false) { importStandardConfigurations -ppmVariables $ppmVariables -ppmStandardConfigValues $ppmStandardConfigValues -ppmEnvironmentalDetails $ppmEnvironmentalDetails getEnvironmentPasswordPolicyDetail -ppmVariables $ppmVariables -ppmEnvironmentalDetails $ppmEnvironmentalDetails exportReportJSON -ppmVariables $ppmVariables -ppmStandardConfigValues $ppmStandardConfigValues -ppmEnvironmentalDetails $ppmEnvironmentalDetails -docCompare Exit } elseif ($publishHTML -and $ppmVariables.skipDocComparison -eq $false) { importStandardConfigurations -ppmVariables $ppmVariables -ppmStandardConfigValues $ppmStandardConfigValues -ppmEnvironmentalDetails $ppmEnvironmentalDetails getEnvironmentPasswordPolicyDetail -ppmVariables $ppmVariables -ppmEnvironmentalDetails $ppmEnvironmentalDetails exportReportHTML -ppmVariables $ppmVariables -ppmStandardConfigValues $ppmStandardConfigValues -ppmEnvironmentalDetails $ppmEnvironmentalDetails -docCompare Exit } elseif ($publishJSON -and $ppmVariables.skipDocComparison -eq $true) { getEnvironmentPasswordPolicyDetail -ppmVariables $ppmVariables -ppmEnvironmentalDetails $ppmEnvironmentalDetails exportReportJSON -ppmVariables $ppmVariables -ppmStandardConfigValues $ppmStandardConfigValues -ppmEnvironmentalDetails $ppmEnvironmentalDetails Exit } elseif ($publishHTML -and $ppmVariables.skipDocComparison -eq $true) { getEnvironmentPasswordPolicyDetail -ppmVariables $ppmVariables -ppmEnvironmentalDetails $ppmEnvironmentalDetails exportReportHTML -ppmVariables $ppmVariables -ppmStandardConfigValues $ppmStandardConfigValues -ppmEnvironmentalDetails $ppmEnvironmentalDetails Exit } elseif ($applyPasswordPolicy) { importStandardConfigurations -ppmVariables $ppmVariables -ppmStandardConfigValues $ppmStandardConfigValues -ppmEnvironmentalDetails $ppmEnvironmentalDetails getEnvironmentPasswordPolicyDetail -ppmVariables $ppmVariables -ppmEnvironmentalDetails $ppmEnvironmentalDetails setEnvironmentPasswordPolicy -ppmVariables $ppmVariables -ppmStandardConfigValues $ppmStandardConfigValues -ppmEnvironmentalDetails $ppmEnvironmentalDetails Exit } } Catch { Debug-ExceptionWriter -object $_ } } } else { Write-Error "Unable to locate workload domain $domainSddc in $sddcFqdn SDDC Manager Server: PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } |