VMware.CloudFoundation.PasswordManagement.psm1
# © Broadcom. All Rights Reserved. # The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. # SPDX-License-Identifier: BSD-2 # 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. # Enable communication with self-signed certificates when using Powershell Core. If you require all communications # to be secure and do not wish to allow communication with self-signed certificates, remove lines 20-40 before # importing the module. if ($PSEdition -eq 'Core') { $PSDefaultParameterValues.Add("Invoke-RestMethod:SkipCertificateCheck", $true) [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null } if ($PSEdition -eq 'Desktop') { # Allow communication with self-signed certificates when using Windows PowerShell [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null if ("TrustAllCertificatePolicy" -as [type]) {} else { Add-Type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertificatePolicy : ICertificatePolicy { public TrustAllCertificatePolicy() {} public bool CheckValidationResult( ServicePoint sPoint, X509Certificate certificate, WebRequest wRequest, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertificatePolicy } } ########################################################################## #Region Non Exported Functions ###### Function Get-Password { param ( [string]$username, [string]$password ) if ([string]::IsNullOrEmpty($password)) { $secureString = Read-Host -Prompt "Enter the password for $username" -AsSecureString $password = ConvertFrom-SecureString $secureString -AsPlainText } return $password } #EndRegion Non Exported Functions ###### ########################################################################## ########################################################################## #Region Begin Global Variables ###### Set-Variable -Name "successStatus" -Value "SUCCESSFUL" -Scope Global Set-Variable -Name "failureStatus" -Value "FAILED" -Scope Global Set-Variable -Name "skippedStatus" -Value "SKIPPED" -Scope Global Set-Variable -Name "preValidationFailureStatus" -Value "PRE_VALIDATION_FAILED" -Scope Global Set-Variable -Name "postValidationFailureStatus" -Value "POST_VALIDATION_FAILED" -Scope Global Set-Variable -Name "managedPasswordMinLength" -Value "20" -Scope Global Set-Variable -Name "minLengthExceeds" -Value "SDDC Manager is not able to the rotate password. Minimum length is greater than the managed range: $minimumPasswordLengthMax." -Scope Global Set-Variable -Name "minLengthNotExceeds" -Value "SDDC Manager is able to rotate the password." -Scope Global #EndRegion End Global Variables ###### ########################################################################## ########################################################################## #Region Begin Password Rotation Functions ###### Function Invoke-PasswordRotationManager { <# .SYNOPSIS Generates a Password Rotation Report for a workload domain or all workload domains. .DESCRIPTION The Invoke-PasswordRotationManager generates a Password Rotation Report for a VMware Cloud Foundation instance. .EXAMPLE Invoke-PasswordRotationManager -sddcManagerFqdn [sddc_manager_fqdn] -sddcManagerUser [admin_username] -sddcManagerPass [admin_password] -sddcRootPass [root_password] -reportPath [report_path] -darkMode -allDomains This example runs a password rotation report for all workload domains within an SDDC Manager instance. .EXAMPLE Invoke-PasswordRotationManager -sddcManagerFqdn [sddc_manager_fqdn] -sddcManagerUser [admin_username] -sddcManagerPass [admin_password] -sddcRootPass [root_password] -reportPath [report_path] -darkMode -workloadDomain [workload_domain_name] This example runs a password rotation report for a specific Workload Domain within an SDDC Manager instance. .PARAMETER sddcManagerFqdn The fully qualified domain name of the SDDC Manager instance. .PARAMETER sddcManagerUser The username to authenticate to the SDDC Manager instance. .PARAMETER sddcManagerPass The password to authenticate to the SDDC Manager instance. .PARAMETER sddcRootPass The password for the SDDC Manager appliance root account. .PARAMETER reportPath The path to save the report to. .PARAMETER allDomains Switch to run the report for all workload domains. .PARAMETER workloadDomain Switch to run the report for a specific workload domain. .PARAMETER darkMode Switch to use dark mode for the report. .PARAMETER json Switch to output the report in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcManagerFqdn, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcManagerUser, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$sddcManagerPass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$sddcRootPass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$darkMode, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $sddcManagerPass = Get-Password -username $sddcManagerUser -password $sddcManagerPass $sddcRootPass = Get-Password -username "root" -password $sddcRootPass Try { Clear-Host; Write-Host "" if (Test-VCFConnection -server $sddcManagerFqdn) { if (Test-VCFAuthentication -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass) { $version = Get-VCFManager -version $managementDomain = Get-VCFWorkloadDomain | Where-Object { $_.Type -eq 'MANAGEMENT' } if ($reportPath.EndsWith("\") -or $reportPath.EndsWith("/")) { $reportPath = $reportPath.TrimEnd("\", "/") } if (!(Test-Path -Path $reportPath)) { Write-Warning "Unable to locate report path $reportPath. Enter a valid path and retry."; Write-Host ""; Break } Start-SetupLogFile -Path $reportPath -ScriptName $MyInvocation.MyCommand.Name # Setup Log Location and Log File $defaultReport = Set-CreateReportDirectoryRotation -path $reportPath -sddcManagerFqdn $sddcManagerFqdn # Setup Report Location and Report File if ($PsBoundParameters.ContainsKey("allDomains")) { $reportName = $defaultReport.Split('.')[0] + "-" + $sddcManagerFqdn.Split(".")[0] + ".htm" $workflowMessage = "VMware Cloud Foundation instance ($sddcManagerFqdn)" $commandSwitch = "-allDomains" } else { $reportName = $defaultReport.Split('.')[0] + "-" + $workloadDomain + ".htm" $workflowMessage = "Workload Domain ($workloadDomain)" $commandSwitch = "-workloadDomain $workloadDomain" } if ($PsBoundParameters.ContainsKey("workloadDomain")) { if (!(Get-VCFWorkloadDomain | Where-Object { $_.name -eq $workloadDomain })) { Write-LogMessage -Type ERROR -Message "Workload Domain $workloadDomain not found. Please review the workload domain name and retry." -Colour Red Break } } if ($PsBoundParameters.ContainsKey("json")) { $commandSwitch = $commandSwitch + " -json" Write-LogMessage -Type INFO -Message "Starting the process of generating the password rotation JSON for $workflowMessage." -Colour Yellow } else { Write-LogMessage -Type INFO -Message "Starting the Process of Generating Password Rotation Report for $workflowMessage." -Colour Yellow Write-LogMessage -Type INFO -Message "Setting up the log file to path $logfile." Write-LogMessage -Type INFO -Message "Setting up report folder and report $reportName." } if ($PsBoundParameters.ContainsKey("json")) { # Platform Resources: Collect Password Rotation Settings Data if ($PsBoundParameters.ContainsKey("allDomains")) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains) { if ($domain | Where-Object { $_.type -eq 'MANAGEMENT' }) { Write-LogMessage -Type INFO -Message "Collecting SDDC Manager password rotation policy for $workflowMessage." $sddcManagerPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'backup' $($commandSwitch)" | ConvertFrom-Json Write-LogMessage -type INFO -Message "Collecting vCenter Single Sign-On password rotation policy for $workflowMessage." $ssoPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'sso' $($commandSwitch)" | ConvertFrom-Json } } } elseif ($PsBoundParameters.ContainsKey("workloadDomain")) { $domain = Get-VCFWorkloadDomain | Where-Object { $_.name -eq $workloadDomain } if ($domain.type -eq "MANAGEMENT") { Write-LogMessage -Type INFO -Message "Collecting SDDC Manager password rotation policy for $workflowMessage." $sddcManagerPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'backup' $($commandSwitch)" | ConvertFrom-Json Write-LogMessage -Type INFO -Message "Collecting vCenter Single Sign-On password rotation policy for $workflowMessage." $ssoPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'sso' $($commandSwitch)" | ConvertFrom-Json } } Write-LogMessage -Type INFO -Message "Collecting vCenter password rotation policy for $workflowMessage." $vcenterServerPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'vcenterServer' $($commandSwitch)" | ConvertFrom-Json Write-LogMessage -Type INFO -Message "Collecting NSX Manager password rotation policy for $workflowMessage." $nsxManagerPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'nsxManager' $($commandSwitch)" | ConvertFrom-Json Write-LogMessage -Type INFO -Message "Collecting NSX Edge password rotation policy for $workflowMessage." $nsxEdgePasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'nsxEdge' $($commandSwitch)" | ConvertFrom-Json # Aria Suite Resources: Build Password Rotation Object # If Aria Suite Lifecycle is enabled and in the SDDC Manager inventory, include it and any other enabled Aria Suite components. if ($PsBoundParameters.ContainsKey('allDomains') -or ($PsBoundParameters.ContainsKey('workloadDomain') -and $workloadDomain -eq $managementDomain.name)) { if (Get-VCFAriaLifecycle) { $ariaResources = @('ariaLifecycle', 'ariaOperationsLogs', 'ariaOperations', 'ariaAutomation', 'workspaceOneAccess') foreach ($resource in $ariaResources) { switch ($resource) { default { $command = "Get-VCF$resource" } 'workspaceOneAccess' { $command = 'Get-VCFWsa'; } } $variableName = "${resource}PasswordRotation" $isEnabled = (Invoke-Expression $command -ErrorAction SilentlyContinue) $resourceTitleCase = switch ($resource) { 'ariaLifecycle' { 'Aria Suite Lifecycle' } 'ariaOperationsLogs' { 'Aria Operations for Logs' } 'ariaOperations' { 'Aria Operations' } 'ariaAutomation' { 'Aria Automation' } 'workspaceOneAccess' { 'Workspace ONE Access' } } if ($isEnabled) { Write-LogMessage -Type INFO -Message "Collecting $($resourceTitleCase) password rotation policy for $workflowMessage." $passwordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource '$resource' $($commandSwitch)" | ConvertFrom-Json if ($passwordRotation) { Set-Variable -Name $variableName -Value $passwordRotation } else { Write-LogMessage -Type INFO -Message "No $($resourceTitleCase) password rotation policy data available." } } else { Write-LogMessage -Type INFO -Message "Skipping: $($resourceTitleCase) is not present in the SDDC Manager inventory." } } } } # Version Information: Build Password Rotation Object $vcfVersion = New-Object -TypeName PSObject $vcfVersion | Add-Member -NotePropertyName 'vcfVersion' -NotePropertyValue $version # Platform Resources: Build Password Rotation Object if ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains) { if ($domain.type -eq 'MANAGEMENT') { $sddcManagerPasswordRotationObj = New-Object -TypeName PSObject $sddcManagerPasswordRotationObj | Add-Member -NotePropertyName 'sddcManager' -NotePropertyValue $sddcManagerPasswordRotation $ssoPasswordRotationObj = New-Object -TypeName PSObject $ssoPasswordRotationObj | Add-Member -NotePropertyName 'sso' -NotePropertyValue $ssoPasswordRotation } } } elseif ($PsBoundParameters.ContainsKey('workloadDomain')) { $domain = Get-VCFWorkloadDomain | Where-Object { $_.name -eq $workloadDomain } if ($domain.type -eq 'MANAGEMENT') { $sddcManagerPasswordRotationObj = New-Object -TypeName PSObject $sddcManagerPasswordRotationObj | Add-Member -NotePropertyName 'sddcManager' -NotePropertyValue $sddcManagerPasswordRotation $ssoPasswordRotationObj = New-Object -TypeName PSObject $ssoPasswordRotationObj | Add-Member -NotePropertyName 'sso' -NotePropertyValue $ssoPasswordRotation } } $vcenterServerPasswordRotationObj = New-Object -TypeName PSObject $vcenterServerPasswordRotationObj | Add-Member -NotePropertyName 'vcenterServer' -NotePropertyValue $vcenterServerPasswordRotation $nsxManagerPasswordRotationObj = New-Object -TypeName PSObject $nsxManagerPasswordRotationObj | Add-Member -NotePropertyName 'nsxManager' -NotePropertyValue $nsxManagerPasswordRotation $nsxEdgePasswordRotationObj = New-Object -TypeName PSObject $nsxEdgePasswordRotationObj | Add-Member -NotePropertyName 'nsxEdge' -NotePropertyValue $nsxEdgePasswordRotation if ($PsBoundParameters.ContainsKey('allDomains') -or ($PsBoundParameters.ContainsKey('workloadDomain') -and $workloadDomain -eq $managementDomain.name)) { if (Get-VCFAriaLifecycle) { $ariaResources = @('ariaLifecycle', 'ariaOperationsLogs', 'ariaOperations', 'ariaAutomation', 'workspaceOneAccess') foreach ($resource in $ariaResources) { switch ($resource) { default { $command = "Get-VCF$resource" } 'workspaceOneAccess' { $command = 'Get-VCFWsa'; } } $isEnabled = (Invoke-Expression $command -ErrorAction SilentlyContinue) $resourceTitleCase = switch ($resource) { 'ariaLifecycle' { 'Aria Suite Lifecycle' } 'ariaOperationsLogs' { 'Aria Operations for Logs' } 'ariaOperations' { 'Aria Operations' } 'ariaAutomation' { 'Aria Automation' } 'workspaceOneAccess' { 'Workspace ONE Access' } } if ($isEnabled) { $variableName = "${resource}PasswordRotation" if (Get-Variable -Name $variableName -ValueOnly) { $ariaPasswordRotationObj = New-Object -TypeName PSObject $ariaPasswordRotationObj | Add-Member -NotePropertyName $resourceTitleCase -NotePropertyValue (Get-Variable -Name $variableName -ValueOnly) Set-Variable -Name "${resource}PasswordRotationObj" -Value $ariaPasswordRotationObj } } } } } # Combine Password Rotation Data $outputJsonObject = New-Object -TypeName PSObject $outputJsonObject | Add-Member -NotePropertyName 'vcf' -NotePropertyValue $vcfVersion # Platform Resources: Combine Password Rotation Data if ($PsBoundParameters.ContainsKey('allDomains') -or ($PsBoundParameters.ContainsKey('workloadDomain') -and $workloadDomain -eq $managementDomain.name)) { $platformResources = @('sddcManager', 'sso', 'vcenterServer', 'nsxManager', 'nsxEdge') } else { $platformResources = @('vcenterServer', 'nsxManager', 'nsxEdge') } foreach ($resource in $platformResources) { $variableName = "${resource}PasswordRotation" if (Get-Variable -Name $variableName -ValueOnly) { $resourceTitleCase = switch ($resource) { 'sddcManager' { 'SDDC Manager' } 'sso' { 'vCenter Single Sign-On' } 'vcenterServer' { 'vCenter' } 'nsxManager' { 'NSX Manager' } 'nsxEdge' { 'NSX Edge' } } $outputJsonObject | Add-Member -NotePropertyName $resourceTitleCase -NotePropertyValue (Get-Variable -Name $variableName -ValueOnly) } } # Aria Suite Resources: Combine Password Rotation Data # If Aria Suite Lifecycle is enabled and in the SDDC Manager inventory, include it and any other enabled Aria Suite components. if ($PsBoundParameters.ContainsKey('allDomains') -or ($PsBoundParameters.ContainsKey('workloadDomain') -and $workloadDomain -eq $managementDomain.name)) { if (Get-VCFAriaLifecycle) { $ariaResources = @('ariaLifecycle', 'ariaOperationsLogs', 'ariaOperations', 'ariaAutomation', 'workspaceOneAccess') foreach ($resource in $ariaResources) { switch ($resource) { default { $command = "Get-VCF$resource" } 'workspaceOneAccess' { $command = 'Get-VCFWsa'; } } $isEnabled = (Invoke-Expression $command -ErrorAction SilentlyContinue) if ($isEnabled) { $variableName = "${resource}PasswordRotation" if (Get-Variable -Name $variableName -ValueOnly) { $resourceTitleCase = switch ($resource) { 'ariaLifecycle' { 'Aria Suite Lifecycle' } 'ariaOperationsLogs' { 'Aria Operations for Logs' } 'ariaOperations' { 'Aria Operations' } 'ariaAutomation' { 'Aria Automation' } 'workspaceOneAccess' { 'Workspace OME Access' } } $outputJsonObject | Add-Member -NotePropertyName $resourceTitleCase -NotePropertyValue (Get-Variable -Name $variableName -ValueOnly) } } } } } # Generate the report as a JSON file. $jsonFile = ($reportFolder + "passwordRotationManager" + ".json") Write-LogMessage -Type INFO -Message "Generating the Final JSON and Saving to ($jsonFile)." $outputJsonObject | ConvertTo-Json -Depth 25 | Out-File -FilePath $jsonFile } else { # Platform Resources: Collect Password Rotation Settings Data if ($PsBoundParameters.ContainsKey("allDomains")) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains) { if ($domain.type -eq "MANAGEMENT") { Write-LogMessage -Type INFO -Message "Collecting SDDC Manager password rotation policy for $workflowMessage." $sddcManagerPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'backup' $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting vCenter Single Sign-On password rotation policy for $workflowMessage." $ssoPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'sso' $($commandSwitch)" } } } elseif ($PsBoundParameters.ContainsKey("workloadDomain")) { $domain = Get-VCFWorkloadDomain | Where-Object { $_.name -eq $workloadDomain } if ($domain.type -eq "MANAGEMENT") { Write-LogMessage -Type INFO -Message "Collecting SDDC Manager password rotation policy for $workflowMessage." $sddcManagerPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'backup' $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting vCenter Single Sign-On password rotation policy for $workflowMessage." $ssoPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'sso' $($commandSwitch)" } } Write-LogMessage -Type INFO -Message "Collecting vCenter password rotation policy for $workflowMessage." $vcenterServerPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'vcenterServer' $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting NSX Manager password rotation policy for $workflowMessage." $nsxManagerPasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'nsxManager' $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting NSX Edge password rotation policy for $workflowMessage." $nsxEdgePasswordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource 'nsxEdge' $($commandSwitch)" # Aria Suite Resources: Collect Password Rotation Settings Data # If Aria Suite Lifecycle is enabled and in the SDDC Manager inventory, include it and any other enabled Aria Suite components. if ($PsBoundParameters.ContainsKey('allDomains') -or ($PsBoundParameters.ContainsKey('workloadDomain') -and $workloadDomain -eq $managementDomain.name)) { if (Get-VCFAriaLifecycle) { $ariaResources = @('ariaLifecycle', 'ariaOperationsLogs', 'ariaOperations', 'ariaAutomation', 'workspaceOneAccess') foreach ($resource in $ariaResources) { switch ($resource) { default { $command = "Get-VCF$resource" } 'workspaceOneAccess' { $command = 'Get-VCFWsa'; } } $variableName = "${resource}PasswordRotation" $isEnabled = (Invoke-Expression $command -ErrorAction SilentlyContinue) $resourceTitleCase = switch ($resource) { 'ariaLifecycle' { 'Aria Suite Lifecycle' } 'ariaOperationsLogs' { 'Aria Operations for Logs' } 'ariaOperations' { 'Aria Operations' } 'ariaAutomation' { 'Aria Automation' } 'workspaceOneAccess' { 'Workspace ONE Access' } } if ($isEnabled) { Write-LogMessage -Type INFO -Message "Collecting $($resourceTitleCase) password rotation policy for $workflowMessage." $passwordRotation = Invoke-Expression "Publish-PasswordRotationPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -resource '$resource' $($commandSwitch)" if ($passwordRotation) { Set-Variable -Name $variableName -Value $passwordRotation } else { Write-LogMessage -Type INFO -Message "No $($resourceTitleCase) password rotation policy data available." } } else { Write-LogMessage -Type INFO -Message "Skipping: $($resourceTitleCase) is not present in the SDDC Manager inventory." } } } } # Platform Resources: Combine Password Rotation Data if ($PsBoundParameters.ContainsKey("allDomains")) { $reportData = "<h1>SDDC Manager: $sddcManagerFqdn</h1>" } else { $reportData = "<h1>Workload Domain: $workloadDomain</h1>" } if ($PsBoundParameters.ContainsKey('allDomains') -or ($PsBoundParameters.ContainsKey('workloadDomain') -and $workloadDomain -eq $managementDomain.name)) { if (($sddcManagerPasswordRotation | Measure-Object).Count -gt 0) { $reportData += $sddcManagerPasswordRotation } if (($ssoPasswordRotation | Measure-Object).Count -gt 0) { $reportData += $ssoPasswordRotation } } if (($vcenterServerPasswordRotation | Measure-Object).Count -gt 0) { $reportData += $vcenterServerPasswordRotation } if (($nsxManagerPasswordRotation | Measure-Object).Count -gt 0) { $reportData += $nsxManagerPasswordRotation } if (($nsxEdgePasswordRotation | Measure-Object).Count -gt 0) { $reportData += $nsxEdgePasswordRotation } # Aria Suite Resources: Combine Password Rotation Data # If Aria Suite Lifecycle is enabled and in the SDDC Manager inventory, include it and any other enabled Aria Suite components. if ($PsBoundParameters.ContainsKey('allDomains') -or ($PsBoundParameters.ContainsKey('workloadDomain') -and $workloadDomain -eq $managementDomain.name)) { if ($ariaLifecyclePasswordRotation) { $ariaResources = @('ariaLifecycle', 'ariaOperationsLogs', 'ariaOperations', 'ariaAutomation', 'workspaceOneAccess') foreach ($resource in $ariaResources) { switch ($resource) { default { $command = "Get-VCF$resource" } 'workspaceOneAccess' { $command = 'Get-VCFWsa'; } } if (Invoke-Expression $command -ErrorAction SilentlyContinue) { $variableName = "${resource}PasswordRotation" if (Get-Variable -Name $variableName -ValueOnly) { $reportData += Get-Variable -Name $variableName -ValueOnly } } } } } # Set Report Header, Navigation, and Footer if ($PsBoundParameters.ContainsKey("darkMode")) { $reportHeader = Save-ClarityReportHeader -dark } else { $reportHeader = Save-ClarityReportHeader } if ($PsBoundParameters.ContainsKey('allDomains')) { $reportNavigation = Save-ClarityReportNavigationForRotation -allDomains } else { $reportNavigation = Save-ClarityReportNavigationForRotation -workloadDomain $workloadDomain } $reportFooter = Save-ClarityReportFooter # Combine Report Sections $report = $reportHeader $report += $reportNavigation $report += $reportData $report += $reportFooter # Generate the report as and HTML file and open it in the default browser. Write-LogMessage -Type INFO -Message "Generating the Final Report and Saving to ($reportName)." $report | Out-File $reportName Invoke-Item $reportName } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Invoke-PasswordRotationManager #EndRegion End Password Rotation Functions ###### ########################################################################## ########################################################################## #Region Begin Password Policy Functions ###### Function Invoke-PasswordPolicyManager { <# .SYNOPSIS Generates a Password Policy Report for a workload domain or all workload domains. .DESCRIPTION The Invoke-PasswordPolicyManager generates a Password Policy Report for a VMware Cloud Foundation instance. .EXAMPLE Invoke-PasswordPolicyManager -sddcManagerFqdn [sddc_manager_fqdn] -sddcManagerUser [admin_username] -sddcManagerPass [admin_password] -sddcRootPass [root_password] -reportPath [report_path] -darkMode -allDomains This example runs a password policy report for all workload domains within an SDDC Manager instance. .EXAMPLE Invoke-PasswordPolicyManager -sddcManagerFqdn [sddc_manager_fqdn] -sddcManagerUser [admin_username] -sddcManagerPass [admin_password] -sddcRootPass [root_password] -reportPath [report_path] -darkMode -allDomains -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -wsaRootPass [wsa_admin_password] This example runs a password policy report for all workload domains within an SDDC Manager instance and Workspace ONE Access. .EXAMPLE Invoke-PasswordPolicyManager -sddcManagerFqdn [sddc_manager_fqdn] -sddcManagerUser [admin_username] -sddcManagerPass [admin_password] -sddcRootPass [root_password] -reportPath [report_path] -darkMode -workloadDomain [workload_domain_name] This example runs a password policy report for a specific Workload Domain within an SDDC Manager instance. .EXAMPLE Invoke-PasswordPolicyManager -sddcManagerFqdn [sddc_manager_fqdn] -sddcManagerUser [admin_username] -sddcManagerPass [admin_password] -sddcRootPass [root_password] -reportPath [report_path] -darkMode -allDomains -drift -policyFile [policy_file].json This example runs a password policy report for all workload domains within an SDDC Manager instance and compares the configuration against the JSON provided. .EXAMPLE Invoke-PasswordPolicyManager -sddcManagerFqdn [sddc_manager_fqdn] -sddcManagerUser [admin_username] -sddcManagerPass [admin_password] -sddcRootPass [root_password] -reportPath [report_path] -darkMode -allDomains -drift This example runs a password policy report for all workload domains within an SDDC Manager instance and compares the configuration against the product defaults. .PARAMETER sddcManagerFqdn The fully qualified domain name of the SDDC Manager instance. .PARAMETER sddcManagerUser The username to authenticate to the SDDC Manager instance. .PARAMETER sddcManagerPass The password to authenticate to the SDDC Manager instance. .PARAMETER sddcRootPass The password for the SDDC Manager appliance root account. .PARAMETER reportPath The path to save the report to. .PARAMETER allDomains Switch to run the report for all workload domains. .PARAMETER workloadDomain Switch to run the report for a specific workload domain. .PARAMETER darkMode Switch to use dark mode for the report. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER policyFile The path to the JSON file containing the policy configuration. .PARAMETER json Switch to output the report in JSON format. .PARAMETER wsaFqdn The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER wsaRootPass The password for the Workspace ONE Access appliance root account. .PARAMETER wsaAdminPass The password for the Workspace ONE Access admin account. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcManagerFqdn, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcManagerUser, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$sddcManagerPass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$sddcRootPass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$darkMode, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$wsaFqdn, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$wsaRootPass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$wsaAdminPass ) $sddcManagerPass = Get-Password -username $sddcManagerUser -password $sddcManagerPass $sddcRootPass = Get-Password -username "root" -password $sddcRootPass if ($wsaFqdn) { $wsaRootPass = Get-Password -username "root" -password $wsaRootPass $wsaAdminPass = Get-Password -username "admin" -password $wsaAdminPass } Try { Clear-Host; Write-Host "" if (Test-VCFConnection -server $sddcManagerFqdn) { if (Test-VCFAuthentication -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass) { $version = Get-VCFManager -version if ($reportPath.EndsWith("\") -or $reportPath.EndsWith("/")) { $reportPath = $reportPath.TrimEnd("\", "/") } if (!(Test-Path -Path $reportPath)) { Write-Warning "Unable to locate report path $reportPath. Enter a valid path and retry."; Write-Host ""; Break } if (!(Test-Path -Path (Join-Path $reportPath $policyFile))) { Write-Warning "Unable to locate policy file $(Join-Path $reportPath $policyFile). Enter a valid path and filename and retry."; Write-Host ""; Break } Start-SetupLogFile -Path $reportPath -ScriptName $MyInvocation.MyCommand.Name # Setup Log Location and Log File $defaultReport = Set-CreateReportDirectory -path $reportPath -sddcManagerFqdn $sddcManagerFqdn # Setup Report Location and Report File if ($PsBoundParameters.ContainsKey("allDomains")) { $reportName = $defaultReport.Split('.')[0] + "-" + $sddcManagerFqdn.Split(".")[0] + ".htm" $workflowMessage = "VMware Cloud Foundation instance ($sddcManagerFqdn)" $commandSwitch = "-allDomains" } else { $reportName = $defaultReport.Split('.')[0] + "-" + $workloadDomain + ".htm" $workflowMessage = "Workload Domain ($workloadDomain)" $commandSwitch = "-workloadDomain $workloadDomain" } if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = $commandSwitch + " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = $commandSwitch + " -drift" } } if ($PsBoundParameters.ContainsKey("json")) { $commandSwitch = $commandSwitch + " -json" Write-LogMessage -Type INFO -Message "Starting the Process of Generating Password Policy Config Drift JSON for $workflowMessage." -Colour Yellow } else { Write-LogMessage -Type INFO -Message "Starting the Process of Generating Password Policy Report for $workflowMessage." -Colour Yellow Write-LogMessage -Type INFO -Message "Setting up the log file to path $logfile." Write-LogMessage -Type INFO -Message "Setting up report folder and report $reportName." } # Collect Password Policies Write-LogMessage -Type INFO -Message "Collecting SDDC Manager Password Policies for $workflowMessage." $sddcManagerPasswordExpiration = Invoke-Expression "Publish-SddcManagerPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -sddcRootPass $sddcRootPass $($commandSwitch)" $sddcManagerPasswordComplexity = Invoke-Expression "Publish-SddcManagerPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -sddcRootPass $sddcRootPass $($commandSwitch)" $sddcManagerAccountLockout = Invoke-Expression "Publish-SddcManagerAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -sddcRootPass $sddcRootPass $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting vCenter Single Sign-On Password Policies for $workflowMessage." $ssoPasswordExpiration = Invoke-Expression "Publish-SsoPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy PasswordExpiration $($commandSwitch)" $ssoPasswordComplexity = Invoke-Expression "Publish-SsoPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy PasswordComplexity $($commandSwitch)" $ssoAccountLockout = Invoke-Expression "Publish-SsoPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy AccountLockout $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting vCenter Password Expiration Policy for $workflowMessage." $vcenterPasswordExpiration = Invoke-Expression "Publish-VcenterPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting vCenter (Local User) Password Policies for $workflowMessage." $vcenterLocalPasswordExpiration = Invoke-Expression "Publish-VcenterLocalPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass $($commandSwitch)" $vcenterLocalPasswordComplexity = Invoke-Expression "Publish-VcenterLocalPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass $($commandSwitch)" $vcenterLocalAccountLockout = Invoke-Expression "Publish-VcenterLocalAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting NSX Manager Password Policies for $workflowMessage." $nsxManagerPasswordExpiration = Invoke-Expression "Publish-NsxManagerPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass $($commandSwitch)" $nsxManagerPasswordComplexity = Invoke-Expression "Publish-NsxManagerPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass $($commandSwitch)" $nsxManagerAccountLockout = Invoke-Expression "Publish-NsxManagerAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting NSX Edge Password Policies for $workflowMessage." $nsxEdgePasswordExpiration = Invoke-Expression "Publish-NsxEdgePasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass $($commandSwitch)" $nsxEdgePasswordComplexity = Invoke-Expression "Publish-NsxEdgePasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass $($commandSwitch)" $nsxEdgeAccountLockout = Invoke-Expression "Publish-NsxEdgeAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting ESX Password Policies for $workflowMessage." $esxiPasswordExpiration = Invoke-Expression "Publish-EsxiPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy PasswordExpiration $($commandSwitch)" $esxiPasswordComplexity = Invoke-Expression "Publish-EsxiPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy PasswordComplexity $($commandSwitch)" $esxiAccountLockout = Invoke-Expression "Publish-EsxiPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy AccountLockout $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting Aria Suite Password Policies for $workflowMessage." $ariaPasswordExpiration = Invoke-Expression "Publish-AriaLocalUserPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy PasswordExpiration $($commandSwitch)" $ariaPasswordComplexity = Invoke-Expression "Publish-AriaLocalUserPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy PasswordComplexity $($commandSwitch)" $ariaAccountLockout = Invoke-Expression "Publish-AriaLocalUserPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy AccountLockout $($commandSwitch)" if ($PsBoundParameters.ContainsKey("wsaFqdn")) { Write-LogMessage -Type INFO -Message "Collecting Workspace ONE Access Directory Password Policies for $workflowMessage." $wsaDirectoryPasswordExpiration = Invoke-Expression "Publish-WsaDirectoryPasswordPolicy -server $wsaFqdn -user admin -pass $wsaAdminPass -policy PasswordExpiration $($commandSwitch)" $wsaDirectoryPasswordComplexity = Invoke-Expression "Publish-WsaDirectoryPasswordPolicy -server $wsaFqdn -user admin -pass $wsaAdminPass -policy PasswordComplexity $($commandSwitch)" $wsaDirectoryAccountLockout = Invoke-Expression "Publish-WsaDirectoryPasswordPolicy -server $wsaFqdn -user admin -pass $wsaAdminPass -policy AccountLockout $($commandSwitch)" Write-LogMessage -Type INFO -Message "Collecting Workspace ONE Access Local User Password Policies for $workflowMessage." $wsaLocalPasswordExpiration = Invoke-Expression "Publish-WsaLocalPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy PasswordExpiration -wsaFqdn $wsaFqdn -wsaRootPass $wsaRootPass $($commandSwitch)" $wsaLocalPasswordComplexity = Invoke-Expression "Publish-WsaLocalPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy PasswordComplexity -wsaFqdn $wsaFqdn -wsaRootPass $wsaRootPass $($commandSwitch)" $wsaLocalAccountLockout = Invoke-Expression "Publish-WsaLocalPasswordPolicy -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -policy AccountLockout -wsaFqdn $wsaFqdn -wsaRootPass $wsaRootPass $($commandSwitch)" } if ($PsBoundParameters.ContainsKey("json")) { # Add VCF version into JSON file $vcfVersion = New-Object -TypeName PSObject $vcfVersion | Add-Member -NotePropertyName 'vcfVersion' -NotePropertyValue $version $sddcManagerPasswordPolicy = New-Object -TypeName PSObject $sddcManagerPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $sddcManagerPasswordExpiration $sddcManagerPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $sddcManagerPasswordComplexity $sddcManagerPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $sddcManagerAccountLockout $ssoPasswordPolicy = New-Object -TypeName PSObject $ssoPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $ssoPasswordExpiration $ssoPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $ssoPasswordComplexity $ssoPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $ssoAccountLockout $vcenterPasswordPolicy = New-Object -TypeName PSObject $vcenterPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $vcenterPasswordExpiration $vcenterLocalPasswordPolicy = New-Object -TypeName PSObject $vcenterLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $vcenterLocalPasswordExpiration $vcenterLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $vcenterLocalPasswordComplexity $vcenterLocalPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $vcenterLocalAccountLockout $nsxManagerPasswordPolicy = New-Object -TypeName PSObject $nsxManagerPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $nsxManagerPasswordExpiration $nsxManagerPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $nsxManagerPasswordComplexity $nsxManagerPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $nsxManagerAccountLockout $nsxEdgePasswordPolicy = New-Object -TypeName PSObject $nsxEdgePasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $nsxEdgePasswordExpiration $nsxEdgePasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $nsxEdgePasswordComplexity $nsxEdgePasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $nsxEdgeAccountLockout $esxiPasswordPolicy = New-Object -TypeName PSObject $esxiPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $esxiPasswordExpiration $esxiPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $esxiPasswordComplexity $esxiPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $esxiAccountLockout $ariaPasswordPolicy = New-Object -TypeName PSObject $ariaPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $ariaPasswordExpiration $ariaPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $ariaPasswordComplexity $ariaPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $ariaAccountLockout if ($PsBoundParameters.ContainsKey("wsaFqdn")) { $wsaDirectoryPasswordPolicy = New-Object -TypeName PSObject $wsaDirectoryPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $wsaDirectoryPasswordExpiration $wsaDirectoryPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $wsaDirectoryPasswordComplexity $wsaDirectoryPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $wsaDirectoryAccountLockout $wsaLocalPasswordPolicy = New-Object -TypeName PSObject $wsaLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $wsaLocalPasswordExpiration $wsaLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $wsaLocalPasswordComplexity $wsaLocalPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $wsaLocalAccountLockout } # Build Final Default Password Policy Object $outputJsonObject = New-Object -TypeName PSObject $outputJsonObject | Add-Member -NotePropertyName 'vcf' -NotePropertyValue $vcfVersion $outputJsonObject | Add-Member -NotePropertyName 'sddcManager' -NotePropertyValue $sddcManagerPasswordPolicy $outputJsonObject | Add-Member -NotePropertyName 'sso' -NotePropertyValue $ssoPasswordPolicy $outputJsonObject | Add-Member -NotePropertyName 'vcenterServer' -NotePropertyValue $vcenterPasswordPolicy $outputJsonObject | Add-Member -NotePropertyName 'vcenterServerLocal' -NotePropertyValue $vcenterLocalPasswordPolicy $outputJsonObject | Add-Member -NotePropertyName 'nsxManager' -NotePropertyValue $nsxManagerPasswordPolicy $outputJsonObject | Add-Member -NotePropertyName 'nsxEdge' -NotePropertyValue $nsxEdgePasswordPolicy $outputJsonObject | Add-Member -NotePropertyName 'esxi' -NotePropertyValue $esxiPasswordPolicy $outputJsonObject | Add-Member -NotePropertyName 'wsaDirectory' -NotePropertyValue $wsaDirectoryPasswordPolicy $outputJsonObject | Add-Member -NotePropertyName 'wsaLocal' -NotePropertyValue $wsaLocalPasswordPolicy $outputJsonObject | Add-Member -NotePropertyName 'ariaLocal' -NotePropertyValue $ariaPasswordPolicy $jsonFile = ($reportFolder + "passwordPolicyManager" + ".json") Write-LogMessage -Type INFO -Message "Generating the Final JSON and Saving to ($jsonFile)." $outputJsonObject | ConvertTo-Json -Depth 25 | Out-File -FilePath $jsonFile } else { # Combine all information gathered into a single HTML report if ($PsBoundParameters.ContainsKey("allDomains")) { $reportData = "<h1>SDDC Manager: $sddcManagerFqdn</h1>" } else { $reportData = "<h1>Workload Domain: $workloadDomain</h1>" } $reportData += $sddcManagerPasswordExpiration $reportData += $ssoPasswordExpiration $reportData += $vcenterPasswordExpiration $reportData += $vcenterLocalPasswordExpiration $reportData += $nsxManagerPasswordExpiration $reportData += $nsxEdgePasswordExpiration $reportData += $esxiPasswordExpiration $reportData += $ariaPasswordExpiration if ($PsBoundParameters.ContainsKey("wsaFqdn")) { $reportData += $wsaDirectoryPasswordExpiration $reportData += $wsaLocalPasswordExpiration } else { $reportData += ($wsaDirectoryPasswordExpiration | ConvertTo-Html -Fragment -PreContent '<a id="standalone-wsa-directory-password-expiration"></a><h3>Local Workspace ONE (Directory) - Password Expiration</h3>' -PostContent '<p>Workspace ONE Access Not Requested</p>') $reportData += ($wsaLocalPasswordExpiration | ConvertTo-Html -Fragment -PreContent '<a id="local-wsa-local-password-expiration"></a><h3>Local Workspace ONE (Local) - Password Expiration</h3>' -PostContent '<p>Workspace ONE Access Not Requested</p>') } $reportData += $sddcManagerPasswordComplexity $reportData += $ssoPasswordComplexity $reportData += $vcenterLocalPasswordComplexity $reportData += $nsxManagerPasswordComplexity $reportData += $nsxEdgePasswordComplexity $reportData += $esxiPasswordComplexity $reportData += $ariaPasswordComplexity if ($PsBoundParameters.ContainsKey("wsaFqdn")) { $reportData += $wsaDirectoryPasswordComplexity $reportData += $wsaLocalPasswordComplexity } else { $reportData += ($wsaDirectoryPasswordComplexity | ConvertTo-Html -Fragment -PreContent '<a id="standalone-wsa-directory-password-complexity"></a><h3>Local Workspace ONE (Directory) - Password Complexity</h3>' -PostContent '<p>Workspace ONE Access Not Requested</p>') $reportData += ($wsaLocalPasswordComplexity | ConvertTo-Html -Fragment -PreContent '<a id="local-wsa-local-password-complexity"></a><h3>Local Workspace ONE (Local) - Password Complexity</h3>' -PostContent '<p>Workspace ONE Access Not Requested</p>') } $reportData += $sddcManagerAccountLockout $reportData += $ssoAccountLockout $reportData += $vcenterLocalAccountLockout $reportData += $nsxManagerAccountLockout $reportData += $nsxEdgeAccountLockout $reportData += $esxiAccountLockout $reportData += $ariaAccountLockout if ($PsBoundParameters.ContainsKey("wsaFqdn")) { $reportData += $wsaDirectoryAccountLockout $reportData += $wsaLocalAccountLockout } else { $reportData += ($wsaDirectoryAccountLockout | ConvertTo-Html -Fragment -PreContent '<a id="standalone-wsa-directory-account-lockout"></a><h3>Local Workspace ONE (Directory) - Account Lockout</h3>' -PostContent '<p>Workspace ONE Access Not Requested</p>') $reportData += ($wsaLocalAccountLockout | ConvertTo-Html -Fragment -PreContent '<a id="local-wsa-local-account-lockout"></a><h3>Local Workspace ONE (Local) - Account Lockout</h3>' -PostContent '<p>Workspace ONE Access Not Requested</p>') } if ($PsBoundParameters.ContainsKey("darkMode")) { $reportHeader = Save-ClarityReportHeader -dark } else { $reportHeader = Save-ClarityReportHeader } $reportNavigation = Save-ClarityReportNavigation $reportFooter = Save-ClarityReportFooter $report = $reportHeader $report += $reportNavigation $report += $reportData $report += $reportFooter # Generate the report to an HTML file and then open it in the default browser Write-LogMessage -Type INFO -Message "Generating the Final Report and Saving to ($reportName)." $report | Out-File $reportName if ($PSEdition -eq "Core" -and ($PSVersionTable.OS).Split(' ')[0] -ne "Linux") { Invoke-Item $reportName } elseif ($PSEdition -eq "Desktop") { Invoke-Item $reportName } } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Invoke-PasswordPolicyManager Function Start-PasswordPolicyConfig { <# .SYNOPSIS Configures all password policies. .DESCRIPTION The Start-PasswordPolicyConfig configures the password policies across all components of the VMware Cloud Foundation instance using the JSON configuration file provided. .EXAMPLE Start-PasswordPolicyConfig -sddcManagerFqdn [sddc_manager_fqdn] -sddcManagerUser [admin_username] -sddcManagerPass [admin_password] -sddcRootPass [root_password] -reportPath [report_path] -policyFile [policy_file].json This examples configures all password policies for all components across a VMware Cloud Foundation instance. .EXAMPLE Start-PasswordPolicyConfig -sddcManagerFqdn [sddc_manager_fqdn] -sddcManagerUser [admin_username] -sddcManagerPass [admin_password] -sddcRootPass [root_password] -reportPath [report_path] -policyFile [policy_file].json -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -wsaRootPass [wsa_admin_password] This example configures all password policies for all components across a VMware Cloud Foundation instance and a Workspace ONE Access instance. .PARAMETER sddcManagerFqdn The fully qualified domain name of the SDDC Manager instance. .PARAMETER sddcManagerUser The username to authenticate to the SDDC Manager instance. .PARAMETER sddcManagerPass The password to authenticate to the SDDC Manager instance. .PARAMETER sddcRootPass The password for the SDDC Manager appliance root account. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the JSON file containing the policy configuration. .PARAMETER wsaFqdn The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER wsaRootPass The password for the Workspace ONE Access appliance root account. .PARAMETER wsaAdminPass The password for the Workspace ONE Access admin account. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcManagerFqdn, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcManagerUser, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$sddcManagerPass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$sddcRootPass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false, ParameterSetName = 'wsa')] [ValidateNotNullOrEmpty()] [String]$wsaFqdn, [Parameter (Mandatory = $false, ParameterSetName = 'wsa')] [ValidateNotNullOrEmpty()] [String]$wsaRootPass, [Parameter (Mandatory = $false, ParameterSetName = 'wsa')] [ValidateNotNullOrEmpty()] [String]$wsaAdminPass ) $sddcManagerPass = Get-Password -username $sddcManagerUser -password $sddcManagerPass $sddcRootPass = Get-Password -username "root" -password $sddcRootPass if ($wsaFqdn) { $wsaRootPass = Get-Password -username "root" -password $wsaRootPass $wsaAdminPass = Get-Password -username "admin" -password $wsaAdminPass } Clear-Host; Write-Host "" Try { if (Test-VCFConnection -server $sddcManagerFqdn) { if (Test-VCFAuthentication -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass) { Start-SetupLogFile -Path $reportPath -ScriptName $MyInvocation.MyCommand.Name # Setup Log Location and Log File $reportPath = $reportPath.TrimEnd('\') if ($reportPath.EndsWith("\") -or $reportPath.EndsWith("/")) { $reportPath = $reportPath.TrimEnd("\", "/") } if (!(Test-Path -Path $reportPath)) { Write-Warning "Unable to locate report path $reportPath. Enter a valid path and retry."; Write-Host ""; Break } if (!(Test-Path -Path (Join-Path $reportPath $policyFile))) { Write-Warning "Unable to locate password policy configuration file $(Join-Path $reportPath $policyFile). Enter a valid path and filename and retry."; Write-Host ""; Break } Write-LogMessage -Type INFO -Message "Starting the Process of Configuring Password Policies for SDDC Manager Instance ($sddcManagerFqdn)." -Colour Yellow $customPolicy = Get-Content -Path (Join-Path $reportPath $policyFile) | ConvertFrom-Json $sddcDomainMgmt = (Get-VCFWorkloadDomain | Where-Object { $_.type -eq "MANAGEMENT" }).name $allWorkloadDomains = Get-VCFWorkloadDomain # Configuring Password Policies for SDDC Manager Write-LogMessage -Type INFO -Message "Configuring Password Policies for SDDC Manager Instance ($sddcManagerFqdn)" -Colour Yellow Write-LogMessage -Type INFO -Message "Configuring SDDC Manager Instance ($sddcManagerFqdn): Password Expiration Policy" $localUsers = @("vcf", "root") foreach ($localUser in $localUsers) { $StatusMsg = Update-LocalUserPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $sddcDomainMgmt -vmName ($sddcManagerFqdn.Split('.')[-0]) -guestUser root -guestPassword $sddcRootPass -localUser $localUser -minDays $customPolicy.sddcManager.passwordExpiration.minDays -maxDays $customPolicy.sddcManager.passwordExpiration.maxDays -warnDays $customPolicy.sddcManager.passwordExpiration.warningDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } } Write-LogMessage -Type INFO -Message "Configuring SDDC Manager Instance ($sddcManagerFqdn): Password Complexity Policy" $StatusMsg = Update-SddcManagerPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -rootPass $sddcRootPass -minLength $customPolicy.sddcManager.passwordComplexity.minLength -minLowercase $customPolicy.sddcManager.passwordComplexity.minLowercase -minUppercase $customPolicy.sddcManager.passwordComplexity.minUppercase -minNumerical $customPolicy.sddcManager.passwordComplexity.minNumerical -minSpecial $customPolicy.sddcManager.passwordComplexity.minSpecial -minUnique $customPolicy.sddcManager.passwordComplexity.minUnique -minClass $customPolicy.sddcManager.passwordComplexity.minClass -maxSequence $customPolicy.sddcManager.passwordComplexity.maxSequence -history $customPolicy.sddcManager.passwordComplexity.history -maxRetry $customPolicy.sddcManager.passwordComplexity.retries -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring SDDC Manager Instance ($sddcManagerFqdn): Account Lockout Policy" $StatusMsg = Update-SddcManagerAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -rootPass $sddcRootPass -failures $customPolicy.sddcManager.accountLockout.maxFailures -unlockInterval $customPolicy.sddcManager.accountLockout.unlockInterval -rootUnlockInterval $customPolicy.sddcManager.accountLockout.rootUnlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for SDDC Manager Instance ($sddcManagerFqdn)" -Colour Yellow # Configuring Password Policies for vCenter Single Sign-On Write-LogMessage -Type INFO -Message "Configuring Password Policies for vCenter Single Sign-On" -Colour Yellow Write-LogMessage -Type INFO -Message "Configuring vCenter Single Sign-On: Password Expiration Policy" $StatusMsg = Update-SsoPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $sddcDomainMgmt -maxDays $customPolicy.sso.passwordExpiration.maxDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring vCenter Single Sign-On: Password Complexity Policy" $StatusMsg = Update-SsoPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $sddcDomainMgmt -minLength $customPolicy.sso.passwordComplexity.minLength -maxLength $customPolicy.sso.passwordComplexity.maxLength -minAlphabetic $customPolicy.sso.passwordComplexity.minAlphabetic -minLowercase $customPolicy.sso.passwordComplexity.minLowercase -minUppercase $customPolicy.sso.passwordComplexity.minUppercase -minNumeric $customPolicy.sso.passwordComplexity.minNumerical -minSpecial $customPolicy.sso.passwordComplexity.minSpecial -maxIdenticalAdjacent $customPolicy.sso.passwordComplexity.maxIdenticalAdjacent -history $customPolicy.sso.passwordComplexity.history -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } $StatusMsg = Write-LogMessage -Type INFO -Message "Configuring vCenter Single Sign-On: Account Lockout Policy" $StatusMsg = Update-SsoAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $sddcDomainMgmt -failures $customPolicy.sso.accountLockout.maxFailures -failureInterval $customPolicy.sso.accountLockout.failedAttemptInterval -unlockInterval $customPolicy.sso.accountLockout.unlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for vCenter Single Sign-On" -Colour Yellow # Configuring Password Policies for vCenter Write-LogMessage -Type INFO -Message "Configuring Password Policies for vCenter" -Colour Yellow foreach ($workloadDomain in $allWorkloadDomains) { Write-LogMessage -Type INFO -Message "Starting the Process of Configuring Password Policies for vCenter for Workload Domain ($($workloadDomain.name))" -Colour Yellow Write-LogMessage -Type INFO -Message "Configuring vCenter: Password Expiration Policy for Workload Domain ($($workloadDomain.name))" $StatusMsg = Update-VcenterPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $($workloadDomain.name) -maxDays $customPolicy.vcenterServer.passwordExpiration.maxDays -minDays $customPolicy.vcenterServer.passwordExpiration.minDays -warnDays $customPolicy.vcenterServer.passwordExpiration.warningDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring vCenter Local Users: Password Expiration Policy for Workload Domain ($($workloadDomain.name))" $StatusMsg = Update-VcenterRootPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $workloadDomain.name -email $customPolicy.vcenterServerLocal.passwordExpiration.email -maxDays $customPolicy.vcenterServerLocal.passwordExpiration.maxDays -warnDays $customPolicy.vcenterServerLocal.passwordExpiration.warningDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring vCenter Local Users: Password Complexity Policy for Workload Domain ($($workloadDomain.name))" $StatusMsg = Update-VcenterPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $workloadDomain.name -minLength $customPolicy.vcenterServerLocal.passwordComplexity.minLength -minLowercase $customPolicy.vcenterServerLocal.passwordComplexity.minLowercase -minUppercase $customPolicy.vcenterServerLocal.passwordComplexity.minUppercase -minNumerical $customPolicy.vcenterServerLocal.passwordComplexity.minNumerical -minSpecial $customPolicy.vcenterServerLocal.passwordComplexity.minSpecial -minUnique $customPolicy.vcenterServerLocal.passwordComplexity.minUnique -history $customPolicy.vcenterServerLocal.passwordComplexity.history -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring vCenter Local Users: Account Lockout Policy for Workload Domain ($($workloadDomain.name))" $StatusMsg = Update-VcenterAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $workloadDomain.name -failures $customPolicy.vcenterServerLocal.accountLockout.maxFailures -unlockInterval $customPolicy.vcenterServerLocal.accountLockout.unlockInterval -rootUnlockInterval $customPolicy.vcenterServerLocal.accountLockout.rootUnlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for vCenter" -Colour Yellow # Configuring Password Policies for NSX Local Managers Write-LogMessage -Type INFO -Message "Configuring Password Policies for NSX Local Managers" -Colour Yellow foreach ($workloadDomain in $allWorkloadDomains) { Write-LogMessage -Type INFO -Message "Starting the Process of Configuring Password Policies for the NSX Local Manager for Workload Domain ($($workloadDomain.name))" -Colour Yellow Write-LogMessage -Type INFO -Message "Configuring NSX Local Managers: Password Expiration Policy ($($workloadDomain.name))" $StatusMsg = Update-NsxtManagerPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $($workloadDomain.name) -maxdays $customPolicy.nsxEdge.passwordExpiration.maxDays -detail false -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring NSX Local Managers: Password Complexity Policy ($($workloadDomain.name))" $StatusMsg = Update-NsxtManagerPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $($workloadDomain.name) -minLength $customPolicy.nsxManager.passwordComplexity.minLength -minLowercase $customPolicy.nsxManager.passwordComplexity.minLowercase -minUppercase $customPolicy.nsxManager.passwordComplexity.minUppercase -minNumerical $customPolicy.nsxManager.passwordComplexity.minNumerical -minSpecial $customPolicy.nsxManager.passwordComplexity.minSpecial -minUnique $customPolicy.nsxManager.passwordComplexity.minUnique -maxRetry $customPolicy.nsxManager.passwordComplexity.retries -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg -match "SUCCESSFUL" ) { Write-LogMessage -Type INFO -Message "Update Password Complexity Policy on NSX Local Managers for Workload Domain ($($workloadDomain.name)): SUCCESSFUL" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message "Update Password Complexity Policy on NSX Local Managers for Workload Domain ($($workloadDomain.name)), already set: SKIPPED" -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring NSX Local Managers: Account Lockout Policy ($($workloadDomain.name))" $StatusMsg = Update-NsxtManagerAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $($workloadDomain.name) -cliFailures $customPolicy.nsxManager.accountLockout.cliMaxFailures -cliUnlockInterval $customPolicy.nsxManager.accountLockout.cliUnlockInterval -apiFailures $customPolicy.nsxManager.accountLockout.apiMaxFailures -apiFailureInterval $customPolicy.nsxManager.accountLockout.apiRestInterval -apiUnlockInterval $customPolicy.nsxManager.accountLockout.apiUnlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg -match "SUCCESSFUL" ) { Write-LogMessage -Type INFO -Message "Update Account Lockout Policy on NSX Local Managers for Workload Domain ($($workloadDomain.name)): SUCCESSFUL" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message "Update Account Lockout Policy on NSX Local Managers for Workload Domain ($($workloadDomain.name)), already set: SKIPPED" -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for NSX Local Managers" -Colour Yellow # Configuring Password Policies for NSX Edge Nodes Write-LogMessage -Type INFO -Message "Configuring Password Policies for NSX Edge Nodes" -Colour Yellow foreach ($workloadDomain in $allWorkloadDomains) { Write-LogMessage -Type INFO -Message "Starting the Process of Configuring Password Policies for the NSX Edge for Workload Domain ($($workloadDomain.name))" -Colour Yellow Write-LogMessage -Type INFO -Message "Configuring NSX Edge Nodes: Password Expiration Policy for Workload Domain ($($workloadDomain.name))" $StatusMsg = Update-NsxtEdgePasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $($workloadDomain.name) -maxdays $customPolicy.nsxEdge.passwordExpiration.maxDays -detail false -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring NSX Edge Nodes: Password Complexity Policy ($($workloadDomain.name))" $StatusMsg = Update-NsxtEdgePasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $($workloadDomain.name) -minLength $customPolicy.nsxEdge.passwordComplexity.minLength -minLowercase $customPolicy.nsxEdge.passwordComplexity.minLowercase -minUppercase $customPolicy.nsxEdge.passwordComplexity.minUppercase -minNumerical $customPolicy.nsxEdge.passwordComplexity.minNumerical -minSpecial $customPolicy.nsxEdge.passwordComplexity.minSpecial -minUnique $customPolicy.nsxEdge.passwordComplexity.minUnique -maxRetry $customPolicy.nsxEdge.passwordComplexity.retries -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg -match "SUCCESSFUL" ) { Write-LogMessage -Type INFO -Message "Update Password Complexity Policy on NSX Edge Nodes for Workload Domain ($($workloadDomain.name)): SUCCESSFUL" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message "Update Password Complexity Policy on NSX Edge Nodes for Workload Domain ($($workloadDomain.name)), already set: SKIPPED" -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring NSX Edge Nodes: Account Lockout Policy ($($workloadDomain.name))" $StatusMsg = Update-NsxtEdgeAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $($workloadDomain.name) -cliFailures $customPolicy.nsxEdge.accountLockout.cliMaxFailures -cliUnlockInterval $customPolicy.nsxEdge.accountLockout.cliUnlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg -match "SUCCESSFUL" ) { Write-LogMessage -Type INFO -Message "Update Password Complexity Policy on NSX Edge Nodes for Workload Domain ($($workloadDomain.name)): SUCCESSFUL" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message "Update Account Lockout Policy on NSX Edge Nodes for Workload Domain ($($workloadDomain.name)), already set: SKIPPED" -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for NSX Edge Nodes" -Colour Yellow # Configuring Password Policies for ESX Hosts Write-LogMessage -Type INFO -Message "Configuring Password Policies for ESX Hosts" -Colour Yellow foreach ($workloadDomain in $allWorkloadDomains) { Write-LogMessage -Type INFO -Message "Starting the Process of Configuring Password Policies for the ESX Hosts for Workload Domain ($($workloadDomain.name))" -Colour Yellow $clusters = $workloadDomain.clusters Write-LogMessage -Type INFO -Message "Configuring ESX Hosts: Password Expiration Policy for Workload Domain ($($workloadDomain.name))" foreach ($cluster in $clusters) { $clusterName = (Get-VCFCluster -id $cluster.id).name $StatusMsg = Update-EsxiPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $($workloadDomain.name) -cluster $clusterName -maxDays $customPolicy.esxi.passwordExpiration.maxDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg -match "SUCCESSFUL" ) { Write-LogMessage -Type INFO -Message "Update Password Expiration Policy on ESX Hosts for Workload Domain / Cluster ($($workloadDomain.name) / $clusterName): SUCCESSFUL" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message "Update Password Expiration Policy on ESX Hosts for Workload Domain / Cluster ($($workloadDomain.name) / $clusterName), already set: SKIPPED" -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } } Write-LogMessage -Type INFO -Message "Configuring ESX Hosts: Password Complexity Policy for Workload Domain ($($workloadDomain.name))" foreach ($cluster in $clusters) { $clusterName = (Get-VCFCluster -id $cluster.id).name $StatusMsg = Update-EsxiPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $($workloadDomain.name) -cluster $clusterName -policy $customPolicy.esxi.passwordComplexity.policy -history $customPolicy.esxi.passwordComplexity.history -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg -match "SUCCESSFUL" ) { Write-LogMessage -Type INFO -Message "Update Password Complexity Policy on ESX Hosts for Workload Domain / Cluster ($($workloadDomain.name) / $clusterName): SUCCESSFUL" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message "Update Password Complexity Policy on ESX Hosts for Workload Domain / Cluster ($($workloadDomain.name) / $clusterName), already set: SKIPPED" -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } } Write-LogMessage -Type INFO -Message "Configuring ESX Hosts: Account Lockout Policy for Workload Domain ($($workloadDomain.name))" foreach ($cluster in $clusters) { $clusterName = (Get-VCFCluster -id $cluster.id).name $StatusMsg = Update-EsxiAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $($workloadDomain.name) -cluster $clusterName -failures $customPolicy.esxi.accountLockout.maxFailures -unlockInterval $customPolicy.esxi.accountLockout.unlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg -match "SUCCESSFUL" ) { Write-LogMessage -Type INFO -Message "Update Account Lockout Policy on ESX Hosts for Workload Domain / Cluster ($($workloadDomain.name) / $clusterName): SUCCESSFUL" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message "Update Account Lockout Policy on ESX Hosts for Workload Domain / Cluster ($($workloadDomain.name) / $clusterName), already set: SKIPPED" -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } } } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for ESX Hosts" -Colour Yellow # Configuring Password Policies for Workspace ONE Access if ($PsBoundParameters.ContainsKey("wsaFqdn")) { # Workspace ONE Access Directory Password Policies Write-LogMessage -Type INFO -Message "Configuring Password Policies for Workspace ONE Access Directory" -Colour Yellow Write-LogMessage -Type INFO -Message "Configuring Workspace ONE Access Directory: Password Expiration Policy for instance ($($wsaFqdn))" $StatusMsg = Update-WsaPasswordExpiration -server $wsaFqdn -user admin -pass $wsaAdminPass -maxDays $customPolicy.wsaDirectory.passwordExpiration.passwordLifetime -warnDays $customPolicy.wsaDirectory.passwordExpiration.passwordReminder -reminderDays $customPolicy.wsaDirectory.passwordExpiration.passwordReminderFrequency -tempPasswordHours $customPolicy.wsaDirectory.passwordExpiration.temporaryPassword -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Workspace ONE Access Directory: Password Complexity Policy for instance ($($wsaFqdn))" $StatusMsg = Update-WsaPasswordComplexity -server $wsaFqdn -user admin -pass $wsaAdminPass -minLength $customPolicy.wsaDirectory.passwordComplexity.minLength -minLowercase $customPolicy.wsaDirectory.passwordComplexity.minLowercase -minUppercase $customPolicy.wsaDirectory.passwordComplexity.minUppercase -minNumeric $customPolicy.wsaDirectory.passwordComplexity.minNumerical -minSpecial $customPolicy.wsaDirectory.passwordComplexity.minSpecial -maxIdenticalAdjacent $customPolicy.wsaDirectory.passwordComplexity.maxIdenticalAdjacent -maxPreviousCharacters $customPolicy.wsaDirectory.passwordComplexity.history -history $customPolicy.wsaDirectory.passwordComplexity.history -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Workspace ONE Access Directory: Account Lockout Policy for instance ($($wsaFqdn))" $StatusMsg = Update-WsaAccountLockout -server $wsaFqdn -user admin -pass $wsaAdminPass -failures $customPolicy.wsaDirectory.accountLockout.maxFailures -failureInterval $customPolicy.wsaDirectory.accountLockout.failedAttemptInterval -unlockInterval $customPolicy.wsaDirectory.accountLockout.unlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for Workspace ONE Access Directory" -Colour Yellow # Workspace ONE Access Local User Password Policies Write-LogMessage -Type INFO -Message "Configuring Password Policies for Workspace ONE Access Local Users" -Colour Yellow Write-LogMessage -Type INFO -Message "Configuring Workspace ONE Access Local Users: Password Expiration Policy for instance ($($wsaFqdn))" $localUsers = @("root", "sshuser") foreach ($localUser in $localUsers) { $StatusMsg = Update-LocalUserPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -domain $sddcDomainMgmt -vmName ($wsaFqdn.Split('.')[-0]) -guestUser root -guestPassword $wsaRootPass -localUser $localUser -minDays $customPolicy.sddcManager.passwordExpiration.minDays -maxDays $customPolicy.sddcManager.passwordExpiration.maxDays -warnDays $customPolicy.sddcManager.passwordExpiration.warningDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } } Write-LogMessage -Type INFO -Message "Configuring Workspace ONE Access Local Users: Password Complexity Policy for instance ($($wsaFqdn))" $StatusMsg = Update-WsaLocalUserPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -wsaFqdn $wsaFqdn -wsaRootPass $wsaRootPass -minLength $customPolicy.wsaLocal.passwordComplexity.minLength -history $customPolicy.wsaLocal.passwordComplexity.history -maxRetry $customPolicy.wsaLocal.passwordComplexity.retries -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Workspace ONE Access Local Users: Account Lockout Policy for instance ($($wsaFqdn))" $StatusMsg = Update-WsaLocalUserAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -wsaFqdn $wsaFqdn -wsaRootPass $wsaRootPass -failures $customPolicy.wsaLocal.accountLockout.maxFailures -unlockInterval $customPolicy.wsaLocal.accountLockout.unlockInterval -rootUnlockInterval $customPolicy.wsaLocal.accountLockout.rootUnlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for Workspace ONE Access Local Users" -Colour Yellow } # Configuring Password Policies for Aria Suite Lifecycle Write-LogMessage -Type INFO -Message "Configuring Password Policies for Aria Suite Lifecycle" Write-LogMessage -Type INFO -Message "Configuring Aria Suite Lifecycle Local Users: Password Expiration Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrslcm' -policyPath $reportPath -policyFile $policyFile -localUser 'root' -minDays $customPolicy.ariaLifecycle.passwordExpiration.minDays -maxDays $customPolicy.ariaLifecycle.passwordExpiration.maxDays -warnDays $customPolicy.ariaLifecycle.passwordExpiration.warningDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Aria Suite Lifecycle Local Users: Password Complexity Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrslcm' -minLength $customPolicy.ariaLifecycle.passwordComplexity.minLength -uppercase $customPolicy.ariaLifecycle.passwordComplexity.minUppercase -lowercase $customPolicy.ariaLifecycle.passwordComplexity.minLowercase -numerical $customPolicy.ariaLifecycle.passwordComplexity.minNumerical -special $customPolicy.ariaLifecycle.passwordComplexity.minSpecial -sequence $customPolicy.ariaLifecycle.passwordComplexity.maxSequence -unique $customPolicy.ariaLifecycle.passwordComplexity.minUnique -class $customPolicy.ariaLifecycle.passwordComplexity.minClass -history $customPolicy.ariaLifecycle.passwordComplexity.history -retry $customPolicy.ariaLifecycle.passwordComplexity.retries -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Aria Suite Lifecycle Local Users: Account Lockout Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrslcm' -failures $customPolicy.ariaLifecycle.accountLockout.maxFailures -unlockInterval $customPolicy.ariaLifecycle.accountLockout.unlockInterval -rootUnlockInterval $customPolicy.ariaLifecycle.accountLockout.rootUnlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for Aria Suite Lifecycle Local Users" # Configuring Password Policies for Aria Operations Write-LogMessage -Type INFO -Message "Configuring Password Policies for Aria Operations" Write-LogMessage -Type INFO -Message "Configuring Aria Operations Local Users: Password Expiration Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrops' -policyPath $reportPath -policyFile $policyFile -localUser 'root' -minDays $customPolicy.ariaOperations.passwordExpiration.minDays -maxDays $customPolicy.ariaOperations.passwordExpiration.maxDays -warnDays $customPolicy.ariaOperations.passwordExpiration.warningDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Aria Operations Local Users: Password Complexity Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrops' -minLength $customPolicy.ariaOperations.passwordComplexity.minLength -uppercase $customPolicy.ariaOperations.passwordComplexity.minUppercase -lowercase $customPolicy.ariaOperations.passwordComplexity.minLowercase -numerical $customPolicy.ariaOperations.passwordComplexity.minNumerical -special $customPolicy.ariaOperations.passwordComplexity.minSpecial -sequence $customPolicy.ariaOperations.passwordComplexity.maxSequence -unique $customPolicy.ariaOperations.passwordComplexity.minUnique -class $customPolicy.ariaOperations.passwordComplexity.minClass -history $customPolicy.ariaOperations.passwordComplexity.history -retry $customPolicy.ariaOperations.passwordComplexity.retries -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Aria Operations Local Users: Account Lockout Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrops' -failures $customPolicy.ariaOperations.accountLockout.maxFailures -unlockInterval $customPolicy.ariaOperations.accountLockout.unlockInterval -rootUnlockInterval $customPolicy.ariaOperations.accountLockout.rootUnlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for Aria Operations Local Users" # Configuring Password Policies for Aria Operations for Logs Write-LogMessage -Type INFO -Message "Configuring Password Policies for Aria Operations for Logs" Write-LogMessage -Type INFO -Message "Configuring Aria Operations for Logs Local Users: Password Expiration Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrli' -policyPath $reportPath -policyFile $policyFile -localUser 'root' -minDays $customPolicy.ariaOperationsLogs.passwordExpiration.minDays -maxDays $customPolicy.ariaOperationsLogs.passwordExpiration.maxDays -warnDays $customPolicy.ariaOperationsLogs.passwordExpiration.warningDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Aria Operations for Logs Local Users: Password Complexity Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrli' -minLength $customPolicy.ariaOperationsLogs.passwordComplexity.minLength -uppercase $customPolicy.ariaOperationsLogs.passwordComplexity.minUppercase -lowercase $customPolicy.ariaOperationsLogs.passwordComplexity.minLowercase -numerical $customPolicy.ariaOperationsLogs.passwordComplexity.minNumerical -special $customPolicy.ariaOperationsLogs.passwordComplexity.minSpecial -sequence $customPolicy.ariaOperationsLogs.passwordComplexity.maxSequence -unique $customPolicy.ariaOperationsLogs.passwordComplexity.minUnique -class $customPolicy.ariaOperationsLogs.passwordComplexity.minClass -history $customPolicy.ariaOperationsLogs.passwordComplexity.history -retry $customPolicy.ariaOperationsLogs.passwordComplexity.retries -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Aria Operations for Logs Local Users: Account Lockout Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrli' -failures $customPolicy.ariaOperationsLogs.accountLockout.maxFailures -unlockInterval $customPolicy.ariaOperationsLogs.accountLockout.unlockInterval -rootUnlockInterval $customPolicy.ariaOperationsLogs.accountLockout.rootUnlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for Aria Operations for Logs Local Users" # Configuring Password Policies for Aria Operations for Networks Write-LogMessage -Type INFO -Message "Configuring Password Policies for Aria Operations for Networks" Write-LogMessage -Type INFO -Message "Configuring Aria Operations for Networks Local Users: Password Expiration Policy for each instance" $localUsers = @("support", "consoleuser") foreach ($localUser in $localUsers) { $StatusMsg = Update-AriaLocalUserPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrni' -policyPath $reportPath -policyFile $policyFile -localUser $localUser -minDays $customPolicy.ariaOperationsNetworks.passwordExpiration.minDays -maxDays $customPolicy.ariaOperationsNetworks.passwordExpiration.maxDays -warnDays $customPolicy.ariaOperationsNetworks.passwordExpiration.warningDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } } Write-LogMessage -Type INFO -Message "Configuring Aria Operations for Networks Local Users: Password Complexity Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrni' -minLength $customPolicy.ariaOperationsNetworks.passwordComplexity.minLength -uppercase $customPolicy.ariaOperationsNetworks.passwordComplexity.minUppercase -lowercase $customPolicy.ariaOperationsNetworks.passwordComplexity.minLowercase -numerical $customPolicy.ariaOperationsNetworks.passwordComplexity.minNumerical -special $customPolicy.ariaOperationsNetworks.passwordComplexity.minSpecial -sequence $customPolicy.ariaOperationsNetworks.passwordComplexity.maxSequence -unique $customPolicy.ariaOperationsNetworks.passwordComplexity.minUnique -class $customPolicy.ariaOperationsNetworks.passwordComplexity.minClass -history $customPolicy.ariaOperationsNetworks.passwordComplexity.history -retry $customPolicy.ariaOperationsNetworks.passwordComplexity.retries -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Aria Operations for Networks Local Users: Account Lockout Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vrni' -failures $customPolicy.ariaOperationsNetworks.accountLockout.maxFailures -unlockInterval $customPolicy.ariaOperationsNetworks.accountLockout.unlockInterval -rootUnlockInterval $customPolicy.ariaOperationsNetworks.accountLockout.rootUnlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for Aria Operations for Networks Local Users" # Configuring Password Policies for Aria Automation Write-LogMessage -Type INFO -Message "Configuring Password Policies for Aria Automation" Write-LogMessage -Type INFO -Message "Configuring Aria Automation Local Users: Password Expiration Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordExpiration -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vra' -policyPath $reportPath -policyFile $policyFile -localUser 'root' -minDays $customPolicy.ariaAutomation.passwordExpiration.minDays -maxDays $customPolicy.ariaAutomation.passwordExpiration.maxDays -warnDays $customPolicy.ariaAutomation.passwordExpiration.warningDays -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Aria Automation Local Users: Password Complexity Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordComplexity -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vra' -minLength $customPolicy.ariaAutomation.passwordComplexity.minLength -uppercase $customPolicy.ariaAutomation.passwordComplexity.minUppercase -lowercase $customPolicy.ariaAutomation.passwordComplexity.minLowercase -numerical $customPolicy.ariaAutomation.passwordComplexity.minNumerical -special $customPolicy.ariaAutomation.passwordComplexity.minSpecial -sequence $customPolicy.ariaAutomation.passwordComplexity.maxSequence -unique $customPolicy.ariaAutomation.passwordComplexity.minUnique -class $customPolicy.ariaAutomation.passwordComplexity.minClass -history $customPolicy.ariaAutomation.passwordComplexity.history -retry $customPolicy.ariaAutomation.passwordComplexity.retries -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Configuring Aria Automation Local Users: Account Lockout Policy for each instance" $StatusMsg = Update-AriaLocalUserPasswordAccountLockout -server $sddcManagerFqdn -user $sddcManagerUser -pass $sddcManagerPass -product 'vra' -failures $customPolicy.ariaAutomation.accountLockout.maxFailures -unlockInterval $customPolicy.ariaAutomation.accountLockout.unlockInterval -rootUnlockInterval $customPolicy.ariaAutomation.accountLockout.rootUnlockInterval -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -WarningVariable WarnMsg -ErrorVariable ErrorMsg if ( $StatusMsg ) { Write-LogMessage -Type INFO -Message "$StatusMsg" } if ( $WarnMsg ) { Write-LogMessage -Type WARNING -Message $WarnMsg -Colour Magenta } if ( $ErrorMsg ) { Write-LogMessage -Type ERROR -Message $ErrorMsg -Colour Red } Write-LogMessage -Type INFO -Message "Completed Configuring Password Policies for Aria Automation Local Users" } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Start-PasswordPolicyConfig Function Get-PasswordPolicyDefault { <# .SYNOPSIS Get password policy default settings. .DESCRIPTION The Get-PasswordPolicyDefault cmdlet returns the default password policy settings, it can also be used to generate the base JSON file used with Password Policy. Default settings for VMware products include: - VMware SDDC Manager - VMware ESX - VMware vCenter Single Sign-On - VMware vCenter - VMware NSX Manager - VMware NSX Edge - VMware Workspace ONE Access - Aria Suite Lifecycle - Aria Operations - Aria Operations for Logs - Aria Operations for Networks - Aria Automation. .EXAMPLE Get-PasswordPolicyDefault -version '5.0.0.0' This example returns the default password policy settings for the VMware Cloud Foundation version. .EXAMPLE Get-PasswordPolicyDefault -generateJson -jsonFile [policy_file].json -version '5.0.0.0' This example creates a JSON file with the default password policy settings for the given version of VMware Cloud Foundation. .EXAMPLE Get-PasswordPolicyDefault -generateJson -jsonFile [policy_file].json -version '5.0.0.0' This example creates a JSON file with the default password policy settings for the given version of VMware Cloud Foundation. If the policy configuration file is already present, it is overwritten due to 'force' parameter. .PARAMETER generateJson Switch to generate a JSON file. .PARAMETER version The VMware Cloud Foundation version to get policy defaults for the JSON file. .PARAMETER jsonFile The name of the JSON file to generate. .PARAMETER force The switch used to overwrite the JSON file if already exists. #> [CmdletBinding(DefaultParametersetName = "All")][OutputType('System.Management.Automation.PSObject')] Param ( [Parameter (Mandatory = $false, ParameterSetName = 'json')] [ValidateNotNullOrEmpty()] [Switch]$generateJson, [Parameter (Mandatory = $true)] [ValidateSet('4.4.0.0', '4.4.1.0', '4.5.0.0', '4.5.1.0', '4.5.2.0', '5.0.0.0', '5.1.0.0', '5.1.1.0', '5.2.0.0', '5.2.1.0')] [String]$version, [Parameter (Mandatory = $true, ParameterSetName = 'json')] [ValidateNotNullOrEmpty()] [String]$jsonFile, [Parameter (Mandatory = $false, ParameterSetName = 'json')] [ValidateNotNullOrEmpty()] [Switch]$force ) if ($PSBoundParameters.ContainsKey('jsonFile')) { if (Test-Path -Path $jsonFile -PathType Container) { Write-Error "The -jsonfile parameter ($jsonfile) contains a folder name and no filename. Review and retry." Break } else { if ((split-path -Path $jsonFile -leaf).split(".")[1] -ne "json") { Write-Error 'The filename provided does not contain a .json extension. Review and retry.' Break } else { if (Test-Path $jsonFile -PathType leaf) { if ($PSBoundParameters.ContainsKey('force')) { Write-Warning "The filename provided ($jsonFile) already exists and will be overwritten." } else { Write-Error "The filename provided ($jsonFile) already exists. Delete or use the -force switch to overwrite the file." Break } } } } } # Add VCF version into JSON file $vcfVersion = New-Object -TypeName PSObject $vcfVersion | Add-Member -NotePropertyName 'vcfVersion' -NotePropertyValue $version # Build Default ESX Password Policy Settings $esxiPasswordExpiration = New-Object -TypeName PSObject $esxiPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "99999" $esxiPasswordComplexity = New-Object -TypeName PSObject $esxiPasswordComplexity | Add-Member -NotePropertyName 'policy' -NotePropertyValue "retry=3 min=disabled,disabled,disabled,7,7" $esxiPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "0" $esxiAccountLockout = New-Object -TypeName PSObject $esxiAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "5" $esxiAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "900" $esxiPasswordPolicy = New-Object -TypeName PSObject $esxiPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $esxiPasswordExpiration $esxiPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $esxiPasswordComplexity $esxiPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $esxiAccountLockout # Build Default vCenter Single Sign-On Password Policy Settings $ssoPasswordExpiration = New-Object -TypeName PSObject $ssoPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "90" $ssoPasswordComplexity = New-Object -TypeName PSObject $ssoPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "8" $ssoPasswordComplexity | Add-Member -NotePropertyName 'maxLength' -NotePropertyValue "20" $ssoPasswordComplexity | Add-Member -NotePropertyName 'minAlphabetic' -NotePropertyValue "2" $ssoPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "1" $ssoPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "1" $ssoPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "1" $ssoPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "1" $ssoPasswordComplexity | Add-Member -NotePropertyName 'maxIdenticalAdjacent' -NotePropertyValue "1" $ssoPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "5" $ssoAccountLockout = New-Object -TypeName PSObject $ssoAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "5" $ssoAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "900" $ssoAccountLockout | Add-Member -NotePropertyName 'failedAttemptInterval' -NotePropertyValue "180" $ssoPasswordPolicy = New-Object -TypeName PSObject $ssoPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $ssoPasswordExpiration $ssoPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $ssoPasswordComplexity $ssoPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $ssoAccountLockout # Build Default vCenter Password Policy Settings $vcenterPasswordExpiration = New-Object -TypeName PSObject $vcenterPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "90" $vcenterPasswordExpiration | Add-Member -NotePropertyName 'minDays' -NotePropertyValue "0" $vcenterPasswordExpiration | Add-Member -NotePropertyName 'warningDays' -NotePropertyValue "7" $vcenterPasswordPolicy = New-Object -TypeName PSObject $vcenterPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $vcenterPasswordExpiration # Build Default vCenter Local Users Password Policy Settings $vcenterLocalPasswordExpiration = New-Object -TypeName PSObject $vcenterLocalPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "90" $vcenterLocalPasswordExpiration | Add-Member -NotePropertyName 'minDays' -NotePropertyValue "0" $vcenterLocalPasswordExpiration | Add-Member -NotePropertyName 'warningDays' -NotePropertyValue "7" $vcenterLocalPasswordExpiration | Add-Member -NotePropertyName 'email' -NotePropertyValue "" $vcenterLocalPasswordComplexity = New-Object -TypeName PSObject $vcenterLocalPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "6" $vcenterLocalPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "-1" $vcenterLocalPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "-1" $vcenterLocalPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "-1" $vcenterLocalPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "-1" $vcenterLocalPasswordComplexity | Add-Member -NotePropertyName 'minUnique' -NotePropertyValue "4" $vcenterLocalPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "5" $vcenterLocalAccountLockout = New-Object -TypeName PSObject $vcenterLocalAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "3" $vcenterLocalAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "900" $vcenterLocalAccountLockout | Add-Member -NotePropertyName 'rootUnlockInterval' -NotePropertyValue "300" $vcenterLocalPasswordPolicy = New-Object -TypeName PSObject $vcenterLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $vcenterLocalPasswordExpiration $vcenterLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $vcenterLocalPasswordComplexity $vcenterLocalPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $vcenterLocalAccountLockout # Build Default NSX Manager Local Users Password Policy Settings $nsxManagerPasswordExpiration = New-Object -TypeName PSObject $nsxManagerPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "90" $nsxManagerPasswordComplexity = New-Object -TypeName PSObject if ($version -ge "5.0") { $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "12" } else { $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "15" } $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "-1" $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "-1" $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "-1" $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "-1" $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'minUnique' -NotePropertyValue "0" $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'retries' -NotePropertyValue "3" if ($version -ge "5.0") { $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'maxLength' -NotePropertyValue "128" $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'maxSequence' -NotePropertyValue "0" $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'maxRepeat' -NotePropertyValue "0" $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'passwordRemembrance' -NotePropertyValue "0" $nsxManagerPasswordComplexity | Add-Member -NotePropertyName 'hashAlgorithm' -NotePropertyValue "sha512" } $nsxManagerAccountLockout = New-Object -TypeName PSObject $nsxManagerAccountLockout | Add-Member -NotePropertyName 'apiMaxFailures' -NotePropertyValue "5" $nsxManagerAccountLockout | Add-Member -NotePropertyName 'apiUnlockInterval' -NotePropertyValue "900" $nsxManagerAccountLockout | Add-Member -NotePropertyName 'apiRestInterval' -NotePropertyValue "180" $nsxManagerAccountLockout | Add-Member -NotePropertyName 'cliMaxFailures' -NotePropertyValue "5" $nsxManagerAccountLockout | Add-Member -NotePropertyName 'cliUnlockInterval' -NotePropertyValue "900" $nsxManagerPasswordPolicy = New-Object -TypeName PSObject $nsxManagerPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $nsxManagerPasswordExpiration $nsxManagerPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $nsxManagerPasswordComplexity $nsxManagerPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $nsxManagerAccountLockout # Build Default NSX Edge Local Users Password Policy Settings $nsxEdgePasswordExpiration = New-Object -TypeName PSObject $nsxEdgePasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "90" $nsxEdgePasswordComplexity = New-Object -TypeName PSObject $nsxEdgePasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "15" $nsxEdgePasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "-1" $nsxEdgePasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "-1" $nsxEdgePasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "-1" $nsxEdgePasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "-1" $nsxEdgePasswordComplexity | Add-Member -NotePropertyName 'minUnique' -NotePropertyValue "0" $nsxEdgePasswordComplexity | Add-Member -NotePropertyName 'retries' -NotePropertyValue "3" $nsxEdgeAccountLockout = New-Object -TypeName PSObject $nsxEdgeAccountLockout | Add-Member -NotePropertyName 'cliMaxFailures' -NotePropertyValue "5" $nsxEdgeAccountLockout | Add-Member -NotePropertyName 'cliUnlockInterval' -NotePropertyValue "900" $nsxEdgePasswordPolicy = New-Object -TypeName PSObject $nsxEdgePasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $nsxEdgePasswordExpiration $nsxEdgePasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $nsxEdgePasswordComplexity $nsxEdgePasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $nsxEdgeAccountLockout # Build Default SDDC Manager Local Users Password Policy Settings $sddcManagerPasswordExpiration = New-Object -TypeName PSObject $sddcManagerPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "90" $sddcManagerPasswordExpiration | Add-Member -NotePropertyName 'minDays' -NotePropertyValue "0" $sddcManagerPasswordExpiration | Add-Member -NotePropertyName 'warningDays' -NotePropertyValue "7" $sddcManagerPasswordComplexity = New-Object -TypeName PSObject if ($version -ge "5.2") { $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "15" } elseif ($version -ge "5.1") { $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "12" } else { $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "8" } $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "-1" $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "-1" $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "-1" $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "-1" $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'minUnique' -NotePropertyValue "4" $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'minClass' -NotePropertyValue "4" $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'maxSequence' -NotePropertyValue "0" $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'retries' -NotePropertyValue "3" $sddcManagerPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "5" $sddcManagerAccountLockout = New-Object -TypeName PSObject $sddcManagerAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "3" $sddcManagerAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "86400" $sddcManagerAccountLockout | Add-Member -NotePropertyName 'rootUnlockInterval' -NotePropertyValue "300" $sddcManagerPasswordPolicy = New-Object -TypeName PSObject $sddcManagerPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $sddcManagerPasswordExpiration $sddcManagerPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $sddcManagerPasswordComplexity $sddcManagerPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $sddcManagerAccountLockout # Build Default Workspace ONE Access Local Users Password Policy Settings $wsaLocalPasswordExpiration = New-Object -TypeName PSObject $wsaLocalPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "60" $wsaLocalPasswordExpiration | Add-Member -NotePropertyName 'minDays' -NotePropertyValue "0" $wsaLocalPasswordExpiration | Add-Member -NotePropertyName 'warningDays' -NotePropertyValue "7" $wsaLocalPasswordComplexity = New-Object -TypeName PSObject $wsaLocalPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "6" $wsaLocalPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "0" $wsaLocalPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "0" $wsaLocalPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "0" $wsaLocalPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "0" $wsaLocalPasswordComplexity | Add-Member -NotePropertyName 'maxIdenticalAdjacent' -NotePropertyValue "0" $wsaLocalPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "5" $wsaLocalPasswordComplexity | Add-Member -NotePropertyName 'retries' -NotePropertyValue "3" $wsaLocalAccountLockout = New-Object -TypeName PSObject $wsaLocalAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "3" $wsaLocalAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "900" $wsaLocalAccountLockout | Add-Member -NotePropertyName 'rootUnlockInterval' -NotePropertyValue "900" $wsaLocalPasswordPolicy = New-Object -TypeName PSObject $wsaLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $wsaLocalPasswordExpiration $wsaLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $wsaLocalPasswordComplexity $wsaLocalPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $wsaLocalAccountLockout # Build Default Workspace ONE Access Directory Users Password Policy Settings $wsaDirectoryPasswordExpiration = New-Object -TypeName PSObject $wsaDirectoryPasswordExpiration | Add-Member -NotePropertyName 'passwordLifetime' -NotePropertyValue "0" $wsaDirectoryPasswordExpiration | Add-Member -NotePropertyName 'passwordReminder' -NotePropertyValue "0" $wsaDirectoryPasswordExpiration | Add-Member -NotePropertyName 'passwordReminderFrequency' -NotePropertyValue "0" $wsaDirectoryPasswordExpiration | Add-Member -NotePropertyName 'temporaryPassword' -NotePropertyValue "168" $wsaDirectoryPasswordComplexity = New-Object -TypeName PSObject $wsaDirectoryPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "8" $wsaDirectoryPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "0" $wsaDirectoryPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "0" $wsaDirectoryPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "0" $wsaDirectoryPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "0" $wsaDirectoryPasswordComplexity | Add-Member -NotePropertyName 'maxIdenticalAdjacent' -NotePropertyValue "0" $wsaDirectoryPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "0" $wsaDirectoryAccountLockout = New-Object -TypeName PSObject $wsaDirectoryAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "5" $wsaDirectoryAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "900" $wsaDirectoryAccountLockout | Add-Member -NotePropertyName 'failedAttemptInterval' -NotePropertyValue "900" $wsaDirectoryPasswordPolicy = New-Object -TypeName PSObject $wsaDirectoryPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $wsaDirectoryPasswordExpiration $wsaDirectoryPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $wsaDirectoryPasswordComplexity $wsaDirectoryPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $wsaDirectoryAccountLockout # Build Aria Automation Local Users Password Policy Settings $vraLocalPasswordExpiration = New-Object -TypeName PSObject $vraLocalPasswordExpiration | Add-Member -NotePropertyName 'minDays' -NotePropertyValue "0" $vraLocalPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "365" $vraLocalPasswordExpiration | Add-Member -NotePropertyName 'warningDays' -NotePropertyValue "7" $vraLocalPasswordComplexity = New-Object -TypeName PSObject $vraLocalPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "-1" $vraLocalPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "-1" $vraLocalPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "-1" $vraLocalPasswordComplexity | Add-Member -NotePropertyName 'minUnique' -NotePropertyValue "4" $vraLocalPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "8" $vraLocalPasswordComplexity | Add-Member -NotePropertyName 'minClass' -NotePropertyValue "4" $vraLocalPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "-1" $vraLocalPasswordComplexity | Add-Member -NotePropertyName 'retries' -NotePropertyValue "3" $vraLocalPasswordComplexity | Add-Member -NotePropertyName 'maxSequence' -NotePropertyValue "0" $vraLocalPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "5" $vraLocalAccountLockout = New-Object -TypeName PSObject $vraLocalAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "3" $vraLocalAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "86400" $vraLocalAccountLockout | Add-Member -NotePropertyName 'rootUnlockInterval' -NotePropertyValue "300" $vraLocalPasswordPolicy = New-Object -TypeName PSObject $vraLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $vraLocalPasswordExpiration $vraLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $vraLocalPasswordComplexity $vraLocalPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $vraLocalAccountLockout # Build Aria Operations Local Users Password Policy Settings $vropsLocalPasswordExpiration = New-Object -TypeName PSObject $vropsLocalPasswordExpiration | Add-Member -NotePropertyName 'minDays' -NotePropertyValue "0" $vropsLocalPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "365" $vropsLocalPasswordExpiration | Add-Member -NotePropertyName 'warningDays' -NotePropertyValue "7" $vropsLocalPasswordComplexity = New-Object -TypeName PSObject $vropsLocalPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "-1" $vropsLocalPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "-1" $vropsLocalPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "-1" $vropsLocalPasswordComplexity | Add-Member -NotePropertyName 'minUnique' -NotePropertyValue "4" $vropsLocalPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "8" $vropsLocalPasswordComplexity | Add-Member -NotePropertyName 'minClass' -NotePropertyValue "4" $vropsLocalPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "-1" $vropsLocalPasswordComplexity | Add-Member -NotePropertyName 'retries' -NotePropertyValue "3" $vropsLocalPasswordComplexity | Add-Member -NotePropertyName 'maxSequence' -NotePropertyValue "0" $vropsLocalPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "5" $vropsLocalAccountLockout = New-Object -TypeName PSObject $vropsLocalAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "3" $vropsLocalAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "900" $vropsLocalAccountLockout | Add-Member -NotePropertyName 'rootUnlockInterval' -NotePropertyValue "900" $vropsLocalPasswordPolicy = New-Object -TypeName PSObject $vropsLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $vropsLocalPasswordExpiration $vropsLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $vropsLocalPasswordComplexity $vropsLocalPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $vropsLocalAccountLockout # Build Aria Operations Logs Local Users Password Policy Settings $vrliLocalPasswordExpiration = New-Object -TypeName PSObject $vrliLocalPasswordExpiration | Add-Member -NotePropertyName 'minDays' -NotePropertyValue "0" $vrliLocalPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "365" $vrliLocalPasswordExpiration | Add-Member -NotePropertyName 'warningDays' -NotePropertyValue "7" $vrliLocalPasswordComplexity = New-Object -TypeName PSObject $vrliLocalPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "-1" $vrliLocalPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "-1" $vrliLocalPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "-1" $vrliLocalPasswordComplexity | Add-Member -NotePropertyName 'minUnique' -NotePropertyValue "4" $vrliLocalPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "8" $vrliLocalPasswordComplexity | Add-Member -NotePropertyName 'minClass' -NotePropertyValue "4" $vrliLocalPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "-1" $vrliLocalPasswordComplexity | Add-Member -NotePropertyName 'retries' -NotePropertyValue "3" $vrliLocalPasswordComplexity | Add-Member -NotePropertyName 'maxSequence' -NotePropertyValue "0" $vrliLocalPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "5" $vrliLocalAccountLockout = New-Object -TypeName PSObject $vrliLocalAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "3" $vrliLocalAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "900" $vrliLocalAccountLockout | Add-Member -NotePropertyName 'rootUnlockInterval' -NotePropertyValue "900" $vrliLocalPasswordPolicy = New-Object -TypeName PSObject $vrliLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $vrliLocalPasswordExpiration $vrliLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $vrliLocalPasswordComplexity $vrliLocalPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $vrliLocalAccountLockout # Build Aria Suite Lifecycle Local Users Password Policy Settings $vrslcmLocalPasswordExpiration = New-Object -TypeName PSObject $vrslcmLocalPasswordExpiration | Add-Member -NotePropertyName 'minDays' -NotePropertyValue "0" $vrslcmLocalPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "365" $vrslcmLocalPasswordExpiration | Add-Member -NotePropertyName 'warningDays' -NotePropertyValue "7" $vrslcmLocalPasswordComplexity = New-Object -TypeName PSObject $vrslcmLocalPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "-1" $vrslcmLocalPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "-1" $vrslcmLocalPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "-1" $vrslcmLocalPasswordComplexity | Add-Member -NotePropertyName 'minUnique' -NotePropertyValue "4" $vrslcmLocalPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "8" $vrslcmLocalPasswordComplexity | Add-Member -NotePropertyName 'minClass' -NotePropertyValue "4" $vrslcmLocalPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "-1" $vrslcmLocalPasswordComplexity | Add-Member -NotePropertyName 'retries' -NotePropertyValue "3" $vrslcmLocalPasswordComplexity | Add-Member -NotePropertyName 'maxSequence' -NotePropertyValue "0" $vrslcmLocalPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "5" $vrslcmLocalAccountLockout = New-Object -TypeName PSObject $vrslcmLocalAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "3" $vrslcmLocalAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "900" $vrslcmLocalAccountLockout | Add-Member -NotePropertyName 'rootUnlockInterval' -NotePropertyValue "900" $vrslcmLocalPasswordPolicy = New-Object -TypeName PSObject $vrslcmLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $vrslcmLocalPasswordExpiration $vrslcmLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $vrslcmLocalPasswordComplexity $vrslcmLocalPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $vrslcmLocalAccountLockout # Build Aria Operations for Networks Local Users Password Policy Settings $vrniLocalPasswordExpiration = New-Object -TypeName PSObject $vrniLocalPasswordExpiration | Add-Member -NotePropertyName 'minDays' -NotePropertyValue "0" $vrniLocalPasswordExpiration | Add-Member -NotePropertyName 'maxDays' -NotePropertyValue "365" $vrniLocalPasswordExpiration | Add-Member -NotePropertyName 'warningDays' -NotePropertyValue "7" $vrniLocalPasswordComplexity = New-Object -TypeName PSObject $vrniLocalPasswordComplexity | Add-Member -NotePropertyName 'minNumerical' -NotePropertyValue "-1" $vrniLocalPasswordComplexity | Add-Member -NotePropertyName 'minUppercase' -NotePropertyValue "-1" $vrniLocalPasswordComplexity | Add-Member -NotePropertyName 'minLowercase' -NotePropertyValue "-1" $vrniLocalPasswordComplexity | Add-Member -NotePropertyName 'minUnique' -NotePropertyValue "4" $vrniLocalPasswordComplexity | Add-Member -NotePropertyName 'minLength' -NotePropertyValue "8" $vrniLocalPasswordComplexity | Add-Member -NotePropertyName 'minClass' -NotePropertyValue "4" $vrniLocalPasswordComplexity | Add-Member -NotePropertyName 'minSpecial' -NotePropertyValue "-1" $vrniLocalPasswordComplexity | Add-Member -NotePropertyName 'retries' -NotePropertyValue "3" $vrniLocalPasswordComplexity | Add-Member -NotePropertyName 'maxSequence' -NotePropertyValue "0" $vrniLocalPasswordComplexity | Add-Member -NotePropertyName 'history' -NotePropertyValue "5" $vrniLocalAccountLockout = New-Object -TypeName PSObject $vrniLocalAccountLockout | Add-Member -NotePropertyName 'maxFailures' -NotePropertyValue "3" $vrniLocalAccountLockout | Add-Member -NotePropertyName 'unlockInterval' -NotePropertyValue "900" $vrniLocalAccountLockout | Add-Member -NotePropertyName 'rootUnlockInterval' -NotePropertyValue "900" $vrniLocalPasswordPolicy = New-Object -TypeName PSObject $vrniLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordExpiration' -NotePropertyValue $vrniLocalPasswordExpiration $vrniLocalPasswordPolicy | Add-Member -NotePropertyName 'passwordComplexity' -NotePropertyValue $vrniLocalPasswordComplexity $vrniLocalPasswordPolicy | Add-Member -NotePropertyName 'accountLockout' -NotePropertyValue $vrniLocalAccountLockout # Build Final Default Password Policy Object $defaultConfig = New-Object -TypeName PSObject $defaultConfig | Add-Member -NotePropertyName 'vcf' -NotePropertyValue $vcfVersion $defaultConfig | Add-Member -NotePropertyName 'esxi' -NotePropertyValue $esxiPasswordPolicy $defaultConfig | Add-Member -NotePropertyName 'sso' -NotePropertyValue $ssoPasswordPolicy $defaultConfig | Add-Member -NotePropertyName 'vcenterServer' -NotePropertyValue $vcenterPasswordPolicy $defaultConfig | Add-Member -NotePropertyName 'vcenterServerLocal' -NotePropertyValue $vcenterLocalPasswordPolicy $defaultConfig | Add-Member -NotePropertyName 'nsxManager' -NotePropertyValue $nsxManagerPasswordPolicy $defaultConfig | Add-Member -NotePropertyName 'nsxEdge' -NotePropertyValue $nsxEdgePasswordPolicy $defaultConfig | Add-Member -NotePropertyName 'sddcManager' -NotePropertyValue $sddcManagerPasswordPolicy $defaultConfig | Add-Member -NotePropertyName 'wsaLocal' -NotePropertyValue $wsaLocalPasswordPolicy $defaultConfig | Add-Member -NotePropertyName 'wsaDirectory' -NotePropertyValue $wsaDirectoryPasswordPolicy $defaultConfig | Add-Member -notepropertyName 'ariaAutomation' -notepropertyValue $vraLocalPasswordPolicy $defaultConfig | Add-Member -notepropertyName 'ariaLifecycle' -notepropertyValue $vrslcmLocalPasswordPolicy $defaultConfig | Add-Member -notepropertyName 'ariaOperations' -notepropertyValue $vropsLocalPasswordPolicy $defaultConfig | Add-Member -notepropertyName 'ariaOperationsLogs' -notepropertyValue $vrliLocalPasswordPolicy $defaultConfig | Add-Member -notepropertyName 'ariaOperationsNetworks' -notepropertyValue $vrniLocalPasswordPolicy if ($PSBoundParameters.ContainsKey('generateJson')) { $defaultConfig | ConvertTo-Json -Depth 25 | Out-File -FilePath $jsonFile Write-Output "Generated JSON File ($jsonFile) with Product Password Policy Default Values" } else { $defaultConfig | ConvertTo-Json -Depth 25 return $defaultConfig } } Export-ModuleMember -Function Get-PasswordPolicyDefault Function Get-PasswordPolicyConfig { Param ( [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $true)] [ValidateSet('4.4.0.0', '4.4.1.0', '4.5.0.0', '4.5.1.0', '4.5.2.0', '5.0.0.0', '5.1.0.0', '5.1.1.0', '5.2.0.0', '5.2.1.0')] [String]$version, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) if ($policyFile) { $policyFilePath = (Join-Path $reportPath $policyFile) if (Test-Path $policyFilePath) { Write-Output "Found the Password Policy Configuration File ($policyFilePath)." $customConfig = Get-Content -Path $policyFilePath | ConvertFrom-Json if ($customConfig.vcf.vcfVersion -eq $version) { $result = Test-PasswordPolicyConfig -customConfig $customConfig -version $version if ($result -eq "true") { Write-Output "Validation of Password Policy Configuration File: PASSED" } else { Write-Error "Validation of Password Policy Configuration File: FAILED" Break } } else { Write-Error "Password Policy Configuration File is $($customConfig.vcf.vcfVersion) and Version Provided is $version : FAILED " Break } } else { Write-Error "Unable to locate password policy configuration file $policyFilePath. Enter a valid path and filename and retry." Break } } else { $customConfig = Get-PasswordPolicyDefault -version $version } $customConfig | ConvertTo-Json -Depth 25 return $customConfig } Export-ModuleMember -Function Get-PasswordPolicyConfig Function checkRange { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$name, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$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-Error "The value for $name has not been configured." return $false } elseif (($value -lt $minRange) -or ($value -gt $maxRange)) { Write-Error "The recommended range for $name should be between $minRange and $maxRange. [$value]" 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-Error "The email address for $name has not been configured." return $false } $checkStatement = $address -match "^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$" if ($checkStatement -eq $true) { return $true } else { Write-Error "The email address for $name is not a valid format. [$address]" return $false } } Function Test-PasswordPolicyConfig { Param ( [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [PSObject]$customConfig, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [PSObject]$version ) # Import default configuration JSON for compare parameters $defaultConfig = Get-PasswordPolicyDefault -version $version $encounterError = "False" # Validating Product Types in the Password Policy Configuration File $defaultProductList = $defaultConfig | Get-Member | Where-Object { $_.MemberType -match "NoteProperty" } | Select-Object Name $customProductList = $customConfig | Get-Member | Where-Object { $_.MemberType -match "NoteProperty" } | Select-Object Name $defaultSection = "passwordExpiration", "passwordComplexity", "accountLockout", "vcfVersion" foreach ($product in $customProductList) { if (-Not $defaultProductList.Name.Contains($product.Name)) { Write-Error "Found Unknown Product ($($product.Name)). Review the password policy configuration file and retry." $encounterError = "True" Break } # Validating Product Sections in the Password Policy Configuration File if ($encounterError -ne "True") { $customSectionList = $customConfig.($product.Name) | Get-Member | Where-Object { $_.MemberType -match "NoteProperty" } | Select-Object Name foreach ($section in $customSectionList) { if (-Not $defaultSection.Contains($section.Name)) { Write-Error "Found Unknown Password Policy Section ($($section.Name)) Under Product ($($product.Name)). Review the password policy configuration file and retry." $encounterError = "True" Break } # Validate parameters in customConfig file if ($encounterError -ne "True") { $defaultParameterList = $defaultConfig.($product.Name).($section.Name) | Get-Member | Where-Object { $_.MemberType -match "NoteProperty" } | Select-Object Name $customParameterList = $customConfig.($product.Name).($section.Name) | Get-Member | Where-Object { $_.MemberType -match "NoteProperty" } | Select-Object Name foreach ( $parameterName in $customParameterList) { if ( -Not $defaultParameterList.Name.Contains($parameterName.Name)) { Write-Error "Found Unknown Parameter ($($parameterName.Name)) Under Section ($($section.Name)) for Product ($($product.Name)). Review the password policy configuration file and retry." $encounterError = "True" Break } elseif ($parameterName.Name -ne "email" -and $customConfig.($product.Name).($section.Name).($parameterName.Name) -eq "") { Write-Error "Parameter ($($product.Name):$($section.Name):$($parameterName.Name)) Not Configured. Review the password policy configuration file and retry." $encounterError = "True" Break } } } } } } # Validating parameter values if ($encounterError -ne "True") { foreach ($product in $customProductList) { $customSectionList = $customConfig.($product.Name) | Get-Member | Where-Object { $_.MemberType -match "NoteProperty" } | Select-Object Name foreach ($section in $customSectionList) { $defaultParameterList = $defaultConfig.($product.Name).($section.Name) | Get-Member | Where-Object { $_.MemberType -match "NoteProperty" } | Select-Object Name $customParameterList = $customConfig.($product.Name).($section.Name) | Get-Member | Where-Object { $_.MemberType -match "NoteProperty" } | Select-Object Name foreach ($parameterName in $customParameterList) { # Validating parameter values Switch ($parameterName.Name) { # Password Expiration Section "maxDays" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):maxDays" -value $customConfig.($product.Name).($section.Name)."maxDays" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "minDays" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):minDays" -value $customConfig.($product.Name).($section.Name)."minDays" -minRange 0 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "warningDays" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):warningDays" -value $customConfig.($product.Name).($section.Name)."warningDays" -minRange 0 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "email" { $emailVariable = $customConfig.($product.Name).($section.Name)."email" if ($emailVariable) { $checkReturn = checkEmailString -name "$($product.Name):$($section.Name):email" -address $customConfig.($product.Name).($section.Name)."email" -required $false if (-Not $checkReturn) { $encounterError = "True" } } } "passwordLifetime" { if ($product.Name -eq "wsaDirectory") { $checkReturn = checkRange -name "$($product.Name):$($section.Name):passwordLifetime" -value $customConfig.($product.Name).($section.Name)."passwordLifetime" -minRange 0 -maxRange 99999 -required $true } else { $checkReturn = checkRange -name "$($product.Name):$($section.Name):passwordLifetime" -value $customConfig.($product.Name).($section.Name)."passwordLifetime" -minRange 1 -maxRange 99999 -required $true } if (-Not $checkReturn) { $encounterError = "True" } } "passwordReminder" { if ($product.Name -eq "wsaDirectory") { $checkReturn = checkRange -name "$($product.Name):$($section.Name):passwordReminder" -value $customConfig.($product.Name).($section.Name)."passwordReminder" -minRange 0 -maxRange 99999 -required $true } else { $checkReturn = checkRange -name "$($product.Name):$($section.Name):passwordReminder" -value $customConfig.($product.Name).($section.Name)."passwordReminder" -minRange 1 -maxRange 99999 -required $true } if (-Not $checkReturn) { $encounterError = "True" } } "passwordReminderFrequency" { if ($product.Name -eq "wsaDirectory") { $checkReturn = checkRange -name "$($product.Name):$($section.Name):passwordReminderFrequency" -value $customConfig.($product.Name).($section.Name)."passwordReminderFrequency" -minRange 0 -maxRange 99999 -required $true } else { $checkReturn = checkRange -name "$($product.Name):$($section.Name):passwordReminderFrequency" -value $customConfig.($product.Name).($section.Name)."passwordReminderFrequency" -minRange 1 -maxRange 99999 -required $true } if (-Not $checkReturn) { $encounterError = "True" } } "temporaryPassword" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):temporaryPassword" -value $customConfig.($product.Name).($section.Name)."temporaryPassword" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } # Password Complexity section "policy" { $policyString = $customConfig.($product.Name).($section.Name).'policy' $policyPattern = '^retry=(\d+)\s+min=(.+),(.+),(.+),(.+),(.+)' $policyMinRange = 7 $policyMaxRange = 999 if ($policyString -match $policyPattern) { $passwdPolicyMinValues = $matches[2.6] } foreach ($passwdPolicyMinValue in $passwdPolicyMinValues) { if ($passwdPolicyMinValue -ine 'disabled') { $checkReturn = checkRange -name "$($product.Name):$($section.Name):policy" -value $passwdPolicyMinValue -minRange $policyMinRange -maxRange $policyMaxRange -required $true if (-Not $checkReturn) { $encounterError = 'True' } } } } "history" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):history" -value $customConfig.($product.Name).($section.Name)."history" -minRange 0 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "minLength" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):minLength" -value $customConfig.($product.Name).($section.Name)."minLength" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "maxLength" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):maxLength" -value $customConfig.($product.Name).($section.Name)."maxLength" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "minAlphabetic" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):minAlphabetic" -value $customConfig.($product.Name).($section.Name)."minAlphabetic" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "minLowercase" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):minLowercase" -value $customConfig.($product.Name).($section.Name)."minLowercase" -minRange -1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "minUppercase" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):minUppercase" -value $customConfig.($product.Name).($section.Name)."minUppercase" -minRange -1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "minNumerical" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):minNumerical" -value $customConfig.($product.Name).($section.Name)."minNumerical" -minRange -1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "minSpecial" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):minSpecial" -value $customConfig.($product.Name).($section.Name)."minSpecial" -minRange -1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "maxIdenticalAdjacent" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):maxIdenticalAdjacent" -value $customConfig.($product.Name).($section.Name)."maxIdenticalAdjacent" -minRange 0 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "minUnique" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):minUnique" -value $customConfig.($product.Name).($section.Name)."minUnique" -minRange 0 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "minClass" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):minClass" -value $customConfig.($product.Name).($section.Name)."minClass" -minRange 0 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "maxSequence" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):maxSequence" -value $customConfig.($product.Name).($section.Name)."maxSequence" -minRange 0 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "retries" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):retries" -value $customConfig.($product.Name).($section.Name)."retries" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "maxIdenticalAdjacent" { if ($product.Name -eq "wsaDirectory") { $checkReturn = checkRange -name "$($product.Name):$($section.Name):maxIdenticalAdjacent" -value $customConfig.($product.Name).($section.Name)."maxIdenticalAdjacent" -minRange 0 -maxRange 99999 -required $true } else { $checkReturn = checkRange -name "$($product.Name):$($section.Name):maxIdenticalAdjacent" -value $customConfig.($product.Name).($section.Name)."maxIdenticalAdjacent" -minRange 1 -maxRange 99999 -required $true } if (-Not $checkReturn) { $encounterError = "True" } } # Account Lockout section "maxFailures" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):maxFailures" -value $customConfig.($product.Name).($section.Name)."maxFailures" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "unlockInterval" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):unlockInterval" -value $customConfig.($product.Name).($section.Name)."unlockInterval" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "failedAttemptInterval" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):failedAttemptInterval" -value $customConfig.($product.Name).($section.Name)."failedAttemptInterval" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "rootUnlockInterval" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):rootUnlockInterval" -value $customConfig.($product.Name).($section.Name)."rootUnlockInterval" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "apiMaxFailures" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):apiMaxFailures" -value $customConfig.($product.Name).($section.Name)."apiMaxFailures" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "apiUnlockInterval" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):apiUnlockInterval" -value $customConfig.($product.Name).($section.Name)."apiUnlockInterval" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "apiRestInterval" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):apiRestInterval" -value $customConfig.($product.Name).($section.Name)."apiRestInterval" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "cliMaxFailures" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):cliMaxFailures" -value $customConfig.($product.Name).($section.Name)."cliMaxFailures" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } "cliUnlockInterval" { $checkReturn = checkRange -name "$($product.Name):$($section.Name):cliUnlockInterval" -value $customConfig.($product.Name).($section.Name)."cliUnlockInterval" -minRange 1 -maxRange 99999 -required $true if (-Not $checkReturn) { $encounterError = "True" } } } } } } } # Check to see if there are any validation errors and exit if any found if ($encounterError -eq "True") { Write-Error "Validation errors found in the password policy configuration file. Review the password policy configuration file and retry." Return $false } else { Return $true } } Function Set-CreateReportDirectory { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$path, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcManagerFqdn ) $fileTimestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss" $Global:reportFolder = $path + '\PasswordPolicyManager\' if ($PSEdition -eq "Core" -and ($PSVersionTable.OS).Split(' ')[0] -eq "Linux") { $reportFolder = ($reportFolder).split('\') -join '/' | Split-Path -NoQualifier } if (!(Test-Path -Path $reportFolder)) { New-Item -Path $reportFolder -ItemType "directory" | Out-Null } $reportName = $reportFolder + $fileTimestamp + "-passwordPolicyManager" + ".htm" $reportName } Function Set-CreateReportDirectoryRotation { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$path, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$sddcManagerFqdn ) $fileTimestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss" $Global:reportFolder = join-path -Path $path -ChildPath 'PasswordRotationManager\' if ($PSEdition -eq "Core" -and ($PSVersionTable.OS).Split(' ')[0] -eq "Linux") { $reportFolder = ($reportFolder).split('\') -join '/' | Split-Path -NoQualifier } if (!(Test-Path -Path $reportFolder)) { New-Item -Path $reportFolder -ItemType "directory" | Out-Null } $reportName = $reportFolder + $fileTimestamp + "-passwordRotationManager" + ".htm" $reportName } Function Save-ClarityReportHeader { Param ( [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$dark ) # Define the default Clarity Cascading Style Sheets (CSS) for the HTML report Header if ($PsBoundParameters.ContainsKey("dark")) { $clarityCssHeader = ' <head> <style> <!--- Used Clarify CSS components for this project ---> article, aside, details, figcaption, figure, footer, header, main, menu, nav, section, summary { display: block; } .main-container { display: flex; flex-direction: column; height: 100vh; background: var(--clr-global-app-background, #21333b); } header.header-6, .header.header-6 { background-color: #0e161b; } header, .header { display: flex; color: #fafafa; background-color: #0e161b; height: 3rem; white-space: nowrap; } .nav { display: flex; height: 1.8rem; list-style-type: none; align-items: center; margin: 0; width: 100%; white-space: nowrap; box-shadow: 0 -0.05rem 0 #495865 inset; } .nav .nav-item { display: inline-block; margin-right: 1.2rem; } .nav .nav-item.active > .nav-link { color: white; box-shadow: 0 -0.05rem 0 #495865 inset; } .nav .nav-link { color: #acbac3; font-size: 0.7rem; font-weight: 400; letter-spacing: normal; line-height: 1.8rem; display: inline-block; padding: 0 0.15rem; box-shadow: none; } .nav .nav-link.btn { text-transform: none; margin: 0; margin-bottom: -0.05rem; border-radius: 0; } .nav .nav-link:hover, .nav .nav-link:focus, .nav .nav-link:active { color: inherit; } .nav .nav-link:hover, .nav .nav-link.active { box-shadow: 0 -0.15rem 0 #4aaed9 inset; transition: box-shadow 0.2s ease-in; } .nav .nav-link:hover, .nav .nav-link:focus, .nav .nav-link:active, .nav .nav-link.active { text-decoration: none; } .nav .nav-link.active { color: white; font-weight: 400; } .nav .nav-link.nav-item { margin-right: 1.2rem; } .sub-nav, .subnav { display: flex; box-shadow: 0 -0.05rem 0 #cccccc inset; justify-content: space-between; align-items: center; background-color: #17242b; height: 1.8rem; } .sub-nav .nav, .subnav .nav { flex: 1 1 auto; padding-left: 1.2rem; } .sub-nav aside, .subnav aside { flex: 0 0 auto; display: flex; align-items: center; height: 1.8rem; padding: 0 1.2rem; } .sub-nav aside > :last-child, .subnav aside > :last-child { margin-right: 0; padding-right: 0; } .sidenav { line-height: 1.2rem; max-width: 15.6rem; min-width: 10.8rem; width: 18%; border-right: 0.05rem solid #152228; display: flex; flex-direction: column; } .sidenav .sidenav-content { flex: 1 1 auto; overflow-x: hidden; padding-bottom: 1.2rem; } .sidenav .sidenav-content .nav-link { border-radius: 0; border-top-left-radius: 0.15rem; border-bottom-left-radius: 0.15rem; display: inline-block; color: inherit; cursor: pointer; text-decoration: none; width: 100%; } .sidenav .sidenav-content > .nav-link { margin: 1.2rem 0 0 1.5rem; padding-left: 0.6rem; color: #acbac3; font-weight: 500; font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-size: 0.7rem; line-height: 1.2rem; letter-spacing: normal; } .sidenav .sidenav-content > .nav-link:hover { background: #324f62; } .sidenav .sidenav-content > .nav-link.active { background: #324f62; color: black; } .sidenav .nav-group { color: #acbac3; font-weight: 400; font-size: 0.7rem; letter-spacing: normal; margin-top: 1.2rem; width: 100%; } .sidenav .nav-group .nav-list, .sidenav .nav-group label { padding: 0 0 0 1.8rem; cursor: pointer; display: inline-block; width: 100%; margin: 0 0.3rem; } .sidenav .nav-group .nav-list { list-style: none; margin-top: 0; } .sidenav .nav-group .nav-list .nav-link { line-height: 0.8rem; padding: 0.2rem 0 0.2rem 0.6rem; } .sidenav .nav-group .nav-list .nav-link:hover { background: #324f62; } .sidenav .nav-group .nav-list .nav-link.active { background: #324f62; color: black; } .sidenav .nav-group label { color: #acbac3; font-weight: 500; font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-size: 0.7rem; line-height: 1.2rem; letter-spacing: normal; } .sidenav .nav-group input[type=checkbox] { position: absolute; clip: rect(1px, 1px, 1px, 1px); clip-path: inset(50%); padding: 0; border: 0; height: 1px; width: 1px; overflow: hidden; white-space: nowrap; top: 0; left: 0; } .sidenav .nav-group input[type=checkbox]:focus + label { outline: #3b99fc auto 0.25rem; } .sidenav .collapsible label { padding: 0 0 0 1.3rem; } .sidenav .collapsible label:after { content: ""; float: left; height: 0.5rem; width: 0.5rem; transform: translateX(-0.4rem) translateY(0.35rem); background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2012%2012%22%3E%0A%20%20%20%20%3Cdefs%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E.cls-1%7Bfill%3A%239a9a9a%3B%7D%3C%2Fstyle%3E%0A%20%20%20%20%3C%2Fdefs%3E%0A%20%20%20%20%3Ctitle%3ECaret%3C%2Ftitle%3E%0A%20%20%20%20%3Cpath%20class%3D%22cls-1%22%20d%3D%22M6%2C9L1.2%2C4.2a0.68%2C0.68%2C0%2C0%2C1%2C1-1L6%2C7.08%2C9.84%2C3.24a0.68%2C0.68%2C0%2C1%2C1%2C1%2C1Z%22%2F%3E%0A%3C%2Fsvg%3E%0A"); background-repeat: no-repeat; background-size: contain; vertical-align: middle; margin: 0; } .sidenav .collapsible input[type=checkbox]:checked ~ .nav-list, .sidenav .collapsible input[type=checkbox]:checked ~ ul { height: 0; display: none; } .sidenav .collapsible input[type=checkbox] ~ .nav-list, .sidenav .collapsible input[type=checkbox] ~ ul { height: auto; } .sidenav .collapsible input[type=checkbox]:checked ~ label:after { transform: rotate(-90deg) translateX(-0.35rem) translateY(-0.4rem); } body:not([cds-text]) { color: #acbac3; font-weight: 400; font-size: 0.7rem; letter-spacing: normal; line-height: 1.2rem; margin-bottom: 0px; font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; margin-top: 0px !important; } html:not([cds-text]) { color: #eaedf0; font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-size: 125%; } a:link { color: #4aaed9; text-decoration: none; } h1:not([cds-text]) { color: #eaedf0; font-weight: 200; font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-size: 1.6rem; letter-spacing: normal; line-height: 2.4rem; margin-top: 1.2rem; margin-bottom: 0; } h2:not([cds-text]) { color: #eaedf0; font-weight: 200; font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-size: 1.4rem; letter-spacing: normal; line-height: 2.4rem; margin-top: 1.2rem; margin-bottom: 0; } h3:not([cds-text]) { color: #eaedf0; font-weight: 200; font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-size: 1.1rem; letter-spacing: normal; line-height: 1.2rem; margin-top: 1.2rem; margin-bottom: 0; } h4:not([cds-text]) { color: #eaedf0; font-weight: 200; font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-size: 0.9rem; letter-spacing: normal; line-height: 1.2rem; margin-top: 1.2rem; margin-bottom: 0; } .table th { color: #eaedf0; font-size: 0.55rem; font-weight: 600; letter-spacing: 0.03em; background-color: #1b2a32; vertical-align: bottom; border-bottom-style: solid; border-bottom-width: 0.05rem; border-bottom-color: #495865; border-top: 0 none; } .table { border-collapse: separate; border-style: solid; border-width: 0.05rem; border-color: #495865; border-radius: 0.15rem; background-color: #21333b; color: #acbac3; margin: 0; margin-top: 1.2rem; max-width: 100%; width: 100%; } h3 { display: block; font-size: 1.17em; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold; } h4 { display: block; margin-block-start: 1.33em; margin-block-end: 1.33em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold; } .table th, .table td {font-size: 0.65rem; line-height: 0.7rem; border-top-style: solid; border-top-width: 0.05rem; border-top-color: #495865; padding: 0.55rem 0.6rem 0.55rem; text-align: left; vertical-align: top; } th { display: table-cell; vertical-align: inherit; font-weight: bold; text-align: -internal-center; } table { display: table; border-collapse: separate; box-sizing: border-box; text-indent: initial; border-spacing: 2px; border-color: gray; } ' } else { $clarityCssHeader = ' <head> <style> <!--- Used Clarify CSS components for this project ---> article, aside, details, figcaption, figure, footer, header, main, menu, nav, section, summary { display: block; } .main-container { display: flex; flex-direction: column; height: 100vh; background: var(--clr-global-app-background, #fafafa); } header.header-6, .header.header-6 { background-color: var(--clr-header-6-bg-color, #00364d); } header, .header { display: flex; color: var(--clr-header-font-color, #fafafa); background-color: var(--clr-header-bg-color, #333333); height: 3rem; white-space: nowrap; } .nav {display: flex; height: 1.8rem; list-style-type: none; align-items: center; margin: 0; width: 100%; white-space: nowrap; box-shadow: 0 -0.05rem 0 #cccccc inset; box-shadow: 0 -0.05rem 0 var(--clr-nav-box-shadow-color, #cccccc) inset; } .nav .nav-item { display: inline-block; margin-right: 1.2rem; } .nav .nav-item.active > .nav-link { color: black; color: var(--clr-nav-link-active-color, black); box-shadow: 0 -0.05rem 0 #cccccc inset; box-shadow: 0 -0.05rem 0 var(--clr-nav-box-shadow-color, #cccccc) inset; } .nav .nav-link { color: #666666; color: var(--clr-nav-link-color, #666666); font-size: 0.7rem; font-weight: 400; font-weight: var(--clr-nav-link-font-weight, 400); letter-spacing: normal; line-height: 1.8rem; display: inline-block; padding: 0 0.15rem; box-shadow: none; } .nav .nav-link.btn { text-transform: none; margin: 0; margin-bottom: -0.05rem; border-radius: 0; } .nav .nav-link:hover, .nav .nav-link:focus, .nav .nav-link:active { color: inherit; } .nav .nav-link:hover, .nav .nav-link.active { box-shadow: 0 -0.15rem 0 #0072a3 inset; box-shadow: 0 -0.15rem 0 var(--clr-nav-active-box-shadow-color, #0072a3) inset; transition: box-shadow 0.2s ease-in; } .nav .nav-link:hover, .nav .nav-link:focus, .nav .nav-link:active, .nav .nav-link.active { text-decoration: none; } .nav .nav-link.active { color: black; color: var(--clr-nav-link-active-color, black); font-weight: 400; font-weight: var(--clr-nav-link-active-font-weight, 400); } .nav .nav-link.nav-item { margin-right: 1.2rem; } .sub-nav, .subnav { display: flex; box-shadow: 0 -0.05rem 0 #cccccc inset; box-shadow: 0 -0.05rem 0 var(--clr-nav-box-shadow-color, #cccccc) inset; justify-content: space-between; align-items: center; background-color: white; background-color: var(--clr-subnav-bg-color, white); height: 1.8rem; } .sub-nav .nav, .subnav .nav { flex: 1 1 auto; padding-left: 1.2rem; } .sub-nav aside, .subnav aside { flex: 0 0 auto; display: flex; align-items: center; height: 1.8rem; padding: 0 1.2rem; } .sub-nav aside > :last-child, .subnav aside > :last-child { margin-right: 0; padding-right: 0; } .sidenav { line-height: 1.2rem; max-width: 15.6rem; min-width: 10.8rem; width: 18%; border-right: 0.05rem solid #cccccc; display: flex; flex-direction: column; } .sidenav .collapsible label padding: 0 0 0 1.3rem; } .sidenav .nav-group label {color: #333333; color: var(--clr-sidenav-header-color, #333333); font-weight: 500; font-weight: var(--clr-sidenav-header-font-weight, 500); font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-family: var(--clr-sidenav-header-font-family, ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif); font-size: 0.7rem; line-height: 1.2rem; letter-spacing: normal; } .sidenav { line-height: 1.2rem; max-width: 15.6rem; min-width: 10.8rem; width: 18%; border-right: 0.05rem solid #cccccc; display: flex; flex-direction: column; } .sidenav .sidenav-content { flex: 1 1 auto; overflow-x: hidden; padding-bottom: 1.2rem; } .sidenav .sidenav-content .nav-link { border-radius: 0; border-top-left-radius: 0.15rem; border-top-left-radius: var(--clr-sidenav-link-active-border-radius, 0.15rem); border-bottom-left-radius: 0.15rem; border-bottom-left-radius: var(--clr-sidenav-link-active-border-radius, 0.15rem); display: inline-block; color: inherit; cursor: pointer; text-decoration: none; width: 100%; } .sidenav .sidenav-content > .nav-link { margin: 1.2rem 0 0 1.5rem; padding-left: 0.6rem; color: #333333; color: var(--clr-sidenav-header-color, #333333); font-weight: 500; font-weight: var(--clr-sidenav-header-font-weight, 500); font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-family: var(--clr-sidenav-header-font-family, ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif);font-size: 0.7rem; line-height: 1.2rem; letter-spacing: normal; } .sidenav .sidenav-content > .nav-link:hover { background: #e8e8e8; background: var(--clr-sidenav-link-hover-color, #e8e8e8); } .sidenav .sidenav-content > .nav-link.active { background: #d8e3e9; background: var(--clr-sidenav-link-active-bg-color, #d8e3e9); color: black; color: var(--clr-sidenav-link-active-color, black); } .sidenav .nav-group { color: #666666; color: var(--clr-sidenav-color, #666666); font-weight: 400; font-weight: var(--clr-sidenav-font-weight, 400); font-size: 0.7rem; letter-spacing: normal; margin-top: 1.2rem; width: 100%; } .sidenav .nav-group .nav-list, .sidenav .nav-group label { padding: 0 0 0 1.8rem; cursor: pointer; display: inline-block; width: 100%; margin: 0 0.3rem; } .sidenav .nav-group .nav-list { list-style: none; margin-top: 0; } .sidenav .nav-group .nav-list .nav-link { line-height: 0.8rem; padding: 0.2rem 0 0.2rem 0.6rem; } .sidenav .nav-group .nav-list .nav-link:hover { background: #e8e8e8; background: var(--clr-sidenav-link-hover-color, #e8e8e8); } .sidenav .nav-group .nav-list .nav-link.active { background: #d8e3e9; background: var(--clr-sidenav-link-active-bg-color, #d8e3e9); color: black; color: var(--clr-sidenav-link-active-color, black); } .sidenav .nav-group label { color: #333333; color: var(--clr-sidenav-header-color, #333333); font-weight: 500; font-weight: var(--clr-sidenav-header-font-weight, 500); font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-family: var(--clr-sidenav-header-font-family, ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif); font-size: 0.7rem; line-height: 1.2rem; letter-spacing: normal; } .sidenav .nav-group input[type=checkbox] { position: absolute; clip: rect(1px, 1px, 1px, 1px); clip-path: inset(50%); padding: 0; border: 0; height: 1px; width: 1px; overflow: hidden; white-space: nowrap; top: 0; left: 0; } .sidenav .nav-group input[type=checkbox]:focus + label { outline: #3b99fc auto 0.25rem; } .sidenav .collapsible label { padding: 0 0 0 1.3rem; } .sidenav .collapsible label:after { content: ""; float: left; height: 0.5rem; width: 0.5rem; transform: translateX(-0.4rem) translateY(0.35rem); background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2012%2012%22%3E%0A%20%20%20%20%3Cdefs%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E.cls-1%7Bfill%3A%239a9a9a%3B%7D%3C%2Fstyle%3E%0A%20%20%20%20%3C%2Fdefs%3E%0A%20%20%20%20%3Ctitle%3ECaret%3C%2Ftitle%3E%0A%20%20%20%20%3Cpath%20class%3D%22cls-1%22%20d%3D%22M6%2C9L1.2%2C4.2a0.68%2C0.68%2C0%2C0%2C1%2C1-1L6%2C7.08%2C9.84%2C3.24a0.68%2C0.68%2C0%2C1%2C1%2C1%2C1Z%22%2F%3E%0A%3C%2Fsvg%3E%0A"); background-repeat: no-repeat; background-size: contain; vertical-align: middle; margin: 0; } .sidenav .collapsible input[type=checkbox]:checked ~ .nav-list, .sidenav .collapsible input[type=checkbox]:checked ~ ul { height: 0; display: none; } .sidenav .collapsible input[type=checkbox] ~ .nav-list, .sidenav .collapsible input[type=checkbox] ~ ul { height: auto; } .sidenav .collapsible input[type=checkbox]:checked ~ label:after { transform: rotate(-90deg) translateX(-0.35rem) translateY(-0.4rem); } body:not([cds-text]) { color: var(--clr-p1-color, #666666); font-weight: var(--clr-p1-font-weight, 400); font-size: 0.7rem; letter-spacing: normal; line-height: 1.2rem; margin-bottom: 0px; font-family: var(--clr-font, ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif); margin-top: 0px !important; } html:not([cds-text]) { color: var(--clr-global-font-color, #666666); font-family: var(--clr-font, ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif); font-size: 125%; } a:link { color: var(--clr-link-color, #0072a3); text-decoration: none; } h1:not([cds-text]) { color: var(--clr-h1-color, black); font-weight: var(--clr-h1-font-weight, 200); font-family: var(--clr-h1-font-family, ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif); font-size: 1.6rem; letter-spacing: normal; line-height: 2.4rem; margin-top: 1.2rem; margin-bottom: 0px; } h2:not([cds-text]) { color: var(--clr-h2-color, black); font-weight: var(--clr-h2-font-weight, 200); font-family: var(--clr-h2-font-family, ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif); font-size: 1.4rem; letter-spacing: normal; line-height: 2.4rem; margin-top: 1.2rem; margin-bottom: 0px; } h3:not([cds-text]) { color: var(--clr-h3-color, black); font-weight: var(--clr-h3-font-weight, 200); font-family: var(--clr-h3-font-family, ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif); font-size: 1.1rem; letter-spacing: normal; line-height: 1.2rem; margin-top: 1.2rem; margin-bottom: 0px; } h4:not([cds-text]) { color: var(--clr-h4-color, black); font-weight: var(--clr-h4-font-weight, 200); font-family: var(--clr-h4-font-family, ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif); font-size: 0.9rem; letter-spacing: normal; line-height: 1.2rem; margin-top: 1.2rem; margin-bottom: 0px; } .table th { color: var(--clr-thead-color, #666666); font-size: 0.55rem; font-weight: 600; letter-spacing: 0.03em; background-color: var(--clr-thead-bgcolor, #fafafa); vertical-align: bottom; border-bottom-style: solid; border-bottom-width: var(--clr-table-borderwidth, 0.05rem); border-bottom-color: var(--clr-table-border-color, #cccccc); border-top: 0px none; } .table { border-collapse: separate; border-style: solid; border-width: var(--clr-table-borderwidth, 0.05rem); border-color: var(--clr-table-border-color, #cccccc); border-radius: var(--clr-table-border-radius, 0.15rem); background-color: var(--clr-table-bgcolor, white); color: var(--clr-table-font-color, #666666); margin: 1.2rem 0px 0px; max-width: 100%; width: 100%; } a { background-color: transparent; } abbr[title] { border-bottom: none; text-decoration: underline dotted; } b, strong { font-weight: inherit; } b, strong { font-weight: bolder; } [type="checkbox"], [type="radio"] { box-sizing: border-box; padding: 0px; } pre { border-color: var(--clr-color-neutral-400, #cccccc); border-width: var(--clr-global-borderwidth, 0.05rem); border-style: solid; border-radius: var(--clr-global-borderradius, 0.15rem); } ul:not([cds-list]), ol:not([cds-list]) { list-style-position: inside; margin-left: 0px; margin-top: 0px; margin-bottom: 0px; padding-left: 0px; } li > ul:not([cds-list]) { margin-top: 0px; margin-left: 1.1em; } body p:not([cds-text]) { color: var(--clr-p1-color, #666666); font-weight: var(--clr-p1-font-weight, 400); font-size: 0.7rem; letter-spacing: normal; line-height: 1.2rem; margin-top: 1.2rem; margin-bottom: 0px; } a:visited { color: var(--clr-link-visited-color, #5659b8); text-decoration: none; } .main-container .content-container .content-area > :first-child { margin-top: 0px; } .nav .nav-link:hover, .nav .nav-link.active { box-shadow: 0 -0.15rem 0 var(--clr-nav-active-box-shadow-color, #0072a3) inset; transition: box-shadow 0.2s ease-in 0s; } .nav .nav-link.active { color: var(--clr-nav-link-active-color, black); font-weight: var(--clr-nav-link-active-font-weight, 400); } :root { --clr-subnav-bg-color:var(--clr-color-neutral-0); --clr-nav-box-shadow-color:var(--clr-color-neutral-400); } :root { --clr-sidenav-border-color:var(--clr-color-neutral-400); --clr-sidenav-border-width:var(--clr-global-borderwidth); --clr-sidenav-link-hover-color:var(--clr-color-neutral-200); --clr-sidenav-link-active-color:var(--clr-color-neutral-1000); --clr-sidenav-link-active-bg-color:var(--clr-global-selection-color); --clr-sidenav-link-active-border-radius:var(--clr-global-borderradius); --clr-sidenav-header-color:var(--clr-h6-color); --clr-sidenav-header-font-weight:var(--clr-h6-font-weight); --clr-sidenav-header-font-family:var(--clr-h6-font-family); --clr-sidenav-color:var(--clr-p1-color); --clr-sidenav-font-weight:var(--clr-p1-font-weight); } .table th, .table td { font-size: 0.65rem; line-height: 0.7rem; border-top-style: solid; border-top-width: var(--clr-table-borderwidth, 0.05rem); border-top-color: var(--clr-tablerow-bordercolor, #e8e8e8); padding: 0.55rem 0.6rem; text-align: left; vertical-align: top; } ' } $clarityCssShared = ' .alertOK { color: #61B715; font-weight: bold } .alertWarning { color: #FDD008; font-weight: bold } .alertCritical { color: #F55047; font-weight: bold } .table th, .table td { text-align: left; } :root { --cds-global-base: 20; } body { margin: 0px; } .main-container .content-container .sidenav { flex: 0 0 auto; order: -1; overflow: hidden; } .main-container .content-container .content-area > :first-child { margin-top: 0; } .main-container .content-container .content-area { flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 1.2rem 1.2rem 1.2rem 1.2rem; } .main-container header, .main-container .header { flex: 0 0 3rem; } .main-container .header .branding { max-width: auto; min-width: 0px; overflow: hidden; } .main-container .sub-nav, .main-container .subnav { flex: 0 0 1.8rem; } .main-container .content-container { display: flex; flex: 1 1 auto; min-height: 0.05rem; } header .branding, .header .branding { display: flex; flex: 0 0 auto; min-width: 10.2rem; padding: 0px 1.2rem; height: 3rem; } header .branding .title, .header .branding .title { color: #fafafa; font-weight: 400; font-family: ClarityCityRegular, "Avenir Next", "Helvetica Neue", Arial, sans-serif; font-size: 0.8rem; letter-spacing: 0.01em; line-height: 3rem; text-decoration: none; } header .branding > a, header .branding > .nav-link, .header .branding > a, .header .branding > .nav-link { display: inline-flex; align-items: center; height: 3rem; } header .branding .clr-icon, header .branding cds-icon, header .branding clr-icon, .header .branding .clr-icon, .header .branding cds-icon, .header .branding clr-icon { flex-grow: 0; flex-shrink: 0; height: 1.8rem; width: 1.8rem; margin-right: 0.45rem; } ul:not([cds-list]), ol:not([cds-list]) { list-style-position: inside; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; } a { background-color: transparent; -webkit-text-decoration-skip: objects; } h1 { font-size: 2em; margin: 0.67em 0px; } img { border-style: none; } img { vertical-align: middle; } *, ::before, ::after { box-sizing: border-box; } *, ::before, ::after { box-sizing: inherit; } table { border-spacing: 0px; } pre { margin: 0.6rem 0px; } html { box-sizing: border-box; } html { -webkit-tap-highlight-color: transparent; } html { -ms-overflow-style: scrollbar; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } html { font-family: sans-serif; line-height: 1.15; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; } .table tbody tr:first-child td { border-top: 0px none; } .table thead th:first-child { border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; border-top-left-radius: var(--clr-table-cornercellradius, 0.1rem); } .table thead th:last-child { border-top-left-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; border-top-right-radius: var(--clr-table-cornercellradius, 0.1rem); } .table tbody:last-child tr:last-child td:first-child { border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: var(--clr-table-cornercellradius, 0.1rem); } .table tbody:last-child tr:last-child td:last-child { border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-left-radius: 0px; border-bottom-right-radius: var(--clr-table-cornercellradius, 0.1rem); } @font-face {font-family: ClarityCityRegular;src: url(data:font/ttf;base64,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AvQAWwLlABkEKwAeBCsAHgQrAB4EKwAeBCsAHgKlABwCoQATAqEAEwKhABMCoQATAqEAEwJlACwCZQAsAmUALAJlACwCLQAkAi0AJAItACQCLQAkAi0AJAItACQCLQAkAi0AJAItACQCLQAkA7IAJAJ7AFcCBwApAgcAKQIHACkCBwApAnsALwJZACsCpQAvAnsALwJHACwCRwAsAkcALAJHACwCRwAsAkcALAJYACwCRwAsAkcALAJYACwCRwAsAT0AGAJ2ACoCdgAqAnYAKgJZAFcA+QBLAPkAVwD5AFcA+f/2APn/7wD5/9IA+f/iAPkAMADv/84A7//OAiUAVwIlAFcA+QBXAPkAVwEWAFcBJwAcA4kAVwJZAFcCWQBXAlkAVwJZAFcCWQBXAmkAKgJpACoCaQAqAmkAKgJpACoCaQAqAmkAKgKBADMCaQAqBCAAKgJ7AFcCfABYAnsALwGMAFcBjABXAYwAVgGMAFcB3gAhAd4AIQHeACEB3gAhAkMAVwFZABUBuQAVAVkAFQJZAEsCWQBLAlkASwJZAEsCWQBLAlkASwJZAEsCWQBLAlkASwIRAAoDHQAQAx0AEAMdABADHQAQAx0AEAH/AAwCGAAJAhgACQIYAAkCGAAJAhgACQHbACEB2wAhAdsAIQHbACECewAvAnsALwJ7AC8CewAvAnsALwJ7AC8CewAvAnsALwJ7AC8CewAvArMAPAFlABQCNQAiAkYAHgJMABsCUQA3AmgAPwIDABYCbQA7AmgAMgFEAGwBOgBlATMAYwE1AGMC1ABsAT0AaAE9AGkCCQAiAgkAMwFBAG0BrgBfAc8AVgKxAC8BtAAAAbQAAAFIADUBSAAaAWIAFgFiABsBcgBpAXIAHQGvAFYCfQBWA64AVgMAAFYB4ABUAeAAUAHgAFQBGABQARgAVAIBACICAAAsATsAIgE6ACwBygBdARYAXQPoAAAB9AAAAPoAAAETAAAApgAAAU0AAAJcAFECkgBGAzkAUAKcAFUC8QA6Ak8AQgLPAIICFgBOAlMARALRAIMCUQBPAlEAOwIbAG0B/AA/A0YAPwS6AD8DqABJAsIAPwKYAD0DrQBKApUAVANBAFMBQgCDAAD/UgAA/10BBwAeAZEANQFbACYBJQAwAVsAJgGxAEsA8QBLAQMAHQHOAB0B4gBWASYAQwFNAD8BxABC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) </style> </head> <body> <div class="main-container"> <header class="header header-6"> <div class="branding"> <a href=""> <cds-icon shape="vm-bug"> <img height="36px" width="36px" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI2LjIuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzNiAzNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzYgMzY7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbDojMDA5MURBO30KCS5zdDF7ZmlsbDojMUQ0MjhBO30KCS5zdDJ7ZmlsbDojMDBDMUQ1O30KPC9zdHlsZT4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI4LjIsMzAuNGMtMC4zLDAtMC41LTAuMi0wLjYtMC40Yy0wLjItMC40LDAtMC44LDAuMy0wLjljMy45LTEuOCw2LjQtNS43LDYuNC05LjljMC0yLjMtMC43LTQuNC0yLTYuMwoJYy0xLjMtMS44LTMtMy4yLTUuMS00Yy0wLjQtMC4xLTAuNi0wLjYtMC40LTAuOWMwLjEtMC40LDAuNi0wLjYsMC45LTAuNGMyLjMsMC45LDQuMywyLjQsNS44LDQuNWMxLjUsMi4xLDIuMyw0LjUsMi4zLDcuMQoJYzAsNC44LTIuOCw5LjItNy4yLDExLjJDMjguNCwzMC40LDI4LjMsMzAuNCwyOC4yLDMwLjR6Ii8+CjxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0yMy4yLDExLjNjLTAuMSwwLTAuMiwwLTAuMywwYy0wLjUtMS44LTEuNi0zLjMtMy4xLTQuNWMtMS43LTEuMy0zLjctMi01LjgtMmMtNS4xLDAtOS4zLDQuMS05LjMsOS4yCgljMCwwLDAsMC4xLDAsMC4xYy0zLjUsMS4xLTUuNCw0LjktNC4zLDguNGMwLjYsMS44LDEuOSwzLjMsMy43LDQuMXYtMS42Yy0yLjUtMS41LTMuNC00LjctMS45LTcuMmMwLjctMS4zLDItMi4yLDMuNC0yLjVsMC42LTAuMQoJbDAtMC42YzAtMC4yLDAtMC40LDAtMC42YzAtNC4zLDMuNS03LjcsNy44LTcuN2MzLjYsMCw2LjgsMi41LDcuNiw2bDAuMSwwLjZsMC42LTAuMWMwLjIsMCwwLjUsMCwwLjcsMGMzLjYsMCw2LjUsMi45LDYuNSw2LjUKCWMwLDEuOS0wLjgsMy43LTIuMiw0Ljl2MS44YzIuMy0xLjQsMy43LTMuOSwzLjctNi42QzMxLjEsMTQuOCwyNy41LDExLjMsMjMuMiwxMS4zeiIvPgo8cGF0aCBjbGFzcz0ic3QyIiBkPSJNMS4yLDEyLjJjMCwwLTAuMSwwLTAuMSwwYy0wLjQtMC4xLTAuNi0wLjQtMC42LTAuOEMxLjcsNC45LDcuNCwwLjIsMTQsMC4yYzMuMSwwLDYuMiwxLjEsOC42LDMKCWMwLjksMC43LDEuNiwxLjUsMi4zLDIuM2MwLjIsMC4zLDAuMiwwLjgtMC4xLDFjLTAuMywwLjItMC44LDAuMi0xLTAuMWMtMC42LTAuOC0xLjMtMS41LTItMi4xYy0yLjItMS44LTUtMi43LTcuOC0yLjcKCWMtNiwwLTExLjEsNC4yLTEyLjIsMTBDMS44LDEyLDEuNSwxMi4yLDEuMiwxMi4yeiBNMTguMywxOGMtMC40LDAtMC43LDAuMy0wLjgsMC43YzAsMC40LDAuMywwLjcsMC43LDAuOGMwLDAsMCwwLDAuMSwwaDMuOQoJbC04LjUsOC4xYy0wLjMsMC4zLTAuMywwLjcsMCwxYzAuMywwLjMsMC43LDAuMywxLDBsOC41LTh2My45YzAsMC40LDAuNCwwLjcsMC44LDAuN2MwLjQsMCwwLjctMC4zLDAuNy0wLjdWMThMMTguMywxOEwxOC4zLDE4egoJIE0xNC43LDIzLjFWMThIOS42Yy0wLjQsMC0wLjcsMC40LTAuNywwLjhjMCwwLjQsMC4zLDAuNywwLjcsMC43aDIuNkw3LDI0LjJjLTAuMywwLjMtMC4zLDAuNywwLDFjMC4zLDAuMywwLjcsMC4zLDEsMGw1LjItNC44djIuNwoJYzAsMC40LDAuNCwwLjcsMC44LDAuN0MxNC40LDIzLjgsMTQuNywyMy41LDE0LjcsMjMuMUwxNC43LDIzLjF6IE0xOC44LDI4LjZjMCwwLjQsMC4zLDAuNywwLjcsMC43aDIuN2wtNC43LDUuMQoJYy0wLjMsMC4zLTAuMywwLjcsMCwxYzAuMywwLjMsMC43LDAuMywxLDBjMCwwLDAsMCwwLjEtMC4xbDQuNi01VjMzYzAsMC40LDAuMywwLjcsMC43LDAuOGMwLjQsMCwwLjctMC4zLDAuOC0wLjdjMCwwLDAsMCwwLTAuMQoJdi01LjFoLTUuMUMxOS4xLDI3LjksMTguOCwyOC4yLDE4LjgsMjguNkwxOC44LDI4LjZ6Ii8+Cjwvc3ZnPgo=" alt="VMware Cloud Foundation"/> </cds-icon> <span class="title">VMware Cloud Foundation</span> </a> </div> </header> ' $clarityCssHeader += $clarityCssShared $clarityCssHeader } Function Save-ClarityReportNavigation { $clarityCssNavigation = ' <nav class="subnav"> <ul class="nav"> <li class="nav-item"> <a class="nav-link active" href="">Password Policy</a> </li> </ul> </nav> <div class="content-container"> <nav class="sidenav"> <section class="sidenav-content"> <section class="nav-group collapsible"> <input id="expiration" type="checkbox"/> <label for="expiration">Password Expiration</label> <ul class="nav-list"> <li><a class="nav-link" href="#sddcmanager-password-expiration">SDDC Manager</a></li> <li><a class="nav-link" href="#sso-password-expiration">vCenter Single Sign-On</a></li> <li><a class="nav-link" href="#vcenter-password-expiration">vCenter</a></li> <li><a class="nav-link" href="#vcenter-password-expiration-local">vCenter</a></li> <li><a class="nav-link" href="#nsxmanager-password-expiration">NSX Manager</a></li> <li><a class="nav-link" href="#nsxedge-password-expiration">NSX Edge</a></li> <li><a class="nav-link" href="#esx-password-expiration">ESX</a></li> <li><a class="nav-link" href="#vrslcm-local-password-expiration">Aria Suite Lifecycle</a></li> <li><a class="nav-link" href="#vrops-local-password-expiration">Aria Operations</a></li> <li><a class="nav-link" href="#vrli-local-password-expiration">Aria Operations for Logs</a></li> <li><a class="nav-link" href="#vrni-local-password-expiration">Aria Operations for Networks</a></li> <li><a class="nav-link" href="#vra-local-password-expiration">Aria Automation</a></li> <li><a class="nav-link" href="#wsa-directory-password-expiration">Workspace ONE (Directory)</a></li> <li><a class="nav-link" href="#wsa-local-password-expiration">Workspace ONE (Local)</a></li> <li><a class="nav-link" href="#local-wsa-directory-password-expiration">Local Workspace ONE (Directory)</a></li> <li><a class="nav-link" href="#local-wsa-local-password-expiration">Local Workspace ONE (Local)</a></li> </ul> </section> <section class="nav-group collapsible"> <input id="complexity" type="checkbox"/> <label for="complexity">Password Complexity</label> <ul class="nav-list"> <li><a class="nav-link" href="#sddcmanager-password-complexity">SDDC Manager</a></li> <li><a class="nav-link" href="#sso-password-complexity">vCenter Single Sign-On</a></li> <li><a class="nav-link" href="#vcenter-password-complexity-local">vCenter</a></li> <li><a class="nav-link" href="#nsxmanager-password-complexity">NSX Manager</a></li> <li><a class="nav-link" href="#nsxedge-password-complexity">NSX Edge</a></li> <li><a class="nav-link" href="#esx-password-complexity">ESX</a></li> <li><a class="nav-link" href="#vrslcm-local-password-complexity">Aria Suite Lifecycle</a></li> <li><a class="nav-link" href="#vrops-local-password-complexity">Aria Operations</a></li> <li><a class="nav-link" href="#vrli-local-password-complexity">Aria Operations for Logs</a></li> <li><a class="nav-link" href="#vrni-local-password-complexity">Aria Operations for Networks</a></li> <li><a class="nav-link" href="#vra-local-password-complexity">Aria Automation</a></li> <li><a class="nav-link" href="#wsa-directory-password-complexity">Workspace ONE (Directory)</a></li> <li><a class="nav-link" href="#wsa-local-password-complexity">Workspace ONE (Local)</a></li> <li><a class="nav-link" href="#local-wsa-directory-password-complexity">Local Workspace ONE (Directory)</a></li> <li><a class="nav-link" href="#local-wsa-local-password-complexity">Local Workspace ONE (Local)</a></li> </ul> </section> <section class="nav-group collapsible"> <input id="lockout" type="checkbox"/> <label for="lockout">Account Lockout</label> <ul class="nav-list"> <li><a class="nav-link" href="#sddcmanager-account-lockout">SDDC Manager</a></li> <li><a class="nav-link" href="#sso-account-lockout">vCenter Single Sign-On</a></li> <li><a class="nav-link" href="#vcenter-account-lockout-local">vCenter</a></li> <li><a class="nav-link" href="#nsxmanager-account-lockout">NSX Manager</a></li> <li><a class="nav-link" href="#nsxedge-account-lockout">NSX Edge</a></li> <li><a class="nav-link" href="#esx-account-lockout">ESX</a></li> <li><a class="nav-link" href="#vrslcm-local-account-lockout">Aria Suite Lifecycle</a></li> <li><a class="nav-link" href="#vrops-local-account-lockout">Aria Operations</a></li> <li><a class="nav-link" href="#vrli-local-account-lockout">Aria Operations for Logs</a></li> <li><a class="nav-link" href="#vrni-local-account-lockout">Aria Operations for Networks</a></li> <li><a class="nav-link" href="#vra-local-account-lockout">Aria Automation</a></li> <li><a class="nav-link" href="#wsa-directory-account-lockout">Workspace ONE (Directory)</a></li> <li><a class="nav-link" href="#wsa-local-account-lockout">Workspace ONE (Local)</a></li> <li><a class="nav-link" href="#local-wsa-directory-account-lockout">Local Workspace ONE (Directory)</a></li> <li><a class="nav-link" href="#local-wsa-local-account-lockout">Local Workspace ONE (Local)</a></li> </ul> </section> </section> </nav> <div class="content-area"> <div class="content-area">' $clarityCssNavigation } Function Save-ClarityReportNavigationForRotation { Param ( [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain ) $managementDomain = Get-VCFWorkloadDomain | Where-Object { $_.Type -eq 'MANAGEMENT' } $clarityCssNavigation = ' <nav class="subnav"> <ul class="nav"> <li class="nav-item"> <a class="nav-link active" href="">Password Rotation</a> </li> </ul> </nav> <div class="content-container"> <nav class="sidenav"> <section class="sidenav-content"> <section class="nav-group collapsible"> <input id="rotation" type="checkbox"/> <label for="rotation">Password Rotation</label> <ul class="nav-list">' if ($PsBoundParameters.ContainsKey('allDomains') -or ($PsBoundParameters.ContainsKey('workloadDomain') -and $workloadDomain -eq $managementDomain.name)) { $clarityCssNavigation += ' <li><a class="nav-link" href="#sddc-manager-password-rotation">SDDC Manager</a></li> <li><a class="nav-link" href="#vcenter-single-sign-on-password-rotation">vCenter Single Sign-On</a></li>' } $clarityCssNavigation += ' <li><a class="nav-link" href="#vcenter-server-password-rotation">vCenter</a></li> <li><a class="nav-link" href="#nsx-manager-password-rotation">NSX Manager</a></li> <li><a class="nav-link" href="#nsx-edge-password-rotation">NSX Edge</a></li>' if ($PsBoundParameters.ContainsKey('allDomains') -or ($PsBoundParameters.ContainsKey('workloadDomain') -and $workloadDomain -eq $managementDomain.name)) { if (Get-VCFAriaLifecycle) { $ariaResources = @('ariaLifecycle', 'ariaOperationsLogs', 'ariaOperations', 'ariaAutomation', 'workspaceOneAccess') foreach ($resource in $ariaResources) { switch ($resource) { default { $command = "Get-VCF$resource" } 'workspaceOneAccess' { $command = 'Get-VCFWsa'; } } if (Invoke-Expression $command -ErrorAction SilentlyContinue) { $isEnabled = (Invoke-Expression $command -ErrorAction SilentlyContinue) if ($isEnabled) { $resourceTitleCase = switch ($resource) { 'ariaLifecycle' { 'Aria Suite Lifecycle' } 'ariaOperationsLogs' { 'Aria Operations for Logs' } 'ariaOperations' { 'Aria Operations' } 'ariaAutomation' { 'Aria Automation' } 'workspaceOneAccess' { 'Workspace ONE Access' } } $resourceKebabCase = $resourceTitleCase.ToLower() -replace ' ', '-' $clarityCssNavigation += "<li><a class='nav-link' href='#$resourceKebabCase-password-rotation'>$resourceTitleCase</a></li>" } } } } } $clarityCssNavigation += ' </ul> </section> </section> </nav> <div class="content-area"> <div class="content-area">' $clarityCssNavigation } Function Save-ClarityReportFooter { # Define the default Clarity Cascading Style Sheets (CSS) for the HTML report Footer $clarityCssFooter = ' </div> </div> </div> </body> </html>' $clarityCssFooter } Function Convert-CssClassStyle { Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [PSCustomObject]$htmlData ) # Function to replace CSS Style # Function to replace Alerts with colour coded CSS Style $oldAlertOK = '<td>GREEN</td>' $newAlertOK = '<td class="alertOK">GREEN</td>' $oldAlertCritical = '<td>RED</td>' $newAlertCritical = '<td class="alertCritical">RED</td>' $oldAlertWarning = '<td>YELLOW</td>' $newAlertWarning = '<td class="alertWarning">YELLOW</td>' $oldTable = '<table>' $newTable = '<table class="table">' $oldAddLine = ':-: ' $newNewLine = '<br/>' $htmlData = $htmlData -replace $oldAlertOK, $newAlertOK $htmlData = $htmlData -replace $oldAlertCritical, $newAlertCritical $htmlData = $htmlData -replace $oldAlertWarning, $newAlertWarning $htmlData = $htmlData -replace $oldTable, $newTable $htmlData = $htmlData -replace $oldAddLine, $newNewLine $htmlData } #EndRegion End Password Policy Functions ###### ########################################################################## ########################################################################## #Region Begin SDDC Manager Password Management Function ###### Function Request-SddcManagerPasswordExpiration { <# .SYNOPSIS Retrieves the password expiration policy for an SDDC Manager. .DESCRIPTION The Request-SddcManagerPasswordExpiration cmdlet retrieves the password expiration policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Retrieves the password expiration policy. .EXAMPLE Request-SddcManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] This example retrieves the password expiration policy for an SDDC Manager. .EXAMPLE Request-SddcManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password expiration policy for an SDDC Manager and compares the configuration against the policy configuration file. .EXAMPLE Request-SddcManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] -drift This example retrieves the password expiration policy for an SDDC Manager and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER rootPass The password for the SDDC Manager appliance root account. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the password policy file to compare against. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$rootPass, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass $rootPass = Get-Password -username "root" -password $rootPass # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } [Array]$localUsers = '"root","vcf","backup"' $pvsCmdlet = "Request-LocalUserPasswordExpiration"; $customSwitch = " -domain $((Get-VCFWorkloadDomain | Where-Object {$_.type -eq "MANAGEMENT"}).name) -product sddcManager -vmName $(($server.Split("."))[-0]) -guestUser root -guestPassword $rootPass -localUser $localUsers" $command = $pvsCmdlet + " -server $server -user $user -pass $pass" + $commandSwitch + $customSwitch Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType MANAGEMENT)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { $sddcManagerLocalPasswordPolicyObject = Invoke-Expression $command if ($sddcManagerLocalPasswordPolicyObject) { $sddcManagerLocalPasswordPolicyObject } } } } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false -WarningAction SilentlyContinue } } } Export-ModuleMember -Function Request-SddcManagerPasswordExpiration Function Request-SddcManagerPasswordComplexity { <# .SYNOPSIS Retrieves the password complexity policy for an SDDC Manager. .DESCRIPTION The Request-SddcManagerPasswordComplexity cmdlet retrieves the password complexity policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager. - Retrieves the password complexity policy. .EXAMPLE Request-SddcManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] This example retrieves the password complexity policy for an SDDC Manager. .EXAMPLE Request-SddcManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password complexity policy for an SDDC Manager and compares the configuration against the policy configuration file. .EXAMPLE Request-SddcManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] -drift This example retrieves the password complexity policy for an SDDC Manager and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER rootPass The password for the SDDC Manager appliance root account. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the password policy file to compare against. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$rootPass, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass $rootPass = Get-Password -username "root" -password $rootPass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType MANAGEMENT)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { Get-LocalPasswordComplexity -version $version -vmName ($server.Split("."))[-0] -guestUser root -guestPassword $rootPass -product sddcManager -drift -reportPath $reportPath -policyFile $policyFile } else { Get-LocalPasswordComplexity -version $version -vmName ($server.Split("."))[-0] -guestUser root -guestPassword $rootPass -product sddcManager -drift } } else { Get-LocalPasswordComplexity -vmName ($server.Split("."))[-0] -guestUser root -guestPassword $rootPass } } } } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false -WarningAction SilentlyContinue } } } Export-ModuleMember -Function Request-SddcManagerPasswordComplexity Function Request-SddcManagerAccountLockout { <# .SYNOPSIS Retrieves the account lockout policy for an SDDC Manager. .DESCRIPTION The Request-SddcManagerAccountLockout cmdlet retrieves the account lockout policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Retrieves the account lockout policy for an SDDC Manager. .EXAMPLE Request-SddcManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] This example retrieves the account lockout policy for an SDDC Manager. .EXAMPLE Request-SddcManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the account lockout policy for an SDDC Manager and and compares the configuration against the policy configuration file. .EXAMPLE Request-SddcManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] -drift This example retrieves the account lockout policy for an SDDC Manager and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER rootPass The password for the SDDC Manager appliance root account. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the password policy file to compare against. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$rootPass, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass $rootPass = Get-Password -username "root" -password $rootPass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType MANAGEMENT)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { Get-LocalAccountLockout -version $version -vmName ($server.Split("."))[-0] -guestUser root -guestPassword $rootPass -product sddcManager -drift -reportPath $reportPath -policyFile $policyFile } else { Get-LocalAccountLockout -version $version -vmName ($server.Split("."))[-0] -guestUser root -guestPassword $rootPass -product sddcManager -drift } } else { Get-LocalAccountLockout -vmName ($server.Split("."))[-0] -guestUser root -guestPassword $rootPass -product sddcManager } } } } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-SddcManagerAccountLockout Function Update-SddcManagerPasswordExpiration { <# .SYNOPSIS Updates the password expiration policy for the default local users on an SDDC Manager. .DESCRIPTION The Update-SddcManagerPasswordExpiration cmdlet configures the password complexity policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager. - Configures the password expiration policy. .EXAMPLE Update-SddcManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] -minDays 0 -maxDays 90 -warnDays 14 This example updates the password expiration policy for the default local users on an SDDC Manager. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER rootPass The password for the SDDC Manager appliance root account. .PARAMETER minDays The minimum number of days between password changes. .PARAMETER maxDays The maximum number of days between password changes. .PARAMETER warnDays The number of days of warning before password expires. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$rootPass, [Parameter (Mandatory = $true)] [ValidateRange(0, 9999)] [Int]$minDays, [Parameter (Mandatory = $true)] [ValidateRange(0, 9999)] [Int]$maxDays, [Parameter (Mandatory = $true)] [ValidateRange(0, 9999)] [Int]$warnDays, [Parameter (Mandatory = $false)] [ValidateSet('true', 'false')] [String]$detail = 'true' ) $pass = Get-Password -username $user -password $pass $rootPass = Get-Password -username "root" -password $rootPass [Array]$localUsers = '"root","vcf","backup"' $cmdlet = 'Update-LocalUserPasswordExpiration'; $customSwitch = " -domain $((Get-VCFWorkloadDomain | Where-Object {$_.type -eq 'MANAGEMENT'}).name) -vmName $(($server.Split('.'))[-0]) -guestUser root -guestPassword $rootPass -localUser $localUsers -minDays $minDays -maxDays $maxDays -warnDays $warnDays -detail $detail" $command = $cmdlet + " -server $server -user $user -pass $pass" + $customSwitch Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { Invoke-Expression -Command $command } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-SddcManagerPasswordExpiration Function Update-SddcManagerPasswordComplexity { <# .SYNOPSIS Updates the password complexity policy for an SDDC Manager. .DESCRIPTION The Update-SddcManagerPasswordComplexity cmdlet configures the password complexity policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager. - Configures the password complexity policy. .EXAMPLE Update-SddcManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] -minLength 6 -minLowercase -1 -minUppercase -1 -minNumerical -1 -minSpecial -1 -minUnique 4 -minClass 4 -maxSequence 0 -history 5 -maxRetry 3 This example configures the password complexity policy for an SDDC Manager. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER rootPass The password for the SDDC Manager appliance root account. .PARAMETER minLength The minimum length of the password. .PARAMETER minLowercase The minimum number of lowercase characters in the password. .PARAMETER minUppercase The minimum number of uppercase characters in the password. .PARAMETER minNumerical The minimum number of numerical characters in the password. .PARAMETER minSpecial The minimum number of special characters in the password. .PARAMETER minUnique The minimum number of unique characters in the password. .PARAMETER minClass The minimum number of character classes in the password. .PARAMETER maxSequence The maximum number of sequential characters in the password. .PARAMETER history The number of previous passwords that a password cannot match. .PARAMETER maxRetry The number of failed login attempts before the account is locked. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$rootPass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minLength, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minLowercase, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minUppercase, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minNumerical, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minSpecial, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minUnique, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minClass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$maxSequence, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$history, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$maxRetry ) $pass = Get-Password -username $user -password $pass $rootPass = Get-Password -username "root" -password $rootPass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType MANAGEMENT)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { $existingConfiguration = Get-LocalPasswordComplexity -vmName ($server.Split("."))[-0] -guestUser root -guestPassword $rootPass $chkExistingConfig = $existingConfiguration.'Min Length' -ne $minLength -or $existingConfiguration.'Min Lowercase' -ne $minLowercase -or $existingConfiguration.'Min Uppercase' -ne $minUppercase -or $existingConfiguration.'Min Numerical' -ne $minNumerical -or $existingConfiguration.'Min Special' -ne $minSpecial -or $existingConfiguration.'Min Unique' -ne $minUnique -or $existingConfiguration.'History' -ne $history -or $existingConfiguration.'Max Retries' -ne $maxRetry if ($existingConfiguration.'Max Sequence') { $chkExistingConfig = $chkExistingConfig -or $existingConfiguration.'Max Sequence' -ne $maxSequence } if ($existingConfiguration.'Min Class') { $chkExistingConfig = $chkExistingConfig -or $existingConfiguration.'Min Class' -ne $minClass } $sddcManagerVersion = Get-VCFManager -version if (($sddcManagerVersion.split(".")[0] -ge 5 -and $sddcManagerVersion.split(".")[1] -ge 1) -and ($null -eq $existingConfiguration.'Min Length' -or $null -eq $existingConfiguration.'Min Lowercase' -or $null -eq $existingConfiguration.'Min Uppercase' -or $null -eq $existingConfiguration.'Min Numerical' -or $null -eq $existingConfiguration.'Min Special' -or $null -eq $existingConfiguration.'Min Unique' -or $null -eq $existingConfiguration.'History' -or $null -eq $existingConfiguration.'Max Retries' -or $null -eq $existingConfiguration.'Max Sequence' -or $null -eq $existingConfiguration.'Min Class')) { $scriptCommand = "sed -E -i.bak -e 's/password.*required.*pam_pwquality.so.*/password required pam_pwquality.so dcredit=$minNumerical ucredit=$minUppercase lcredit=$minLowercase ocredit=$minSpecial minlen=$minLength difok=$minUnique minclass=$minClass maxsequence=$maxSequence enforce_for_root/" $scriptCommand += "' -e 's/password.*required.*pam_pwhistory.so.*/password required pam_pwhistory.so remember=$history retry=$maxRetry enforce_for_root use_authtok/" $scriptCommand += "' /etc/pam.d/system-password" Invoke-VMScript -VM ($server.Split("."))[0] -ScriptText $scriptCommand -GuestUser "root" -GuestPass $rootPass -Confirm:$false | Out-Null # validate if changes take effect $updatedConfiguration = Get-LocalPasswordComplexity -vmName ($server.Split("."))[-0] -guestUser root -guestPassword $rootPass $chkUpdatedConfig = $updatedConfiguration.'Min Length' -eq $minLength -and $updatedConfiguration.'Min Lowercase' -eq $minLowercase -and $updatedConfiguration.'Min Uppercase' -eq $minUppercase -and $updatedConfiguration.'Min Numerical' -eq $minNumerical -and $updatedConfiguration.'Min Special' -eq $minSpecial -and $updatedConfiguration.'Min Unique' -eq $minUnique -and $updatedConfiguration.'History' -eq $history -and $updatedConfiguration.'Max Retries' -eq $maxRetry if ($updatedConfiguration.'Max Sequence') { $chkUpdatedConfig = $chkUpdatedConfig -and $updatedConfiguration.'Max Sequence' -eq $maxSequence } if ($updatedConfiguration.'Min Class') { $chkUpdatedConfig = $chkUpdatedConfig -and $updatedConfiguration.'Min Class' -eq $minClass } if ($chkUpdatedConfig) { Write-Output "Update Password Complexity Policy on SDDC Manager ($server): SUCCESSFUL" } else { Write-Error "Update Password Complexity Policy on SDDC Manager ($server): POST_VALIDATION_FAILED" } } elseif ($chkExistingConfig) { Set-LocalPasswordComplexity -vmName ($server.Split("."))[0] -guestUser root -guestPassword $rootPass -minLength $minLength -uppercase $minUppercase -lowercase $minLowercase -numerical $minNumerical -special $minSpecial -unique $minUnique -class $minClass -sequence $maxSequence -history $history -retry $maxRetry | Out-Null $updatedConfiguration = Get-LocalPasswordComplexity -vmName ($server.Split("."))[-0] -guestUser root -guestPassword $rootPass $chkUpdatedConfig = $updatedConfiguration.'Min Length' -eq $minLength -and $updatedConfiguration.'Min Lowercase' -eq $minLowercase -and $updatedConfiguration.'Min Uppercase' -eq $minUppercase -and $updatedConfiguration.'Min Numerical' -eq $minNumerical -and $updatedConfiguration.'Min Special' -eq $minSpecial -and $updatedConfiguration.'Min Unique' -eq $minUnique -and $updatedConfiguration.'History' -eq $history -and $updatedConfiguration.'Max Retries' -eq $maxRetry if ($updatedConfiguration.'Max Sequence') { $chkUpdatedConfig = $chkUpdatedConfig -and $updatedConfiguration.'Max Sequence' -eq $maxSequence } if ($updatedConfiguration.'Min Class') { $chkUpdatedConfig = $chkUpdatedConfig -and $updatedConfiguration.'Min Class' -eq $minClass } if ($chkUpdatedConfig) { Write-Output "Update Password Complexity Policy on SDDC Manager ($server): SUCCESSFUL" } else { Write-Error "Update Password Complexity Policy on SDDC Manager ($server): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Password Complexity Policy on SDDC Manager ($server), already set: SKIPPED" } } } } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-SddcManagerPasswordComplexity Function Update-SddcManagerAccountLockout { <# .SYNOPSIS Updates the account lockout policy for an SDDC Manager. .DESCRIPTION The Update-SddcManagerAccountLockout cmdlet configures the account lockout policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the account lockout policy. .EXAMPLE Update-SddcManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -rootPass [root_password] -failures 3 -unlockInterval 86400 -rootUnlockInterval 300 This example configures the account lockout policy for an SDDC Manager. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER rootPass The password for the SDDC Manager appliance root account. .PARAMETER failures The number of failed login attempts before the account is locked. .PARAMETER unlockInterval The number of seconds before a locked account is unlocked. .PARAMETER rootUnlockInterval The number of seconds before a locked root account is unlocked. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$rootPass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$failures, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$unlockInterval, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$rootUnlockInterval ) $pass = Get-Password -username $user -password $pass $rootPass = Get-Password -username "root" -password $rootPass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType MANAGEMENT)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { $existingConfiguration = Get-LocalAccountLockout -vmName ($server.Split("."))[0] -guestUser root -guestPassword $rootPass -product sddcManager if ($existingConfiguration.'Max Failures' -ne $failures -or $existingConfiguration.'Unlock Interval (sec)' -ne $unlockInterval -or $existingConfiguration.'Root Unlock Interval (sec)' -ne $rootUnlockInterval) { Set-LocalAccountLockout -vmName ($server.Split("."))[0] -guestUser root -guestPassword $rootPass -failures $failures -unlockInterval $unlockInterval -rootUnlockInterval $rootUnlockInterval | Out-Null $updatedConfiguration = Get-LocalAccountLockout -vmName ($server.Split("."))[0] -guestUser root -guestPassword $rootPass -product sddcManager if ($updatedConfiguration.'Max Failures' -eq $failures -and $updatedConfiguration.'Unlock Interval (sec)' -eq $unlockInterval -and $updatedConfiguration.'Root Unlock Interval (sec)' -eq $rootUnlockInterval) { Write-Output "Update Account Lockout Policy on SDDC Manager ($server): SUCCESSFUL" } else { Write-Error "Update Account Lockout Policy on SDDC Manager ($server): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Account Lockout Policy on SDDC Manager ($server), already set: SKIPPED" } } } } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-SddcManagerAccountLockout Function Publish-SddcManagerPasswordExpiration { <# .SYNOPSIS Publishes the password expiration policy for an SDDC Manager. .DESCRIPTION The Publish-SddcManagerPasswordExpiration cmdlet returns password expiration policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects password expiration policy for each local user of SDDC Manager. .EXAMPLE Publish-SddcManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -allDomains This example returns password expiration policy for each local user of SDDC Manager. .EXAMPLE Publish-SddcManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -workloadDomain [workload_domain_name] This example will NOT return the password expiration policy for each local user of SDDC Manager as the workload domain provided is not the management domain. .EXAMPLE Publish-SddcManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns the password expiration policy for each local user of SDDC Manager and compares the configuration against the policy configuration file. .EXAMPLE Publish-SddcManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -workloadDomain [workload_domain_name] -drift This example returns the password expiration policy for each local user of SDDC Manager and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER sddcRootPass The password for the SDDC Manager appliance root account. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$sddcRootPass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass $sddcRootPass = Get-Password -username "root" -password $sddcRootPass # Define the Command to be Executed [Array]$localUsers = '"root","vcf","backup"' $command = "Request-LocalUserPasswordExpiration -server $server -user $user -pass $pass -domain $((Get-VCFWorkloadDomain | Where-Object {$_.type -eq "MANAGEMENT"}).name) -vmName $(($server.Split("."))[-0]) -guestUser root -guestPassword $sddcRootPass -localUser $localUsers -product sddcManager" if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $command = $command + " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $command = $command + " -drift" } } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $allSddcManagerPasswordExpirationObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $workloadDomain -and $_.type -eq "MANAGEMENT" }) { $userPasswordExpiration = Invoke-Expression $command ; $allSddcManagerPasswordExpirationObject += $userPasswordExpiration } } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { if ($domain | Where-Object { $_.type -eq "MANAGEMENT" }) { $userPasswordExpiration = Invoke-Expression $command ; $allSddcManagerPasswordExpirationObject += $userPasswordExpiration } } } if ($PsBoundParameters.ContainsKey('json')) { $allSddcManagerPasswordExpirationObject | ConvertTo-Json -Depth 10 } else { if ($allSddcManagerPasswordExpirationObject.Count -eq 0) { $notManagement = $true } if ($notManagement) { $allSddcManagerPasswordExpirationObject = $allSddcManagerPasswordExpirationObject | ConvertTo-Html -Fragment -PreContent '<a id="sddcmanager-password-expiration"></a><h3>SDDC Manager - Password Expiration</h3>' -PostContent '<p>Management Domain not requested.</p>' } else { $allSddcManagerPasswordExpirationObject = $allSddcManagerPasswordExpirationObject | Sort-Object 'Workload Domain', 'System', 'User' | ConvertTo-Html -Fragment -PreContent '<a id="sddcmanager-password-expiration"></a><h3>SDDC Manager - Password Expiration</h3>' -As Table } $allSddcManagerPasswordExpirationObject = Convert-CssClassStyle -htmldata $allSddcManagerPasswordExpirationObject $allSddcManagerPasswordExpirationObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-SddcManagerPasswordExpiration Function Publish-SddcManagerPasswordComplexity { <# .SYNOPSIS Publishes the password complexity policy for an SDDC Manager. .DESCRIPTION The Publish-SddcManagerPasswordComplexity cmdlet returns password complexity policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects password complexity policy for an SDDC Manager. .EXAMPLE Publish-SddcManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -allDomains This example returns password complexity policy for an SDDC Manager. .EXAMPLE Publish-SddcManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -workloadDomain [workload_domain_name] This example will NOT return the password complexity policy for an SDDC Manager as the workload domain provided is not the management domain. .EXAMPLE Publish-SddcManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns the password complexity policy for an SDDC Manager and compares the configuration against the policy configuration file. .EXAMPLE Publish-SddcManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -workloadDomain [workload_domain_name] -drift This example returns the password complexity policy for an SDDC Manager and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER sddcRootPass The password for the SDDC Manager appliance root account. .PARAMETER allDomains Switch to return the policy for all workload domains. .PARAMETER workloadDomain Switch to return the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$sddcRootPass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass $sddcRootPass = Get-Password -username "root" -password $sddcRootPass # Define the Command to be Executed $command = "Request-SddcManagerPasswordComplexity -server $server -user $user -pass $pass -rootPass $sddcRootPass" if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $command = $command + " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $command = $command + " -drift" } } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $sddcManagerPasswordComplexityObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $workloadDomain -and $_.type -eq "MANAGEMENT" }) { $sddcManagerPasswordComplexity = Invoke-Expression $command ; $sddcManagerPasswordComplexityObject += $sddcManagerPasswordComplexity } } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { if ($domain | Where-Object { $_.type -eq "MANAGEMENT" }) { $sddcManagerPasswordComplexity = Invoke-Expression $command ; $sddcManagerPasswordComplexityObject += $sddcManagerPasswordComplexity } } } if ($PsBoundParameters.ContainsKey('json')) { $sddcManagerPasswordComplexityObject | ConvertTo-Json -Depth 10 } else { if ($sddcManagerPasswordComplexityObject.Count -eq 0) { $notManagement = $true } if ($notManagement) { $sddcManagerPasswordComplexityObject = $sddcManagerPasswordComplexityObject | ConvertTo-Html -Fragment -PreContent '<a id="sddcmanager-password-complexity"></a><h3>SDDC Manager - Password Complexity</h3>' -PostContent '<p>Management Domain not requested.</p>' } else { $sddcManagerPasswordComplexityObject = $sddcManagerPasswordComplexityObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent '<a id="sddcmanager-password-complexity"></a><h3>SDDC Manager - Password Complexity</h3>' -As Table } $sddcManagerPasswordComplexityObject = Convert-CssClassStyle -htmldata $sddcManagerPasswordComplexityObject $sddcManagerPasswordComplexityObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-SddcManagerPasswordComplexity Function Publish-SddcManagerAccountLockout { <# .SYNOPSIS Publishes the password complexity policy for an SDDC Manager. .DESCRIPTION The Publish-SddcManagerAccountLockout cmdlet returns account lockout policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects account lockout policy forSDDC Manager. .EXAMPLE Publish-SddcManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -allDomains This example returns account lockout policy for an SDDC Manager. .EXAMPLE Publish-SddcManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -workloadDomain [workload_domain_name] This example will NOT return the account lockout policy for an SDDC Manager as the workload domain provided is not the management domain. .EXAMPLE Publish-SddcManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns the account lockout policy for an SDDC Manager and compares the configuration against the policy configuration file. .EXAMPLE Publish-SddcManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -sddcRootPass [root_password] -workloadDomain [workload_domain_name] -drift This example returns the account lockout policy for an SDDC Manager and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER sddcRootPass The password for the SDDC Manager appliance root account. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$sddcRootPass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass $sddcRootPass = Get-Password -username "root" -password $sddcRootPass # Define the Command to be Executed $command = "Request-SddcManagerAccountLockout -server $server -user $user -pass $pass -rootPass $sddcRootPass" if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $command = $command + " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $command = $command + " -drift" } } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $sddcManagerAccountLockoutObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $workloadDomain -and $_.type -eq "MANAGEMENT" }) { $sddcManagerAccountLockout = Invoke-Expression $command ; $sddcManagerAccountLockoutObject += $sddcManagerAccountLockout } } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { if ($domain | Where-Object { $_.type -eq "MANAGEMENT" }) { $sddcManagerAccountLockout = Invoke-Expression $command ; $sddcManagerAccountLockoutObject += $sddcManagerAccountLockout } } } if ($PsBoundParameters.ContainsKey('json')) { $sddcManagerAccountLockoutObject | ConvertTo-Json -Depth 10 } else { if ($sddcManagerAccountLockoutObject.Count -eq 0) { $notManagement = $true } if ($notManagement) { $sddcManagerAccountLockoutObject = $sddcManagerAccountLockoutObject | ConvertTo-Html -Fragment -PreContent '<a id="sddcmanager-account-lockout"></a><h3>SDDC Manager - Account Lockout</h3>' -PostContent '<p>Management Domain not requested.</p>' } else { $sddcManagerAccountLockoutObject = $sddcManagerAccountLockoutObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent '<a id="sddcmanager-account-lockout"></a><h3>SDDC Manager - Account Lockout</h3>' -As Table } $sddcManagerAccountLockoutObject = Convert-CssClassStyle -htmldata $sddcManagerAccountLockoutObject $sddcManagerAccountLockoutObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-SddcManagerAccountLockout #EndRegion End SDDC Manager Password Management Functions ###### ########################################################################## ########################################################################## #Region Begin SSO Password Management Functions ###### Function Request-SsoPasswordExpiration { <# .SYNOPSIS Retrieves the password expiration policy for a vCenter Single Sign-On domain. .DESCRIPTION The Request-SsoPasswordExpiration cmdlet retrieves the password expiration policy for a vCenter Single Sign-On domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Retrieves the global password expiration policy. .EXAMPLE Request-SsoPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the password expiration policy for the vCenter Single Sign-On domain. .EXAMPLE Request-SsoPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password expiration policy for the vCenter Single Sign-On domain and compares the configuration against the policy configuration file. .EXAMPLE Request-SsoPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the password expiration policy for the vCenter Single Sign-On domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).sso.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).sso.passwordExpiration } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-SsoConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-SsoAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { Try { $certificateValidator = New-Object 'VMware.vSphere.SsoAdmin.Utils.AcceptAllX509CertificateValidator' $securePass = ConvertTo-SecureString $vcfVcenterDetails.ssoAdminPass -AsPlainText -Force $ssoAdminServer = New-Object ` 'VMware.vSphere.SsoAdminClient.DataTypes.SsoAdminServer' ` -ArgumentList @( $vcfVcenterDetails.fqdn, $vcfVcenterDetails.ssoAdmin, $securePass, $certificateValidator) } Catch { Write-Error $_.Exception } if ($SsoPasswordExpiration = Get-SsoPasswordPolicy -server $ssoAdminServer) { $SsoPasswordExpirationObject = New-Object -TypeName PSObject $SsoPasswordExpirationObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $SsoPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($vcfVcenterDetails.fqdn) $SsoPasswordExpirationObject | Add-Member -NotePropertyName "Max Days" -NotePropertyValue $(if ($drift) { if ($SsoPasswordExpiration.PasswordLifetimeDays -ne $requiredConfig.maxDays) { "$($SsoPasswordExpiration.PasswordLifetimeDays) [ $($requiredConfig.maxDays) ]" } else { "$($SsoPasswordExpiration.PasswordLifetimeDays)" } } else { "$($SsoPasswordExpiration.PasswordLifetimeDays)" }) } else { Write-Error "Unable to retrieve password expiration policy from vCenter Single Sign-On ($($vcfVcenterDetails.fqdn)): PRE_VALIDATION_FAILED" } return $SsoPasswordExpirationObject } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($Global:DefaultSsoAdminServers) { Disconnect-SsoAdminServer -Server $Global:DefaultSsoAdminServers } } } Export-ModuleMember -Function Request-SsoPasswordExpiration Function Request-SsoPasswordComplexity { <# .SYNOPSIS Retrieves the password complexity policy for a vCenter Single Sign-On domain. .DESCRIPTION The Request-SsoPasswordComplexity cmdlet retrieves password complexity policy for a vCenter Single Sign-On domain. policy. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that the workload domain exists in the SDDC Manager inventory - Validates that network connectivity and authentication is possible to vCenter Single Sign-On domain - Retrieves the password complexity policy. .EXAMPLE Request-SsoPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the password complexity policy for vCenter Single Sign-On domain of the workload domain. .EXAMPLE Request-SsoPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password complexity policy for vCenter Single Sign-On domain of the workload domain and compares the configuration against the policy configuration file. .EXAMPLE Request-SsoPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the password complexity policy for vCenter Single Sign-On domain of the workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).sso.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).sso.passwordComplexity } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-SsoConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-SsoAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { Try { $certificateValidator = New-Object 'VMware.vSphere.SsoAdmin.Utils.AcceptAllX509CertificateValidator' $securePass = ConvertTo-SecureString $vcfVcenterDetails.ssoAdminPass -AsPlainText -Force $ssoAdminServer = New-Object ` 'VMware.vSphere.SsoAdminClient.DataTypes.SsoAdminServer' ` -ArgumentList @( $vcfVcenterDetails.fqdn, $vcfVcenterDetails.ssoAdmin, $securePass, $certificateValidator) } Catch { Write-Error $_.Exception } if ($SsoPasswordComplexity = Get-SsoPasswordPolicy -server $ssoAdminServer) { $SsoPasswordComplexityObject = New-Object -TypeName PSObject $SsoPasswordComplexityObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $SsoPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($vcfVcenterDetails.fqdn) $SsoPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" -NotePropertyValue $(if ($drift) { if ($SsoPasswordComplexity.MinLength -ne $requiredConfig.minLength) { "$($SsoPasswordComplexity.MinLength) [ $($requiredConfig.minLength) ]" } else { "$($SsoPasswordComplexity.MinLength)" } } else { "$($SsoPasswordComplexity.MinLength)" }) $SsoPasswordComplexityObject | Add-Member -NotePropertyName "Max Length" -NotePropertyValue $(if ($drift) { if ($SsoPasswordComplexity.MaxLength -ne $requiredConfig.maxLength) { "$($SsoPasswordComplexity.MaxLength) [ $($requiredConfig.maxLength) ]" } else { "$($SsoPasswordComplexity.MaxLength)" } } else { "$($SsoPasswordComplexity.MaxLength)" }) $SsoPasswordComplexityObject | Add-Member -NotePropertyName "Min Alphabetic" -NotePropertyValue $(if ($drift) { if ($SsoPasswordComplexity.MinAlphabeticCount -ne $requiredConfig.minAlphabetic) { "$($SsoPasswordComplexity.MinAlphabeticCount) [ $($requiredConfig.minAlphabetic) ]" } else { "$($SsoPasswordComplexity.MinAlphabeticCount)" } } else { "$($SsoPasswordComplexity.MinAlphabeticCount)" }) $SsoPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" -NotePropertyValue $(if ($drift) { if ($SsoPasswordComplexity.MinLowercaseCount -ne $requiredConfig.minLowercase) { "$($SsoPasswordComplexity.MinLowercaseCount) [ $($requiredConfig.minLowercase) ]" } else { "$($SsoPasswordComplexity.MinLowercaseCount)" } } else { "$($SsoPasswordComplexity.MinLowercaseCount)" }) $SsoPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" -NotePropertyValue $(if ($drift) { if ($SsoPasswordComplexity.MinUppercaseCount -ne $requiredConfig.minUppercase) { "$($SsoPasswordComplexity.MinUppercaseCount) [ $($requiredConfig.minUppercase) ]" } else { "$($SsoPasswordComplexity.MinUppercaseCount)" } } else { "$($SsoPasswordComplexity.MinUppercaseCount)" }) $SsoPasswordComplexityObject | Add-Member -NotePropertyName "Min Numeric" -NotePropertyValue $(if ($drift) { if ($SsoPasswordComplexity.MinNumericCount -ne $requiredConfig.minNumerical) { "$($SsoPasswordComplexity.MinNumericCount) [ $($requiredConfig.minNumerical) ]" } else { "$($SsoPasswordComplexity.MinNumericCount)" } } else { "$($SsoPasswordComplexity.MinNumericCount)" }) $SsoPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" -NotePropertyValue $(if ($drift) { if ($SsoPasswordComplexity.MinSpecialCharCount -ne $requiredConfig.minSpecial) { "$($SsoPasswordComplexity.MinSpecialCharCount) [ $($requiredConfig.minSpecial) ]" } else { "$($SsoPasswordComplexity.MinSpecialCharCount)" } } else { "$($SsoPasswordComplexity.MinSpecialCharCount)" }) $SsoPasswordComplexityObject | Add-Member -NotePropertyName "Max Identical Adjacent" -NotePropertyValue $(if ($drift) { if ($SsoPasswordComplexity.MaxIdenticalAdjacentCharacters -ne $requiredConfig.maxIdenticalAdjacent) { "$($SsoPasswordComplexity.MaxIdenticalAdjacentCharacters) [ $($requiredConfig.maxIdenticalAdjacent) ]" } else { "$($SsoPasswordComplexity.MaxIdenticalAdjacentCharacters)" } } else { "$($SsoPasswordComplexity.MaxIdenticalAdjacentCharacters)" }) $SsoPasswordComplexityObject | Add-Member -NotePropertyName "History" -NotePropertyValue $(if ($drift) { if ($SsoPasswordComplexity.ProhibitedPreviousPasswordsCount -ne $requiredConfig.history) { "$($SsoPasswordComplexity.ProhibitedPreviousPasswordsCount) [ $($requiredConfig.history) ]" } else { "$($SsoPasswordComplexity.ProhibitedPreviousPasswordsCount)" } } else { "$($SsoPasswordComplexity.ProhibitedPreviousPasswordsCount)" }) } else { Write-Error "Unable to retrieve password complexity policy from vCenter Single Sign-On ($($vcfVcenterDetails.fqdn)): PRE_VALIDATION_FAILED" } return $SsoPasswordComplexityObject } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($Global:DefaultSsoAdminServers) { Disconnect-SsoAdminServer -Server $Global:DefaultSsoAdminServers } } } Export-ModuleMember -Function Request-SsoPasswordComplexity Function Request-SsoAccountLockout { <# .SYNOPSIS Retrieves the account lockout policy policy for a vCenter Single Sign-On domain. .DESCRIPTION The Request-SsoAccountLockout cmdlet retrieves the vCenter Single Sign-On domain account lockout policy. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that the workload domain exists in the SDDC Manager inventory - Validates that network connectivity and authentication is possible to vCenter Single Sign-On domain - Retrieves the account lockout policy. .EXAMPLE Request-SsoAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the account lockout policy for vCenter Single Sign-On domain of the workload domain. .EXAMPLE Request-SsoAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the account lockout policy for vCenter Single Sign-On domain of the workload domain and compares the configuration against the policy configuration file. .EXAMPLE Request-SsoAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the account lockout policy for vCenter Single Sign-On domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).sso.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).sso.accountLockout } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-SsoConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-SsoAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { Try { $certificateValidator = New-Object 'VMware.vSphere.SsoAdmin.Utils.AcceptAllX509CertificateValidator' $securePass = ConvertTo-SecureString $vcfVcenterDetails.ssoAdminPass -AsPlainText -Force $ssoAdminServer = New-Object ` 'VMware.vSphere.SsoAdminClient.DataTypes.SsoAdminServer' ` -ArgumentList @( $vcfVcenterDetails.fqdn, $vcfVcenterDetails.ssoAdmin, $securePass, $certificateValidator) } Catch { Write-Error $_.Exception } if ($SsoAccountLockout = Get-SsoLockoutPolicy -server $ssoAdminServer) { $SsoAccountLockoutObject = New-Object -TypeName PSObject $SsoAccountLockoutObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $SsoAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($vcfVcenterDetails.fqdn) $SsoAccountLockoutObject | Add-Member -NotePropertyName "Max Failures" -NotePropertyValue $(if ($drift) { if ($SsoAccountLockout.MaxFailedAttempts -ne $requiredConfig.maxFailures) { "$($SsoAccountLockout.MaxFailedAttempts) [ $($requiredConfig.maxFailures) ]" } else { "$($SsoAccountLockout.MaxFailedAttempts)" } } else { "$($SsoAccountLockout.MaxFailedAttempts)" }) $SsoAccountLockoutObject | Add-Member -NotePropertyName "Unlock Interval (sec)" -NotePropertyValue $(if ($drift) { if ($SsoAccountLockout.AutoUnlockIntervalSec -ne $requiredConfig.unlockInterval) { "$($SsoAccountLockout.AutoUnlockIntervalSec) [ $($requiredConfig.unlockInterval) ]" } else { "$($SsoAccountLockout.AutoUnlockIntervalSec)" } } else { "$($SsoAccountLockout.AutoUnlockIntervalSec)" }) $SsoAccountLockoutObject | Add-Member -NotePropertyName "Failed Attempt Interval (sec)" -NotePropertyValue $(if ($drift) { if ($SsoAccountLockout.FailedAttemptIntervalSec -ne $requiredConfig.failedAttemptInterval) { "$($SsoAccountLockout.FailedAttemptIntervalSec) [ $($requiredConfig.failedAttemptInterval) ]" } else { "$($SsoAccountLockout.FailedAttemptIntervalSec)" } } else { "$($SsoAccountLockout.FailedAttemptIntervalSec)" }) } else { Write-Error "Unable to retrieve account lockout policy from vCenter Single Sign-On ($($vcfVcenterDetails.fqdn)): PRE_VALIDATION_FAILED" } return $SsoAccountLockoutObject } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($Global:DefaultSsoAdminServers) { Disconnect-SsoAdminServer -Server $Global:DefaultSsoAdminServers } } } Export-ModuleMember -Function Request-SsoAccountLockout Function Update-SsoPasswordExpiration { <# .SYNOPSIS Updates the password expiration policy for a vCenter Single Sign-On domain. .DESCRIPTION The Update-SsoPasswordExpiration cmdlet configures the password expiration policy for a vCenter Single Sign-On domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the vCenter Single Sign-On password expiration policy. .EXAMPLE Update-SsoPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -maxDays 999 This example configures the password expiration policy for a vCenter Single Sign-On domain. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER maxDays The maximum number of days that a password is valid for. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$maxDays ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-SsoConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-SsoAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { Try { $certificateValidator = New-Object 'VMware.vSphere.SsoAdmin.Utils.AcceptAllX509CertificateValidator' $securePass = ConvertTo-SecureString $vcfVcenterDetails.ssoAdminPass -AsPlainText -Force $ssoAdminServer = New-Object ` 'VMware.vSphere.SsoAdminClient.DataTypes.SsoAdminServer' ` -ArgumentList @( $vcfVcenterDetails.fqdn, $vcfVcenterDetails.ssoAdmin, $securePass, $certificateValidator) } Catch { Write-Error $_.Exception } if ((Get-SsoPasswordPolicy -server $ssoAdminServer).PasswordLifetimeDays -ne $maxDays) { Get-SsoPasswordPolicy -server $ssoAdminServer | Set-SsoPasswordPolicy -PasswordLifetimeDays $maxDays | Out-Null if ((Get-SsoPasswordPolicy -server $ssoAdminServer).PasswordLifetimeDays -eq $maxDays) { Write-Output "Update Single Sign-On Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)): SUCCESSFUL" } else { Write-Error "Update Single Sign-On Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Single Sign-On Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)), already set: SKIPPED" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($Global:DefaultSsoAdminServers) { Disconnect-SsoAdminServer -Server $Global:DefaultSsoAdminServers } } } Export-ModuleMember -Function Update-SsoPasswordExpiration Function Update-SsoPasswordComplexity { <# .SYNOPSIS Updates the password complexity policy for a vCenter Single Sign-On domain. .DESCRIPTION The Update-SsoPasswordComplexity cmdlet configures the password complexity policy of a vCenter Single Sign-On domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the vCenter Single Sign-On password complexity policy. .EXAMPLE Update-SsoPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -minLength 15 -maxLength 20 -minAlphabetic 2 -minLowercase 1 -minUppercase 1 -minNumeric 1 -minSpecial 1 -maxIdenticalAdjacent 1 -history 5 This example configures the password complexity policy for a vCenter Single Sign-On domain. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER minLength The minimum length of the password. .PARAMETER maxLength The maximum length of the password. .PARAMETER minAlphabetic The minimum number of alphabetic characters in the password. .PARAMETER minLowercase The minimum number of lowercase characters in the password. .PARAMETER minUppercase The minimum number of uppercase characters in the password. .PARAMETER minNumeric The minimum number of numeric characters in the password. .PARAMETER minSpecial The minimum number of special characters in the password. .PARAMETER maxIdenticalAdjacent The maximum number of identical adjacent characters in the password. .PARAMETER history The number of previous passwords that a password cannot match. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minLength, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$maxLength, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minAlphabetic, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minLowercase, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minUppercase, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minNumeric, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minSpecial, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$maxIdenticalAdjacent, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$history ) $pass = Get-Password -username $user -password $pass Try { if ($minLength -gt $maxLength) { Write-Error "The value for minLength($minLength) is greater than maxLength($maxLength): PRE_VALIDATION_FAILED" Break } elseif (($minLowercase + $minUppercase) -gt $minAlphabetic) { Write-Error "The sum value of min number of lowercase characters($minLowercase) and min uppercase characters($minUppercase) is greater than total number of min alphabetic characters ($minAlphabetic) allowed: PRE_VALIDATION_FAILED" Break } elseif (($minAlphabetic + $minNumeric + $minSpecial) -gt $minLength) { Write-Error "The sum value of min number of alphabetic characters($minAlphabetic) and min number of numeric characters($minNumeric) and min number of special characters($minSpecial) is greater than total number of min length($minLength): PRE_VALIDATION_FAILED" Break } if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-SsoConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-SsoAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { Try { $certificateValidator = New-Object 'VMware.vSphere.SsoAdmin.Utils.AcceptAllX509CertificateValidator' $securePass = ConvertTo-SecureString $vcfVcenterDetails.ssoAdminPass -AsPlainText -Force $ssoAdminServer = New-Object ` 'VMware.vSphere.SsoAdminClient.DataTypes.SsoAdminServer' ` -ArgumentList @( $vcfVcenterDetails.fqdn, $vcfVcenterDetails.ssoAdmin, $securePass, $certificateValidator) } Catch { Write-Error $_.Exception } $passwordComplexityConfigBefore = Get-SsoPasswordPolicy -server $ssoAdminServer if ($passwordComplexityConfigBefore.MinLength -ne $minLength -or $passwordComplexityConfigBefore.MaxLength -ne $maxLength -or $passwordComplexityConfigBefore.MinAlphabeticCount -ne $minAlphabetic -or $passwordComplexityConfigBefore.MinLowercaseCount -ne $minLowercase -or $passwordComplexityConfigBefore.MinUppercaseCount -ne $minUppercase -or $passwordComplexityConfigBefore.MinNumericCount -ne $minNumeric -or $passwordComplexityConfigBefore.MinSpecialCharCount -ne $minSpecial -or $passwordComplexityConfigBefore.MaxIdenticalAdjacentCharacters -ne $maxIdenticalAdjacent -or $passwordComplexityConfigBefore.ProhibitedPreviousPasswordsCount -ne $history) { Get-SsoPasswordPolicy -server $ssoAdminServer | Set-SsoPasswordPolicy -MinLength $minLength -MaxLength $maxLength -MinAlphabeticCount $minAlphabetic -MinLowercaseCount $minLowercase -MinUppercaseCount $minUppercase -MinNumericCount $minNumeric -MinSpecialCharCount $minSpecial -MaxIdenticalAdjacentCharacters $maxIdenticalAdjacent -ProhibitedPreviousPasswordsCount $history | Out-Null $passwordComplexityConfigAfter = Get-SsoPasswordPolicy -server $ssoAdminServer if ($passwordComplexityConfigAfter.MinLength -eq $minLength -and $passwordComplexityConfigAfter.MaxLength -eq $maxLength -and $passwordComplexityConfigAfter.MinAlphabeticCount -eq $minAlphabetic -and $passwordComplexityConfigAfter.MinLowercaseCount -eq $minLowercase -and $passwordComplexityConfigAfter.MinUppercaseCount -eq $minUppercase -and $passwordComplexityConfigAfter.MinNumericCount -eq $minNumeric -and $passwordComplexityConfigAfter.MinSpecialCharCount -eq $minSpecial -and $passwordComplexityConfigAfter.MaxIdenticalAdjacentCharacters -eq $maxIdenticalAdjacent -and $passwordComplexityConfigAfter.ProhibitedPreviousPasswordsCount -eq $history) { Write-Output "Update Single Sign-On Password Complexity Policy on vCenter ($($vcfVcenterDetails.fqdn)): SUCCESSFUL" } else { Write-Error "Update Single Sign-On Password Complexity Policy on vCenter ($($vcfVcenterDetails.fqdn)): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Single Sign-On Password Complexity Policy on vCenter ($($vcfVcenterDetails.fqdn)), already set: SKIPPED" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($Global:DefaultSsoAdminServers) { Disconnect-SsoAdminServer -Server $Global:DefaultSsoAdminServers } } } Export-ModuleMember -Function Update-SsoPasswordComplexity Function Update-SsoAccountLockout { <# .SYNOPSIS Updates the account lockout policy of a vCenter Single Sign-On domain. .DESCRIPTION The Update-SsoAccountLockout cmdlet configures the account lockout policy of a vCenter Single Sign-On domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the vCenter Single Sign-On account lockout policy. .EXAMPLE Update-SsoAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -failures 5 -failureInterval 180 -unlockInterval 900 This example configures the account lockout policy for a vCenter Single Sign-On domain. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER failures The number of failed login attempts before the account is locked. .PARAMETER failureInterval The number of seconds before the failed login attempts counter is reset. .PARAMETER unlockInterval The number of seconds before a locked account is unlocked. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$failures, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$failureInterval, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$unlockInterval ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-SsoConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-SsoAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { Try { $certificateValidator = New-Object 'VMware.vSphere.SsoAdmin.Utils.AcceptAllX509CertificateValidator' $securePass = ConvertTo-SecureString $vcfVcenterDetails.ssoAdminPass -AsPlainText -Force $ssoAdminServer = New-Object ` 'VMware.vSphere.SsoAdminClient.DataTypes.SsoAdminServer' ` -ArgumentList @( $vcfVcenterDetails.fqdn, $vcfVcenterDetails.ssoAdmin, $securePass, $certificateValidator) } Catch { Write-Error $_.Exception } $lockoutPolicyBefore = Get-SsoLockoutPolicy -server $ssoAdminServer if ($lockoutPolicyBefore.MaxFailedAttempts -ne $failures -or $lockoutPolicyBefore.FailedAttemptIntervalSec -ne $failureInterval -or $lockoutPolicyBefore.AutoUnlockIntervalSec -ne $unlockInterval) { Get-SsoLockoutPolicy -server $ssoAdminServer | Set-SsoLockoutPolicy -AutoUnlockIntervalSec $unlockInterval -FailedAttemptIntervalSec $failureInterval -MaxFailedAttempts $failures | Out-Null $lockoutPolicyAfter = Get-SsoLockoutPolicy -server $ssoAdminServer if ($lockoutPolicyAfter.MaxFailedAttempts -eq $failures -and $lockoutPolicyAfter.FailedAttemptIntervalSec -eq $failureInterval -and $lockoutPolicyAfter.AutoUnlockIntervalSec -eq $unlockInterval) { Write-Output "Update Single Sign-On Account Lockout Policy on vCenter ($($vcfVcenterDetails.fqdn)): SUCCESSFUL" } else { Write-Error "Update Single Sign-On Account Lockout Policy on vCenter ($($vcfVcenterDetails.fqdn)): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Single Sign-On Account Lockout Policy on vCenter ($($vcfVcenterDetails.fqdn)), already set: SKIPPED" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($Global:DefaultSsoAdminServers) { Disconnect-SsoAdminServer -Server $Global:DefaultSsoAdminServers } } } Export-ModuleMember -Function Update-SsoAccountLockout Function Publish-SsoPasswordPolicy { <# .SYNOPSIS Publishes a requested password policy for vCenter Single Sign-On for a workload domain or all workload domains. .DESCRIPTION The Publish-SsoPasswordPolicy cmdlet retrieves the requested password policy for vCenter Single Sign-On and converts the output to HTML. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Retrieves the requested password policy for vCenter Single Sign-On and converts to HTML. .EXAMPLE Publish-SsoPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -allDomains This example returns password expiration policy for vCenter Single Sign-On across all workload domains. .EXAMPLE Publish-SsoPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -workloadDomain [workload_domain_name] This example returns password expiration policy for vCenter Single Sign-On for a workload domain. .EXAMPLE Publish-SsoPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordComplexity -allDomains This example returns password complexity policy for vCenter Single Sign-On across all workload domains. .EXAMPLE Publish-SsoPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordComplexity -workloadDomain [workload_domain_name] This example returns password complexity policy for vCenter Single Sign-On for a workload domain. .EXAMPLE Publish-SsoPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy AccountLockout -allDomains This example returns account lockout policy for vCenter Single Sign-On across all workload domains. .EXAMPLE Publish-SsoPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy AccountLockout -workloadDomain [workload_domain_name] This example returns account lockout policy for vCenter Single Sign-On for a workload domain. .EXAMPLE Publish-SsoPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password expiration policy for vCenter Single Sign-On for a workload domain and compares the configuration against the policy configuration file. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER policy The policy to publish. One of: PasswordExpiration, PasswordComplexity, AccountLockout. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateSet('PasswordExpiration', 'PasswordComplexity', 'AccountLockout')] [String]$policy, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-SsoPasswordExpiration"; $preHtmlContent = '<a id="sso-password-expiration"></a><h3>vCenter Single Sign-On - Password Expiration</h3>' } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-SsoPasswordComplexity"; $preHtmlContent = '<a id="sso-password-complexity"></a><h3>vCenter Single Sign-On - Password Complexity</h3>' } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-SsoAccountLockout"; $preHtmlContent = '<a id="sso-account-lockout"></a><h3>vCenter Single Sign-On - Account Lockout</h3>' } # Define the Command $command = $pvsCmdlet + " -server $server -user $user -pass $pass" if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $ssoPasswordPolicyObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $workloadDomain }) { $command = $command + " -domain " + $workloadDomain + $commandSwitch $ssoPolicy = Invoke-Expression $command ; $ssoPasswordPolicyObject += $ssoPolicy } } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { if ($domain | Where-Object { $_.type -eq "MANAGEMENT" }) { $command = $command + " -domain " + $($domain.name) + $commandSwitch $ssoPolicy = Invoke-Expression $command ; $ssoPasswordPolicyObject += $ssoPolicy } } } if ($PsBoundParameters.ContainsKey('json')) { $ssoPasswordPolicyObject | ConvertTo-Json -Depth 10 } else { if ($ssoPasswordPolicyObject.Count -eq 0) { $notManagement = $true } if ($notManagement) { $ssoPasswordPolicyObject = $ssoPasswordPolicyObject | ConvertTo-Html -Fragment -PreContent $preHtmlContent -PostContent '<p>Management Domain not requested.</p>' } else { $ssoPasswordPolicyObject = $ssoPasswordPolicyObject | Sort-Object 'Workload Domain', 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table } $ssoPasswordPolicyObject = Convert-CssClassStyle -htmldata $ssoPasswordPolicyObject $ssoPasswordPolicyObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-SsoPasswordPolicy #EndRegion End SSO Password Management Functions ###### ########################################################################## ########################################################################## #Region Begin vCenter Password Management Function ###### Function Request-VcenterPasswordExpiration { <# .SYNOPSIS Retrieves the global password expiration policy for a vCenter instance. .DESCRIPTION The Request-VcenterPasswordExpiration cmdlet retrieves the global password expiration policy for a vCenter Server. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Retrieves the global password expiration policy. .EXAMPLE Request-VcenterPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the global password expiration policy for a vCenter instance. .EXAMPLE Request-VcenterPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the global password expiration policy for a vCenter instance and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-VcenterPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the global password expiration policy for a vCenter instance and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).vcenterServer.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).vcenterServer.passwordExpiration } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-vSphereApiConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereApiAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if ($VcenterPasswordExpiration = Get-VcenterPasswordExpiration) { $VcenterPasswordExpirationObject = New-Object -TypeName PSObject $VcenterPasswordExpirationObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $VcenterPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($vcfVcenterDetails.fqdn) $VcenterPasswordExpirationObject | Add-Member -NotePropertyName "Min Days" -NotePropertyValue $(if ($drift) { if ($VcenterPasswordExpiration.min_days -ne $requiredConfig.minDays) { "$($VcenterPasswordExpiration.min_days) [ $($requiredConfig.minDays) ]" } else { "$($VcenterPasswordExpiration.min_days)" } } else { "$($VcenterPasswordExpiration.min_days)" }) $VcenterPasswordExpirationObject | Add-Member -NotePropertyName "Max Days" -NotePropertyValue $(if ($drift) { if ($VcenterPasswordExpiration.max_days -ne $requiredConfig.maxDays) { "$($VcenterPasswordExpiration.max_days) [ $($requiredConfig.maxDays) ]" } else { "$($VcenterPasswordExpiration.max_days)" } } else { "$($VcenterPasswordExpiration.max_days)" }) $VcenterPasswordExpirationObject | Add-Member -NotePropertyName "Warning Days" -NotePropertyValue $(if ($drift) { if ($VcenterPasswordExpiration.warn_days -ne $requiredConfig.warningDays) { "$($VcenterPasswordExpiration.warn_days) [ $($requiredConfig.warningDays) ]" } else { "$($VcenterPasswordExpiration.warn_days)" } } else { "$($VcenterPasswordExpiration.warn_days)" }) } else { Write-Error "Unable to retrieve password expiration policy from vCenter ($($vcfVcenterDetails.fqdn)): PRE_VALIDATION_FAILED" } return $VcenterPasswordExpirationObject } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-VcenterPasswordExpiration Function Request-VcenterPasswordComplexity { <# .SYNOPSIS Retrieves the password complexity policy. .DESCRIPTION The Request-VcenterPasswordComplexity cmdlet retrieves the password complexity policy of a vCenter instance. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Retrieves the password complexity policy. .EXAMPLE Request-VcenterPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the password complexity policy for a vCenter instance based on the workload domain. .EXAMPLE Request-VcenterPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password complexity policy for a vCenter instance based on the workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-VcenterPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the password complexity policy for a vCenter instance based on the workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { $vcenterDomain = $vcfVcenterDetails.type if ($vcenterDomain -ne "MANAGEMENT") { if (Get-VCFWorkloadDomain | Where-Object { $_.type -eq "MANAGEMENT" }) { if (($vcfMgmtVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType "Management")) { if (Test-vSphereConnection -server $($vcfMgmtVcenterDetails.fqdn)) { if (-not (Test-vSphereAuthentication -server $vcfMgmtVcenterDetails.fqdn -user $vcfMgmtVcenterDetails.ssoAdmin -pass $vcfMgmtVcenterDetails.ssoAdminPass)) { return } } } } else { Write-Error "Unable to find Workload Domain typed (MANAGEMENT) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { $vcenterLocalPolicy = Get-LocalPasswordComplexity -version $version -vmName ($vcfVcenterDetails.fqdn.Split("."))[-0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass -product vcenterServerLocal -drift -reportPath $reportPath -policyFile $policyFile $VcenterLocalPasswordComplexityObject = New-Object -TypeName PSObject $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($vcfVcenterDetails.fqdn) $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" -NotePropertyValue $vcenterLocalPolicy.'Min Length' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" -NotePropertyValue $vcenterLocalPolicy.'Min Lowercase' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" -NotePropertyValue $vcenterLocalPolicy.'Min Uppercase' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" -NotePropertyValue $vcenterLocalPolicy.'Min Numerical' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" -NotePropertyValue $vcenterLocalPolicy.'Min Special' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" -NotePropertyValue $vcenterLocalPolicy.'Min Unique' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "History" -NotePropertyValue $vcenterLocalPolicy.'History' if ( $vcenterLocalPolicy.minlen -gt $managedPasswordMinLength ) { $alert = "RED" $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue $minLengthExceeds } else { $alert = "GREEN" $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue $minLengthNotExceeds } $VcenterLocalPasswordComplexityPolicy += $VcenterLocalPasswordComplexityObject } else { $vcenterLocalPolicy = Get-LocalPasswordComplexity -version $version -vmName ($vcfVcenterDetails.fqdn.Split("."))[-0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass -product vcenterServerLocal -drift $VcenterLocalPasswordComplexityObject = New-Object -TypeName PSObject $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($vcfVcenterDetails.fqdn) $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" -NotePropertyValue $vcenterLocalPolicy.'Min Length' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" -NotePropertyValue $vcenterLocalPolicy.'Min Lowercase' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" -NotePropertyValue $vcenterLocalPolicy.'Min Uppercase' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" -NotePropertyValue $vcenterLocalPolicy.'Min Numerical' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" -NotePropertyValue $vcenterLocalPolicy.'Min Special' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" -NotePropertyValue $vcenterLocalPolicy.'Min Unique' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "History" -NotePropertyValue $vcenterLocalPolicy.'History' if ( $vcenterLocalPolicy.minlen -gt $managedPasswordMinLength ) { $alert = "RED" $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue $minLengthExceeds } else { $alert = "GREEN" $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue $minLengthNotExceeds } $VcenterLocalPasswordComplexityPolicy += $VcenterLocalPasswordComplexityObject } } else { $vcenterLocalPolicy = Get-LocalPasswordComplexity -vmName ($vcfVcenterDetails.fqdn.Split("."))[-0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass $VcenterLocalPasswordComplexityObject = New-Object -TypeName PSObject $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($vcfVcenterDetails.fqdn) $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" -NotePropertyValue $vcenterLocalPolicy.'Min Length' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" -NotePropertyValue $vcenterLocalPolicy.'Min Lowercase' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" -NotePropertyValue $vcenterLocalPolicy.'Min Uppercase' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" -NotePropertyValue $vcenterLocalPolicy.'Min Numerical' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" -NotePropertyValue $vcenterLocalPolicy.'Min Special' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" -NotePropertyValue $vcenterLocalPolicy.'Min Unique' $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "History" -NotePropertyValue $vcenterLocalPolicy.'History' if ( $vcenterLocalPolicy.minlen -gt $managedPasswordMinLength ) { $alert = "RED" $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue $minLengthExceeds } else { $alert = "GREEN" $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $VcenterLocalPasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue $minLengthNotExceeds } $VcenterLocalPasswordComplexityPolicy += $VcenterLocalPasswordComplexityObject } } return $VcenterLocalPasswordComplexityPolicy } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-VcenterPasswordComplexity Function Request-VcenterAccountLockout { <# .SYNOPSIS Retrieves the account lockout policy for a vCenter instance based on the workload domain. .DESCRIPTION The Request-VcenterAccountLockout cmdlet retrieves the account lockout policy of a vCenter instance. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Retrieves the account lockout policy. .EXAMPLE Request-VcenterAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the account lockout policy for a vCenter instance based on the workload domain. .EXAMPLE Request-VcenterAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the account lockout policy for a vCenter instance based on the workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-VcenterAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the account lockout policy for a vCenter instance based on the workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($vcenterDomain = Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { # Connect to Management domain if provided domain is VI if ($vcenterDomain.type -ne "MANAGEMENT") { if (($vcfMgmtVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType "MANAGEMENT")) { if (Test-vSphereConnection -server $($vcfMgmtVcenterDetails.fqdn)) { if (-not (Test-vSphereAuthentication -server $vcfMgmtVcenterDetails.fqdn -user $vcfMgmtVcenterDetails.ssoAdmin -pass $vcfMgmtVcenterDetails.ssoAdminPass)) { return } } } } if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { Get-LocalAccountLockout -version $version -vmName ($vcfVcenterDetails.fqdn.Split("."))[-0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass -product vcenterServerLocal -drift -reportPath $reportPath -policyFile $policyFile } else { Get-LocalAccountLockout -version $version -vmName ($vcfVcenterDetails.fqdn.Split("."))[-0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass -product vcenterServerLocal -drift } } else { Get-LocalAccountLockout -vmName ($vcfVcenterDetails.fqdn.Split("."))[-0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass -product vcenterServerLocal } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { #Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-VcenterAccountLockout Function Update-VcenterPasswordExpiration { <# .SYNOPSIS Updates the global password expiration policy. .DESCRIPTION The Update-VcenterPasswordExpiration cmdlet configures the global password expiration policy of a vCenter instance. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the global password expiration policy. .EXAMPLE Update-VcenterPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -maxDays 999 -minDays 0 -warnDays 14 This example configures the global password expiration policy for a vCenter instance .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER maxDays The maximum number of days that a password is valid. .PARAMETER minDays The minimum number of days that a password is valid. .PARAMETER warnDays The number of days before a password expires that a warning is issued. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$maxDays, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minDays, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$warnDays ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-vSphereApiConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereApiAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if ((Get-VcenterPasswordExpiration).max_days -ne $maxDays -or (Get-VcenterPasswordExpiration).min_days -ne $minDays -or (Get-VcenterPasswordExpiration).warn_days -ne $warnDays) { Set-VcenterPasswordExpiration -maxDays $maxDays -minDays $minDays -warnDays $warnDays | Out-Null if ((Get-VcenterPasswordExpiration).max_days -eq $maxDays -and (Get-VcenterPasswordExpiration).min_days -eq $minDays -and (Get-VcenterPasswordExpiration).warn_days -eq $warnDays) { Write-Output "Update Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)): SUCCESSFUL" } else { Write-Error "Update Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)), already set: SKIPPED" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Update-VcenterPasswordExpiration Function Update-VcenterPasswordComplexity { <# .SYNOPSIS Updates the password complexity policy. .DESCRIPTION The Update-VcenterPasswordComplexity cmdlet configures the password complexity policy of a vCenter instance. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the password complexity policy. .EXAMPLE Update-VcenterPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -minLength 6 -minLowercase -1 -minUppercase -1 -minNumerical -1 -minSpecial -1 -minUnique 4 -history 5 This example configures the password complexity policy for a vCenter instance based on the workload domain .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER minLength The minimum length of a password. .PARAMETER minLowercase The minimum number of lowercase characters in a password. .PARAMETER minUppercase The minimum number of uppercase characters in a password. .PARAMETER minNumerical The minimum number of numerical characters in a password. .PARAMETER minSpecial The minimum number of special characters in a password. .PARAMETER minUnique The minimum number of unique characters in a password. .PARAMETER history The number of previous passwords that a password cannot match. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minLength, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minLowercase, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minUppercase, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minNumerical, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minSpecial, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minUnique, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$history ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { $vcenterDomain = $vcfVcenterDetails.type if ($vcenterDomain -ne "MANAGEMENT") { if (Get-VCFWorkloadDomain | Where-Object { $_.type -eq "MANAGEMENT" }) { if (($vcfMgmtVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType "Management")) { if (Test-vSphereConnection -server $($vcfMgmtVcenterDetails.fqdn)) { if (-not (Test-vSphereAuthentication -server $vcfMgmtVcenterDetails.fqdn -user $vcfMgmtVcenterDetails.ssoAdmin -pass $vcfMgmtVcenterDetails.ssoAdminPass)) { return } } } } else { Write-Error "Unable to find Workload Domain typed (MANAGEMENT) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { $existingConfiguration = Get-LocalPasswordComplexity -vmName ($vcfVcenterDetails.fqdn.Split("."))[-0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass if ($existingConfiguration.'Min Length' -ne $minLength -or $existingConfiguration.'Min Lowercase' -ne $minLowercase -or $existingConfiguration.'Min Uppercase' -ne $minUppercase -or $existingConfiguration.'Min Numerical' -ne $minNumerical -or $existingConfiguration.'Min Special' -ne $minSpecial -or $existingConfiguration.'Min Unique' -ne $minUnique -or $existingConfiguration.'History' -ne $history) { Set-LocalPasswordComplexity -vmName ($vcfVcenterDetails.fqdn.Split("."))[-0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass -minLength $minLength -uppercase $minUppercase -lowercase $minLowercase -numerical $minNumerical -special $minSpecial -unique $minUnique -history $history | Out-Null $updatedConfiguration = Get-LocalPasswordComplexity -vmName ($vcfVcenterDetails.fqdn.Split("."))[-0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass if ($updatedConfiguration.'Min Length' -eq $minLength -and $updatedConfiguration.'Min Lowercase' -eq $minLowercase -and $updatedConfiguration.'Min Uppercase' -eq $minUppercase -and $updatedConfiguration.'Min Numerical' -eq $minNumerical -and $updatedConfiguration.'Min Special' -eq $minSpecial -and $updatedConfiguration.'Min Unique' -eq $minUnique -and $updatedConfiguration.'History' -eq $history) { Write-Output "Update Password Complexity Policy on vCenter ($($vcfVcenterDetails.fqdn)): SUCCESSFUL" } else { Write-Error "Update Password Complexity Policy on vCenter ($($vcfVcenterDetails.fqdn)): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Password Complexity Policy on vCenter ($($vcfVcenterDetails.fqdn)), already set: SKIPPED" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-VcenterPasswordComplexity Function Update-VcenterAccountLockout { <# .SYNOPSIS Updates the account lockout policy of vCenter. .DESCRIPTION The Update-VcenterAccountLockout cmdlet configures the account lockout policy of a vCenter instance. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the account lockout policy. .EXAMPLE Update-VcenterAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -failures 3 -unlockInterval 900 -rootUnlockInterval 300 This example configures the account lockout policy for a vCenter instance based on the workload domain .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER failures The number of failed login attempts before the account is locked. .PARAMETER unlockInterval The number of seconds before a locked out account is unlocked. .PARAMETER rootUnlockInterval The number of seconds before a locked out root account is unlocked. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$failures, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$unlockInterval, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$rootUnlockInterval ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($vcenterDomain = Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if ($vcenterDomain.type -ne "MANAGEMENT") { if (($vcfMgmtVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType "Management")) { if (Test-vSphereConnection -server $($vcfMgmtVcenterDetails.fqdn)) { if (-not (Test-vSphereAuthentication -server $vcfMgmtVcenterDetails.fqdn -user $vcfMgmtVcenterDetails.ssoAdmin -pass $vcfMgmtVcenterDetails.ssoAdminPass)) { return } } } } if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { $existingConfiguration = Get-LocalAccountLockout -vmName ($vcfVcenterDetails.fqdn.Split("."))[0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass -product vcenterServerLocal if ($existingConfiguration.'Max Failures' -ne $failures -or $existingConfiguration.'Unlock Interval (sec)' -ne $unlockInterval -or $existingConfiguration.'Root Unlock Interval (sec)' -ne $rootUnlockInterval) { Set-LocalAccountLockout -vmName ($vcfVcenterDetails.fqdn.Split("."))[-0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass -failures $failures -unlockInterval $unlockInterval -rootUnlockInterval $rootUnlockInterval | Out-Null $updatedConfiguration = Get-LocalAccountLockout -vmName ($vcfVcenterDetails.fqdn.Split("."))[0] -guestUser $vcfVcenterDetails.root -guestPassword $vcfVcenterDetails.rootPass -product vcenterServerLocal if ($updatedConfiguration.'Max Failures' -eq $failures -and $updatedConfiguration.'Unlock Interval (sec)' -eq $unlockInterval -and $updatedConfiguration.'Root Unlock Interval (sec)' -eq $rootUnlockInterval) { Write-Output "Update Account Lockout Policy on vCenter ($($vcfVcenterDetails.fqdn)): SUCCESSFUL" } else { Write-Error "Update Account Lockout Policy on vCenter ($($vcfVcenterDetails.fqdn)): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Account Lockout Policy on vCenter ($($vcfVcenterDetails.fqdn)), already set: SKIPPED" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-VcenterAccountLockout Function Request-VcenterRootPasswordExpiration { <# .SYNOPSIS Retrieves the root user password expiration policy. .DESCRIPTION The Request-VcenterRootPasswordExpiration cmdlet retrieves the root user password expiration policy for a vCenter. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Retrieves the root user password expiration policy. .EXAMPLE Request-VcenterRootPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the root user password expiration policy for a vCenter instance. .EXAMPLE Request-VcenterRootPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the root user password expiration policy for a vCenter instance and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-VcenterRootPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the root user password expiration policy for a vCenter instance and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).vcenterServerLocal.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).vcenterServerLocal.passwordExpiration } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-vSphereApiConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereApiAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if ($VcenterRootPasswordExpiration = Get-VcenterRootPasswordExpiration) { $VcenterRootPasswordExpirationObject = New-Object -TypeName PSObject $VcenterRootPasswordExpirationObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $VcenterRootPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($vcfVcenterDetails.fqdn) $VcenterRootPasswordExpirationObject | Add-Member -NotePropertyName "User" -NotePropertyValue "root" $VcenterRootPasswordExpirationObject | Add-Member -NotePropertyName "Min Days" -NotePropertyValue $(if ($drift) { if ($VcenterRootPasswordExpiration.min_days_between_password_change -ne $requiredConfig.minDays) { "$($VcenterRootPasswordExpiration.min_days_between_password_change) [ $($requiredConfig.minDays) ]" } else { "$($VcenterRootPasswordExpiration.min_days_between_password_change)" } } else { "$($VcenterRootPasswordExpiration.min_days_between_password_change)" }) $VcenterRootPasswordExpirationObject | Add-Member -NotePropertyName "Max Days" -NotePropertyValue $(if ($drift) { if ($VcenterRootPasswordExpiration.max_days_between_password_change -ne $requiredConfig.maxDays) { "$($VcenterRootPasswordExpiration.max_days_between_password_change) [ $($requiredConfig.maxDays) ]" } else { "$($VcenterRootPasswordExpiration.max_days_between_password_change)" } } else { "$($VcenterRootPasswordExpiration.max_days_between_password_change)" }) $VcenterRootPasswordExpirationObject | Add-Member -NotePropertyName "Warning Days" -NotePropertyValue $(if ($drift) { if ($VcenterRootPasswordExpiration.warn_days_before_password_expiration -ne $requiredConfig.warningDays) { "$($VcenterRootPasswordExpiration.warn_days_before_password_expiration) [ $($requiredConfig.warningDays) ]" } else { "$($VcenterRootPasswordExpiration.warn_days_before_password_expiration)" } } else { "$($VcenterRootPasswordExpiration.warn_days_before_password_expiration)" }) $VcenterRootPasswordExpirationObject | Add-Member -NotePropertyName "Email" -NotePropertyValue $(if ($drift) { if ($VcenterRootPasswordExpiration.email -ne $requiredConfig.email) { "$($VcenterRootPasswordExpiration.email) [ $($requiredConfig.email) ]" } else { "$($VcenterRootPasswordExpiration.email)" } } else { "$($VcenterRootPasswordExpiration.email)" }) } else { Write-Error "Unable to retrieve root password expiration policy from vCenter ($($vcfVcenterDetails.fqdn)): PRE_VALIDATION_FAILED" } return $VcenterRootPasswordExpirationObject } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-VcenterRootPasswordExpiration Function Update-VcenterRootPasswordExpiration { <# .SYNOPSIS Updates the root user password expiration policy. .DESCRIPTION The Update-VcenterRootPasswordExpiration cmdlet configures the root user password expiration policy of a vCenter. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the root user password expiration policy. .EXAMPLE Update-VcenterRootPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -email [email_address] -maxDays 999 -warnDays 14 This example configures the configures password expiration settings for a vCenter instance root account to expire after 999 days with email for warning set. .EXAMPLE Update-VcenterRootPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -neverexpire This example configures the configures password expiration settings for a vCenter instance root account to never expire .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER email The email address to send password expiration warnings to. .PARAMETER maxDays The maximum number of days before the root user password expires. .PARAMETER warnDays The number of days before the root user password expires in which to send a warning email. .PARAMETER neverexpire Switch to configure the root user password to never expire. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'expire')] [String]$email, [Parameter (Mandatory = $false, ParameterSetName = 'expire')] [ValidateNotNullOrEmpty()] [String]$maxDays, [Parameter (Mandatory = $false, ParameterSetName = 'expire')] [ValidateNotNullOrEmpty()] [String]$warnDays, [Parameter (Mandatory = $false, ParameterSetName = 'neverexpire')] [ValidateNotNullOrEmpty()] [Switch]$neverexpire ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-vSphereApiConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereApiAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if ($PsBoundParameters.ContainsKey("neverexpire")) { if ((Get-VcenterRootPasswordExpiration).max_days_between_password_change -ne -1) { Set-VcenterRootPasswordExpiration -neverexpire | Out-Null if ((Get-VcenterRootPasswordExpiration).max_days_between_password_change -ne -1) { Write-Output "Update Root Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)): SUCCESSFUL" } else { Write-Error "Update Root Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Root Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)), already set: SKIPPED" } } else { $vCenterRootPasswordExpirationSettings = Get-VcenterRootPasswordExpiration $runUpdate = $true $updateCommand = "Set-VcenterRootPasswordExpiration" if ($maxDays) { $updateCommand = $updateCommand + " -maxDays $maxDays" if (($vCenterRootPasswordExpirationSettings).max_days_between_password_change -ne $maxDays) { $runUpdate = $runUpdate -and $true } else { $runUpdate = $runUpdate -and $false } } if ($warnDays) { $updateCommand = $updateCommand + " -warnDays $warnDays" if (($vCenterRootPasswordExpirationSettings).warn_days_before_password_expiration -ne $warnDays) { $runUpdate = $runUpdate -and $true } else { $runUpdate = $runUpdate -and $false } } if ($email) { $updateCommand = $updateCommand + " -email $email" if (($vCenterRootPasswordExpirationSettings).email -ne $email) { $runUpdate = $runUpdate -and $true } else { $runUpdate = $runUpdate -and $false } } if ($runUpdate) { $condition = $true Invoke-Expression $updateCommand | Out-Null $vCenterRootPasswordExpirationSettings = Get-VcenterRootPasswordExpiration if ($maxDays) { $condition = $condition -and ($vCenterRootPasswordExpirationSettings).max_days_between_password_change -eq $maxDays } if ($warnDays) { $condition = $condition -and ($vCenterRootPasswordExpirationSettings).warn_days_before_password_expiration -eq $warnDays } if ($email) { $condition = $condition -and ($vCenterRootPasswordExpirationSettings).email -eq $email } if ($condition) { Write-Output "Update Root Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)): SUCCESSFUL" } else { Write-Error "Update Root Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Root Password Expiration Policy on vCenter ($($vcfVcenterDetails.fqdn)), already set: SKIPPED" } } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Update-VcenterRootPasswordExpiration Function Publish-VcenterPasswordExpiration { <# .SYNOPSIS Publishes the password expiration policy for vCenter for a workload domain or all workload domains. .DESCRIPTION The Publish-VcenterPasswordExpiration cmdlet returns password expiration policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects password expiration policy for vCenter. .EXAMPLE Publish-VcenterPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example returns password expiration policy for each vCenter. .EXAMPLE Publish-VcenterPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password expiration policy for a vCenter and checks the configuration drift using the provided configuration JSON. .EXAMPLE Publish-VcenterPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift This example returns password expiration policy for a vCenter and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Define the Command $GLobal:command = "Request-VcenterPasswordExpiration -server $server -user $user -pass $pass" if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $vcenterPasswordExpirationObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { $command = "Request-VcenterPasswordExpiration -server $server -user $user -pass $pass -domain $workloadDomain" + $commandSwitch $vcenterPasswordExpiration = Invoke-Expression $command ; $vcenterPasswordExpirationObject += $vcenterPasswordExpiration } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { $command = "Request-VcenterPasswordExpiration -server $server -user $user -pass $pass -domain $($domain.name)" + $commandSwitch $vcenterPasswordExpiration = Invoke-Expression $command ; $vcenterPasswordExpirationObject += $vcenterPasswordExpiration } } if ($PsBoundParameters.ContainsKey('json')) { $vcenterPasswordExpirationObject | ConvertTo-Json -Depth 10 } else { $vcenterPasswordExpirationObject = $vcenterPasswordExpirationObject | Sort-Object 'Workload Domain', 'System', 'User' | ConvertTo-Html -Fragment -PreContent '<a id="vcenter-password-expiration"></a><h3>vCenter - Password Expiration</h3>' -As Table $vcenterPasswordExpirationObject = Convert-CssClassStyle -htmldata $vcenterPasswordExpirationObject $vcenterPasswordExpirationObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-VcenterPasswordExpiration Function Publish-VcenterLocalPasswordExpiration { <# .SYNOPSIS Publishes the password expiration policy for each local user of vCenter for a workload domain or all workload domains. .DESCRIPTION The Publish-VcenterLocalPasswordExpiration cmdlet returns password expiration policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects password expiration policy for each local user of vCenter. .EXAMPLE Publish-VcenterLocalPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example returns password expiration policy for each local user of vCenter for all workload domains. .EXAMPLE Publish-VcenterLocalPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password expiration policy for each local user of vCenter and checks the configuration drift using the provided configuration JSON. .EXAMPLE Publish-VcenterLocalPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift This example returns password expiration policy for each local user of vCenter and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $vcenterLocalPasswordExpirationObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { $command = "Request-VcenterRootPasswordExpiration -server $server -user $user -pass $pass -domain $workloadDomain" + $commandSwitch $vcenterLocalPasswordExpiration = Invoke-Expression $command ; $vcenterLocalPasswordExpirationObject += $vcenterLocalPasswordExpiration } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { $command = "Request-VcenterRootPasswordExpiration -server $server -user $user -pass $pass -domain $($domain.name)" + $commandSwitch $vcenterLocalPasswordExpiration = Invoke-Expression $command ; $vcenterLocalPasswordExpirationObject += $vcenterLocalPasswordExpiration } } if ($PsBoundParameters.ContainsKey('json')) { $vcenterLocalPasswordExpirationObject | ConvertTo-Json -Depth 10 } else { $vcenterLocalPasswordExpirationObject = $vcenterLocalPasswordExpirationObject | Sort-Object 'Workload Domain', 'System', 'User' | ConvertTo-Html -Fragment -PreContent '<a id="vcenter-password-expiration-local"></a><h3>vCenter - Password Expiration</h3>' -As Table $vcenterLocalPasswordExpirationObject = Convert-CssClassStyle -htmldata $vcenterLocalPasswordExpirationObject $vcenterLocalPasswordExpirationObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-VcenterLocalPasswordExpiration Function Publish-VcenterLocalPasswordComplexity { <# .SYNOPSIS Publishes the password complexity policy for each vCenter instance for a workload domain or all workload domains. .DESCRIPTION The Publish-VcenterLocalPasswordComplexity cmdlet returns password complexity policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects password complexity policy for each vCenter. .EXAMPLE Publish-VcenterLocalPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example returns password complexity policy for each vCenter for all workload domains. .EXAMPLE Publish-VcenterLocalPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] This example returns password complexity policy for a vCenter. .EXAMPLE Publish-VcenterLocalPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password complexity policy for a vCenter and checks the configuration drift using the provided configuration JSON. .EXAMPLE Publish-VcenterLocalPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift This example returns password complexity policy for a vCenter and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $vcenterLocalPasswordComplexityObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { $command = "Request-VcenterPasswordComplexity -server $server -user $user -pass $pass -domain $workloadDomain" + $commandSwitch $vcenterLocalPasswordComplexity = Invoke-Expression $command ; $vcenterLocalPasswordComplexityObject += $vcenterLocalPasswordComplexity } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { $command = "Request-VcenterPasswordComplexity -server $server -user $user -pass $pass -domain $($domain.name)" + $commandSwitch $vcenterLocalPasswordComplexity = Invoke-Expression $command ; $vcenterLocalPasswordComplexityObject += $vcenterLocalPasswordComplexity } } if ($PsBoundParameters.ContainsKey('json')) { $vcenterLocalPasswordComplexityObject | ConvertTo-Json -Depth 10 } else { $vcenterLocalPasswordComplexityObject = $vcenterLocalPasswordComplexityObject | Sort-Object 'Workload Domain', 'System' | ConvertTo-Html -Fragment -PreContent '<a id="vcenter-password-complexity-local"></a><h3>vCenter - Password Complexity</h3>' -As Table $vcenterLocalPasswordComplexityObject = Convert-CssClassStyle -htmldata $vcenterLocalPasswordComplexityObject $vcenterLocalPasswordComplexityObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-VcenterLocalPasswordComplexity Function Publish-VcenterLocalAccountLockout { <# .SYNOPSIS Publish account lockout policy for each vCenter instance for a workload domain or all workload domains. .DESCRIPTION The Publish-VcenterLocalAccountLockout cmdlet returns account lockout policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects password account lockout for each vCenter. .EXAMPLE Publish-VcenterLocalAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example returns password account lockout for each vCenter for all workload domains. .EXAMPLE Publish-VcenterLocalAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] This example returns password account lockout for a vCenter. .EXAMPLE Publish-VcenterLocalAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password account lockout for a vCenter and checks the configuration drift using the provided configuration JSON. .EXAMPLE Publish-VcenterLocalAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift This example returns password account lockout for a vCenter and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift " } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $vcenterLocalAccountLockoutObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { $command = "Request-VcenterAccountLockout -server $server -user $user -pass $pass -domain $workloadDomain" + $commandSwitch $vcenterLocalAccountLockout = Invoke-Expression $command ; $vcenterLocalAccountLockoutObject += $vcenterLocalAccountLockout } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { $command = "Request-VcenterAccountLockout -server $server -user $user -pass $pass -domain $($domain.name)" + $commandSwitch $vcenterLocalAccountLockout = Invoke-Expression $command ; $vcenterLocalAccountLockoutObject += $vcenterLocalAccountLockout } } if ($PsBoundParameters.ContainsKey('json')) { $vcenterLocalAccountLockoutObject | ConvertTo-Json -Depth 10 } else { $vcenterLocalAccountLockoutObject = $vcenterLocalAccountLockoutObject | Sort-Object 'Workload Domain', 'System' | ConvertTo-Html -Fragment -PreContent '<a id="vcenter-account-lockout-local"></a><h3>vCenter - Account Lockout</h3>' -As Table $vcenterLocalAccountLockoutObject = Convert-CssClassStyle -htmldata $vcenterLocalAccountLockoutObject $vcenterLocalAccountLockoutObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-VcenterLocalAccountLockout #EndRegion End vCenter Password Management Functions ###### ########################################################################## ########################################################################## #Region Begin NSX Manager Password Management Function ###### Function Request-NsxtManagerPasswordExpiration { <# .SYNOPSIS Retrieves the password expiration policy for NSX Local Manager. .DESCRIPTION The Request-NsxtManagerPasswordExpiration cmdlet retrieves the password complexity policy for all NSX Local Manager cluster users for a workload domain. The cmdlet connects to th SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager. - Retrieves the password expiration policy for all users. .EXAMPLE Request-NsxtManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the password expiration policy for all users for the NSX Local Manager cluster for a workload domain. .EXAMPLE Request-NsxtManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password expiration policy for all users for the NSX Local Manager cluster for a workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-NsxtManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the password expiration policy for all users for the NSX Local Manager cluster for a workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).nsxManager.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).nsxManager.passwordExpiration } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { if (Test-NSXTConnection -server $($vcfNsxDetails.fqdn)) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { $nsxtPasswordExpirationPolicy = New-Object System.Collections.ArrayList $localUsers = Get-NsxtApplianceUser foreach ($localUser in $localUsers) { $localUserPasswordExpirationPolicy = New-Object -TypeName PSObject $localUserPasswordExpirationPolicy | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $localUserPasswordExpirationPolicy | Add-Member -NotePropertyName "System" -NotePropertyValue $($vcfNsxDetails.fqdn) $localUserPasswordExpirationPolicy | Add-Member -NotePropertyName "User" -NotePropertyValue $($localUser.username) $localUserPasswordExpirationPolicy | Add-Member -NotePropertyName "Max Days" -NotePropertyValue $(if ($drift) { if ($localUser.password_change_frequency -ne $requiredConfig.maxDays) { "$($localUser.password_change_frequency) [ $($requiredConfig.maxDays) ]" } else { "$($localUser.password_change_frequency)" } } else { "$($localUser.password_change_frequency)" }) $nsxtPasswordExpirationPolicy += $localUserPasswordExpirationPolicy } Return $nsxtPasswordExpirationPolicy } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-NsxtManagerPasswordExpiration Function Request-NsxtManagerPasswordComplexity { <# .SYNOPSIS Retrieves the password complexity policy for NSX Local Manager. .DESCRIPTION The Request-NsxtManagerPasswordComplexity cmdlet retrieves the password complexity policy for each NSX Local Manager node for a workload domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager. - Retrieves the password complexity policy. .EXAMPLE Request-NsxtManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the password complexity policy for each NSX Local Manager node for a workload domain. .EXAMPLE Request-NsxtManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password complexity policy for each NSX Local Manager node for a workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-NsxtManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the password complexity policy for each NSX Local Manager node for a workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $version = Get-VCFManager -version if ($drift) { if ($PsBoundParameters.ContainsKey('policyFile')) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).nsxManager.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).nsxManager.passwordComplexity } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { $vcenterDomain = $vcfVcenterDetails.type if ($vcenterDomain -ne "MANAGEMENT") { if (Get-VCFWorkloadDomain | Where-Object { $_.type -eq "MANAGEMENT" }) { if (($vcfMgmtVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType "Management")) { if (Test-vSphereConnection -server $($vcfMgmtVcenterDetails.fqdn)) { if (-not (Test-vSphereAuthentication -server $vcfMgmtVcenterDetails.fqdn -user $vcfMgmtVcenterDetails.ssoAdmin -pass $vcfMgmtVcenterDetails.ssoAdminPass)) { return } } } } else { Write-Error "Unable to find Workload Domain typed (MANAGEMENT) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { $nsxtPasswordComplexityPolicy = New-Object System.Collections.ArrayList foreach ($nsxtManagerNode in $vcfNsxDetails.nodes) { if (Test-NSXTConnection -server $nsxtManagerNode.fqdn) { if (Test-NSXTAuthentication -server $nsxtManagerNode.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { if ($version -lt "5.0") { if ($nsxtManagerNodePolicy = Get-LocalPasswordComplexity -vmName ($nsxtManagerNode.fqdn.Split("."))[-0] -guestUser $vcfNsxDetails.rootUser -guestPassword $vcfNsxDetails.rootPass -nsx ) { $NsxtManagerPasswordComplexityObject = New-Object -TypeName PSObject $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($nsxtManagerNode.fqdn) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.'Min Length' -ne $requiredConfig.minLength) { "$($nsxtManagerNodePolicy.'Min Length') [ $($requiredConfig.minLength) ]" } else { "$($nsxtManagerNodePolicy.'Min Length')" } } else { "$($nsxtManagerNodePolicy.'Min Length')" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.'Min Lowercase' -ne $requiredConfig.minLowercase) { "$($nsxtManagerNodePolicy.'Min Lowercase') [ $($requiredConfig.minLowercase) ]" } else { "$($nsxtManagerNodePolicy.'Min Lowercase')" } } else { "$($nsxtManagerNodePolicy.'Min Lowercase')" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.'Min Uppercase' -ne $requiredConfig.minUppercase) { "$($nsxtManagerNodePolicy.'Min Uppercase') [ $($requiredConfig.minUppercase) ]" } else { "$($nsxtManagerNodePolicy.'Min Uppercase')" } } else { "$($nsxtManagerNodePolicy.'Min Uppercase')" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.'Min Numerical' -ne $requiredConfig.minNumerical) { "$($nsxtManagerNodePolicy.'Min Numerical') [ $($requiredConfig.minNumerical) ]" } else { "$($nsxtManagerNodePolicy.'Min Numerical')" } } else { "$($nsxtManagerNodePolicy.'Min Numerical')" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.'Min Special' -ne $requiredConfig.minSpecial) { "$($nsxtManagerNodePolicy.'Min Special') [ $($requiredConfig.minSpecial) ]" } else { "$($nsxtManagerNodePolicy.'Min Special')" } } else { "$($nsxtManagerNodePolicy.'Min Special')" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.'Min Unique' -ne $requiredConfig.minUnique) { "$($nsxtManagerNodePolicy.'Min Unique') [ $($requiredConfig.minUnique) ]" } else { "$($nsxtManagerNodePolicy.'Min Unique')" } } else { "$($nsxtManagerNodePolicy.'Min Unique')" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Max Retries" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.'Max Retries' -ne $requiredConfig.retries) { "$($nsxtManagerNodePolicy.'Max Retries') [ $($requiredConfig.retries) ]" } else { "$($nsxtManagerNodePolicy.'Max Retries')" } } else { "$($nsxtManagerNodePolicy.'Max Retries')" }) if ( $nsxtManagerNodePolicy.minimum_password_length -gt $managedPasswordMinLength ) { $alert = "RED" $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue $minLengthExceeds } else { $alert = "GREEN" $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue $minLengthNotExceeds } $nsxtPasswordComplexityPolicy += $NsxtManagerPasswordComplexityObject } else { Write-Error "Unable to retrieve Password Complexity Policy from NSX Local Manager node ($($nsxtManagerNode.fqdn)): PRE_VALIDATION_FAILED" } } else { if ($nsxtManagerNodePolicy = Get-NsxtManagerAuthPolicy -nsxtManagerNode $nsxtManagerNode.fqdn) { $NsxtManagerPasswordComplexityObject = New-Object -TypeName PSObject $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($nsxtManagerNode.fqdn) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.minimum_password_length -ne $requiredConfig.minLength) { "$($nsxtManagerNodePolicy.minimum_password_length) [ $($requiredConfig.minLength) ]" } else { "$($nsxtManagerNodePolicy.minimum_password_length)" } } else { "$($nsxtManagerNodePolicy.minimum_password_length)" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Max Length" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.maximum_password_length -ne $requiredConfig.maxLength) { "$($nsxtManagerNodePolicy.maximum_password_length) [ $($requiredConfig.maxLength) ]" } else { "$($nsxtManagerNodePolicy.maximum_password_length)" } } else { "$($nsxtManagerNodePolicy.maximum_password_length)" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.lower_chars -ne $requiredConfig.minLowercase) { "$($nsxtManagerNodePolicy.lower_chars) [ $($requiredConfig.minLowercase) ]" } else { "$($nsxtManagerNodePolicy.lower_chars)" } } else { "$($nsxtManagerNodePolicy.lower_chars)" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.upper_chars -ne $requiredConfig.minUppercase) { "$($nsxtManagerNodePolicy.upper_chars) [ $($requiredConfig.minUppercase) ]" } else { "$($nsxtManagerNodePolicy.upper_chars)" } } else { "$($nsxtManagerNodePolicy.upper_chars)" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.digits -ne $requiredConfig.minNumerical) { "$($nsxtManagerNodePolicy.digits) [ $($requiredConfig.minNumerical) ]" } else { "$($nsxtManagerNodePolicy.digits)" } } else { "$($nsxtManagerNodePolicy.digits)" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.special_chars -ne $requiredConfig.minSpecial) { "$($nsxtManagerNodePolicy.special_chars) [ $($requiredConfig.minSpecial) ]" } else { "$($nsxtManagerNodePolicy.special_chars)" } } else { "$($nsxtManagerNodePolicy.special_chars)" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.minimum_unique_chars -ne $requiredConfig.minUnique) { "$($nsxtManagerNodePolicy.minimum_unique_chars) [ $($requiredConfig.minUnique) ]" } else { "$($nsxtManagerNodePolicy.minimum_unique_chars)" } } else { "$($nsxtManagerNodePolicy.minimum_unique_chars)" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Max Repeats" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.max_repeats -ne $requiredConfig.maxRepeat) { "$($nsxtManagerNodePolicy.max_repeats) [ $($requiredConfig.maxRepeat) ]" } else { "$($nsxtManagerNodePolicy.max_repeats)" } } else { "$($nsxtManagerNodePolicy.max_repeats)" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Max Sequence" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.max_sequence -ne $requiredConfig.maxSequence) { "$($nsxtManagerNodePolicy.max_sequence) [ $($requiredConfig.maxSequence) ]" } else { "$($nsxtManagerNodePolicy.max_sequence)" } } else { "$($nsxtManagerNodePolicy.max_sequence)" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "History" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.password_remembrance -ne $requiredConfig.passwordRemembrance) { "$($nsxtManagerNodePolicy.password_remembrance) [ $($requiredConfig.passwordRemembrance) ]" } else { "$($nsxtManagerNodePolicy.password_remembrance)" } } else { "$($nsxtManagerNodePolicy.password_remembrance)" }) $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Hash Algorithm" -NotePropertyValue $(if ($drift) { if ($nsxtManagerNodePolicy.hash_algorithm -ne $requiredConfig.hashAlgorithm) { "$($nsxtManagerNodePolicy.hash_algorithm) [ $($requiredConfig.hashAlgorithm) ]" } else { "$($nsxtManagerNodePolicy.hash_algorithm)" } } else { "$($nsxtManagerNodePolicy.hash_algorithm)" }) if ( $nsxtManagerNodePolicy.minimum_password_length -gt $managedPasswordMinLength ) { $alert = "RED" $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue $minLengthExceeds } else { $alert = "GREEN" $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $NsxtManagerPasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue $minLengthNotExceeds } $nsxtPasswordComplexityPolicy += $NsxtManagerPasswordComplexityObject } else { Write-Error "Unable to retrieve Account Lockout Policy from NSX Local Manager node ($($nsxtManagerNode.fqdn)): PRE_VALIDATION_FAILED" } } } } } return $nsxtPasswordComplexityPolicy } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-NsxtManagerPasswordComplexity Function Request-NsxtManagerAccountLockout { <# .SYNOPSIS Retrieves the account lockout policy for NSX Local Manager. .DESCRIPTION The Request-NsxtManagerAccountLockout cmdlet retrieves the account lockout policy for each NSX Local Manager node for a workload domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager - Retrieves the account lockout policy. .EXAMPLE Request-NsxtManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the account lockout policy for the NSX Local Manager nodes in the workload domain. .EXAMPLE Request-NsxtManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the account lockout policy for the NSX Local Manager nodes in the workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-NsxtManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the account lockout policy for the NSX Local Manager nodes in the workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).nsxManager.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).nsxManager.accountLockout } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { $nsxtAccountLockoutPolicy = New-Object System.Collections.ArrayList foreach ($nsxtManagerNode in $vcfNsxDetails.nodes) { if (Test-NSXTConnection -server $nsxtManagerNode.fqdn) { if (Test-NSXTAuthentication -server $nsxtManagerNode.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { if ($NsxtManagerAccountLockout = Get-NsxtManagerAuthPolicy -nsxtManagerNode $nsxtManagerNode.fqdn) { $NsxtManagerAccountLockoutObject = New-Object -TypeName PSObject $NsxtManagerAccountLockoutObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $NsxtManagerAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $($nsxtManagerNode.fqdn) $NsxtManagerAccountLockoutObject | Add-Member -NotePropertyName "CLI Max Failures" -NotePropertyValue $(if ($drift) { if ($NsxtManagerAccountLockout.cli_max_auth_failures -ne $requiredConfig.cliMaxFailures) { "$($NsxtManagerAccountLockout.cli_max_auth_failures) [ $($requiredConfig.cliMaxFailures) ]" } else { "$($NsxtManagerAccountLockout.cli_max_auth_failures)" } } else { "$($NsxtManagerAccountLockout.cli_max_auth_failures)" }) $NsxtManagerAccountLockoutObject | Add-Member -NotePropertyName "CLI Unlock Interval (sec)" -NotePropertyValue $(if ($drift) { if ($NsxtManagerAccountLockout.cli_failed_auth_lockout_period -ne $requiredConfig.cliUnlockInterval) { "$($NsxtManagerAccountLockout.cli_failed_auth_lockout_period) [ $($requiredConfig.cliUnlockInterval) ]" } else { "$($NsxtManagerAccountLockout.cli_failed_auth_lockout_period)" } } else { "$($NsxtManagerAccountLockout.cli_failed_auth_lockout_period)" }) $NsxtManagerAccountLockoutObject | Add-Member -NotePropertyName "API Max Failures" -NotePropertyValue $(if ($drift) { if ($NsxtManagerAccountLockout.api_max_auth_failures -ne $requiredConfig.apiMaxFailures) { "$($NsxtManagerAccountLockout.api_max_auth_failures) [ $($requiredConfig.apiMaxFailures) ]" } else { "$($NsxtManagerAccountLockout.api_max_auth_failures)" } } else { "$($NsxtManagerAccountLockout.api_max_auth_failures)" }) $NsxtManagerAccountLockoutObject | Add-Member -NotePropertyName "API Unlock Interval (sec)" -NotePropertyValue $(if ($drift) { if ($NsxtManagerAccountLockout.api_failed_auth_lockout_period -ne $requiredConfig.apiUnlockInterval) { "$($NsxtManagerAccountLockout.api_failed_auth_lockout_period) [ $($requiredConfig.apiUnlockInterval) ]" } else { "$($NsxtManagerAccountLockout.api_failed_auth_lockout_period)" } } else { "$($NsxtManagerAccountLockout.api_failed_auth_lockout_period)" }) $NsxtManagerAccountLockoutObject | Add-Member -NotePropertyName "API Reset Interval (sec)" -NotePropertyValue $(if ($drift) { if ($NsxtManagerAccountLockout.api_failed_auth_reset_period -ne $requiredConfig.apiRestInterval) { "$($NsxtManagerAccountLockout.api_failed_auth_reset_period) [ $($requiredConfig.apiRestInterval) ]" } else { "$($NsxtManagerAccountLockout.api_failed_auth_reset_period)" } } else { "$($NsxtManagerAccountLockout.api_failed_auth_reset_period)" }) $nsxtAccountLockoutPolicy += $NsxtManagerAccountLockoutObject } else { Write-Error "Unable to retrieve Account Lockout Policy from NSX Local Manager node ($($nsxtManagerNode.fqdn)): PRE_VALIDATION_FAILED" } } } } return $nsxtAccountLockoutPolicy } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-NsxtManagerAccountLockout Function Update-NsxtManagerPasswordExpiration { <# .SYNOPSIS Updates the password expiration policy for NSX Local Manager. .DESCRIPTION The Update-NsxtManagerPasswordExpiration cmdlet configures the password expiration policy for NSX Local Manager local users for a workload domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager - Updates the password expiration policy. .EXAMPLE Update-NsxtManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -maxdays 999 This example configures the password expiration policy in NSX Local Manager for all local users in the workload domain .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER maxdays The maximum number of days that a password is valid for. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateRange(0, 9999)] [Int]$maxDays, [Parameter (Mandatory = $false)] [ValidateSet("true", "false")] [String]$detail = "true" ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { if (Test-NSXTConnection -server $($vcfNsxDetails.fqdn)) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { $localUsers = Get-NsxtApplianceUser foreach ($localUser in $localUsers) { if ($localUser.password_change_frequency -ne $maxDays) { Set-NsxtApplianceUserExpirationPolicy -userId $localUser.userid -maxDays $maxDays | Out-Null $updatedConfiguration = Get-NsxtApplianceUser | Where-Object { $_.userid -eq $localUser.userid } if (($updatedConfiguration).password_change_frequency -eq $maxDays ) { if ($detail -eq "true") { Write-Output "Update Password Expiration Policy on NSX Local Manager ($($vcfNsxDetails.fqdn)) for Local User ($($localUser.username)): SUCCESSFUL" } } else { Write-Error "Update Password Expiration Policy on NSX Local Manager ($($vcfNsxDetails.fqdn)) for Local User ($($localUser.username)): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Password Expiration Policy on NSX Local Manager ($($vcfNsxDetails.fqdn)) for Local User ($($localUser.username)):, already set: SKIPPED" } } } if ($detail -eq "false") { Write-Output "Update Password Expiration Policy for all NSX Local Manager Local Users in Workload Domain ($domain): SUCCESSFUL" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Update-NsxtManagerPasswordExpiration Function Update-NsxtManagerPasswordComplexity { <# .SYNOPSIS Updates the password complexity policy for NSX Local Manager. .DESCRIPTION The Update-NsxtManagerPasswordComplexity cmdlet updates the password complexity policy for each NSX Local Manager node for a workload domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager. - Updates the password complexity policy. .EXAMPLE Update-NsxtManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -minLength 15 -minLowercase -1 -minUppercase -1 -minNumerical -1 -minSpecial -1 -minUnique 4 -maxRetry 3 This example updates the password complexity policy for each NSX Local Manager node for a workload domain .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER minLength The minimum length of a password. .PARAMETER maxLength The maximum length of a password. .PARAMETER minLowercase The minimum number of lowercase characters in a password. .PARAMETER minUppercase The minimum number of uppercase characters in a password. .PARAMETER minNumerical The minimum number of numerical characters in a password. .PARAMETER minSpecial The minimum number of special characters in a password. .PARAMETER minUnique The minimum number of unique characters in a password. .PARAMETER maxRetry The maximum number of retries for a password. .PARAMETER maxRepeats The maximum number of times a single character may be repeated in a password. .PARAMETER maxSequence The maximum number of monotonic sequence in a password. .PARAMETER history The maximum number of passwords the system remembers. .PARAMETER hash_algorithm The hash/cryptographic algorithm type for new passwords. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minLength, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$maxLength, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minLowercase, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minUppercase, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minNumerical, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minSpecial, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minUnique, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$maxRetry, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$history, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$maxRepeats, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$maxSequence, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$hash_algorithm, [Parameter (Mandatory = $false)] [ValidateSet("true", "false")] [String]$detail = "true" ) $pass = Get-Password -username $user -password $pass Try { $chkVersion = $false $error_presence = $false if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType "MANAGEMENT")) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { $chkVersion = ((Get-VCFManager).version -gt "5.0") -and ((Get-VCFNsxtcluster | Where-Object { $_.vipFqdn -eq $vcfNsxDetails.fqdn }).version -gt "4.0") foreach ($nsxtManagerNode in $vcfNsxDetails.nodes) { if (Test-NSXTConnection -server $nsxtManagerNode.fqdn) { if (Test-NSXTAuthentication -server $nsxtManagerNode.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { if ($chkVersion) { $existingConfiguration = Get-NsxtManagerAuthPolicy -nsxtManagerNode $nsxtManagerNode.fqdn if (!$PsBoundParameters.ContainsKey("minLength")) { $minLength = [int]$existingConfiguration.minimum_password_length } if (!$PsBoundParameters.ContainsKey("maxLength")) { $maxLength = [int]$existingConfiguration.maximum_password_length } if (!$PsBoundParameters.ContainsKey("minNumerical")) { $minNumerical = [int]$existingConfiguration.digits } if (!$PsBoundParameters.ContainsKey("minLowercase")) { $minLowercase = [int]$existingConfiguration.lower_chars } if (!$PsBoundParameters.ContainsKey("minUppercase")) { $minUppercase = [int]$existingConfiguration.upper_chars } if (!$PsBoundParameters.ContainsKey("minSpecial")) { $minSpecial = [int]$existingConfiguration.special_chars } if (!$PsBoundParameters.ContainsKey("history")) { $history = [int]$existingConfiguration.password_remembrance } if (!$PsBoundParameters.ContainsKey("minUnique")) { $minUnique = [int]$existingConfiguration.minimum_unique_chars } if (!$PsBoundParameters.ContainsKey("maxRepeats")) { $maxRepeats = [int]$existingConfiguration.max_repeats } if (!$PsBoundParameters.ContainsKey("maxSequence")) { $maxSequence = [int]$existingConfiguration.max_sequence } if (!$PsBoundParameters.ContainsKey("hash_algorithm")) { $hash_algorithm = $existingConfiguration.hash_algorithm } if ($PsBoundParameters.ContainsKey("maxRetry")) { Write-Warning "'maxRetry' on NSX Local Manager ($($nsxtManagerNode.fqdn)) for Workload Domain ($domain) is not configurable for VCF5.0" } if (($existingConfiguration).hash_algorithm -ne $hash_algorithm -or ($existingConfiguration).minimum_password_length -ne $minLength -or ($existingConfiguration).maximum_password_length -ne $maxLength -or ($existingConfiguration).digits -ne $minNumerical -or ($existingConfiguration).lower_chars -ne $minLowercase -or ($existingConfiguration).upper_chars -ne $minUppercase -or ($existingConfiguration).special_chars -ne $minSpecial -or ($existingConfiguration).max_repeats -ne $maxRepeats -or ($existingConfiguration).max_sequence -ne $maxSequence -or ($existingConfiguration).minimum_unique_chars -ne $minUnique -or ($existingConfiguration).password_remembrance -ne $history) { Set-NsxtManagerAuthPolicy -nsxtManagerNode $nsxtManagerNode.fqdn -hash_algorithm $hash_algorithm -min_passwd_length $minLength -maximum_password_length $maxLength -digits $minNumerical -lower_chars $minLowercase -upper_chars $minUppercase -special_chars $minSpecial -max_repeats $maxRepeats -max_sequence $maxSequence -minimum_unique_chars $minUnique -password_remembrance $history | Out-Null $updatedConfiguration = Get-NsxtManagerAuthPolicy -nsxtManagerNode $nsxtManagerNode.fqdn if (($updatedConfiguration).hash_algorithm -eq $hash_algorithm -and ($updatedConfiguration).minimum_password_length -eq $minLength -and ($updatedConfiguration).maximum_password_length -eq $maxLength -and ($updatedConfiguration).digits -eq $minNumerical -and ($updatedConfiguration).lower_chars -eq $minLowercase -and ($updatedConfiguration).upper_chars -eq $minUppercase -and ($updatedConfiguration).special_chars -eq $minSpecial -and ($updatedConfiguration).max_repeats -eq $maxRepeats -and ($updatedConfiguration).max_sequence -eq $maxSequence -and ($updatedConfiguration).minimum_unique_chars -eq $minUnique -and ($updatedConfiguration).password_remembrance -eq $history) { if ($detail -eq "true") { Write-Output "Update Password Complexity Policy on NSX Local Manager ($($nsxtManagerNode.fqdn)) for Workload Domain ($domain): SUCCESSFUL" } } else { $error_presence = $true Write-Error "Update Password Complexity Policy on NSX Local Manager ($($nsxtManagerNode.fqdn)) for Workload Domain ($domain): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Password Complexity Policy on NSX Local Manager ($($nsxtManagerNode.fqdn)) for Workload Domain ($domain):, already set: SKIPPED" } } } else { if ($PsBoundParameters.ContainsKey("maxSequence") -or $PsBoundParameters.ContainsKey("maxRepeats") -or $PsBoundParameters.ContainsKey("history") -or $PsBoundParameters.ContainsKey("maxLength")) { Write-Warning "Update for 'maxSequence' or 'maxRepeats' or 'history' or 'maxLength' parameters on NSX Local Manager ($($nsxtManagerNode.fqdn)) for Workload Domain ($domain) is not supported. Requires VMware Cloud Foundation 5.0 or later: SKIPPING" } $existingConfiguration = Get-LocalPasswordComplexity -vmName ($nsxtManagerNode.fqdn.Split("."))[-0] -guestUser $vcfNsxDetails.rootUser -guestPassword $vcfNsxDetails.rootPass -nsx if ($existingConfiguration.'Min Length' -ne $minLength -or $existingConfiguration.'Min Lowercase' -ne $minLowercase -or $existingConfiguration.'Min Uppercase' -ne $minUppercase -or $existingConfiguration.'Min Numerical' -ne $minNumerical -or $existingConfiguration.'Min Special' -ne $minSpecial -or $existingConfiguration.'Min Unique' -ne $minUnique -or $existingConfiguration.'Max Retries' -ne $maxRetry) { Set-LocalPasswordComplexity -vmName ($nsxtManagerNode.fqdn.Split("."))[-0] -guestUser $vcfNsxDetails.rootUser -guestPassword $vcfNsxDetails.rootPass -nsx -minLength $minLength -uppercase $minUppercase -lowercase $minLowercase -numerical $minNumerical -special $minSpecial -unique $minUnique -retry $maxRetry | Out-Null $updatedConfiguration = Get-LocalPasswordComplexity -vmName ($nsxtManagerNode.fqdn.Split("."))[-0] -guestUser $vcfNsxDetails.rootUser -guestPassword $vcfNsxDetails.rootPass -nsx if ($updatedConfiguration.'Min Length' -eq $minLength -and $updatedConfiguration.'Min Lowercase' -eq $minLowercase -and $updatedConfiguration.'Min Uppercase' -eq $minUppercase -and $updatedConfiguration.'Min Numerical' -eq $minNumerical -and $updatedConfiguration.'Min Special' -eq $minSpecial -and $updatedConfiguration.'Min Unique' -eq $minUnique -and $updatedConfiguration.'Max Retries' -eq $maxRetry) { if ($detail -eq "true") { Write-Output "Update Password Complexity Policy on NSX Local Manager Node ($($nsxtManagerNode.fqdn)): SUCCESSFUL" } } else { $error_presence = $true Write-Error "Update Password Complexity Policy on NSX Local Manager Node ($($nsxtManagerNode.fqdn)): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Password Complexity Policy on NSX Local Manager Node ($($nsxtManagerNode.fqdn)), already set: SKIPPED" } } } } } } if (($detail -eq "true") -and ($error_presence -eq $false)) { Write-Output "Update Password Complexity Policy for all NSX Local Manager Nodes in Workload Domain ($domain): SUCCESSFUL" } } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-NsxtManagerPasswordComplexity Function Update-NsxtManagerAccountLockout { <# .SYNOPSIS Updates the account lockout policy for NSX Local Manager. .DESCRIPTION The Update-NsxtManagerAccountLockout cmdlet configures the account lockout policy for NSX Local Manager nodes within a workload domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager - Configure the account lockout policy. .EXAMPLE Update-NsxtManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cliFailures 5 -cliUnlockInterval 900 -apiFailures 5 -apiFailureInterval 120 -apiUnlockInterval 900 This example configures the account lockout policy in NSX Local Manager nodes in the workload domain .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER cliFailures The number of failed login attempts before the account is locked out for the CLI. .PARAMETER cliUnlockInterval The number of seconds before the account is unlocked for the CLI. .PARAMETER apiFailures The number of failed login attempts before the account is locked out for the API. .PARAMETER apiFailureInterval The number of seconds before the account is unlocked for the API. .PARAMETER apiUnlockInterval The number of seconds before the account is unlocked for the API. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false)] [ValidateRange(1, [int]::MaxValue)] [int]$cliFailures, [Parameter (Mandatory = $false)] [ValidateRange(1, [int]::MaxValue)] [int]$cliUnlockInterval, [Parameter (Mandatory = $false)] [ValidateRange(1, [int]::MaxValue)] [int]$apiFailures, [Parameter (Mandatory = $false)] [ValidateRange(1, [int]::MaxValue)] [int]$apiFailureInterval, [Parameter (Mandatory = $false)] [ValidateRange(1, [int]::MaxValue)] [int]$apiUnlockInterval, [Parameter (Mandatory = $false)] [ValidateSet("true", "false")] [String]$detail = "true" ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { if (Test-NSXTConnection -server $vcfNsxDetails.fqdn) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { foreach ($nsxtManagerNode in $vcfNsxDetails.nodes) { if (Test-NSXTAuthentication -server $nsxtManagerNode.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.AdminPass) { $existingConfiguration = Get-NsxtManagerAuthPolicy -nsxtManagerNode $nsxtManagerNode.fqdn if (($existingConfiguration).cli_max_auth_failures -ne $cliFailures -or ($existingConfiguration).cli_failed_auth_lockout_period -ne $cliUnlockInterval -or ($existingConfiguration).api_max_auth_failures -ne $apiFailures -or ($existingConfiguration).api_failed_auth_reset_period -ne $apiFailureInterval -or ($existingConfiguration).api_failed_auth_lockout_period -ne $apiUnlockInterval ) { if (!$PsBoundParameters.ContainsKey("cliFailures")) { $cliFailures = [int]$existingConfiguration.cli_max_auth_failures } if (!$PsBoundParameters.ContainsKey("cliUnlockInterval")) { $cliUnlockInterval = [int]$existingConfiguration.cli_failed_auth_lockout_period } if (!$PsBoundParameters.ContainsKey("apiFailures")) { $apiFailures = [int]$existingConfiguration.api_max_auth_failures } if (!$PsBoundParameters.ContainsKey("apiFailureInterval")) { $apiFailureInterval = [int]$existingConfiguration.api_failed_auth_reset_period } if (!$PsBoundParameters.ContainsKey("apiUnlockInterval")) { $apiUnlockInterval = [int]$existingConfiguration.api_failed_auth_lockout_period } Set-NsxtManagerAuthPolicy -nsxtManagerNode $nsxtManagerNode.fqdn -cli_max_attempt $cliFailures -cli_lockout_period $cliUnlockInterval -api_max_attempt $apiFailures -api_reset_period $apiFailureInterval -api_lockout_period $apiUnlockInterval | Out-Null $updatedConfiguration = Get-NsxtManagerAuthPolicy -nsxtManagerNode $nsxtManagerNode.fqdn if (($updatedConfiguration).cli_max_auth_failures -eq $cliFailures -and ($updatedConfiguration).cli_failed_auth_lockout_period -eq $cliUnlockInterval -and ($updatedConfiguration).api_max_auth_failures -eq $apiFailures -and ($updatedConfiguration).api_failed_auth_reset_period -eq $apiFailureInterval -and ($updatedConfiguration).api_failed_auth_lockout_period -eq $apiUnlockInterval ) { if ($detail -eq "true") { Write-Output "Update Account Lockout Policy on NSX Local Manager ($($nsxtManagerNode.fqdn)) for Workload Domain ($domain): SUCCESSFUL" } } else { Write-Error "Update Account Lockout Policy on NSX Local Manager ($($nsxtManagerNode.fqdn)) for Workload Domain ($domain): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Account Lockout Policy on NSX Local Manager ($($nsxtManagerNode.fqdn)) for Workload Domain ($domain):, already set: SKIPPED" } } } } if ($detail -eq "false") { Write-Output "Update Account Lockout Policy for all NSX Local Manager Nodes in Workload Domain ($domain): SUCCESSFUL" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Update-NsxtManagerAccountLockout Function Publish-NsxManagerPasswordExpiration { <# .SYNOPSIS Publishes the password expiration policy for NSX Local Manager for a workload domain or all workload domains. .DESCRIPTION The Publish-NsxManagerPasswordExpiration cmdlet returns password expiration policy for local users of NSX Local Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects password expiration policy for each local user of NSX Local Manager. .EXAMPLE Publish-NsxManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example returns password expiration policy for each local user of NSX Local Manager for all workload domains. .EXAMPLE Publish-NsxManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] This example returns password expiration policy for each local user of NSX Local Manager for a workload domain. .EXAMPLE Publish-NsxManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password expiration policy for each local user of NSX Local Manager for a workload domain and compares the configuration against the policy configuration file. .EXAMPLE Publish-NsxManagerPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift This example returns password expiration policy for each local user of NSX Local Manager for a workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $nsxManagerPasswordExpirationObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { if (Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $workloadDomain -listNodes) { $command = "Request-NsxtManagerPasswordExpiration -server $server -user $user -pass $pass -domain $workloadDomain$commandSwitch" $nsxPasswordExpiration = Invoke-Expression $command $nsxManagerPasswordExpirationObject += $nsxPasswordExpiration } } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { if (Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain.name -listNodes) { $command = "Request-NsxtManagerPasswordExpiration -server $server -user $user -pass $pass -domain $($domain.name)" + $commandSwitch $nsxPasswordExpiration = Invoke-Expression $command ; $nsxManagerPasswordExpirationObject += $nsxPasswordExpiration } } } if ($PsBoundParameters.ContainsKey('json')) { $nsxManagerPasswordExpirationObject | ConvertTo-Json -Depth 10 } else { $nsxManagerPasswordExpirationObject = $nsxManagerPasswordExpirationObject | Sort-Object 'Workload Domain', 'System', 'User' | ConvertTo-Html -Fragment -PreContent '<a id="nsxmanager-password-expiration"></a><h3>NSX Manager - Password Expiration</h3>' -As Table $nsxManagerPasswordExpirationObject = Convert-CssClassStyle -htmldata $nsxManagerPasswordExpirationObject $nsxManagerPasswordExpirationObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-NsxManagerPasswordExpiration Function Publish-NsxManagerPasswordComplexity { <# .SYNOPSIS Publishes the password complexity policy for NSX Local Manager for a workload domain or all workload domains. .DESCRIPTION The Publish-NsxManagerPasswordComplexity cmdlet returns password complexity policy for local users of NSX Local Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects password complexity policy for each NSX Local Manager. .EXAMPLE Publish-NsxManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example returns password complexity policy for each NSX Local Manager for all workload domains. .EXAMPLE Publish-NsxManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] This example returns password complexity policy for each NSX Local Manager for a workload domain. .EXAMPLE Publish-NsxManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password complexity policy of NSX Local Manager for a workload domain and compares the configuration against the policy configuration file. .EXAMPLE Publish-NsxManagerPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains -drift This example returns password complexity policy of NSX Local Manager for a workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $nsxManagerPasswordComplexityObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { $command = "Request-NsxtManagerPasswordComplexity -server $server -user $user -pass $pass -domain $workloadDomain" + $commandSwitch $nsxPasswordComplexity = Invoke-Expression $command ; $nsxManagerPasswordComplexityObject += $nsxPasswordComplexity } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { $command = "Request-NsxtManagerPasswordComplexity -server $server -user $user -pass $pass -domain $($domain.name)" + $commandSwitch $nsxPasswordComplexity = Invoke-Expression $command ; $nsxManagerPasswordComplexityObject += $nsxPasswordComplexity } } if ($PsBoundParameters.ContainsKey('json')) { $nsxManagerPasswordComplexityObject | ConvertTo-Json -Depth 10 } else { $nsxManagerPasswordComplexityObject = $nsxManagerPasswordComplexityObject | Sort-Object 'Workload Domain', 'System' | ConvertTo-Html -Fragment -PreContent '<a id="nsxmanager-password-complexity"></a><h3>NSX Manager - Password Complexity</h3>' -As Table $nsxManagerPasswordComplexityObject = Convert-CssClassStyle -htmldata $nsxManagerPasswordComplexityObject $nsxManagerPasswordComplexityObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-NsxManagerPasswordComplexity Function Publish-NsxManagerAccountLockout { <# .SYNOPSIS Publish account lockout policy for NSX Local Manager for a workload domain or all workload domains. .DESCRIPTION The Publish-NsxManagerAccountLockout cmdlet returns account lockout policy for local users of NSX Local Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects account lockout policy for each NSX Local Manager. .EXAMPLE Publish-NsxManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example returns account lockout policy for each NSX Local Manager for all workload domains. .EXAMPLE Publish-NsxManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] This example returns account lockout policy for each NSX Local Manager for a workload domain. .EXAMPLE Publish-NsxManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns account lockout policy for each NSX Local Manager for a workload domain and compares the configuration against the policy configuration file. .EXAMPLE Publish-NsxManagerAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift This example returns account lockout policy for each NSX Local Manager for a workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $nsxManagerAccountLockoutObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { $command = "Request-NsxtManagerAccountLockout -server $server -user $user -pass $pass -domain $workloadDomain" + $commandSwitch $nsxAccountLockout = Invoke-Expression $command ; $nsxManagerAccountLockoutObject += $nsxAccountLockout } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { $command = "Request-NsxtManagerAccountLockout -server $server -user $user -pass $pass -domain $($domain.name)" + $commandSwitch $nsxAccountLockout = Invoke-Expression $command ; $nsxManagerAccountLockoutObject += $nsxAccountLockout } } if ($PsBoundParameters.ContainsKey('json')) { $nsxManagerAccountLockoutObject | ConvertTo-Json -Depth 10 } else { $nsxManagerAccountLockoutObject = $nsxManagerAccountLockoutObject | Sort-Object 'Workload Domain', 'System' | ConvertTo-Html -Fragment -PreContent '<a id="nsxmanager-account-lockout"></a><h3>NSX Manager - Account Lockout</h3>' -As Table $nsxManagerAccountLockoutObject = Convert-CssClassStyle -htmldata $nsxManagerAccountLockoutObject $nsxManagerAccountLockoutObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-NsxManagerAccountLockout #EndRegion End NSX Manager Password Management Functions ###### ########################################################################## ########################################################################## #Region Begin NSX Edge Password Management Function ###### Function Request-NsxtEdgePasswordExpiration { <# .SYNOPSIS Retrieves the password expiration policy for NSX Edge node users. .DESCRIPTION The Request-NsxtEdgePasswordExpiration cmdlet retrieves the password complexity policy for all NSX Edge node users for a workload domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager. - Retrieves the password expiration policy for all users. .EXAMPLE Request-NsxtEdgePasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the password expiration policy for all users for the NSX Edge nodes for a workload domain. .EXAMPLE Request-NsxtEdgePasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password expiration policy for all users for the NSX Edge nodes for a workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-NsxtEdgePasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieves the password expiration policy for all users for the NSX Edge nodes for a workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).nsxManager.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).nsxManager.passwordExpiration } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { if (Test-NSXTConnection -server $($vcfNsxDetails.fqdn)) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { $allNsxEdgePasswordExpirationPolicy = New-Object System.Collections.ArrayList $nsxtEdgeNodes = (Get-NsxtEdgeCluster | Where-Object { $_.member_node_type -eq "EDGE_NODE" }) foreach ($nsxtEdgeNode in $nsxtEdgeNodes.members) { $localUsers = Get-NsxtApplianceUser -transportNodeId $nsxtEdgeNode.transport_node_id foreach ($localUser in $localUsers) { $nsxEdgePasswordExpirationPolicy = New-Object -TypeName PSObject $nsxEdgePasswordExpirationPolicy | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $nsxEdgePasswordExpirationPolicy | Add-Member -NotePropertyName "System" -NotePropertyValue $nsxtEdgeNode.display_name $nsxEdgePasswordExpirationPolicy | Add-Member -NotePropertyName "User" -NotePropertyValue $($localUser.username) $nsxEdgePasswordExpirationPolicy | Add-Member -NotePropertyName "Max Days" -NotePropertyValue $(if ($drift) { if ($localUser.password_change_frequency -ne $requiredConfig.maxDays) { "$($localUser.password_change_frequency) [ $($requiredConfig.maxDays) ]" } else { "$($localUser.password_change_frequency)" } } else { "$($localUser.password_change_frequency)" }) $allNsxEdgePasswordExpirationPolicy += $nsxEdgePasswordExpirationPolicy } } Return $allNsxEdgePasswordExpirationPolicy } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-NsxtEdgePasswordExpiration Function Request-NsxtEdgePasswordComplexity { <# .SYNOPSIS Retrieves the password complexity policy for NSX Edge nodes.=. .DESCRIPTION The Request-NsxtEdgePasswordComplexity cmdlet retrieves the password complexity policy for each NSX Edge node for a workload domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager. - Retrieves the password complexity policy. .EXAMPLE Request-NsxtEdgePasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the password complexity policy for each NSX Edge node for a workload domain. .EXAMPLE Request-NsxtEdgePasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password complexity policy for each NSX Edge node for a workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-NsxtEdgePasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the password complexity policy for each NSX Edge node for a workload domain and compares the configuration against the product defaults. .EXAMPLE Request-NsxtEdgePasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -unmanagedEdgeNode [vm_name] -unmanagedEdgeNodePass [admin_password] This example retrieves the password complexity policy for an NSX Edge node that is not managed by SDDC Manager. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER unmanagedEdgeNode The name of the unmanaged NSX Edge node. .PARAMETER unmanagedEdgeNodePass The password for the unmanaged NSX Edge node. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$unmanagedEdgeNode, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$unmanagedEdgeNodePass ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).nsxEdge.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).nsxEdge.passwordComplexity } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { if (Test-NSXTConnection -server $vcfNsxDetails.fqdn) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { $nsxtPasswordComplexityPolicy = New-Object System.Collections.ArrayList $nsxtEdgeNodes = (Get-NsxtEdgeCluster | Where-Object { $_.member_node_type -eq "EDGE_NODE" }) if (!($PsBoundParameters.ContainsKey("unmanagedEdgeNode"))) { foreach ($nsxtEdgeNode in $nsxtEdgeNodes.members) { $nsxEdgeRootPass = (Get-VCFCredential | Where-Object { $_.resource.resourceName -eq ($nsxtEdgeNode.display_name + '.' + $vcfNsxDetails.fqdn.Split('.', 2)[-1]) -and $_.username -eq "root" }).password if ($nsxtEdgeNodePolicy = Get-LocalPasswordComplexity -vmName $($nsxtEdgeNode.display_name) -guestUser root -guestPassword $nsxEdgeRootPass -nsx ) { $NsxtEdgePasswordComplexityObject = New-Object -TypeName PSObject $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $nsxtEdgeNode.display_name $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Length" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Length' -ne $requiredConfig.minLength) { "$($nsxtEdgeNodePolicy.'Min Length') [ $($requiredConfig.minLength) ]" } else { "$($nsxtEdgeNodePolicy.'Min Length')" } } else { "$($nsxtEdgeNodePolicy.'Min Length')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Lowercase' -ne $requiredConfig.minLowercase) { "$($nsxtEdgeNodePolicy.'Min Lowercase') [ $($requiredConfig.minLowercase) ]" } else { "$($nsxtEdgeNodePolicy.'Min Lowercase')" } } else { "$($nsxtEdgeNodePolicy.'Min Lowercase')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Uppercase' -ne $requiredConfig.minUppercase) { "$($nsxtEdgeNodePolicy.'Min Uppercase') [ $($requiredConfig.minUppercase) ]" } else { "$($nsxtEdgeNodePolicy.'Min Uppercase')" } } else { "$($nsxtEdgeNodePolicy.'Min Uppercase')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Numerical' -ne $requiredConfig.minNumerical) { "$($nsxtEdgeNodePolicy.'Min Numerical') [ $($requiredConfig.minNumerical) ]" } else { "$($nsxtEdgeNodePolicy.'Min Numerical')" } } else { "$($nsxtEdgeNodePolicy.'Min Numerical')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Special" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Special' -ne $requiredConfig.minSpecial) { "$($nsxtEdgeNodePolicy.'Min Special') [ $($requiredConfig.minSpecial) ]" } else { "$($nsxtEdgeNodePolicy.'Min Special')" } } else { "$($nsxtEdgeNodePolicy.'Min Special')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Unique' -ne $requiredConfig.minUnique) { "$($nsxtEdgeNodePolicy.'Min Unique') [ $($requiredConfig.minUnique) ]" } else { "$($nsxtEdgeNodePolicy.'Min Unique')" } } else { "$($nsxtEdgeNodePolicy.'Min Unique')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Max Retries" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Max Retries' -ne $requiredConfig.retries) { "$($nsxtEdgeNodePolicy.'Max Retries') [ $($requiredConfig.retries) ]" } else { "$($nsxtEdgeNodePolicy.'Max Retries')" } } else { "$($nsxtEdgeNodePolicy.'Max Retries')" }) if ( $nsxtEdgeNodePolicy.'Min Length' -gt $managedPasswordMinLength ) { $alert = "RED" $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue ${minLengthExceeds} } else { $alert = "GREEN" $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue ${minLengthNotExceeds} } $nsxtPasswordComplexityPolicy += $NsxtEdgePasswordComplexityObject } else { Write-Error "Unable to retrieve Password Complexity Policy from NSX Edge node ($($nsxtEdgeNode.display_name)): PRE_VALIDATION_FAILED" } } } elseif ($PsBoundParameters.ContainsKey("unmanagedEdgeNode")) { if ($nsxtEdgeNodePolicy = Get-LocalPasswordComplexity -vmName $($unmanagedEdgeNode) -guestUser root -guestPassword $unmanagedEdgeNodePass -nsx ) { $NsxtEdgePasswordComplexityObject = New-Object -TypeName PSObject $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $unmanagedEdgeNode $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Length" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Length' -ne $requiredConfig.minLength) { "$($nsxtEdgeNodePolicy.'Min Length') [ $($requiredConfig.minLength) ]" } else { "$($nsxtEdgeNodePolicy.'Min Length')" } } else { "$($nsxtEdgeNodePolicy.'Min Length')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Lowercase' -ne $requiredConfig.minLowercase) { "$($nsxtEdgeNodePolicy.'Min Lowercase') [ $($requiredConfig.minLowercase) ]" } else { "$($nsxtEdgeNodePolicy.'Min Lowercase')" } } else { "$($nsxtEdgeNodePolicy.'Min Lowercase')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Uppercase' -ne $requiredConfig.minUppercase) { "$($nsxtEdgeNodePolicy.'Min Uppercase') [ $($requiredConfig.minUppercase) ]" } else { "$($nsxtEdgeNodePolicy.'Min Uppercase')" } } else { "$($nsxtEdgeNodePolicy.'Min Uppercase')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Numerical' -ne $requiredConfig.minNumerical) { "$($nsxtEdgeNodePolicy.'Min Numerical') [ $($requiredConfig.minNumerical) ]" } else { "$($nsxtEdgeNodePolicy.'Min Numerical')" } } else { "$($nsxtEdgeNodePolicy.'Min Numerical')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Special" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Special' -ne $requiredConfig.minSpecial) { "$($nsxtEdgeNodePolicy.'Min Special') [ $($requiredConfig.minSpecial) ]" } else { "$($nsxtEdgeNodePolicy.'Min Special')" } } else { "$($nsxtEdgeNodePolicy.'Min Special')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Min Unique' -ne $requiredConfig.minUnique) { "$($nsxtEdgeNodePolicy.'Min Unique') [ $($requiredConfig.minUnique) ]" } else { "$($nsxtEdgeNodePolicy.'Min Unique')" } } else { "$($nsxtEdgeNodePolicy.'Min Unique')" }) $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Max Retries" -NotePropertyValue $(if ($drift) { if ($nsxtEdgeNodePolicy.'Max Retries' -ne $requiredConfig.retries) { "$($nsxtEdgeNodePolicy.'Max Retries') [ $($requiredConfig.retries) ]" } else { "$($nsxtEdgeNodePolicy.'Max Retries')" } } else { "$($nsxtEdgeNodePolicy.'Max Retries')" }) if ( $nsxtEdgeNodePolicy.'Min Length' -gt $managedPasswordMinLength ) { $alert = "RED" $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue ${minLengthExceeds} } else { $alert = "GREEN" $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $NsxtEdgePasswordComplexityObject | Add-Member -NotePropertyName "Message" -NotePropertyValue ${minLengthNotExceeds} } $nsxtPasswordComplexityPolicy += $NsxtEdgePasswordComplexityObject } } } } return $nsxtPasswordComplexityPolicy } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-NsxtEdgePasswordComplexity Function Request-NsxtEdgeAccountLockout { <# .SYNOPSIS Retrieves the account lockout policy for NSX Edge nodes based on the workload domain. .DESCRIPTION The Request-NsxtEdgeAccountLockout cmdlet retrieves the account lockout policy for NSX Edge nodes within a workload domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager - Retrieves the account lockout policy. .EXAMPLE Request-NsxtEdgeAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieving the account lockout policy for NSX Edge nodes in the workload domain. .EXAMPLE Request-NsxtEdgeAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieving the account lockout policy for NSX Edge nodes in the workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-NsxtEdgeAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -drift This example retrieving the account lockout policy for NSX Edge nodes in the workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey('policyFile')) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).nsxEdge.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).nsxEdge.accountLockout } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { if (Test-NSXTConnection -server $vcfNsxDetails.fqdn) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { $nsxtAccountLockoutPolicy = New-Object System.Collections.ArrayList $nsxtEdgeNodes = (Get-NsxtEdgeCluster | Where-Object { $_.member_node_type -eq "EDGE_NODE" }) foreach ($nsxtEdgeNode in $nsxtEdgeNodes.members) { if ($NsxtEdgeAccountLockout = Get-NsxtEdgeNodeAuthPolicy -nsxtManager $vcfNsxDetails.fqdn -nsxtEdgeNodeID $nsxtEdgeNode.transport_node_id) { $NsxtEdgeAccountLockoutObject = New-Object -TypeName PSObject $NsxtEdgeAccountLockoutObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $NsxtEdgeAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $nsxtEdgeNode.display_name $NsxtEdgeAccountLockoutObject | Add-Member -NotePropertyName "CLI Max Failures" -NotePropertyValue $(if ($drift) { if ($NsxtEdgeAccountLockout.cli_max_auth_failures -ne $requiredConfig.cliMaxFailures) { "$($NsxtEdgeAccountLockout.cli_max_auth_failures) [ $($requiredConfig.cliMaxFailures) ]" } else { "$($NsxtEdgeAccountLockout.cli_max_auth_failures)" } } else { "$($NsxtEdgeAccountLockout.cli_max_auth_failures)" }) $NsxtEdgeAccountLockoutObject | Add-Member -NotePropertyName "CLI Unlock Interval (sec)" -NotePropertyValue $(if ($drift) { if ($NsxtEdgeAccountLockout.cli_failed_auth_lockout_period -ne $requiredConfig.cliUnlockInterval) { "$($NsxtEdgeAccountLockout.cli_failed_auth_lockout_period) [ $($requiredConfig.cliUnlockInterval) ]" } else { "$($NsxtEdgeAccountLockout.cli_failed_auth_lockout_period)" } } else { "$($NsxtEdgeAccountLockout.cli_failed_auth_lockout_period)" }) $nsxtAccountLockoutPolicy += $NsxtEdgeAccountLockoutObject } else { Write-Error "Unable to retrieve Account Lockout Policy from NSX Edge node ($($nsxtEdgeNode.display_name)): PRE_VALIDATION_FAILED" } } return $nsxtAccountLockoutPolicy } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-NsxtEdgeAccountLockout Function Update-NsxtEdgePasswordExpiration { <# .SYNOPSIS Updates the local user password expiration policy for NSX Edge node local users. .DESCRIPTION The Update-NsxtEdgePasswordExpiration cmdlet configures the password expiration policy for NSX Edge node local users for a workload domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager - Updates the password expiration policy. .EXAMPLE Update-NsxtEdgePasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -maxdays 999 This example configures the password expiration policy for NSX Edge node local users in the workload domain .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER maxDays The maximum number of days before the password expires. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateRange(0, 9999)] [Int]$maxDays, [Parameter (Mandatory = $false)] [ValidateSet("true", "false")] [String]$detail = "true" ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { if (Test-NSXTConnection -server $($vcfNsxDetails.fqdn)) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { $nsxtEdgeNodes = (Get-NsxtEdgeCluster | Where-Object { $_.member_node_type -eq "EDGE_NODE" }) foreach ($nsxtEdgeNode in $nsxtEdgeNodes.members) { $localUsers = Get-NsxtApplianceUser -transportNodeId $nsxtEdgeNode.transport_node_id foreach ($localUser in $localUsers) { if ($localUser.password_change_frequency -ne $maxDays) { Set-NsxtApplianceUserExpirationPolicy -transportNodeId $nsxtEdgeNode.transport_node_id -userId $localUser.userid -maxDays $maxDays | Out-Null $updatedConfiguration = Get-NsxtApplianceUser -transportNodeId $nsxtEdgeNode.transport_node_id | Where-Object { $_.userid -eq $localUser.userid } if (($updatedConfiguration).password_change_frequency -eq $maxDays ) { if ($detail -eq "true") { Write-Output "Update Password Expiration Policy on NSX Edge ($($nsxtEdgeNode.display_name)) for Local User ($($localUser.username)): SUCCESSFUL" } } else { Write-Error "Update Password Expiration Policy on NSX Edge ($($nsxtEdgeNode.display_name)) for Local User ($($localUser.username)): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Password Expiration Policy on NSX Edge ($($nsxtEdgeNode.display_name)) for Local User ($($localUser.username)):, already set: SKIPPED" } } } } if ($detail -eq "false") { Write-Output "Update Password Expiration Policy for all NSX Edge Local Users in Workload Domain ($domain): SUCCESSFUL" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Update-NsxtEdgePasswordExpiration Function Update-NsxtEdgePasswordComplexity { <# .SYNOPSIS Updates the password complexity policy for NSX Edge nodes based on the workload domain. .DESCRIPTION The Update-NsxtEdgePasswordComplexity cmdlet updates the password complexity policy for each NSX Edge node for a workload domain. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager. - Updates the password complexity policy. .EXAMPLE Update-NsxtEdgePasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -minLength 15 -minLowercase -1 -minUppercase -1 -minNumerical -1 -minSpecial -1 -minUnique 4 -maxRetry 3 This example updates the password complexity policy for each NSX Edge node for a workload domain .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER minLength The minimum length of the password. .PARAMETER minLowercase The minimum number of lowercase characters in the password. .PARAMETER minUppercase The minimum number of uppercase characters in the password. .PARAMETER minNumerical The minimum number of numerical characters in the password. .PARAMETER minSpecial The minimum number of special characters in the password. .PARAMETER minUnique The minimum number of unique characters in the password. .PARAMETER maxRetry The maximum number of retries before the account is locked. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minLength, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minLowercase, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minUppercase, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minNumerical, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minSpecial, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minUnique, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$maxRetry, [Parameter (Mandatory = $false)] [ValidateSet("true", "false")] [String]$detail = "true" ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { if (Test-NSXTConnection -server $vcfNsxDetails.fqdn) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { $nsxtEdgeNodes = (Get-NsxtEdgeCluster | Where-Object { $_.member_node_type -eq "EDGE_NODE" }) foreach ($nsxtEdgeNode in $nsxtEdgeNodes.members) { $nsxEdgeRootPass = (Get-VCFCredential | Where-Object { $_.resource.resourceName -eq ($nsxtEdgeNode.display_name + '.' + $vcfNsxDetails.fqdn.Split('.', 2)[-1]) -and $_.username -eq "root" }).password $existingConfiguration = Get-LocalPasswordComplexity -vmName $($nsxtEdgeNode.display_name) -guestUser root -guestPassword $nsxEdgeRootPass -nsx if ($existingConfiguration.'Min Length' -ne $minLength -or $existingConfiguration.'Min Lowercase' -ne $minLowercase -or $existingConfiguration.'Min Uppercase' -ne $minUppercase -or $existingConfiguration.'Min Numerical' -ne $minNumerical -or $existingConfiguration.'Min Special' -ne $minSpecial -or $existingConfiguration.'Min Unique' -ne $minUnique -or $existingConfiguration.'Max Retries' -ne $maxRetry) { Set-LocalPasswordComplexity -vmName $nsxtEdgeNode.display_name -guestUser root -guestPassword $nsxEdgeRootPass -nsx -minLength $minLength -uppercase $minUppercase -lowercase $minLowercase -numerical $minNumerical -special $minSpecial -unique $minUnique -retry $maxRetry | Out-Null $updatedConfiguration = Get-LocalPasswordComplexity -vmName $nsxtEdgeNode.display_name -guestUser root -guestPassword $nsxEdgeRootPass -nsx if ($updatedConfiguration.'Min Length' -eq $minLength -and $updatedConfiguration.'Min Lowercase' -eq $minLowercase -and $updatedConfiguration.'Min Uppercase' -eq $minUppercase -and $updatedConfiguration.'Min Numerical' -eq $minNumerical -and $updatedConfiguration.'Min Special' -eq $minSpecial -and $updatedConfiguration.'Min Unique' -eq $minUnique -and $updatedConfiguration.'Max Retries' -eq $maxRetry) { if ($detail -eq "true") { Write-Output "Update Password Complexity Policy on NSX Edge Node ($($nsxtEdgeNode.display_name)): SUCCESSFUL" } } else { Write-Error "Update Password Complexity Policy on NSX Edge Node ($($nsxtEdgeNode.display_name)): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Password Complexity Policy on NSX Edge Node ($($nsxtEdgeNode.display_name)), already set: SKIPPED" } } } if ($detail -eq "false") { Write-Output "Update Password Complexity for all NSX Edge Nodes in Workload Domain ($domain): SUCCESSFUL" } } } } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-NsxtEdgePasswordComplexity Function Update-NsxtEdgeAccountLockout { <# .SYNOPSIS Updates the account lockout policy for NSX Edge nodes based on the workload domain. .DESCRIPTION The Update-NsxtEdgeAccountLockout cmdlet configures the account lockout policy for NSX Edge nodes. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to NSX Local Manager - Configure the account lockout policy. .EXAMPLE Update-NsxtEdgeAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cliFailures 5 -cliUnlockInterval 900 This example configures the account lockout policy of the NSX Edge nodes in the workload domain .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER cliFailures The number of failed login attempts before the account is locked for the CLI .PARAMETER cliUnlockInterval The number of seconds before the account is unlocked for the CLI. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false)] [ValidateRange(1, [int]::MaxValue)] [int]$cliFailures, [Parameter (Mandatory = $false)] [ValidateRange(1, [int]::MaxValue)] [int]$cliUnlockInterval, [Parameter (Mandatory = $false)] [ValidateSet("true", "false")] [String]$detail = "true" ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain -listNodes)) { if (Test-NSXTConnection -server $vcfNsxDetails.fqdn) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { $nsxtEdgeNodes = (Get-NsxtEdgeCluster | Where-Object { $_.member_node_type -eq "EDGE_NODE" }) foreach ($nsxtEdgeNode in $nsxtEdgeNodes.members) { $existingConfiguration = Get-NsxtEdgeNodeAuthPolicy -nsxtManager $vcfNsxDetails.fqdn -nsxtEdgeNodeID $nsxtEdgeNode.transport_node_id if (($existingConfiguration).cli_max_auth_failures -ne $cliFailures -or ($existingConfiguration).cli_failed_auth_lockout_period -ne $cliUnlockInterval) { if (!$PsBoundParameters.ContainsKey("cliFailures")) { $cliFailures = [int]$existingConfiguration.cli_max_auth_failures } if (!$PsBoundParameters.ContainsKey("cliUnlockInterval")) { $cliUnlockInterval = [int]$existingConfiguration.cli_failed_auth_lockout_period } Set-NsxtEdgeNodeAuthPolicy -nsxtManager $vcfNsxDetails.fqdn -nsxtEdgeNodeID $nsxtEdgeNode.transport_node_id -cli_max_attempt $cliFailures -cli_lockout_period $cliUnlockInterval | Out-Null $updatedConfiguration = Get-NsxtEdgeNodeAuthPolicy -nsxtManager $vcfNsxDetails.fqdn -nsxtEdgeNodeID $nsxtEdgeNode.transport_node_id if (($updatedConfiguration).cli_max_auth_failures -eq $cliFailures -and ($updatedConfiguration).cli_failed_auth_lockout_period -eq $cliUnlockInterval) { if ($detail -eq "true") { Write-Output "Update Account Lockout Policy on NSX Edge ($($nsxtEdgeNode.display_name)) for Workload Domain ($domain): SUCCESSFUL" } } else { Write-Error "Update Account Lockout Policy on NSX Edge ($($nsxtEdgeNode.display_name)) for Workload Domain ($domain): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Account Lockout Policy on NSX Edge ($($nsxtEdgeNode.display_name)) for Workload Domain ($domain):, already set: SKIPPED" } } } if ($detail -eq "false") { Write-Output "Update Account Lockout Policy for all NSX Edge Nodes in Workload Domain ($domain): SUCCESSFUL" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Update-NsxtEdgeAccountLockout Function Publish-NsxEdgePasswordExpiration { <# .SYNOPSIS Publishes the password expiration policy for NSX Edge nodes for a workload domain or all workload domains. .DESCRIPTION The Publish-NsxEdgePasswordExpiration cmdlet returns password expiration policy for local users of NSX Edge nodes. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects password expiration policy for each local user of NSX Edge. .EXAMPLE Publish-NsxEdgePasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example returns password expiration policy for each local user of NSX Edge nodes for all workload domains. .EXAMPLE Publish-NsxEdgePasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] This example returns password expiration policy for each local user of NSX Edge nodes for a workload domain. .EXAMPLE Publish-NsxEdgePasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password expiration policy for each local user of NSX Edge nodes for a workload domain and compares the configuration against the policy configuration file. .EXAMPLE Publish-NsxEdgePasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift This example returns password expiration policy for each local user of NSX Edge nodes for a workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $nsxEdgePasswordExpirationObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $workloadDomain)) { if (Test-NSXTConnection -server $vcfNsxDetails.fqdn) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { # $nsxtEdgeNodes = (Get-NsxtEdgeCluster | Where-Object {$_.member_node_type -eq "EDGE_NODE"}) # foreach ($nsxtEdgeNode in $nsxtEdgeNodes.members) { $command = "Request-NsxtEdgePasswordExpiration -server $server -user $user -pass $pass -domain $workloadDomain" + $commandSwitch $nsxEdgePasswordExpiration = Invoke-Expression $command ; $nsxEdgePasswordExpirationObject += $nsxEdgePasswordExpiration # } } } } } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { if (($vcfNsxDetails = Get-NsxtServerDetail -fqdn $server -username $user -password $pass -domain $domain.name)) { if (Test-NSXTConnection -server $vcfNsxDetails.fqdn) { if (Test-NSXTAuthentication -server $vcfNsxDetails.fqdn -user $vcfNsxDetails.adminUser -pass $vcfNsxDetails.adminPass) { # $nsxtEdgeNodes = (Get-NsxtEdgeCluster | Where-Object {$_.member_node_type -eq "EDGE_NODE"}) # foreach ($nsxtEdgeNode in $nsxtEdgeNodes.members) { $command = "Request-NsxtEdgePasswordExpiration -server $server -user $user -pass $pass -domain $($domain.name)" + $commandSwitch $nsxEdgePasswordExpiration = Invoke-Expression $command ; $nsxEdgePasswordExpirationObject += $nsxEdgePasswordExpiration # } } } } } } if ($PsBoundParameters.ContainsKey('json')) { $nsxEdgePasswordExpirationObject | ConvertTo-Json -Depth 10 } else { $nsxEdgePasswordExpirationObject = $nsxEdgePasswordExpirationObject | Sort-Object 'Workload Domain', 'System', 'User' | ConvertTo-Html -Fragment -PreContent '<a id="nsxedge-password-expiration"></a><h3>NSX Edge - Password Expiration</h3>' -As Table $nsxEdgePasswordExpirationObject = Convert-CssClassStyle -htmldata $nsxEdgePasswordExpirationObject $nsxEdgePasswordExpirationObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-NsxEdgePasswordExpiration Function Publish-NsxEdgePasswordComplexity { <# .SYNOPSIS Publishes the password complexity policy for NSX Edge nodes for a workload domain or all workload domains. .DESCRIPTION The Publish-NsxEdgePasswordComplexity cmdlet returns password complexity policy for local users of NSX Edge Mnodes. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects password complexity policy for each local user of NSX Edge. .EXAMPLE Publish-NsxEdgePasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example returns password complexity policy for each local user of NSX Edge nodes for all workload domains. .EXAMPLE Publish-NsxEdgePasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] This example returns password complexity policy for each local user of NSX Edge nodes for a workload domain. .EXAMPLE Publish-NsxEdgePasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password complexity policy for each local user of NSX Edge nodes for a workload domain and compares the configuration against the policy configuration file. .EXAMPLE Publish-NsxEdgePasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift This example returns password complexity policy for each local user of NSX Edge nodes for a workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $nsxEdgePasswordComplexityObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { $command = "Request-NsxtEdgePasswordComplexity -server $server -user $user -pass $pass -domain $workloadDomain" + $commandSwitch $nsxEdgePasswordComplexity = Invoke-Expression $command ; $nsxEdgePasswordComplexityObject += $nsxEdgePasswordComplexity } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { $command = "Request-NsxtEdgePasswordComplexity -server $server -user $user -pass $pass -domain $($domain.name)" + $commandSwitch $nsxEdgePasswordComplexity = Invoke-Expression $command ; $nsxEdgePasswordComplexityObject += $nsxEdgePasswordComplexity } } if ($PsBoundParameters.ContainsKey('json')) { $nsxEdgePasswordComplexityObject | ConvertTo-Json -Depth 10 } else { $nsxEdgePasswordComplexityObject = $nsxEdgePasswordComplexityObject | Sort-Object 'Workload Domain', 'System' | ConvertTo-Html -Fragment -PreContent '<a id="nsxedge-password-complexity"></a><h3>NSX Edge - Password Complexity</h3>' -As Table $nsxEdgePasswordComplexityObject = Convert-CssClassStyle -htmldata $nsxEdgePasswordComplexityObject $nsxEdgePasswordComplexityObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-NsxEdgePasswordComplexity Function Publish-NsxEdgeAccountLockout { <# .SYNOPSIS Publishes the account lockout policy for NSX Edge nodes for a workload domain or all workload domains. .DESCRIPTION The Publish-NsxEdgeAccountLockout cmdlet returns account lockout policy for local users of NSX Edge nodes. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Collects account lockout policy for NSX Edge node. .EXAMPLE Publish-NsxEdgeAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example returns account lockout policy for each NSX Edge nodes for all workload domains. .EXAMPLE Publish-NsxEdgeAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] This example returns account lockout policy for each NSX Edge nodes for a workload domain. .EXAMPLE Publish-NsxEdgeAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns account lockout policy for each NSX Edge nodes for a workload domain and compares the configuration against the policy configuration file. .EXAMPLE Publish-NsxEdgeAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -drift This example returns account lockout policy for each NSX Edge nodes for a workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $nsxEdgeAccountLockoutObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { $command = "Request-NsxtEdgeAccountLockout -server $server -user $user -pass $pass -domain $workloadDomain" + $commandSwitch $nsxEdgeAccountLockout = Invoke-Expression $command ; $nsxEdgeAccountLockoutObject += $nsxEdgeAccountLockout } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { $command = "Request-NsxtEdgeAccountLockout -server $server -user $user -pass $pass -domain $($domain.name)" + $commandSwitch $nsxEdgeAccountLockout = Invoke-Expression $command ; $nsxEdgeAccountLockoutObject += $nsxEdgeAccountLockout } } if ($PsBoundParameters.ContainsKey('json')) { $nsxEdgeAccountLockoutObject | ConvertTo-Json -Depth 10 } else { $nsxEdgeAccountLockoutObject = $nsxEdgeAccountLockoutObject | Sort-Object 'Workload Domain', 'System' | ConvertTo-Html -Fragment -PreContent '<a id="nsxedge-account-lockout"></a><h3>NSX Edge - Account Lockout</h3>' -As Table $nsxEdgeAccountLockoutObject = Convert-CssClassStyle -htmldata $nsxEdgeAccountLockoutObject $nsxEdgeAccountLockoutObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-NsxEdgeAccountLockout #EndRegion End NSX Edge Password Management Functions ###### ########################################################################## ########################################################################## #Region Begin ESX Password Management Functions ###### Function Request-EsxiPasswordExpiration { <# .SYNOPSIS Retrieves the password expiration policy for ESX hosts in a cluster. .DESCRIPTION The Request-EsxiPasswordExpiration cmdlet retrieves a list of ESX hosts for a cluster displaying the currently configured password expiration policy (Advanced Setting Security.PasswordMaxDays). The cmdlet connects to SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that the workload domain exists in the SDDC Manager inventory - Validates that network connectivity and authentication is possible to vCenter - Gathers the ESX hosts for the cluster specificed - Retrieves the password expiration policy for all ESX hosts in a cluster. .EXAMPLE Request-EsxiPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] This example retrieves all ESX hosts password expiration policy for the cluster in the workload domain. .EXAMPLE Request-EsxiPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves all ESX hosts password expiration policy for the cluster in the workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-EsxiPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -drift This example retrieves all ESX hosts password expiration policy for the cluster in the workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER cluster The name of the cluster to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$cluster, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).esxi.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).esxi.passwordExpiration } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-VsphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-VsphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (Get-Cluster | Where-Object { $_.Name -eq $cluster }) { $esxiPasswdPolicy = New-Object System.Collections.Generic.List[System.Object] $esxiHosts = Get-Cluster $cluster | Get-VMHost | Sort-Object -Property Name if ($esxiHosts) { Foreach ($esxiHost in $esxiHosts) { $passwordExpire = Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordMaxDays" } if ($passwordExpire) { $nodePasswdPolicy = New-Object -TypeName PSObject $nodePasswdPolicy | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $nodePasswdPolicy | Add-Member -NotePropertyName "Cluster" -NotePropertyValue $cluster $nodePasswdPolicy | Add-Member -NotePropertyName "System" -NotePropertyValue $esxiHost.Name $nodePasswdPolicy | Add-Member -NotePropertyName "Max Days" -NotePropertyValue $(if ($drift) { if ($passwordExpire.Value -ne $requiredConfig.maxdays) { "$($passwordExpire.Value) [ $($requiredConfig.maxdays) ]" } else { "$($passwordExpire.Value)" } } else { "$($passwordExpire.Value)" }) $esxiPasswdPolicy.Add($nodePasswdPolicy) Remove-Variable -Name nodePasswdPolicy } else { Write-Error "Unable to retrieve password expiration policy from ESX host ($esxiHost.Name): PRE_VALIDATION_FAILED" } } return $esxiPasswdPolicy } else { Write-Warning "No ESX hosts found within cluster named ($cluster): PRE_VALIDATION_FAILED" } } else { Write-Error "Unable to locate Cluster ($cluster) in vCenter ($($vcfVcenterDetails.fqdn)): PRE_VALIDATION_FAILED" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-EsxiPasswordExpiration Function Request-EsxiPasswordComplexity { <# .SYNOPSIS Retrieves the password complexity policy for all ESX hosts in a cluster. .DESCRIPTION The Request-EsxiPasswordComplexity cmdlet retrieves a list of ESX hosts for a cluster displaying the currently configured password complexity policy (Advanced Settings Security.PasswordHistory and Security.PasswordQualityControl). The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that the workload domain exists in the SDDC Manager inventory - Validates that network connectivity and authentication is possible to vCenter - Gathers the ESX hosts for the cluster specificed - Retrieves the password complexity policy for all ESX hosts in a cluster. .EXAMPLE Request-EsxiPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] This example retrieves all ESX hosts password complexity policy for the cluster in the workload domain. .EXAMPLE Request-EsxiPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves all ESX hosts password complexity policy for the cluster in the workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-EsxiPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -drift This example retrieves all ESX hosts password complexity policy for the cluster in the workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER cluster The name of the cluster to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$cluster, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).esxi.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).esxi.passwordComplexity } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-VsphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-VsphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (Get-Cluster | Where-Object { $_.Name -eq $cluster }) { $esxiPasswdPolicy = New-Object System.Collections.Generic.List[System.Object] $esxiHosts = Get-Cluster $cluster | Get-VMHost | Sort-Object -Property Name if ($esxiHosts) { Foreach ($esxiHost in $esxiHosts) { # retreving ESX Advanced Setting: Security.PasswordHistory $passwordHistory = Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordHistory" } # retreving ESX Advanced Setting: Security.PasswordQualityControl $passwordQualityControl = Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordQualityControl" } if ($passwordHistory -and $passwordQualityControl) { $nodePasswdPolicy = New-Object -TypeName PSObject $nodePasswdPolicy | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $nodePasswdPolicy | Add-Member -NotePropertyName "Cluster" -NotePropertyValue $cluster $nodePasswdPolicy | Add-Member -NotePropertyName "System" -NotePropertyValue $esxiHost.Name $nodePasswdPolicy | Add-Member -NotePropertyName "Policy" -NotePropertyValue $(if ($drift) { if ($passwordQualityControl.value -ne $requiredConfig.policy) { "$($passwordQualityControl.value) [ $($requiredConfig.policy) ]" } else { "$($passwordQualityControl.value)" } } else { "$($passwordQualityControl.value)" }) $nodePasswdPolicy | Add-Member -NotePropertyName "History" -NotePropertyValue $(if ($drift) { if ($passwordHistory.Value -ne $requiredConfig.history) { "$($passwordHistory.Value) [ $($requiredConfig.history) ]" } else { "$($passwordHistory.Value)" } } else { "$($passwordHistory.Value)" }) if ( $passwordQualityControl.Value.Trim().Split(',')[2] -ne "disabled" -and [int]$passwordQualityControl.Value.Trim().Split(',')[2] -gt $managedPasswordMinLength ) { $alert = "Red" $nodePasswdPolicy | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $nodePasswdPolicy | Add-Member -NotePropertyName "Message" -NotePropertyValue ${minLengthExceeds} } else { $alert = "Green" $nodePasswdPolicy | Add-Member -NotePropertyName "Alert" -NotePropertyValue $alert $nodePasswdPolicy | Add-Member -NotePropertyName "Message" -NotePropertyValue ${minLengthNotExceeds} } $esxiPasswdPolicy.Add($nodePasswdPolicy) Remove-Variable -Name nodePasswdPolicy } else { Write-Error "Unable to retrieve password complexity policy from ESX host ($esxiHost.Name): PRE_VALIDATION_FAILED" } } return $esxiPasswdPolicy } else { Write-Warning "No ESX hosts found within cluster named ($cluster): PRE_VALIDATION_FAILED" } } else { Write-Error "Unable to locate Cluster ($cluster) in vCenter ($($vcfVcenterDetails.fqdn)): PRE_VALIDATION_FAILED" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-EsxiPasswordComplexity Function Request-EsxiAccountLockout { <# .SYNOPSIS Retrieves the account lockout policy for all ESX hosts in a cluster. .DESCRIPTION The Request-EsxiAccountLockout cmdlet retrieves a list of ESX hosts for a cluster displaying the currently configured account lockout policy (Advanced Settings Security.AccountLockFailures and Security.AccountUnlockTime). The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that the workload domain exists in the SDDC Manager inventory - Validates that network connectivity and authentication is possible to vCenter - Gathers the ESX hosts for the cluster specificed - Retrieves the account lockout policy for all ESX hosts in the cluster. .EXAMPLE Request-EsxiAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] This example retrieves the account lockout policy for all ESX hosts in the cluster in the workload domain. .EXAMPLE Request-EsxiAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the account lockout policy for all ESX hosts in the cluster in the workload domain and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-EsxiAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -drift This example retrieves the account lockout policy for all ESX hosts in the cluster in the workload domain and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the policy from. .PARAMETER cluster The name of the cluster to retrieve the policy from. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$cluster, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).esxi.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).esxi.accountLockout } } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-VsphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-VsphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (Get-Cluster | Where-Object { $_.Name -eq $cluster }) { $esxiPasswdPolicy = New-Object System.Collections.Generic.List[System.Object] $esxiHosts = Get-Cluster $cluster | Get-VMHost | Sort-Object -Property Name if ($esxiHosts) { Foreach ($esxiHost in $esxiHosts) { # retreving ESX Advanced Setting: Security.PasswordHistory $lockFailues = Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.AccountLockFailures" } # retreving ESX Advanced Setting: Security.PasswordQualityControl $unlockTime = Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.AccountUnlockTime" } if ($lockFailues -and $unlockTime) { $nodePasswdPolicy = New-Object -TypeName PSObject $nodePasswdPolicy | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $nodePasswdPolicy | Add-Member -NotePropertyName "Cluster" -NotePropertyValue $cluster $nodePasswdPolicy | Add-Member -NotePropertyName "System" -NotePropertyValue $esxiHost.Name $nodePasswdPolicy | Add-Member -NotePropertyName "Max Failures" -NotePropertyValue $(if ($drift) { if ($lockFailues.Value -ne $requiredConfig.maxFailures) { "$($lockFailues.Value) [ $($requiredConfig.maxFailures) ]" } else { "$($lockFailues.Value)" } } else { "$($lockFailues.Value)" }) $nodePasswdPolicy | Add-Member -NotePropertyName "Unlock Interval (sec)" -NotePropertyValue $(if ($drift) { if ($unlockTime.value -ne $requiredConfig.unlockInterval) { "$($unlockTime.value) [ $($requiredConfig.unlockInterval) ]" } else { "$($unlockTime.value)" } } else { "$($unlockTime.value)" }) $esxiPasswdPolicy.Add($nodePasswdPolicy) Remove-Variable -Name nodePasswdPolicy } else { Write-Error "Unable to retrieve account lockout policy from ESX host ($esxiHost.Name): PRE_VALIDATION_FAILED" } } return $esxiPasswdPolicy } else { Write-Warning "No ESX hosts found within cluster named ($cluster): PRE_VALIDATION_FAILED" } } else { Write-Error "Unable to locate Cluster ($cluster) in vCenter ($($vcfVcenterDetails.fqdn)): PRE_VALIDATION_FAILED" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-EsxiAccountLockout Function Update-EsxiPasswordExpiration { <# .SYNOPSIS Updates the password expiration period in days for all ESX hosts in a cluster. .DESCRIPTION The Update-EsxiPasswordExpiration cmdlet configures the password expiration policy on an ESX host. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that the workload domain exists in the SDDC Manager inventory - Validates that network connectivity and authentication is possible to vCenter - Gathers the ESX hosts for the cluster specificed - Configures the password expiration policy for all ESX hosts in the cluster. .EXAMPLE Update-EsxiPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -maxDays 999 This example configures all ESX hosts within the cluster for the workload domain. .EXAMPLE Update-EsxiPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -maxDays 999 -detail false This example configures all ESX hosts within the cluster for the workload domain but does not show the detail per host .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER cluster The name of the cluster to update the policy for. .PARAMETER maxDays The maximum number of days before the password expires. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$cluster, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$maxDays, [Parameter (Mandatory = $false)] [ValidateSet("true", "false")] [String]$detail = "true" ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-VsphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-VsphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (Get-Cluster | Where-Object { $_.Name -eq $cluster }) { $esxiHosts = Get-Cluster $cluster | Get-VMHost Foreach ($esxiHost in $esxiHosts) { # $passwordExpire = Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordMaxDays" } if ((Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordMaxDays" }).value -ne $maxDays) { Set-AdvancedSetting -AdvancedSetting (Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordMaxDays" }) -Value $maxDays -Confirm:$false | Out-Null if ((Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordMaxDays" }) -match $maxDays) { if ($detail -eq "true") { Write-Output "Update Advanced System Setting (Security.PasswordMaxDays) to ($maxDays) on ESX Host ($esxiHost): SUCCESSFUL" } } else { Write-Error "Update Advanced System Setting (Security.PasswordMaxDays) to ($maxDays) on ESX Host ($esxiHost): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Advanced System Setting (Security.PasswordMaxDays) to ($maxDays) on ESX Host ($esxiHost), already set: SKIPPED" } } } if ($detail -eq "false") { Write-Output "Update Advanced System Setting (Security.PasswordQualityControl) to ($maxDays) on all ESX Hosts for Workload Domain ($domain): SUCCESSFUL" } } else { Write-Error "Unable to find Cluster ($cluster) in vCenter ($vcfVcenterDetails.fqdn), check details and retry: PRE_VALIDATION_FAILED" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-EsxiPasswordExpiration Function Update-EsxiPasswordComplexity { <# .SYNOPSIS Updates ESX password complexity policy. .DESCRIPTION The Update-EsxiPasswordComplexity cmdlet configures the password complexity policy on an ESX host. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that the workload domain exists in the SDDC Manager inventory - Validates that network connectivity and authentication is possible to vCenter - Gathers the ESX hosts for the cluster specificed - Configures the password complexity policy for all ESX hosts in the cluster. .EXAMPLE Update-EsxiPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -policy "retry=5 min=disabled,disabled,disabled,disabled,15" -history 5 This example configures all ESX hosts within the cluster in the workload domain. .EXAMPLE Update-EsxiPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -policy "retry=5 min=disabled,disabled,disabled,disabled,15" -history 5 -detail false This example configures all ESX hosts within the cluster in the workload domain but does not show the detail per host .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER cluster The name of the cluster to update the policy for. .PARAMETER policy The policy to apply to the ESX hosts. .PARAMETER history The number of previous passwords that a password cannot match. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$cluster, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$policy, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$history, [Parameter (Mandatory = $false)] [ValidateSet("true", "false")] [String]$detail = "true" ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-VsphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-VsphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (Get-Cluster | Where-Object { $_.Name -eq $cluster }) { $esxiHosts = Get-Cluster $cluster | Get-VMHost Foreach ($esxiHost in $esxiHosts) { if ((Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordQualityControl" }).value -ne $policy) { Set-AdvancedSetting -AdvancedSetting (Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordQualityControl" }) -Value $policy -Confirm:$false | Out-Null if ((Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordQualityControl" }).value -match $policy) { if ($detail -eq "true") { Write-Output "Update Password Complexity Policy (Security.PasswordQualityControl) on ESX Host ($esxiHost): SUCCESSFUL" } } else { Write-Error "Update Password Complexity Policy (Security.PasswordQualityControl) on ESX Host ($esxiHost): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Password Complexity Policy (Security.PasswordQualityControl) on ESX Host ($esxiHost), already set: SKIPPED" } } if ((Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordHistory" }).value -ne $history) { Set-AdvancedSetting -AdvancedSetting (Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordHistory" }) -Value $history -Confirm:$false | Out-Null if ((Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.PasswordHistory" }) -match $history) { if ($detail -eq "true") { Write-Output "Update Password Complexity Policy (Security.PasswordHistory) to ($history) on ESX Host ($esxiHost): SUCCESSFUL" } } else { Write-Error "Update Password Complexity Policy (Security.PasswordHistory) to ($history) on ESX Host ($esxiHost): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Password Complexity Policy (Security.PasswordHistory) to ($history) on ESX Host ($esxiHost), already set: SKIPPED" } } } if ($detail -eq "false") { Write-Output "Update Password Complexity Policy (Security.PasswordQualityControl and Security.PasswordHistory) on all ESX Hosts for Workload Domain ($domain): SUCCESSFUL" } } else { Write-Error "Unable to find Cluster ($cluster) in vCenter ($($vcfVcenterDetails.fqdn)), check details and retry: PRE_VALIDATION_FOUND" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-EsxiPasswordComplexity Function Update-EsxiAccountLockout { <# .SYNOPSIS Updates ESX account lockout policy. .DESCRIPTION The Update-EsxiAccountLockout cmdlet configures the account lockout policy on an ESX host. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that the workload domain exists in the SDDC Manager inventory - Validates that network connectivity and authentication is possible to vCenter - Gathers the ESX hosts for the cluster specificed - Configures the account lockout policy for all ESX hosts in the cluster. .EXAMPLE Update-EsxiAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -failures 5 -unlockInterval 900 This example configures all ESX hosts within the cluster in the workload domain. .EXAMPLE Update-EsxiAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -cluster [cluster_name] -failures 5 -unlockInterval 900 -detail false This example configures all ESX hosts within the cluster in the workload domain but does not show the detail per host .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to update the policy for. .PARAMETER cluster The name of the cluster to update the policy for. .PARAMETER failures The number of failed login attempts before the account is locked. .PARAMETER unlockInterval The number of seconds before a locked out account is unlocked. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$cluster, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$failures, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$unlockInterval, [Parameter (Mandatory = $false)] [ValidateSet("true", "false")] [String]$detail = "true" ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-VsphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-VsphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (Get-Cluster | Where-Object { $_.Name -eq $cluster }) { $esxiHosts = Get-Cluster $cluster | Get-VMHost Foreach ($esxiHost in $esxiHosts) { if ((Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.AccountLockFailures" }).value -ne $failures) { Set-AdvancedSetting -AdvancedSetting (Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.AccountLockFailures" }) -Value $failures -Confirm:$false | Out-Null if ((Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.AccountLockFailures" }).value -match $failures) { if ($detail -eq "true") { Write-Output "Update Password Complexity Policy (Security.AccountLockFailures) to ($failures) on ESX Host ($esxiHost): SUCCESSFUL" } } else { Write-Error "Update Password Complexity Policy (Security.AccountLockFailures) to ($failures) on ESX Host ($esxiHost): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Password Complexity Policy (Security.AccountLockFailures) to ($failures) on ESX Host ($esxiHost), already set: SKIPPED" } } if ((Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.AccountUnlockTime" }).value -ne $unlockInterval) { Set-AdvancedSetting -AdvancedSetting (Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.AccountUnlockTime" }) -Value $unlockInterval -Confirm:$false | Out-Null if ((Get-VMHost -name $esxiHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-AdvancedSetting | Where-Object { $_.Name -eq "Security.AccountUnlockTime" }) -match $unlockInterval) { if ($detail -eq "true") { Write-Output "Update Password Complexity Policy (Security.AccountUnlockTime) to ($unlockInterval) on ESX Host ($esxiHost): SUCCESSFUL" } } else { Write-Error "Update Password Complexity Policy (Security.AccountUnlockTime) to ($unlockInterval) on ESX Host ($esxiHost): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Password Complexity Policy (Security.AccountUnlockTime) to ($unlockInterval) on ESX Host ($esxiHost), already set: SKIPPED" } } } if ($detail -eq "false") { Write-Output "Update Password Complexity Policy (Security.AccountLockFailures and Security.AccountUnlockTime) on all ESX Hosts for Workload Domain ($domain): SUCCESSFUL" } } else { Write-Error "Unable to find Cluster ($cluster) in vCenter ($($vcfVcenterDetails.fqdn)), check details and retry: PRE_VALIDATION_FOUND" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-EsxiAccountLockout Function Publish-EsxiPasswordPolicy { <# .SYNOPSIS Publishes the password policies for ESX hosts for a workload domain or all workload domains. .DESCRIPTION The Publish-EsxiPasswordPolicy cmdlet retrieves the requested password policy for all ESX hosts and converts the output to HTML. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Retrieves the requested password policy for all ESX hosts and converts to HTML. .EXAMPLE Publish-EsxiPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -allDomains This example returns password expiration policy for all ESX hosts across all workload domains. .EXAMPLE Publish-EsxiPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -workloadDomain [workload_domain_name] This example returns password expiration policy for all ESX hosts for a workload domain. .EXAMPLE Publish-EsxiPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordComplexity -allDomains This example returns password complexity policy for all ESX hosts across all workload domains. .EXAMPLE Publish-EsxiPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordComplexity -workloadDomain [workload_domain_name] This example returns password complexity policy for all ESX hosts for a workload domain. .EXAMPLE Publish-EsxiPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy AccountLockout -allDomains This example returns account lockout policy for all ESX hosts across all workload domains. .EXAMPLE Publish-EsxiPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy AccountLockout -workloadDomain [workload_domain_name] This example returns account lockout policy for all ESX hosts for a workload domain. .EXAMPLE Publish-EsxiPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -workloadDomain [workload_domain_name] -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password expiration policy for all ESX hosts across all workload domains and compares the configuration against the policy configuration file. .EXAMPLE Publish-EsxiPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -workloadDomain [workload_domain_name] -drift This example returns password expiration policy for all ESX hosts across all workload domains and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER policy The policy to publish. One of: PasswordExpiration, PasswordComplexity, AccountLockout. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateSet('PasswordExpiration', 'PasswordComplexity', 'AccountLockout')] [String]$policy, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-EsxiPasswordExpiration"; $preHtmlContent = '<a id="esx-password-expiration"></a><h3>ESX - Password Expiration</h3>' } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-EsxiPasswordComplexity"; $preHtmlContent = '<a id="esx-password-complexity"></a><h3>ESX - Password Complexity</h3>' } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-EsxiAccountLockout"; $preHtmlContent = '<a id="esx-account-lockout"></a><h3>ESX - Account Lockout</h3>' } # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $esxiPasswordPolicyObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $workloadDomain)) { if (Test-VsphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-VsphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { $clusters = Get-Cluster -Server $vcfVcenterDetails.fqdn foreach ($cluster in $clusters) { $command = $pvsCmdlet + " -server $server -user $user -pass $pass -cluster $($cluster.name) -domain $workloadDomain" + $commandSwitch $esxiPolicy = Invoke-Expression $command ; $esxiPasswordPolicyObject += $esxiPolicy } } } } } elseif ($PsBoundParameters.ContainsKey('allDomains')) { $allWorkloadDomains = Get-VCFWorkloadDomain foreach ($domain in $allWorkloadDomains ) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain.name)) { if (Test-VsphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-VsphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { $clusters = Get-Cluster -Server $vcfVcenterDetails.fqdn foreach ($cluster in $clusters) { $command = $pvsCmdlet + " -server $server -user $user -pass $pass -cluster $($cluster.name) -domain $($domain.name)" + $commandSwitch $esxiPolicy = Invoke-Expression $command; $esxiPasswordPolicyObject += $esxiPolicy } } } } } } if ($PsBoundParameters.ContainsKey('json')) { $esxiPasswordPolicyObject | ConvertTo-Json -Depth 10 } else { $esxiPasswordPolicyObject = $esxiPasswordPolicyObject | Sort-Object 'Workload Domain', 'Cluster', 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table $esxiPasswordPolicyObject = Convert-CssClassStyle -htmldata $esxiPasswordPolicyObject $esxiPasswordPolicyObject } } } } Catch { Debug-CatchWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Publish-EsxiPasswordPolicy #EndRegion End ESX Password Management Functions ###### ########################################################################## ########################################################################## #Region Begin Workspace ONE Access Password Management Function ###### Function Request-WsaPasswordExpiration { <# .SYNOPSIS Retrieves Workspace ONE Access password expiration. .DESCRIPTION The Request-WsaPasswordExpiration cmdlet retrieves the Workspace ONE Access password expiration policy. - Validates that network connectivity and authentication is possible to Workspace ONE Access - Retrieves the password expiration policy. .EXAMPLE Request-WsaPasswordExpiration -server [wsa_fqdn] -user [admin_username] -pass [admin_password] This example retrieves the password expiration policy for Workspace ONE Access instance. .EXAMPLE Request-WsaPasswordExpiration -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password expiration policy for Workspace ONE Access instance and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-WsaPasswordExpiration -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -drift This example retrieves the password expiration policy for Workspace ONE Access instance and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER user The username to authenticate to the Workspace ONE Access instance. .PARAMETER pass The password to authenticate to the Workspace ONE Access instance. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).wsaDirectory.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).wsaDirectory.passwordExpiration } } Try { if (Test-WsaConnection -server $server) { if (Test-WsaAuthentication -server $server -user $user -pass $pass) { if ($WsaPasswordExpiration = Get-WsaPasswordPolicy) { $WsaPasswordExpirationObject = New-Object -TypeName PSObject $WsaPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue ($server.Split("."))[-0] $WsaPasswordExpirationObject | Add-Member -NotePropertyName "Password Lifetime (days)" -NotePropertyValue $(if ($drift) { if (($WsaPasswordExpiration.passwordTtlInHours / 24) -ne $requiredConfig.passwordLifetime) { "$(($WsaPasswordExpiration.passwordTtlInHours / 24)) [ $($requiredConfig.passwordLifetime) ]" } else { "$(($WsaPasswordExpiration.passwordTtlInHours / 24))" } } else { "$(($WsaPasswordExpiration.passwordTtlInHours / 24))" }) $WsaPasswordExpirationObject | Add-Member -NotePropertyName "Password Reminder (days)" -NotePropertyValue $(if ($drift) { if (($WsaPasswordExpiration.notificationThreshold / 24 / 3600 / 1000) -ne $requiredConfig.passwordReminder) { "$(($WsaPasswordExpiration.notificationThreshold / 24 / 3600 / 1000)) [ $($requiredConfig.passwordReminder) ]" } else { "$(($WsaPasswordExpiration.notificationThreshold / 24 / 3600 / 1000))" } } else { "$(($WsaPasswordExpiration.notificationThreshold / 24 / 3600 / 1000))" }) $WsaPasswordExpirationObject | Add-Member -NotePropertyName "Temporary Password (hours)" -NotePropertyValue $(if ($drift) { if ($WsaPasswordExpiration.tempPasswordTtl -ne $requiredConfig.temporaryPassword) { "$($WsaPasswordExpiration.tempPasswordTtl) [ $($requiredConfig.temporaryPassword) ]" } else { "$($WsaPasswordExpiration.tempPasswordTtl)" } } else { "$($WsaPasswordExpiration.tempPasswordTtl)" }) $WsaPasswordExpirationObject | Add-Member -NotePropertyName "Password Reminder Frequency (days)" -NotePropertyValue $(if ($drift) { if (($WsaPasswordExpiration.notificationInterval / 24 / 3600 / 1000) -ne $requiredConfig.temporaryPassword) { "$(($WsaPasswordExpiration.notificationInterval / 24 / 3600 / 1000)) [ $($requiredConfig.temporaryPassword) ]" } else { "$(($WsaPasswordExpiration.notificationInterval / 24 / 3600 / 1000))" } } else { "$(($WsaPasswordExpiration.notificationInterval / 24 / 3600 / 1000))" }) } else { Write-Error "Unable to retrieve password expiration policy from Workspace ONE Access instance ($server): PRE_VALIDATION_FAILED" } return $WsaPasswordExpirationObject } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-WsaPasswordExpiration Function Request-WsaPasswordComplexity { <# .SYNOPSIS Retrieves the password complexity policy for Workspace ONE Access instance. .DESCRIPTION The Request-WsaPasswordComplexity cmdlet retrieves the Workspace ONE Access password complexity policy. - Validates that network connectivity and authentication is possible to Workspace ONE Access - Retrieves the password complexity policy for Workspace ONE Access instance. .EXAMPLE Request-WsaPasswordComplexity -server [wsa_fqdn] -user [admin_username] -pass [admin_password] This example retrieves the password complexity policy for Workspace ONE Access instance. .EXAMPLE Request-WsaPasswordComplexity -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password complexity policy for Workspace ONE Access instance and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-WsaPasswordComplexity -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -drift This example retrieves the password complexity policy for Workspace ONE Access instance and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER user The username to authenticate to the Workspace ONE Access instance. .PARAMETER pass The password to authenticate to the Workspace ONE Access instance. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).wsaDirectory.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).wsaDirectory.passwordComplexity } } $(if ($drift) { if ($WsaPasswordComplexity.History -ne $requiredConfig.history) { "$($WsaPasswordComplexity.History) [ $($requiredConfig.history) ]" } else { "$($WsaPasswordComplexity.History)" } } else { "$($WsaPasswordComplexity.History)" }) Try { if (Test-WsaConnection -server $server) { if (Test-WsaAuthentication -server $server -user $user -pass $pass) { if ($WsaPasswordComplexity = Get-WsaPasswordPolicy) { $WsaPasswordComplexityObject = New-Object -TypeName PSObject $WsaPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue ($server.Split("."))[-0] $WsaPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" -NotePropertyValue $(if ($drift) { if ($WsaPasswordComplexity.minLen -ne $requiredConfig.minLength) { "$($WsaPasswordComplexity.minLen) [ $($requiredConfig.minLength) ]" } else { "$($WsaPasswordComplexity.minLen)" } } else { "$($WsaPasswordComplexity.minLen)" }) $WsaPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" -NotePropertyValue $(if ($drift) { if ($WsaPasswordComplexity.minLower -ne $requiredConfig.minLowercase) { "$($WsaPasswordComplexity.minLower) [ $($requiredConfig.minLowercase) ]" } else { "$($WsaPasswordComplexity.minLower)" } } else { "$($WsaPasswordComplexity.minLower)" }) $WsaPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" -NotePropertyValue $(if ($drift) { if ($WsaPasswordComplexity.minUpper -ne $requiredConfig.minUppercase) { "$($WsaPasswordComplexity.minUpper) [ $($requiredConfig.minUppercase) ]" } else { "$($WsaPasswordComplexity.minUpper)" } } else { "$($WsaPasswordComplexity.minUpper)" }) $WsaPasswordComplexityObject | Add-Member -NotePropertyName "Min Numeric" -NotePropertyValue $(if ($drift) { if ($WsaPasswordComplexity.minDigit -ne $requiredConfig.minNumerical) { "$($WsaPasswordComplexity.minDigit) [ $($requiredConfig.minNumerical) ]" } else { "$($WsaPasswordComplexity.minDigit)" } } else { "$($WsaPasswordComplexity.minDigit)" }) $WsaPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" -NotePropertyValue $(if ($drift) { if ($WsaPasswordComplexity.minSpecial -ne $requiredConfig.minSpecial) { "$($WsaPasswordComplexity.minSpecial) [ $($requiredConfig.minSpecial) ]" } else { "$($WsaPasswordComplexity.minSpecial)" } } else { "$($WsaPasswordComplexity.minSpecial)" }) $WsaPasswordComplexityObject | Add-Member -NotePropertyName "Max Identical Adjacent" -NotePropertyValue $(if ($drift) { if ($WsaPasswordComplexity.maxConsecutiveIdenticalCharacters -ne $requiredConfig.maxIdenticalAdjacent) { "$($WsaPasswordComplexity.maxConsecutiveIdenticalCharacters) [ $($requiredConfig.maxIdenticalAdjacent) ]" } else { "$($WsaPasswordComplexity.maxConsecutiveIdenticalCharacters)" } } else { "$($WsaPasswordComplexity.maxConsecutiveIdenticalCharacters)" }) $WsaPasswordComplexityObject | Add-Member -NotePropertyName "History" -NotePropertyValue $(if ($drift) { if ($WsaPasswordComplexity.History -ne $requiredConfig.history) { "$($WsaPasswordComplexity.History) [ $($requiredConfig.history) ]" } else { "$($WsaPasswordComplexity.History)" } } else { "$($WsaPasswordComplexity.History)" }) } else { Write-Error "Unable to retrieve password complexity policy from Workspace ONE Access instance ($server): PRE_VALIDATION_FAILED" } return $WsaPasswordComplexityObject } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-WsaPasswordComplexity Function Request-WsaLocalUserPasswordComplexity { <# .SYNOPSIS Retrieves the local user password complexity policy for Workspace ONE Access. .DESCRIPTION The Request-WsaLocalUserPasswordComplexity cmdlet retrieves the local user password complexity policy for Workspace ONE Access. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Retrieves the local user password complexity policy for Workspace ONE Access. .EXAMPLE Request-WsaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] This example retrieves the local user password complexity policy for Workspace ONE Access. .EXAMPLE Request-WsaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the local user password complexity policy for Workspace ONE Access and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-WsaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -drift This example retrieves the local user password complexity policy for Workspace ONE Access and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER wsaFqdn The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER wsaRootPass The password for the Workspace ONE Access appliance root account. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$wsaFqdn, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$wsaRootPass, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass $wsaRootPass = Get-Password -username "root" -password $wsaRootPass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType MANAGEMENT)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if ($drift) { if ($PsBoundParameters.ContainsKey('policyFile')) { Get-LocalPasswordComplexity -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass -drift -product wsaLocal -reportPath $reportPath -policyFile $policyFile } else { $version = Get-VCFManager -version Get-LocalPasswordComplexity -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass -drift -product wsaLocal -version $version } } else { Get-LocalPasswordComplexity -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass -product wsaLocal } } } } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-WsaLocalUserPasswordComplexity Function Request-WsaLocalUserAccountLockout { <# .SYNOPSIS Retrieves the local user account lockout policy for Workspace ONE Access instance. .DESCRIPTION The Request-WsaLocalUserAccountLockout cmdlet retrieves the account lockout policy for an SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager. - Retrieves the account lockout policy of Workspace ONE Access. .EXAMPLE Request-WsaLocalUserAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] This example retrieves the account lockout policy for Workspace ONE Access. .EXAMPLE Request-WsaLocalUserAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the local user password complexity policy for Workspace ONE Access and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-WsaLocalUserAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -drift This example retrieves the local user password complexity policy for Workspace ONE Access and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER wsaFqdn The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER wsaRootPass The password for the Workspace ONE Access appliance root account. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$wsaFqdn, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$wsaRootPass, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass $wsaRootPass = Get-Password -username "root" -password $wsaRootPass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType MANAGEMENT)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if ($drift) { if ($PsBoundParameters.ContainsKey('policyFile')) { Get-LocalAccountLockout -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass -product wsaLocal -drift -reportPath $reportPath -policyFile $policyFile } else { $version = Get-VCFManager -version Get-LocalAccountLockout -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass -product wsaLocal -drift -version $version } } else { Get-LocalAccountLockout -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass -product wsaLocal } } } } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-WsaLocalUserAccountLockout Function Request-WsaAccountLockout { <# .SYNOPSIS Retrieves the account lockout policy for Workspace ONE Access instance. .DESCRIPTION The Request-WsaAccountLockout cmdlet retrieves the Workspace ONE Access account lockout policy. - Validates that network connectivity and authentication is possible to Workspace ONE Access - Retrieves the account lockout policy. .EXAMPLE Request-WsaAccountLockout -server [wsa_fqdn] -user [admin_username] -pass [admin_password] This example retrieves the account lockout policy for Workspace ONE Access instance. .EXAMPLE Request-WsaAccountLockout -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the local user password complexity policy for Workspace ONE Access and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-WsaAccountLockout -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -drift This example retrieves the local user password complexity policy for Workspace ONE Access and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER user The username to authenticate to the Workspace ONE Access instance. .PARAMETER pass The password to authenticate to the Workspace ONE Access instance. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass if ($drift) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).wsaDirectory.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).wsaDirectory.accountLockout } } $(if ($drift) { if ($WsaAccountLockout.numAttempts -ne $requiredConfig.maxFailures) { "$($WsaAccountLockout.numAttempts) [ $($requiredConfig.maxFailures) ]" } else { "$($WsaAccountLockout.numAttempts)" } } else { "$($WsaAccountLockout.numAttempts)" }) Try { if (Test-WsaConnection -server $server) { if (Test-WsaAuthentication -server $server -user $user -pass $pass) { if ($WsaAccountLockout = Get-WsaAccountLockout) { $WsaAccountLockoutObject = New-Object -TypeName PSObject $WsaAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue ($server.Split("."))[-0] $WsaAccountLockoutObject | Add-Member -NotePropertyName "Max Failures" -NotePropertyValue $(if ($drift) { if ($WsaAccountLockout.numAttempts -ne $requiredConfig.maxFailures) { "$($WsaAccountLockout.numAttempts) [ $($requiredConfig.maxFailures) ]" } else { "$($WsaAccountLockout.numAttempts)" } } else { "$($WsaAccountLockout.numAttempts)" }) $WsaAccountLockoutObject | Add-Member -NotePropertyName "Unlock Interval (min)" -NotePropertyValue $WsaAccountLockout.unlockInterval $WsaAccountLockoutObject | Add-Member -NotePropertyName "Failed Attempt Interval (min)" -NotePropertyValue $WsaAccountLockout.attemptInterval } else { Write-Error "Unable to retrieve account lockout policy from Workspace ONE Access instance ($server): PRE_VALIDATION_FAILED" } return $WsaAccountLockoutObject } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-WsaAccountLockout Function Update-WsaPasswordExpiration { <# .SYNOPSIS Updates the Workspace ONE Access password expiration policy. .DESCRIPTION The Update-WsaPasswordExpiration cmdlet configures the password expiration policy for a Workspace ONE Access instance. - Validates that network connectivity and authentication is possible to Workspace ONE Access. - Configures the Workspace ONE Access password expiration policy. .EXAMPLE Update-WsaPasswordExpiration -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -maxDays 999 -warnDays 14 -reminderDays 7 -tempPasswordHours 24 This example configures the password expiration policy for Workspace ONE Access .PARAMETER server The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER user The username to authenticate to the Workspace ONE Access instance. .PARAMETER pass The password to authenticate to the Workspace ONE Access instance. .PARAMETER maxDays The maximum number of days that a password is valid. .PARAMETER warnDays The number of days before a password expires that a warning is issued. .PARAMETER reminderDays The number of days before a password expires that a reminder is issued. .PARAMETER tempPasswordHours The number of hours that a temporary password is valid. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$maxDays, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$warnDays, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$reminderDays, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$tempPasswordHours ) $pass = Get-Password -username $user -password $pass Try { if (Test-WsaConnection -server $server) { if (Test-WsaAuthentication -server $server -user $user -pass $pass) { $newMaxDays = ($maxDays * 24) $newWarnDays = ($warnDays * 24 * 3600 * 1000) $newReminderDays = ($reminderDays * 24 * 3600 * 1000) $newMaxDays = $maxDays $newWarnDays = $warnDays $newReminderDays = $reminderDays if ((Get-WsaPasswordPolicy).passwordTtlInHours -ne $newMaxDays -or (Get-WsaPasswordPolicy).notificationThreshold -ne $newWarnDays -or (Get-WsaPasswordPolicy).notificationInterval -ne $newReminderDays -or (Get-WsaPasswordPolicy).tempPasswordTtl -ne $tempPasswordHours) { Set-WsaPasswordPolicy -passwordTtlInDays $newMaxDays -notificationThresholdInDays $newWarnDays -notificationIntervalInDays $newReminderDays -tempPasswordTtlInHrs $tempPasswordHours -minLen (Get-WsaPasswordPolicy).minLen -minLower (Get-WsaPasswordPolicy).minLower -minUpper (Get-WsaPasswordPolicy).minUpper -minDigit (Get-WsaPasswordPolicy).minDigit -minSpecial (Get-WsaPasswordPolicy).minSpecial -history (Get-WsaPasswordPolicy).history -maxConsecutiveIdenticalCharacters (Get-WsaPasswordPolicy).maxConsecutiveIdenticalCharacters -maxPreviousPasswordCharactersReused (Get-WsaPasswordPolicy).maxPreviousPasswordCharactersReused | Out-Null if ((Get-WsaPasswordPolicy).passwordTtlInHours / 24 -eq $newMaxDays -and (Get-WsaPasswordPolicy).notificationThreshold / 24 / 3600 / 1000 -eq $newWarnDays -and (Get-WsaPasswordPolicy).notificationInterval / 24 / 3600 / 1000 -eq $newReminderDays -and (Get-WsaPasswordPolicy).tempPasswordTtl -eq $tempPasswordHours) { Write-Output "Update Workspace ONE Access Password Expiration Policy on server ($server): SUCCESSFUL" } else { Write-Error "Update Workspace ONE Access Password Expiration Policy on server ($server): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Workspace ONE Access Password Expiration Policy on server ($server), already set: SKIPPED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Update-WsaPasswordExpiration Function Update-WsaPasswordComplexity { <# .SYNOPSIS Updates the password complexity policy for a Workspace ONE Access instance. .DESCRIPTION The Update-WsaPasswordComplexity cmdlet configures the password complexity policy for a Workspace ONE Access instance. - Validates that network connectivity and authentication is possible to Workspace ONE Access. - Configures the Workspace ONE Access password complexity policy. .EXAMPLE Update-WsaPasswordComplexity -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -minLength 15 -minLowercase 1 -minUppercase 1 -minNumeric 1 -minSpecial 1 -maxIdenticalAdjacent 1 -maxPreviousCharacters 0 -history 5 This example configures the password complexity policy for Workspace ONE Access .PARAMETER server The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER user The username to authenticate to the Workspace ONE Access instance. .PARAMETER pass The password to authenticate to the Workspace ONE Access instance. .PARAMETER minLength The minimum number of characters that a password must contain. .PARAMETER minLowercase The minimum number of lowercase characters that a password must contain. .PARAMETER minUppercase The minimum number of uppercase characters that a password must contain. .PARAMETER minNumeric The minimum number of numeric characters that a password must contain. .PARAMETER minSpecial The minimum number of special characters that a password must contain. .PARAMETER maxIdenticalAdjacent The maximum number of identical adjacent characters that a password can contain. .PARAMETER maxPreviousCharacters The maximum number of previous characters that a password can contain. .PARAMETER history The number of previous passwords that a password cannot match. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minLength, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minLowercase, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minUppercase, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minNumeric, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minSpecial, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$maxIdenticalAdjacent, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$maxPreviousCharacters, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$history ) $pass = Get-Password -username $user -password $pass Try { if (Test-WsaConnection -server $server) { if (Test-WsaAuthentication -server $server -user $user -pass $pass) { $currentPasswordPolicy = Get-WsaPasswordPolicy $currentMaxDays = (($currentPasswordPolicy).passwordTtlInHours / 24) $currentWarnDays = (($currentPasswordPolicy).notificationThreshold / 24 / 3600 / 1000) $currentReminderDays = (($currentPasswordPolicy).notificationInterval / 24 / 3600 / 1000) if ((Get-WsaPasswordPolicy).minLen -ne $minLength -or (Get-WsaPasswordPolicy).minLower -ne $minLowercase -or (Get-WsaPasswordPolicy).minUpper -ne $minUppercase -or (Get-WsaPasswordPolicy).minDigit -ne $minNumeric -or (Get-WsaPasswordPolicy).minSpecial -ne $minSpecial -or (Get-WsaPasswordPolicy).maxConsecutiveIdenticalCharacters -ne $maxIdenticalAdjacent -or (Get-WsaPasswordPolicy).maxPreviousPasswordCharactersReused -ne $maxPreviousCharacters -or (Get-WsaPasswordPolicy).history -ne $history) { Set-WsaPasswordPolicy -minLen $minLength -minLower $minLowercase -minUpper $minUppercase -minDigit $minNumeric -minSpecial $minSpecial -history $history -maxConsecutiveIdenticalCharacters $maxIdenticalAdjacent -maxPreviousPasswordCharactersReused $maxPreviousCharacters -tempPasswordTtlInHrs (Get-WsaPasswordPolicy).tempPasswordTtl -passwordTtlInDays $currentMaxDays -notificationThresholdInDays $currentWarnDays -notificationIntervalInDays $currentReminderDays | Out-Null if ((Get-WsaPasswordPolicy).minLen -eq $minLength -and (Get-WsaPasswordPolicy).minLower -eq $minLowercase -and (Get-WsaPasswordPolicy).minUpper -eq $minUppercase -and (Get-WsaPasswordPolicy).minDigit -eq $minNumeric -and (Get-WsaPasswordPolicy).minSpecial -eq $minSpecial -and (Get-WsaPasswordPolicy).maxConsecutiveIdenticalCharacters -eq $maxIdenticalAdjacent -and (Get-WsaPasswordPolicy).maxPreviousPasswordCharactersReused -eq $maxPreviousCharacters -and (Get-WsaPasswordPolicy).history -eq $history) { Write-Output "Updated Workspace ONE Access Password Complexity on Server ($server): SUCCESSFUL" } else { Write-Error "Update Workspace ONE Access Password Complexity Policy on server ($server): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Workspace ONE Access Password Complexity Policy on server ($server), already set: SKIPPED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Update-WsaPasswordComplexity Function Update-WsaLocalUserPasswordComplexity { <# .SYNOPSIS Updates the local user password complexity policy for Workspace ONE Access. .DESCRIPTION The Update-WsaLocalUserPasswordComplexity cmdlet configures the local user password complexity policy for Workspace ONE Access. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the password complexity policy. .EXAMPLE Update-WsaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -minLength 1 -history 5 -maxRetry 3 This example configures the local user password complexity policy for Workspace ONE Access .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER wsaFqdn The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER wsaRootPass The password for the Workspace ONE Access appliance root account. .PARAMETER minLength The minimum length of the password. .PARAMETER history The number of previous passwords that a password cannot match. .PARAMETER maxRetry The number of failed login attempts before the account is locked. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$wsaFqdn, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$wsaRootPass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$minLength, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$history, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$maxRetry ) $pass = Get-Password -username $user -password $pass $wsaRootPass = Get-Password -username "root" -password $wsaRootPass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType MANAGEMENT)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { $existingConfiguration = Get-LocalPasswordComplexity -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass if ($existingConfiguration.'Min Length' -ne $minLength -or $existingConfiguration.'History' -ne $history -or $existingConfiguration.'Max Retries' -ne $maxRetry) { Set-LocalPasswordComplexity -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass -minLength $minLength -uppercase $minUppercase -lowercase $minLowercase -numerical $minNumerical -special $minSpecial -unique $minUnique -class $minClass -sequence $maxSequence -history $history -retry $maxRetry | Out-Null $updatedConfiguration = Get-LocalPasswordComplexity -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass if ($updatedConfiguration.'Min Length' -eq $minLength -and $updatedConfiguration.'History' -eq $history -and $updatedConfiguration.'Max Retries' -eq $maxRetry) { Write-Output "Update Local User Password Complexity Policy on Workspace ONE Access ($wsaFqdn): SUCCESSFUL" } else { Write-Error "Update Local User Password Complexity Policy on Workspace ONE Access ($wsaFqdn): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Local User Password Complexity Policy on Workspace ONE Access ($wsaFqdn), already set: SKIPPED" } } } } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-WsaLocalUserPasswordComplexity Function Update-WsaAccountLockout { <# .SYNOPSIS Updates the account lockout policy for a Workspace ONE Access instance. .DESCRIPTION The Update-WsaAccountLockout cmdlet configures the account lockout policy for Workspace ONE Access. - Validates that network connectivity and authentication is possible to Workspace ONE Access. - Configures the Workspace ONE Access account lockout policy. .EXAMPLE Update-WsaAccountLockout -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -failures 5 -failureInterval 180 -unlockInterval 900 This example configures the account lockout policy for Workspace ONE Access .PARAMETER server The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER user The username to authenticate to the Workspace ONE Access instance. .PARAMETER pass The password to authenticate to the Workspace ONE Access instance. .PARAMETER failures The number of failed login attempts before the account is locked. .PARAMETER failureInterval The number of seconds before the failed login attempts counter is reset. .PARAMETER unlockInterval The number of seconds before a locked account is unlocked. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$failures, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$failureInterval, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$unlockInterval ) $pass = Get-Password -username $user -password $pass Try { if (Test-WsaConnection -server $server) { if (Test-WsaAuthentication -server $server -user $user -pass $pass) { $failureInterval = ($failureInterval / 60) $unlockInterval = ($unlockInterval / 60) if ((Get-WsaAccountLockout).numAttempts -ne $failures -or (Get-WsaAccountLockout).attemptInterval -ne $failureInterval -or (Get-WsaAccountLockout).unlockInterval -ne $unlockInterval) { Set-WsaAccountLockout -numAttempts $failures -attemptInterval $failureInterval -unlockInterval $unlockInterval | Out-Null if ((Get-WsaAccountLockout).numAttempts -eq $failures -and (Get-WsaAccountLockout).attemptInterval -eq $failureInterval -and (Get-WsaAccountLockout).unlockInterval -eq $unlockInterval) { Write-Output "Update Workspace ONE Access Account Lockout Policy on instance ($server): SUCCESSFUL" } else { Write-Error "Update Workspace ONE Access Account Lockout Policy on instance ($server): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Workspace ONE Access Account Lockout Policy on instance ($server), already set: SKIPPED" } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Update-WsaAccountLockout Function Update-WsaLocalUserAccountLockout { <# .SYNOPSIS Updates the account lockout policy of Workspace ONE Access. .DESCRIPTION The Update-WsaLocalUserAccountLockout cmdlet configures the account lockout policy of Workspace ONE Access. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the account lockout policy. .EXAMPLE Update-WsaLocalUserAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -failures 3 -unlockInterval 900 -rootUnlockInterval 900 This example configures the account lockout policy for Workspace ONE Access .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER wsaFqdn The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER wsaRootPass The password for the Workspace ONE Access appliance root account. .PARAMETER failures The number of failed login attempts before the account is locked. .PARAMETER unlockInterval The number of seconds before a locked account is unlocked. .PARAMETER rootUnlockInterval The number of seconds before a locked root account is unlocked. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$wsaFqdn, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$wsaRootPass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Int]$failures, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$unlockInterval, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$rootUnlockInterval ) $pass = Get-Password -username $user -password $pass $wsaRootPass = Get-Password -username "root" -password $wsaRootPass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType MANAGEMENT)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { $existingConfiguration = Get-LocalAccountLockout -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass -product wsaLocal if ($existingConfiguration.'Max Failures' -ne $failures -or $existingConfiguration.'Unlock Interval (sec)' -ne $unlockInterval -or $existingConfiguration.'Root Unlock Interval (sec)' -ne $rootUnlockInterval) { Set-LocalAccountLockout -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass -failures $failures -unlockInterval $unlockInterval -rootUnlockInterval $rootUnlockInterval | Out-Null $updatedConfiguration = Get-LocalAccountLockout -vmName ($wsaFqdn.Split("."))[-0] -guestUser root -guestPassword $wsaRootPass -product wsaLocal if ($updatedConfiguration.'Max Failures' -eq $failures -and $updatedConfiguration.'Unlock Interval (sec)' -eq $unlockInterval -and $updatedConfiguration.'Root Unlock Interval (sec)' -eq $rootUnlockInterval) { Write-Output "Update Account Lockout Policy on Workspace ONE Access ($wsaFqdn): SUCCESSFUL" } else { Write-Error "Update Account Lockout Policy on Workspace ONE Access ($wsaFqdn): POST_VALIDATION_FAILED" } } else { Write-Warning "Update Account Lockout Policy on Workspace ONE Access ($wsaFqdn), already set: SKIPPED" } } } } } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Update-WsaLocalUserAccountLockout Function Publish-WsaDirectoryPasswordPolicy { <# .SYNOPSIS Publishes the password policies for Workspace ONE Access Directory. .DESCRIPTION The Publish-WsaDirectoryPasswordPolicy cmdlet retrieves the requested password policy for Workspace ONE Access and converts the output to HTML. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to Workspace ONE Access - Retrieves the requested password policy for Workspace ONE Access and converts to HTML. .EXAMPLE Publish-WsaDirectoryPasswordPolicy -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -allDomains This example returns the password expiration policy for Workspace ONE Access Directory Users. .EXAMPLE Publish-WsaDirectoryPasswordPolicy -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordComplexity -allDomains This example returns the password complexity policy for Workspace ONE Access Directory Users. .EXAMPLE Publish-WsaDirectoryPasswordPolicy -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -policy AccountLockout -allDomains This example returns the account lockout policy for Workspace ONE Access Directory Users. .EXAMPLE Publish-WsaDirectoryPasswordPolicy -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -allDomains -drift -reportPath [report_path] -policyFile [policy_file].json This example returns the password expiration policy for Workspace ONE Access Directory Users and compares the configuration against the policy configuration file. .EXAMPLE Publish-WsaDirectoryPasswordPolicy -server [wsa_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -allDomains -drift This example returns the password expiration policy for Workspace ONE Access Directory Users and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER policy The policy to publish. One of: PasswordExpiration, PasswordComplexity, AccountLockout. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateSet('PasswordExpiration', 'PasswordComplexity', 'AccountLockout')] [String]$policy, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain ) $pass = Get-Password -username $user -password $pass if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-WsaPasswordExpiration"; $preHtmlContent = '<a id="standalone-wsa-directory-password-expiration"></a><h3>Local Workspace ONE Access Directory - Password Expiration</h3>' } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-WsaPasswordComplexity"; $preHtmlContent = '<a id="standalone-wsa-directory-password-complexity"></a><h3>Local Workspace ONE Access Directory - Password Complexity</h3>' } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-WsaAccountLockout"; $preHtmlContent = '<a id="standalone-wsa-directory-account-lockout"></a><h3>Local Workspace ONE Access Directory - Account Lockout</h3>' } # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } Try { $command = $pvsCmdlet + " -server $server -user $user -pass $pass" + $commandSwitch $wsaDirectoryPasswordPolicyObject = Invoke-Expression $command if ($PsBoundParameters.ContainsKey('json')) { $wsaDirectoryPasswordPolicyObject | ConvertTo-Json -Depth 10 } else { if ($wsaDirectoryPasswordPolicyObject.Count -eq 0) { $wsaDirectoryPasswordPolicyObject = $wsaDirectoryPasswordPolicyObject | ConvertTo-Html -Fragment -PreContent $preHtmlContent -PostContent '<p>Workspace ONE Access Not Requested</p>' } else { $wsaDirectoryPasswordPolicyObject = $wsaDirectoryPasswordPolicyObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table } $wsaDirectoryPasswordPolicyObject = Convert-CssClassStyle -htmldata $wsaDirectoryPasswordPolicyObject $wsaDirectoryPasswordPolicyObject } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-WsaDirectoryPasswordPolicy Function Publish-WsaLocalPasswordPolicy { <# .SYNOPSIS Publishes the password policies for Workspace ONE Access Local Users. .DESCRIPTION The Publish-WsaDirectoryPasswordPolicy cmdlet retrieves the requested password policy for all ESX hosts and converts the output to HTML. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter - Retrieves the requested password policy for Workspace ONE Access Local Users and converts to HTML. .EXAMPLE Publish-WsaLocalPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -allDomains This example returns password expiration policy for Workspace ONE Access Directory Users. .EXAMPLE Publish-WsaLocalPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordComplexity -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -allDomains This example returns password complexity policy for Workspace ONE Access Directory Users. .EXAMPLE Publish-WsaLocalPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy AccountLockout -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -allDomains This example returns account lockout policy for Workspace ONE Access Directory Users. .EXAMPLE Publish-WsaLocalPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -allDomains -drift -reportPath [report_path] -policyFile [policy_file].json This example returns password expiration policy for Workspace ONE Access Directory Users and compares the configuration against the policy configuration file. .EXAMPLE Publish-WsaLocalPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -wsaFqdn [wsa_fqdn] -wsaRootPass [wsa_root_password] -allDomains -drift This example returns password expiration policy for Workspace ONE Access Directory Users and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER wsaFqdn The fully qualified domain name of the Workspace ONE Access instance. .PARAMETER wsaRootPass The password for the Workspace ONE Access appliance root account. .PARAMETER policy The policy to publish. One of: PasswordExpiration, PasswordComplexity, AccountLockout. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$wsaFqdn, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$wsaRootPass, [Parameter (Mandatory = $true)] [ValidateSet('PasswordExpiration', 'PasswordComplexity', 'AccountLockout')] [String]$policy, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain ) $pass = Get-Password -username $user -password $pass $wsaRootPass = Get-Password -username "root" -password $wsaRootPass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { # Define the Command Switch if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } [Array]$localUsers = '"root","sshuser"' if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-LocalUserPasswordExpiration"; $preHtmlContent = '<a id="local-wsa-local-password-expiration"></a><h3>Local Workspace ONE (Local) - Password Expiration</h3>'; $customSwitch = " -domain $((Get-VCFWorkloadDomain | Where-Object {$_.type -eq "MANAGEMENT"}).name) -product wsaLocal -vmName $(($wsaFqdn.Split("."))[-0]) -guestUser root -guestPassword $wsaRootPass -localUser $localUsers" } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-WsaLocalUserPasswordComplexity"; $preHtmlContent = '<a id="local-wsa-local-password-complexity"></a><h3>Local Workspace ONE (Local) - Password Complexity</h3>'; $customSwitch = " -wsaFqdn $wsaFqdn -wsaRootPass $wsaRootPass" } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-WsaLocalUserAccountLockout"; $preHtmlContent = '<a id="local-wsa-local-account-lockout"></a><h3>Local Workspace ONE (Local) - Account Lockout</h3>'; $customSwitch = " -wsaFqdn $wsaFqdn -wsaRootPass $wsaRootPass" } $command = $pvsCmdlet + " -server $server -user $user -pass $pass" + $commandSwitch + $customSwitch $wsaLocalPasswordPolicyObject = Invoke-Expression $command if ($PsBoundParameters.ContainsKey('json')) { $wsaLocalPasswordPolicyObject | ConvertTo-Json -Depth 10 } else { if ($wsaLocalPasswordPolicyObject.Count -eq 0) { $wsaLocalPasswordPolicyObject = $wsaLocalPasswordPolicyObject | ConvertTo-Html -Fragment -PreContent $preHtmlContent -PostContent '<p>Local Workspace ONE Access Not Requested</p>' } else { $wsaLocalPasswordPolicyObject = $wsaLocalPasswordPolicyObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table } $wsaLocalPasswordPolicyObject = Convert-CssClassStyle -htmldata $wsaLocalPasswordPolicyObject $wsaLocalPasswordPolicyObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-WsaLocalPasswordPolicy #EndRegion End Workspace ONE Access Password Management Functions ###### ########################################################################## ########################################################################## #Region Begin Aria Product Password Management Function ###### Function Get-AriaLocalUserPasswordExpiration { <# .SYNOPSIS Retrieves the password expiration policy for the specified local user. .DESCRIPTION The Get-AriaLocalUserPasswordExpiration cmdlet retrieves a local user password expiration policy. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Retrieves the password expiration policy for the specified local user. .EXAMPLE Get-AriaLocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -localUser [local_username] This example retrieves the global password expiration policy for a Aria Automation instance. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain which the product is deployed .PARAMETER vmName The name of the virtual machine to retrieve the policy from. .PARAMETER guestUser The username to authenticate to the virtual machine guest operating system. .PARAMETER guestPassword The password to authenticate to the virtual machine guest operating system. .PARAMETER localUser The local user to retrieve the password expiration policy for. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$vmName, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$guestUser, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$guestPassword, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [switch]$sudo, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Array]$localUser ) $pass = Get-Password -username $user -password $pass $guestPassword = Get-Password -username $guestUser -password $guestPassword Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { $vcenterDomain = $vcfVcenterDetails.type if ($vcenterDomain -ne "MANAGEMENT") { if (Get-VCFWorkloadDomain | Where-Object { $_.type -eq "MANAGEMENT" }) { if (($vcfMgmtVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType "Management")) { if (Test-vSphereConnection -server $($vcfMgmtVcenterDetails.fqdn)) { if (-not (Test-vSphereAuthentication -server $vcfMgmtVcenterDetails.fqdn -user $vcfMgmtVcenterDetails.ssoAdmin -pass $vcfMgmtVcenterDetails.ssoAdminPass)) { return } } } } else { Write-Error "Unable to find Workload Domain typed (MANAGEMENT) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } if ($PsBoundParameters.ContainsKey('sudo')) { $allLocalUserExpirationObject = New-Object System.Collections.ArrayList foreach ($user in $localUser) { if ($localUserPasswordExpiration = Get-LocalUserPasswordExpiration -vmName $vmName -guestUser $guestUser -guestPassword $guestPassword -localUser $user -sudo) { $localUserExpirationObject = New-Object -TypeName PSObject $localUserExpirationObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $localUserExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vmName $localUserExpirationObject | Add-Member -NotePropertyName "User" -NotePropertyValue $user $localUserExpirationObject | Add-Member -NotePropertyName "Min Days" -NotePropertyValue $(($localUserPasswordExpiration | Where-Object { $_.Setting -match "Minimum number of days between password change" }).Value) $localUserExpirationObject | Add-Member -NotePropertyName "Max Days" -NotePropertyValue $(($localUserPasswordExpiration | Where-Object { $_.Setting -match "Maximum number of days between password change" }).Value) $localUserExpirationObject | Add-Member -NotePropertyName "Warning Days" -NotePropertyValue $(($localUserPasswordExpiration | Where-Object { $_.Setting -match "Number of days of warning before password expires" }).Value) $allLocalUserExpirationObject += $localUserExpirationObject } else { Write-Error "Unable to retrieve password expiration policy for local user ($user) from Virtual Machine ($vmName): PRE_VALIDATION_FAILED" } } return $allLocalUserExpirationObject } else { $allLocalUserExpirationObject = New-Object System.Collections.ArrayList foreach ($user in $localUser) { if ($localUserPasswordExpiration = Get-LocalUserPasswordExpiration -vmName $vmName -guestUser $guestUser -guestPassword $guestPassword -localUser $user) { $localUserExpirationObject = New-Object -TypeName PSObject $localUserExpirationObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $localUserExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vmName $localUserExpirationObject | Add-Member -NotePropertyName "User" -NotePropertyValue $user $localUserExpirationObject | Add-Member -NotePropertyName "Min Days" -NotePropertyValue $(($localUserPasswordExpiration | Where-Object { $_.Setting -match "Minimum number of days between password change" }).Value) $localUserExpirationObject | Add-Member -NotePropertyName "Max Days" -NotePropertyValue $(($localUserPasswordExpiration | Where-Object { $_.Setting -match "Maximum number of days between password change" }).Value) $localUserExpirationObject | Add-Member -NotePropertyName "Warning Days" -NotePropertyValue $(($localUserPasswordExpiration | Where-Object { $_.Setting -match "Number of days of warning before password expires" }).Value) $allLocalUserExpirationObject += $localUserExpirationObject } else { Write-Error "Unable to retrieve password expiration policy for local user ($user) from Virtual Machine ($vmName): PRE_VALIDATION_FAILED" } } return $allLocalUserExpirationObject } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Function Get-AriaLocalUserPasswordComplexity { <# .SYNOPSIS Get password complexity for local users. .DESCRIPTION The Get-AriaLocalUserPasswordComplexity cmdlet retrieves the password complexity for local users. .EXAMPLE Get-AriaLocalUserPasswordComplexity -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -product vrli This example retrieves the password complexity from a Aria Operations for Logs appliance. .EXAMPLE Get-AriaLocalUserPasswordComplexity -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -product vrops This example retrieves the password complexity from a Aria Operations appliance. .EXAMPLE Get-AriaLocalUserPasswordComplexity -vmName [vm_name] -guestUser support -guestPassword [guest_password] -product vrni This example retrieves the password complexity from a Aria Operations for Networks appliance. .EXAMPLE Get-AriaLocalUserPasswordComplexity -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -product vra This example retrieves the password complexity from a Aria Automation appliance. .PARAMETER vmName The virtual machine name. .PARAMETER guestUser The guest user name. .PARAMETER guestPassword The guest user password. .PARAMETER product The product to retrieve the password complexity policy. One of: vrslcm, vrli, vrops, vrni, or vra. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$vmName, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$guestUser, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$guestPassword, [Parameter (Mandatory = $false)] [ValidateSet('vrslcm', 'vrops', 'vrli', 'vrni', 'vra')] [String]$product ) Try { $cmd = "cat /etc/photon-release" $output = Invoke-VMScript -VM $vmName -ScriptText $cmd -GuestUser $guestUser -GuestPassword $guestPassword -Confirm:$false $photonRelease = [regex]::match($output.ScriptOutput, '(\d+\.\d+)').Groups[1].Value $photoRelease if (($photonRelease -ge "4.0")) { $scriptCommand = "cat /etc/security/pwquality.conf" $output = Invoke-VMScript -VM $vmName -ScriptText $scriptCommand -GuestUser $guestUser -GuestPassword $guestPassword -Confirm:$false if ([regex]::Matches($output.ScriptOutput, 'dcredit = [-]?[0-9]+')) { $minNumerical = (([regex]::Matches($output.ScriptOutput, 'dcredit = [-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'ucredit = [-]?[0-9]+')) { $minUppercase = (([regex]::Matches($output.ScriptOutput, 'ucredit = [-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'lcredit = [-]?[0-9]+')) { $minLowercase = (([regex]::Matches($output.ScriptOutput, 'lcredit = [-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'ocredit = [-]?[0-9]+')) { $minSpecial = (([regex]::Matches($output.ScriptOutput, 'ocredit = [-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'minlen = [-]?[0-9]+')) { $minLen = (([regex]::Matches($output.ScriptOutput, 'minlen = [-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'minclass = [-]?[0-9]+')) { $minClass = (([regex]::Matches($output.ScriptOutput, 'minclass = [-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'difok = [-]?[0-9]+')) { $minUnique = (([regex]::Matches($output.ScriptOutput, 'difok = [-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'retry = [-]?[0-9]+')) { $retry = (([regex]::Matches($output.ScriptOutput, 'retry = [-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'maxrepeat = [-]?[0-9]+')) { $maxRepeat = (([regex]::Matches($output.ScriptOutput, 'maxrepeat = [-]?[0-9]+').Value) -Split ('='))[-1] } $scriptCommand = "cat /etc/security/pwhistory.conf" $output = Invoke-VMScript -VM $vmName -ScriptText $scriptCommand -GuestUser $guestUser -GuestPassword $guestPassword -Confirm:$false if ([regex]::Matches($output.ScriptOutput, 'remember = [-]?[0-9]+')) { $history = (([regex]::Matches($output.ScriptOutput, 'remember = [-]?[0-9]+').Value) -Split ('='))[-1] } } elseif ($product -ne 'vrni' -and $photonRelease -lt "4.0") { $scriptCommand = "cat /etc/pam.d/system-password" $output = Invoke-VMScript -VM $vmName -ScriptText $scriptCommand -GuestUser $guestUser -GuestPassword $guestPassword -Confirm:$false if ([regex]::Matches($output.ScriptOutput, 'dcredit=[-]?[0-9]+')) { $minNumerical = (([regex]::Matches($output.ScriptOutput, 'dcredit=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'ucredit=[-]?[0-9]+')) { $minUppercase = (([regex]::Matches($output.ScriptOutput, 'ucredit=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'ocredit=[-]?[0-9]+')) { $minSpecial = (([regex]::Matches($output.ScriptOutput, 'ocredit=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'lcredit=[-]?[0-9]+')) { $minLowercase = (([regex]::Matches($output.ScriptOutput, 'lcredit=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'minlen=[-]?[0-9]+')) { $minLen = (([regex]::Matches($output.ScriptOutput, 'minlen=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'minclass=[-]?[0-9]+')) { $minClass = (([regex]::Matches($output.ScriptOutput, 'minclass=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'difok=[-]?[0-9]+')) { $minUnique = (([regex]::Matches($output.ScriptOutput, 'difok=[-]?[0-9]+').Value) -Split ('='))[-1] } if ($product -ne 'vrops' -or $product -ne 'vrli') { if ([regex]::Matches($output.ScriptOutput, 'maxsequence=[-]?[0-9]+')) { $maxSequence = (([regex]::Matches($output.ScriptOutput, 'maxsequence=[-]?[0-9]+').Value) -Split ('='))[-1] } } else { if ([regex]::Matches($output.ScriptOutput, 'maxrepeat=[-]?[0-9]+')) { $maxRepeat = (([regex]::Matches($output.ScriptOutput, 'maxrepeat=[-]?[0-9]+').Value) -Split ('='))[-1] } } if ([regex]::Matches($output.ScriptOutput, 'retry=[-]?[0-9]+')) { $retry = (([regex]::Matches($output.ScriptOutput, 'retry=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'remember=[-]?[0-9]+')) { $history = (([regex]::Matches($output.ScriptOutput, 'remember=[-]?[0-9]+').Value) -Split ('='))[-1] } } elseif ($product -eq 'vrni') { $scriptCommand = "cat /etc/pam.d/common-password" $output = Invoke-VMScript -VM $vmName -ScriptText $scriptCommand -GuestUser $guestUser -GuestPassword $guestPassword -Confirm:$false if ([regex]::Matches($output.ScriptOutput, 'dcredit=[-]?[0-9]+')) { $minNumerical = (([regex]::Matches($output.ScriptOutput, 'dcredit=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'ucredit=[-]?[0-9]+')) { $minUppercase = (([regex]::Matches($output.ScriptOutput, 'ucredit=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'ocredit=[-]?[0-9]+')) { $minSpecial = (([regex]::Matches($output.ScriptOutput, 'ocredit=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'lcredit=[-]?[0-9]+')) { $minLowercase = (([regex]::Matches($output.ScriptOutput, 'lcredit=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'minlen=[-]?[0-9]+')) { $minLen = (([regex]::Matches($output.ScriptOutput, 'minlen=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'minclass=[-]?[0-9]+')) { $minClass = (([regex]::Matches($output.ScriptOutput, 'minclass=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'difok=[-]?[0-9]+')) { $minUnique = (([regex]::Matches($output.ScriptOutput, 'difok=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'retry=[-]?[0-9]+')) { $retry = (([regex]::Matches($output.ScriptOutput, 'retry=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'remember=[-]?[0-9]+')) { $history = (([regex]::Matches($output.ScriptOutput, 'remember=[-]?[0-9]+').Value) -Split ('='))[-1] } } $passwordComplexityObject = New-Object -TypeName PSObject $passwordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vmName if ($minNumerical) { $passwordComplexityObject | Add-Member -NotePropertyName "Min Numerical" -NotePropertyValue $minNumerical } if ($minUppercase) { $passwordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" -NotePropertyValue $minUppercase } if ($minLowercase) { $passwordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" -NotePropertyValue $minLowercase } if ($minSpecial) { $passwordComplexityObject | Add-Member -NotePropertyName "Min Special" -NotePropertyValue $minSpecial } if ($minLen) { $passwordComplexityObject | Add-Member -NotePropertyName "Min Length" -NotePropertyValue $minLen } if ($minClass) { $passwordComplexityObject | Add-Member -NotePropertyName "Min Class" -NotePropertyValue $minClass } if ($minUnique) { $passwordComplexityObject | Add-Member -NotePropertyName "Min Unique" -NotePropertyValue $minUnique } if ($maxSequence) { $passwordComplexityObject | Add-Member -NotePropertyName "Max Sequence" -NotePropertyValue $maxSequence } if ($maxRepeat) { $passwordComplexityObject | Add-Member -NotePropertyName "Max Repeat" -NotePropertyValue $maxRepeat } if ($retry) { $passwordComplexityObject | Add-Member -NotePropertyName "Max Retries" -NotePropertyValue $retry } if ($history) { $passwordComplexityObject | Add-Member -NotePropertyName "History" -NotePropertyValue $history } Return $passwordComplexityObject } Catch { Write-Error $_.Exception.Message } } Function Get-AriaLocalUserAccountLockout { <# .SYNOPSIS Retrieves the password account lockout for local users. .DESCRIPTION The Get-AriaLocalUserAccountLockout cmdlets retrieves the account lockout for local users. .EXAMPLE Get-AriaLocalUserAccountLockout -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -product vrli This example retrieves the account lockout from a Aria Operations for Logs appliance. .EXAMPLE Get-AriaLocalUserAccountLockout -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -product vrops This example retrieves the account lockout from a Aria Operations appliance. .EXAMPLE Get-AriaLocalUserAccountLockout -vmName [vm_name] -guestUser support -guestPassword [guest_password] -product vrni This example retrieves the account lockout from a Aria Operations for Networks appliance. .EXAMPLE Get-AriaLocalUserAccountLockout -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -product vra This example retrieves the account lockout from a Aria Automation appliance. .PARAMETER vmName The virtual machine name. .PARAMETER guestUser The guest user name. .PARAMETER guestPassword The guest user password. .PARAMETER product The product to retrieve the account lockout. One of: vrslcm, vrli, vrops, vrni, or vra. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$vmName, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$guestUser, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$guestPassword, [Parameter (Mandatory = $false)] [ValidateSet('vra', 'vrops', 'vrli', 'vrslcm', 'vrni')] [String]$product ) Try { $cmd = "cat /etc/photon-release" $output = Invoke-VMScript -VM $vmName -ScriptText $cmd -GuestUser $guestUser -GuestPassword $guestPassword -Confirm:$false $photonRelease = [regex]::match($output.ScriptOutput, '(\d+\.\d+)').Groups[1].Value if (($photonRelease -ge "4.0")) { $scriptCommand = "cat /etc/security/faillock.conf" $output = Invoke-VMScript -VM $vmName -ScriptText $scriptCommand -GuestUser $guestUser -GuestPassword $guestPassword -Confirm:$false if ([regex]::Matches($output.ScriptOutput, 'deny = [-]?[0-9]+')) { $failures = (([regex]::Matches($output.ScriptOutput, 'deny = [-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'unlock_time = [-]?[0-9]+')) { $unlockInterval = (([regex]::Matches($output.ScriptOutput, 'unlock_time = [-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'root_unlock_time = [-]?[0-9]+')) { $rootUnlockInterval = (([regex]::Matches($output.ScriptOutput, 'root_unlock_time = [-]?[0-9]+').Value) -Split ('='))[-1] } } elseif ($product -ne 'vrni' -and $photonRelease -lt "4.0") { $scriptCommand = "cat /etc/pam.d/system-auth" $output = Invoke-VMScript -VM $vmName -ScriptText $scriptCommand -GuestUser $guestUser -GuestPassword $guestPassword -Confirm:$false if ([regex]::Matches($output.ScriptOutput, 'deny=[-]?[0-9]+')) { $failures = (([regex]::Matches($output.ScriptOutput, 'deny=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, ' unlock_time=[-]?[0-9]+')) { $unlockInterval = (([regex]::Matches($output.ScriptOutput, ' unlock_time=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'root_unlock_time=[-]?[0-9]+')) { $rootUnlockInterval = (([regex]::Matches($output.ScriptOutput, 'root_unlock_time=[-]?[0-9]+').Value) -Split ('='))[-1] } } elseif ($product -eq 'vrni') { $scriptCommand = "cat /etc/pam.d/common-auth" $output = Invoke-VMScript -VM $vmName -ScriptText $scriptCommand -GuestUser $guestUser -GuestPassword $guestPassword -Confirm:$false if ([regex]::Matches($output.ScriptOutput, 'deny=[-]?[0-9]+')) { $failures = (([regex]::Matches($output.ScriptOutput, 'deny=[-]?[0-9]+').Value) -Split ('='))[-1] } if ([regex]::Matches($output.ScriptOutput, 'unlock_time=[-]?[0-9]+')) { $unlockInterval = (([regex]::Matches($output.ScriptOutput, 'unlock_time=[-]?[0-9]+').Value) -Split ('='))[-1] } } $accountLockoutObject = New-Object -TypeName PSObject $accountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vmName if ($failures) { $accountLockoutObject | Add-Member -NotePropertyName "Max Failures" -NotePropertyValue $failures } if ($unlockInterval) { $accountLockoutObject | Add-Member -NotePropertyName "Unlock Interval (sec)" -NotePropertyValue $unlockInterval } if ($rootUnlockInterval) { $accountLockoutObject | Add-Member -NotePropertyName "Root Unlock Interval (sec)" -NotePropertyValue $rootUnlockInterval } Return $accountLockoutObject } Catch { Write-Error $_.Exception.Message } } Function Request-AriaLocalUserPasswordExpiration { <# .SYNOPSIS Retrieves the Aria product password expiration. .DESCRIPTION The Request-AriaLocalUserPasswordExpiration cmdlet retrieves the Aria Automation password expiration policy. - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to Aria Suite Lifecycle - Retrieves the password expiration policy. .EXAMPLE Request-AriaLocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra This example retrieves the password expiration policy for Aria Automation instances. .EXAMPLE Request-AriaLocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password expiration policy for Aria Automation instances and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-AriaLocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -drift This example retrieves the password expiration policy for Aria Automation instances and compares the configuration against the product defaults. .EXAMPLE Request-AriaLocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -vidm -settings directory This example retrieves the password expiration policy for Workspace ONE Access directory users. .EXAMPLE Request-AriaLocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -vidm -settings directory -vidmdrift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password expiration policy for Workspace ONE Access directory users and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-AriaLocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -vidm -settings directory -vidmdrift This example retrieves the password expiration policy for Workspace ONE Access directory users and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER product The product to retrieve the password expiration policy. One of: vrslcm. vrops, vrli, vrni, or vra. .PARAMETER vidm Switch to retrieve the password expiration policy for Workspace ONE Access. .PARAMETER settings The settings to retrieve the password expiration policy for Workspace ONE Access. One of: directory, localuser. .PARAMETER vidmdrift Switch to compare the current configuration against the product defaults or a JSON file for Workspace ONE Access. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [CmdletBinding(DefaultParameterSetName = 'novidm')] [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter(ParameterSetName = 'novidm', Mandatory = $false)] [ValidateSet('vrslcm', 'vrops', 'vrli', 'vrni', 'vra')] [String]$product, [Parameter (Mandatory = $false, ParameterSetName = "vidm")] [Switch]$vidm, [Parameter (Mandatory = $false, ParameterSetName = "vidm")] [ValidateNotNullOrEmpty()] [Switch]$vidmdrift, [Parameter (Mandatory = $false, ParameterSetName = "novidm")] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVrslcmDetails = Get-vRSLCMServerDetail -fqdn $server -username $user -password $pass)) { if (Test-vRSLCMAuthentication -server $vcfVrslcmDetails.fqdn -user $vcfVrslcmDetails.adminUser -pass $vcfVrslcmDetails.adminPass) { $version = Get-VCFManager -version $domain = Get-VCFWorkloadDomain | Select-Object name, type | Where-Object { $_.type -eq "MANAGEMENT" } if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain.name)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { } } } } } } } Try { # Aria Suite Lifecycle if ($product -eq 'vrslcm') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaLifecycle.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaLifecycle.passwordExpiration } } $allvrslcmPasswordExpirationObject = New-Object System.Collections.ArrayList if ($vrslcmPasswordExpiration = Get-AriaLocalUserPasswordExpiration -server $server -user $user -pass $pass -domain $domain.name -vmName $vcfVrslcmDetails.fqdn.split('.')[0] -guestUser $vcfVrslcmDetails.rootUser -guestPassword $vcfVrslcmDetails.rootPassword -localUser "root") { $vrslcmPasswordExpirationObject = New-Object -TypeName PSObject $vrslcmPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vrslcmPasswordExpiration.system $vrslcmPasswordExpirationObject | Add-Member -NotePropertyName "Local User" -NotePropertyValue "root" $vrslcmPasswordExpirationObject | Add-Member -NotePropertyName "Minimum (days)" $(if ($null -eq $vrslcmPasswordExpiration.'Min Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordExpiration.'Min Days') -ne $requiredConfig.minDays) { "$($vrslcmPasswordExpiration.'Min Days') [ $($requiredConfig.minDays) ]" } else { "$($vrslcmPasswordExpiration.'Min Days')" } } else { "$($vrslcmPasswordExpiration.'Min Days')" }) }) $vrslcmPasswordExpirationObject | Add-Member -NotePropertyName "Maximum (days)" $(if ($null -eq $vrslcmPasswordExpiration.'Max Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordExpiration.'Max Days') -ne $requiredConfig.maxDays) { "$($vrslcmPasswordExpiration.'Max Days') [ $($requiredConfig.maxDays) ]" } else { "$($vrslcmPasswordExpiration.'Max Days')" } } else { "$($vrslcmPasswordExpiration.'Max Days')" }) }) $vrslcmPasswordExpirationObject | Add-Member -NotePropertyName "Warning (days)" $(if ($null -eq $vrslcmPasswordExpiration.'Warning Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordExpiration.'Warning Days') -ne $requiredConfig.warningDays) { "$($vrslcmPasswordExpiration.'Warning Days') [ $($requiredConfig.warningDays) ]" } else { "$($vrslcmPasswordExpiration.'Warning Days')" } } else { "$($vrslcmPasswordExpiration.'Warning Days')" }) }) $allvrslcmPasswordExpirationObject += $vrslcmPasswordExpirationObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Suite Lifecycle ($node): PRE_VALIDATION_FAILED" } return $allvrslcmPasswordExpirationObject } # Aria Operation if ($product -eq 'vrops') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaOperations.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaOperations.passwordExpiration } } $vropsnodes = ((Get-vRSLCMProductDetails -productId vrops).nodes).properties.hostName $allvropsPasswordExpirationObject = New-Object System.Collections.ArrayList foreach ($node in $vropsnodes) { $vropspassword = (Get-vRSLCMProductPassword -productId vrops -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vropsusername = (Get-vRSLCMLockerPassword -vmid $vropspassword.passwordvmid).userName if ($vropsPasswordExpiration = Get-AriaLocalUserPasswordExpiration -server $server -user $user -pass $pass -domain $domain.name -vmName $node.split('.')[0] -guestUser $vropsusername -guestPassword $vropspassword.password -localUser "root") { $vropsPasswordExpirationObject = New-Object -TypeName PSObject $vropsPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vropsPasswordExpiration.system $vropsPasswordExpirationObject | Add-Member -NotePropertyName "Local User" -NotePropertyValue "root" $vropsPasswordExpirationObject | Add-Member -NotePropertyName "Minimum (days)" $(if ($null -eq $vropsPasswordExpiration.'Min Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordExpiration.'Min Days') -ne $requiredConfig.minDays) { "$($vropsPasswordExpiration.'Min Days') [ $($requiredConfig.minDays) ]" } else { "$($vropsPasswordExpiration.'Min Days')" } } else { "$($vropsPasswordExpiration.'Min Days')" }) }) $vropsPasswordExpirationObject | Add-Member -NotePropertyName "Maximum (days)" $(if ($null -eq $vropsPasswordExpiration.'Max Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordExpiration.'Max Days') -ne $requiredConfig.maxDays) { "$($vropsPasswordExpiration.'Max Days') [ $($requiredConfig.maxDays) ]" } else { "$($vropsPasswordExpiration.'Max Days')" } } else { "$($vropsPasswordExpiration.'Max Days')" }) }) $vropsPasswordExpirationObject | Add-Member -NotePropertyName "Warning (days)" $(if ($null -eq $vropsPasswordExpiration.'Warning Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordExpiration.'Warning Days') -ne $requiredConfig.warningDays) { "$($vropsPasswordExpiration.'Warning Days') [ $($requiredConfig.warningDays) ]" } else { "$($vropsPasswordExpiration.'Warning Days')" } } else { "$($vropsPasswordExpiration.'Warning Days')" }) }) $allvropsPasswordExpirationObject += $vropsPasswordExpirationObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations ($node): PRE_VALIDATION_FAILED" } if ($vropsPasswordExpiration = Get-AriaLocalUserPasswordExpiration -server $server -user $user -pass $pass -domain $domain.name -vmName $node.split('.')[0] -guestUser $vropsusername -guestPassword $vropspassword.password -localUser "admin") { $vropsPasswordExpirationObject = New-Object -TypeName PSObject $vropsPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vropsPasswordExpiration.system $vropsPasswordExpirationObject | Add-Member -NotePropertyName "Local User" -NotePropertyValue "admin" $vropsPasswordExpirationObject | Add-Member -NotePropertyName "Minimum (days)" $(if ($null -eq $vropsPasswordExpiration.'Min Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordExpiration.'Min Days') -ne $requiredConfig.minDays) { "$($vropsPasswordExpiration.'Min Days') [ $($requiredConfig.minDays) ]" } else { "$($vropsPasswordExpiration.'Min Days')" } } else { "$($vropsPasswordExpiration.'Min Days')" }) }) $vropsPasswordExpirationObject | Add-Member -NotePropertyName "Maximum (days)" $(if ($null -eq $vropsPasswordExpiration.'Max Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordExpiration.'Max Days') -ne $requiredConfig.maxDays) { "$($vropsPasswordExpiration.'Max Days') [ $($requiredConfig.maxDays) ]" } else { "$($vropsPasswordExpiration.'Max Days')" } } else { "$($vropsPasswordExpiration.'Max Days')" }) }) $vropsPasswordExpirationObject | Add-Member -NotePropertyName "Warning (days)" $(if ($null -eq $vropsPasswordExpiration.'Warning Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordExpiration.'Warning Days') -ne $requiredConfig.warningDays) { "$($vropsPasswordExpiration.'Warning Days') [ $($requiredConfig.warningDays) ]" } else { "$($vropsPasswordExpiration.'Warning Days')" } } else { "$($vropsPasswordExpiration.'Warning Days')" }) }) $allvropsPasswordExpirationObject += $vropsPasswordExpirationObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations ($node): PRE_VALIDATION_FAILED" } } return $allvropsPasswordExpirationObject } # Aria Operatons for Logs if ($product -eq 'vrli') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaOperationsLogs.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaOperationsLogs.passwordExpiration } } $vrlinodes = ((Get-vRSLCMProductDetails -productId vrli).nodes).properties.hostName $allvrliPasswordExpirationObject = New-Object System.Collections.ArrayList foreach ($node in $vrlinodes) { $vrlipassword = (Get-vRSLCMProductPassword -productId vrli -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) if ($vrliPasswordExpiration = Get-AriaLocalUserPasswordExpiration -server $server -user $user -pass $pass -domain $domain.name -vmName $node.split('.')[0] -guestUser root -guestPassword $vrlipassword.password -localUser "root") { $vrliPasswordExpirationObject = New-Object -TypeName PSObject $vrliPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vrliPasswordExpiration.system $vrliPasswordExpirationObject | Add-Member -NotePropertyName "Local User" -NotePropertyValue "root" $vrliPasswordExpirationObject | Add-Member -NotePropertyName "Minimum (days)" $(if ($null -eq $vrliPasswordExpiration.'Min Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordExpiration.'Min Days') -ne $requiredConfig.minDays) { "$($vrliPasswordExpiration.'Min Days') [ $($requiredConfig.minDays) ]" } else { "$($vrliPasswordExpiration.'Min Days')" } } else { "$($vrliPasswordExpiration.'Min Days')" }) }) $vrliPasswordExpirationObject | Add-Member -NotePropertyName "Maximum (days)" $(if ($null -eq $vrliPasswordExpiration.'Max Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordExpiration.'Max Days') -ne $requiredConfig.maxDays) { "$($vrliPasswordExpiration.'Max Days') [ $($requiredConfig.maxDays) ]" } else { "$($vrliPasswordExpiration.'Max Days')" } } else { "$($vrliPasswordExpiration.'Max Days')" }) }) $vrliPasswordExpirationObject | Add-Member -NotePropertyName "Warning (days)" $(if ($null -eq $vrliPasswordExpiration.'Warning Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordExpiration.'Warning Days') -ne $requiredConfig.warningDays) { "$($vrliPasswordExpiration.'Warning Days') [ $($requiredConfig.warningDays) ]" } else { "$($vrliPasswordExpiration.'Warning Days')" } } else { "$($vrliPasswordExpiration.'Warning Days')" }) }) $allvrliPasswordExpirationObject += $vrliPasswordExpirationObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations for Logs ($node): PRE_VALIDATION_FAILED" } } return $allvrliPasswordExpirationObject } # Aria Operations for Networks if ($product -eq 'vrni') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaOperationsNetworks.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaOperationsNetworks.passwordExpiration } } $vrninodes = ((Get-vRSLCMProductDetails -productId vrni).nodes | Select-Object type -ExpandProperty properties) $allvrniPasswordExpirationObject = New-Object System.Collections.ArrayList foreach ($node in $vrninodes) { $vrninodedata = ((Get-vRSLCMProductDetails -productId vrni).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.vmname -eq $node.vmName }) $vrnivmid = $vrninodedata.supportPassword.Split(':')[2] $vrnipassword = (Get-vRSLCMProductPassword -productId vrni -vmid $vrnivmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) if ($vrniPasswordExpiration = Get-AriaLocalUserPasswordExpiration -server $server -user $user -pass $pass -domain $domain.name -vmName $node.vmname -guestUser support -guestPassword $vrnipassword.password -localUser "support" -sudo) { $vrniPasswordExpirationObject = New-Object -TypeName PSObject $vrniPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vrniPasswordExpiration.system $vrniPasswordExpirationObject | Add-Member -NotePropertyName "Local User" -NotePropertyValue "support" $vrniPasswordExpirationObject | Add-Member -NotePropertyName "Minimum (days)" $(if ($null -eq $vrniPasswordExpiration.'Min Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordExpiration.'Min Days') -ne $requiredConfig.minDays) { "$($vrniPasswordExpiration.'Min Days') [ $($requiredConfig.minDays) ]" } else { "$($vrniPasswordExpiration.'Min Days')" } } else { "$($vrniPasswordExpiration.'Min Days')" }) }) $vrniPasswordExpirationObject | Add-Member -NotePropertyName "Maximum (days)" $(if ($null -eq $vrniPasswordExpiration.'Max Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordExpiration.'Max Days') -ne $requiredConfig.maxDays) { "$($vrniPasswordExpiration.'Max Days') [ $($requiredConfig.maxDays) ]" } else { "$($vrniPasswordExpiration.'Max Days')" } } else { "$($vrniPasswordExpiration.'Max Days')" }) }) $vrniPasswordExpirationObject | Add-Member -NotePropertyName "Warning (days)" $(if ($null -eq $vrniPasswordExpiration.'Warning Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordExpiration.'Warning Days') -ne $requiredConfig.warningDays) { "$($vrniPasswordExpiration.'Warning Days') [ $($requiredConfig.warningDays) ]" } else { "$($vrniPasswordExpiration.'Warning Days')" } } else { "$($vrniPasswordExpiration.'Warning Days')" }) }) $allvrniPasswordExpirationObject += $vrniPasswordExpirationObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations for Networks ($node): PRE_VALIDATION_FAILED" } if ($vrniPasswordExpiration = Get-AriaLocalUserPasswordExpiration -server $server -user $user -pass $pass -domain $domain.name -vmName $node.vmName -guestUser support -guestPassword $vrnipassword.password -localUser "consoleuser" -sudo) { $vrniPasswordExpirationObject = New-Object -TypeName PSObject $vrniPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vrniPasswordExpiration.system $vrniPasswordExpirationObject | Add-Member -NotePropertyName "Local User" -NotePropertyValue "consoleuser" $vrniPasswordExpirationObject | Add-Member -NotePropertyName "Minimum (days)" $(if ($null -eq $vrniPasswordExpiration.'Min Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordExpiration.'Min Days') -ne $requiredConfig.minDays) { "$($vrniPasswordExpiration.'Min Days') [ $($requiredConfig.minDays) ]" } else { "$($vrniPasswordExpiration.'Min Days')" } } else { "$($vrniPasswordExpiration.'Min Days')" }) }) $vrniPasswordExpirationObject | Add-Member -NotePropertyName "Maximum (days)" $(if ($null -eq $vrniPasswordExpiration.'Max Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordExpiration.'Max Days') -ne $requiredConfig.maxDays) { "$($vrniPasswordExpiration.'Max Days') [ $($requiredConfig.maxDays) ]" } else { "$($vrniPasswordExpiration.'Max Days')" } } else { "$($vrniPasswordExpiration.'Max Days')" }) }) $vrniPasswordExpirationObject | Add-Member -NotePropertyName "Warning (days)" $(if ($null -eq $vrniPasswordExpiration.'Warning Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordExpiration.'Warning Days') -ne $requiredConfig.warningDays) { "$($vrniPasswordExpiration.'Warning Days') [ $($requiredConfig.warningDays) ]" } else { "$($vrniPasswordExpiration.'Warning Days')" } } else { "$($vrniPasswordExpiration.'Warning Days')" }) }) $allvrniPasswordExpirationObject += $vrniPasswordExpirationObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations for Networks ($node): PRE_VALIDATION_FAILED" } } return $allvrniPasswordExpirationObject } # Aria Automation if ($product -eq 'vra') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaAutomation.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaAutomation.passwordExpiration } } $vranodes = ((Get-vRSLCMProductDetails -productId vra).nodes).properties.hostName $allvraPasswordExpirationObject = New-Object System.Collections.ArrayList foreach ($node in $vranodes) { $vrapassword = (Get-vRSLCMProductPassword -productId vra -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vrausername = (Get-vRSLCMLockerPassword -vmid $vrapassword.passwordvmid).userName if ($vraPasswordExpiration = Get-AriaLocalUserPasswordExpiration -server $server -user $user -pass $pass -domain $domain.name -vmName $node.split('.')[0] -guestUser $vrausername -guestPassword $vrapassword.password -localUser "root") { $vraPasswordExpirationObject = New-Object -TypeName PSObject $vraPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vraPasswordExpiration.system $vraPasswordExpirationObject | Add-Member -NotePropertyName "Local User" -NotePropertyValue "root" $vraPasswordExpirationObject | Add-Member -NotePropertyName "Minimum (days)" $(if ($null -eq $vraPasswordExpiration.'Min Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordExpiration.'Min Days') -ne $requiredConfig.minDays) { "$($vraPasswordExpiration.'Min Days') [ $($requiredConfig.minDays) ]" } else { "$($vraPasswordExpiration.'Min Days')" } } else { "$($vraPasswordExpiration.'Min Days')" }) }) $vraPasswordExpirationObject | Add-Member -NotePropertyName "Maximum (days)" $(if ($null -eq $vraPasswordExpiration.'Max Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordExpiration.'Max Days') -ne $requiredConfig.maxDays) { "$($vraPasswordExpiration.'Max Days') [ $($requiredConfig.maxDays) ]" } else { "$($vraPasswordExpiration.'Max Days')" } } else { "$($vraPasswordExpiration.'Max Days')" }) }) $vraPasswordExpirationObject | Add-Member -NotePropertyName "Warning (days)" $(if ($null -eq $vraPasswordExpiration.'Warning Days') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordExpiration.'Warning Days') -ne $requiredConfig.warningDays) { "$($vraPasswordExpiration.'Warning Days') [ $($requiredConfig.warningDays) ]" } else { "$($vraPasswordExpiration.'Warning Days')" } } else { "$($vraPasswordExpiration.'Warning Days')" }) }) $allvraPasswordExpirationObject += $vraPasswordExpirationObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Automation ($node): PRE_VALIDATION_FAILED" } } return $allvraPasswordExpirationObject } # Workspace ONE Access if ($vidm) { if ($vidmdrift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).wsaDirectory.passwordExpiration } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).wsaDirectory.passwordExpiration } } $vidmnodes = ((Get-vRSLCMProductDetails -productId vidm).nodes | Where-Object { $_.type -ne 'vidm-connector' }).properties.hostName $allvidmPasswordDirectoryExpirationObject = New-Object System.Collections.ArrayList foreach ($node in $vidmnodes) { $vidmdirectorynodedata = ((Get-vRSLCMProductDetails -productId vidm).properties) $vidmdirectoryvmid = $vidmdirectorynodedata.defaultConfigurationPassword.split(':')[2] $vidmdirectorypassword = (Get-vRSLCMProductPassword -productId vidm -vmid $vidmdirectoryvmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vidmdirectoryusername = $vidmdirectorynodedata.defaultConfigurationUsername if (Test-WsaConnection -server $node) { if (Test-WsaAuthentication -server $node -user $vidmdirectoryusername -pass $vidmdirectorypassword.password) { if ($vidmPasswordExpiration = Get-WsaPasswordPolicy) { $vidmPasswordExpirationObject = New-Object -TypeName PSObject $vidmPasswordExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue ($node.Split("."))[-0] $vidmPasswordExpirationObject | Add-Member -NotePropertyName "Password Lifetime (days)" -NotePropertyValue $(if ($vidmdrift) { if (($vidmPasswordExpiration.passwordTtlInHours / 24) -ne $requiredConfig.passwordLifetime) { "$(($vidmPasswordExpiration.passwordTtlInHours / 24)) [ $($requiredConfig.passwordLifetime) ]" } else { "$(($vidmPasswordExpiration.passwordTtlInHours / 24))" } } else { "$(($vidmPasswordExpiration.passwordTtlInHours / 24))" }) $vidmPasswordExpirationObject | Add-Member -NotePropertyName "Password Reminder (days)" -NotePropertyValue $(if ($vidmdrift) { if (($vidmPasswordExpiration.notificationThreshold / 24 / 3600 / 1000) -ne $requiredConfig.passwordReminder) { "$(($vidmPasswordExpiration.notificationThreshold / 24 / 3600 / 1000)) [ $($requiredConfig.passwordReminder) ]" } else { "$(($vidmPasswordExpiration.notificationThreshold / 24 / 3600 / 1000))" } } else { "$(($vidmPasswordExpiration.notificationThreshold / 24 / 3600 / 1000))" }) $vidmPasswordExpirationObject | Add-Member -NotePropertyName "Temporary Password (hours)" -NotePropertyValue $(if ($vidmdrift) { if ($vidmPasswordExpiration.tempPasswordTtl -ne $requiredConfig.temporaryPassword) { "$($vidmPasswordExpiration.tempPasswordTtl) [ $($requiredConfig.temporaryPassword) ]" } else { "$($vidmPasswordExpiration.tempPasswordTtl)" } } else { "$($vidmPasswordExpiration.tempPasswordTtl)" }) $vidmPasswordExpirationObject | Add-Member -NotePropertyName "Password Reminder Frequency (days)" -NotePropertyValue $(if ($vidmdrift) { if (($vidmPasswordExpiration.notificationInterval / 24 / 3600 / 1000) -ne $requiredConfig.temporaryPassword) { "$(($vidmPasswordExpiration.notificationInterval / 24 / 3600 / 1000)) [ $($requiredConfig.temporaryPassword) ]" } else { "$(($vidmPasswordExpiration.notificationInterval / 24 / 3600 / 1000))" } } else { "$(($vidmPasswordExpiration.notificationInterval / 24 / 3600 / 1000))" }) $allvidmPasswordDirectoryExpirationObject += $vidmPasswordExpirationObject } else { Write-Error "Unable to retrieve password expiration policy from Workspace ONE Access instance ($node): PRE_VALIDATION_FAILED" } } } } return $allvidmPasswordDirectoryExpirationObject } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-AriaLocalUserPasswordExpiration Function Request-AriaLocalUserPasswordComplexity { <# .SYNOPSIS Retrieves the Aria product password complexity. .DESCRIPTION The Request-AriaLocalUserPasswordComplexity cmdlet retrieves the Aria Automation password expiration policy. - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to Aria Suite Lifecycle - Retrieves the password complexity policy. .EXAMPLE Request-AriaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra This example retrieves the password complexity policy for Aria Automation instances. .EXAMPLE Request-AriaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password complexity policy for Aria Automation instances and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-AriaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -drift This example retrieves the password complexity policy for Aria Automation instances and compares the configuration against the product defaults. .EXAMPLE Request-AriaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -vidm -settings directory. This example retrieves the password complexity policy for Workspace ONE Access directory users. .EXAMPLE Request-AriaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -vidm -settings directory -vidmdrift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password complexity policy for Workspace ONE Access directory users and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-AriaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -vidm -settings directory -vidmdrift This example retrieves the password complexity policy for Workspace ONE Access directory users and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER product The product to retrieve the password complexity policy. One of: vrslcm. vrops, vrli, vrni, or vra. .PARAMETER vidm Switch to retrieve the password complexity policy for Workspace ONE Access. .PARAMETER settings The settings to retrieve the password complexity policy for Workspace ONE Access. One of: directory, localuser. .PARAMETER vidmdrift Switch to compare the current configuration against the product defaults or a JSON file for Workspace ONE Access. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [CmdletBinding(DefaultParameterSetName = 'novidm')] [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter(ParameterSetName = 'novidm', Mandatory = $false)] [ValidateSet('vrslcm', 'vrops', 'vrli', 'vrni', 'vra')] [String]$product, [Parameter (Mandatory = $false, ParameterSetName = "vidm")] [Switch]$vidm, [Parameter(ParameterSetName = 'vidm', Mandatory = $true)] [ValidateSet('directory', 'localuser')] [String]$settings, [Parameter (Mandatory = $false, ParameterSetName = "vidm")] [ValidateNotNullOrEmpty()] [Switch]$vidmdrift, [Parameter (Mandatory = $false, ParameterSetName = "novidm")] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVrslcmDetails = Get-vRSLCMServerDetail -fqdn $server -username $user -password $pass)) { if (Test-vRSLCMAuthentication -server $vcfVrslcmDetails.fqdn -user $vcfVrslcmDetails.adminUser -pass $vcfVrslcmDetails.adminPass) { $version = Get-VCFManager -version $domain = Get-VCFWorkloadDomain | Select-Object name, type | Where-Object { $_.type -eq "MANAGEMENT" } if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain.name)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { } } } } } } } Try { # Aria Suite Lifecycle if ($product -eq 'vrslcm') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaLifecycle.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaLifecycle.passwordComplexity } } $allvrslcmPasswordComplexityObject = New-Object System.Collections.ArrayList if ($vrslcmPasswordComplexity = Get-AriaLocalUserPasswordComplexity -vmName $vcfVrslcmDetails.fqdn.split('.')[0] -guestUser $vcfVrslcmDetails.rootUser -guestPassword $vcfVrslcmDetails.rootPassword -product vrslcm) { $vrslcmPasswordComplexityObject = New-Object -TypeName PSObject $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vrslcmPasswordComplexity.system $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" $(if ($null -eq $vrslcmPasswordComplexity.'Min Numerical') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordComplexity.'Min Numerical').trim() -ne $requiredConfig.minNumerical.trim()) { "$($vrslcmPasswordComplexity.'Min Numerical') [ $($requiredConfig.minNumerical) ]" } else { "$($vrslcmPasswordComplexity.'Min Numerical')" } } else { "$($vrslcmPasswordComplexity.'Min Numerical')" }) }) $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" $(if ($null -eq $vrslcmPasswordComplexity.'Min Uppercase') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordComplexity.'Min Uppercase').trim() -ne $requiredConfig.minUppercase.trim()) { "$($vrslcmPasswordComplexity.'Min Uppercase') [ $($requiredConfig.minUppercase) ]" } else { "$($vrslcmPasswordComplexity.'Min Uppercase')" } } else { "$($vrslcmPasswordComplexity.'Min Uppercase')" }) }) $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" $(if ($null -eq $vrslcmPasswordComplexity.'Min Lowercase') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordComplexity.'Min Lowercase').trim() -ne $requiredConfig.minLowercase.trim()) { "$($vrslcmPasswordComplexity.'Min Lowercase') [ $($requiredConfig.minLowercase) ]" } else { "$($vrslcmPasswordComplexity.'Min Lowercase')" } } else { "$($vrslcmPasswordComplexity.'Min Uppercase')" }) }) $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" $(if ($null -eq $vrslcmPasswordComplexity.'Min Special') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordComplexity.'Min Special').trim() -ne $requiredConfig.minSpecial.trim()) { "$($vrslcmPasswordComplexity.'Min Special') [ $($requiredConfig.minSpecial) ]" } else { "$($vrslcmPasswordComplexity.'Min Special')" } } else { "$($vrslcmPasswordComplexity.'Min Special')" }) }) $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" $(if ($null -eq $vrslcmPasswordComplexity.'Min Length') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordComplexity.'Min Length').trim() -ne $requiredConfig.minLength.trim()) { "$($vrslcmPasswordComplexity.'Min Length') [ $($requiredConfig.minLength) ]" } else { "$($vrslcmPasswordComplexity.'Min Length')" } } else { "$($vrslcmPasswordComplexity.'Min Length')" }) }) $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" $(if ($null -eq $vrslcmPasswordComplexity.'Min Unique') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordComplexity.'Min Unique').trim() -ne $requiredConfig.minUnique.trim()) { "$($vrslcmPasswordComplexity.'Min Unique') [ $($requiredConfig.minUnique) ]" } else { "$($vrslcmPasswordComplexity.'Min Unique')" } } else { "$($vrslcmPasswordComplexity.'Min Unique')" }) }) $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "Min Class" $(if ($null -eq $vrslcmPasswordComplexity.'Min Class') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordComplexity.'Min Class').trim() -ne $requiredConfig.minClass.trim()) { "$($vrslcmPasswordComplexity.'Min Class') [ $($requiredConfig.minClass) ]" } else { "$($vrslcmPasswordComplexity.'Min Class')" } } else { "$($vrslcmPasswordComplexity.'Min Class')" }) }) if ($vrslcmPasswordComplexity -match "Max Sequence") { $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "Max Sequence" $(if ($null -eq $vrslcmPasswordComplexity.'Max Sequence') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordComplexity.'Max Sequence').trim() -ne $requiredConfig.maxSequence.trim()) { "$($vrslcmPasswordComplexity.'Max Sequence') [ $($requiredConfig.maxSequence) ]" } else { "$($vrslcmPasswordComplexity.'Max Sequence')" } } else { "$($vrslcmPasswordComplexity.'Max Sequence')" }) }) } $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "Max Retries" $(if ($null -eq $vrslcmPasswordComplexity.'Max Retries') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordComplexity.'Max Retries').trim() -ne $requiredConfig.retries.trim()) { "$($vrslcmPasswordComplexity.'Max Retries') [ $($requiredConfig.retries) ]" } else { "$($vrslcmPasswordComplexity.'Max Retries')" } } else { "$($vrslcmPasswordComplexity.'Max Retries')" }) }) $vrslcmPasswordComplexityObject | Add-Member -NotePropertyName "History" $(if ($null -eq $vrslcmPasswordComplexity.History) { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmPasswordComplexity.History).trim() -ne $requiredConfig.history.trim()) { "$($vrslcmPasswordComplexity.History) [ $($requiredConfig.history) ]" } else { "$($vrslcmPasswordComplexity.History)" } } else { "$($vrslcmPasswordComplexity.History)" }) }) $allvrslcmPasswordComplexityObject += $vrslcmPasswordComplexityObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Suite Lifecycle ($node): PRE_VALIDATION_FAILED" } return $allvrslcmPasswordComplexityObject } # Aria Operations if ($product -eq 'vrops') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaOperations.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaOperations.passwordComplexity } } $vropsnodes = ((Get-vRSLCMProductDetails -productId vrops).nodes).properties.hostName $allvropsPasswordComplexityObject = New-Object System.Collections.ArrayList foreach ($node in $vropsnodes) { $vropspassword = (Get-vRSLCMProductPassword -productId vrops -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vropsusername = (Get-vRSLCMLockerPassword -vmid $vropspassword.passwordvmid).userName if ($vropsPasswordComplexity = Get-AriaLocalUserPasswordComplexity -vmName $node.split('.')[0] -guestUser $vropsusername -guestPassword $vropspassword.password -product vrops) { $vropsPasswordComplexityObject = New-Object -TypeName PSObject $vropsPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vropsPasswordComplexity.system $vropsPasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" $(if ($null -eq $vropsPasswordComplexity.'Min Numerical') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordComplexity.'Min Numerical').trim() -ne $requiredConfig.minNumerical.trim()) { "$($vropsPasswordComplexity.'Min Numerical') [ $($requiredConfig.minNumerical) ]" } else { "$($vropsPasswordComplexity.'Min Numerical')" } } else { "$($vropsPasswordComplexity.'Min Numerical')" }) }) $vropsPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" $(if ($null -eq $vropsPasswordComplexity.'Min Uppercase') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordComplexity.'Min Uppercase').trim() -ne $requiredConfig.minUppercase.trim()) { "$($vropsPasswordComplexity.'Min Uppercase') [ $($requiredConfig.minUppercase) ]" } else { "$($vropsPasswordComplexity.'Min Uppercase')" } } else { "$($vropsPasswordComplexity.'Min Uppercase')" }) }) $vropsPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" $(if ($null -eq $vropsPasswordComplexity.'Min Lowercase') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordComplexity.'Min Lowercase').trim() -ne $requiredConfig.minLowercase.trim()) { "$($vropsPasswordComplexity.'Min Lowercase') [ $($requiredConfig.minLowercase) ]" } else { "$($vropsPasswordComplexity.'Min Lowercase')" } } else { "$($vropsPasswordComplexity.'Min Uppercase')" }) }) $vropsPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" $(if ($null -eq $vropsPasswordComplexity.'Min Special') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordComplexity.'Min Special').trim() -ne $requiredConfig.minSpecial.trim()) { "$($vropsPasswordComplexity.'Min Special') [ $($requiredConfig.minSpecial) ]" } else { "$($vropsPasswordComplexity.'Min Special')" } } else { "$($vropsPasswordComplexity.'Min Special')" }) }) $vropsPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" $(if ($null -eq $vropsPasswordComplexity.'Min Length') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordComplexity.'Min Length').trim() -ne $requiredConfig.minLength.trim()) { "$($vropsPasswordComplexity.'Min Length') [ $($requiredConfig.minLength) ]" } else { "$($vropsPasswordComplexity.'Min Length')" } } else { "$($vropsPasswordComplexity.'Min Length')" }) }) $vropsPasswordComplexityObject | Add-Member -NotePropertyName "Min Class" $(if ($null -eq $vropsPasswordComplexity.'Min Class') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordComplexity.'Min Class').trim() -ne $requiredConfig.minClass.trim()) { "$($vropsPasswordComplexity.'Min Class') [ $($requiredConfig.minClass) ]" } else { "$($vropsPasswordComplexity.'Min Class')" } } else { "$($vropsPasswordComplexity.'Min Class')" }) }) $vropsPasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" $(if ($null -eq $vropsPasswordComplexity.'Min Unique') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordComplexity.'Min Unique').trim() -ne $requiredConfig.minUnique.trim()) { "$($vropsPasswordComplexity.'Min Unique') [ $($requiredConfig.minUnique) ]" } else { "$($vropsPasswordComplexity.'Min Unique')" } } else { "$($vropsPasswordComplexity.'Min Unique')" }) }) $vropsPasswordComplexityObject | Add-Member -NotePropertyName "Max Retries" $(if ($null -eq $vropsPasswordComplexity.'Max Retries') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordComplexity.'Max Retries').trim() -ne $requiredConfig.retries.trim()) { "$($vropsPasswordComplexity.'Max Retries') [ $($requiredConfig.retries) ]" } else { "$($vropsPasswordComplexity.'Max Retries')" } } else { "$($vropsPasswordComplexity.'Max Retries')" }) }) $vropsPasswordComplexityObject | Add-Member -NotePropertyName "Max Repeat" $(if ($null -eq $vropsPasswordComplexity.'Max Repeat') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordComplexity.'Max Repeat') -ne $requiredConfig.maxRepeat) { "$($vropsPasswordComplexity.'Max Repeat') [ $($requiredConfig.maxSequence) ]" } else { "$($vropsPasswordComplexity.'Max Repeat')" } } else { "$($vropsPasswordComplexity.'Max Repeat')" }) }) $vropsPasswordComplexityObject | Add-Member -NotePropertyName "History" $(if ($null -eq $vropsPasswordComplexity.History) { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsPasswordComplexity.History).trim() -ne $requiredConfig.history.trim()) { "$($vropsPasswordComplexity.History) [ $($requiredConfig.history) ]" } else { "$($vropsPasswordComplexity.History)" } } else { "$($vropsPasswordComplexity.History)" }) }) $allvropsPasswordComplexityObject += $vropsPasswordComplexityObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations ($node): PRE_VALIDATION_FAILED" } } return $allvropsPasswordComplexityObject } # Aria Operatons for Logs if ($product -eq 'vrli') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaOperationsLogs.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaOperationsLogs.passwordComplexity } } $vrlinodes = ((Get-vRSLCMProductDetails -productId vrli).nodes).properties.hostName $allvrliPasswordComplexityObject = New-Object System.Collections.ArrayList foreach ($node in $vrlinodes) { $vrlipassword = (Get-vRSLCMProductPassword -productId vrli -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) if ($vrliPasswordComplexity = Get-AriaLocalUserPasswordComplexity -vmName $node.split('.')[0] -guestUser root -guestPassword $vrlipassword.password -product vrli) { $vrliPasswordComplexityObject = New-Object -TypeName PSObject $vrliPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vrliPasswordComplexity.system $vrliPasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" $(if ($null -eq $vrliPasswordComplexity.'Min Numerical') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordComplexity.'Min Numerical').trim() -ne $requiredConfig.minNumerical.trim()) { "$($vrliPasswordComplexity.'Min Numerical') [ $($requiredConfig.minNumerical) ]" } else { "$($vrliPasswordComplexity.'Min Numerical')" } } else { "$($vrliPasswordComplexity.'Min Numerical')" }) }) $vrliPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" $(if ($null -eq $vrliPasswordComplexity.'Min Uppercase') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordComplexity.'Min Uppercase').trim() -ne $requiredConfig.minUppercase.trim()) { "$($vrliPasswordComplexity.'Min Uppercase') [ $($requiredConfig.minUppercase) ]" } else { "$($vrliPasswordComplexity.'Min Uppercase')" } } else { "$($vrliPasswordComplexity.'Min Uppercase')" }) }) $vrliPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" $(if ($null -eq $vrliPasswordComplexity.'Min Lowercase') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordComplexity.'Min Lowercase').trim() -ne $requiredConfig.minLowercase.trim()) { "$($vrliPasswordComplexity.'Min Lowercase') [ $($requiredConfig.minLowercase) ]" } else { "$($vrliPasswordComplexity.'Min Lowercase')" } } else { "$($vrliPasswordComplexity.'Min Uppercase')" }) }) $vrliPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" $(if ($null -eq $vrliPasswordComplexity.'Min Special') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordComplexity.'Min Special').trim() -ne $requiredConfig.minSpecial.trim()) { "$($vrliPasswordComplexity.'Min Special') [ $($requiredConfig.minSpecial) ]" } else { "$($vrliPasswordComplexity.'Min Special')" } } else { "$($vrliPasswordComplexity.'Min Special')" }) }) $vrliPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" $(if ($null -eq $vrliPasswordComplexity.'Min Length') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordComplexity.'Min Length').trim() -ne $requiredConfig.minLength.trim()) { "$($vrliPasswordComplexity.'Min Length') [ $($requiredConfig.minLength) ]" } else { "$($vrliPasswordComplexity.'Min Length')" } } else { "$($vrliPasswordComplexity.'Min Length')" }) }) $vrliPasswordComplexityObject | Add-Member -NotePropertyName "Min Class" $(if ($null -eq $vrliPasswordComplexity.'Min Class') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordComplexity.'Min Class').trim() -ne $requiredConfig.minClass.trim()) { "$($vrliPasswordComplexity.'Min Class') [ $($requiredConfig.minClass) ]" } else { "$($vrliPasswordComplexity.'Min Class')" } } else { "$($vrliPasswordComplexity.'Min Class')" }) }) $vrliPasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" $(if ($null -eq $vrliPasswordComplexity.'Min Unique') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordComplexity.'Min Unique').trim() -ne $requiredConfig.minUnique.trim()) { "$($vrliPasswordComplexity.'Min Unique') [ $($requiredConfig.minUnique) ]" } else { "$($vrliPasswordComplexity.'Min Unique')" } } else { "$($vrliPasswordComplexity.'Min Unique')" }) }) $vrliPasswordComplexityObject | Add-Member -NotePropertyName "Max Retries" $(if ($null -eq $vrliPasswordComplexity.'Max Retries') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordComplexity.'Max Retries').trim() -ne $requiredConfig.retries.trim()) { "$($vrliPasswordComplexity.'Max Retries') [ $($requiredConfig.retries) ]" } else { "$($vrliPasswordComplexity.'Max Retries')" } } else { "$($vrliPasswordComplexity.'Max Retries')" }) }) $vrliPasswordComplexityObject | Add-Member -NotePropertyName "Max Repeat" $(if ($null -eq $vrliPasswordComplexity.'Max Repeat') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordComplexity.'Max Repeat').trim() -ne $requiredConfig.maxSequence.trim()) { "$($vrliPasswordComplexity.'Max Repeat') [ $($requiredConfig.maxSequence) ]" } else { "$($vrliPasswordComplexity.'Max Repeat')" } } else { "$($vrliPasswordComplexity.'Max Repeat')" }) }) $vrliPasswordComplexityObject | Add-Member -NotePropertyName "History" $(if ($null -eq $vrliPasswordComplexity.History) { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliPasswordComplexity.History).trim() -ne $requiredConfig.history.trim()) { "$($vrliPasswordComplexity.History) [ $($requiredConfig.history) ]" } else { "$($vrliPasswordComplexity.History)" } } else { "$($vrliPasswordComplexity.History)" }) }) $allvrliPasswordComplexityObject += $vrliPasswordComplexityObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations for Logs ($node): PRE_VALIDATION_FAILED" } } return $allvrliPasswordComplexityObject } # Aria Operations for Networks if ($product -eq 'vrni') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaOperationsNetworks.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaOperationsNetworks.passwordComplexity } } $vrninodes = ((Get-vRSLCMProductDetails -productId vrni).nodes | Select-Object type -ExpandProperty properties) $allvrniPasswordComplexityObject = New-Object System.Collections.ArrayList foreach ($node in $vrninodes) { $vrninodedata = ((Get-vRSLCMProductDetails -productId vrni).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.vmname -eq $node.vmName }) $vrnivmid = $vrninodedata.supportPassword.Split(':')[2] $vrnipassword = (Get-vRSLCMProductPassword -productId vrni -vmid $vrnivmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) if ($vrniPasswordComplexity = Get-AriaLocalUserPasswordComplexity -vmName $node.vmname -guestUser support -guestPassword $vrnipassword.password -product vrni) { $vrniPasswordComplexityObject = New-Object -TypeName PSObject $vrniPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vrniPasswordComplexity.system $vrniPasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" $(if ($null -eq $vrniPasswordComplexity.'Min Numerical') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordComplexity.'Min Numerical').trim() -ne $requiredConfig.minNumerical.trim()) { "$($vrniPasswordComplexity.'Min Numerical') [ $($requiredConfig.minNumerical) ]" } else { "$($vrniPasswordComplexity.'Min Numerical')" } } else { "$($vrniPasswordComplexity.'Min Numerical')" }) }) $vrniPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" $(if ($null -eq $vrniPasswordComplexity.'Min Uppercase') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordComplexity.'Min Uppercase').trim() -ne $requiredConfig.minUppercase.trim()) { "$($vrniPasswordComplexity.'Min Uppercase') [ $($requiredConfig.minUppercase) ]" } else { "$($vrniPasswordComplexity.'Min Uppercase')" } } else { "$($vrniPasswordComplexity.'Min Uppercase')" }) }) $vrniPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" $(if ($null -eq $vrniPasswordComplexity.'Min Lowercase') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordComplexity.'Min Lowercase').trim() -ne $requiredConfig.minLowercase.trim()) { "$($vrniPasswordComplexity.'Min Lowercase') [ $($requiredConfig.minLowercase) ]" } else { "$($vrniPasswordComplexity.'Min Lowercase')" } } else { "$($vrniPasswordComplexity.'Min Uppercase')" }) }) $vrniPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" $(if ($null -eq $vrniPasswordComplexity.'Min Special') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordComplexity.'Min Special').trim() -ne $requiredConfig.minSpecial.trim()) { "$($vrniPasswordComplexity.'Min Special') [ $($requiredConfig.minSpecial) ]" } else { "$($vrniPasswordComplexity.'Min Special')" } } else { "$($vrniPasswordComplexity.'Min Special')" }) }) $vrniPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" $(if ($null -eq $vrniPasswordComplexity.'Min Length') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordComplexity.'Min Length').trim() -ne $requiredConfig.minLength.trim()) { "$($vrniPasswordComplexity.'Min Length') [ $($requiredConfig.minLength) ]" } else { "$($vrniPasswordComplexity.'Min Length')" } } else { "$($vrniPasswordComplexity.'Min Length')" }) }) $vrniPasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" $(if ($null -eq $vrniPasswordComplexity.'Min Unique') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordComplexity.'Min Unique').trim() -ne $requiredConfig.minUnique.trim()) { "$($vrniPasswordComplexity.'Min Unique') [ $($requiredConfig.minUnique) ]" } else { "$($vrniPasswordComplexity.'Min Unique')" } } else { "$($vrniPasswordComplexity.'Min Unique')" }) }) $vrniPasswordComplexityObject | Add-Member -NotePropertyName "Max Retries" $(if ($null -eq $vrniPasswordComplexity.'Max Retries') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordComplexity.'Max Retries').trim() -ne $requiredConfig.retries.trim()) { "$($vrniPasswordComplexity.'Max Retries') [ $($requiredConfig.retries) ]" } else { "$($vrniPasswordComplexity.'Max Retries')" } } else { "$($vrniPasswordComplexity.'Max Retries')" }) }) $vrniPasswordComplexityObject | Add-Member -NotePropertyName "History" $(if ($null -eq $vrniPasswordComplexity.History) { Write-Output "Not configured." } else { $(if ($drift) { if (($vrniPasswordComplexity.History).trim() -ne $requiredConfig.history.trim()) { "$($vrniPasswordComplexity.History) [ $($requiredConfig.history) ]" } else { "$($vrniPasswordComplexity.History)" } } else { "$($vrniPasswordComplexity.History)" }) }) $allvrniPasswordComplexityObject += $vrniPasswordComplexityObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations for Networks ($node): PRE_VALIDATION_FAILED" } } return $allvrniPasswordComplexityObject } # Aria Automation if ($product -eq 'vra') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaAutomation.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaAutomation.passwordComplexity } } $vranodes = ((Get-vRSLCMProductDetails -productId vra ).nodes).properties.hostName $allvraPasswordComplexityObject = New-Object System.Collections.ArrayList foreach ($node in $vranodes) { $vrapassword = (Get-vRSLCMProductPassword -productId vra -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vrausername = (Get-vRSLCMLockerPassword -vmid $vrapassword.passwordvmid).userName if ($vraPasswordComplexity = Get-AriaLocalUserPasswordComplexity -vmName $node.split('.')[0] -guestUser $vrausername -guestPassword $vrapassword.password -product vra) { $vraPasswordComplexityObject = New-Object -TypeName PSObject $vraPasswordComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vraPasswordComplexity.system $vraPasswordComplexityObject | Add-Member -NotePropertyName "Min Numerical" $(if ($null -eq $vraPasswordComplexity.'Min Numerical') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.'Min Numerical').trim() -ne $requiredConfig.minNumerical) { "$($vraPasswordComplexity.'Min Numerical') [ $($requiredConfig.minNumerical) ]" } else { "$($vraPasswordComplexity.'Min Numerical')" } } else { "$($vraPasswordComplexity.'Min Numerical')" }) }) $vraPasswordComplexityObject | Add-Member -NotePropertyName "Min Uppercase" $(if ($null -eq $vraPasswordComplexity.'Min Uppercase') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.'Min Uppercase').trim() -ne $requiredConfig.minUppercase) { "$($vraPasswordComplexity.'Min Uppercase') [ $($requiredConfig.minUppercase) ]" } else { "$($vraPasswordComplexity.'Min Uppercase')" } } else { "$($vraPasswordComplexity.'Min Uppercase')" }) }) $vraPasswordComplexityObject | Add-Member -NotePropertyName "Min Lowercase" $(if ($null -eq $vraPasswordComplexity.'Min Lowercase') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.'Min Lowercase').trim() -ne $requiredConfig.minLowercase) { "$($vraPasswordComplexity.'Min Lowercase') [ $($requiredConfig.minLowercase) ]" } else { "$($vraPasswordComplexity.'Min Lowercase')" } } else { "$($vraPasswordComplexity.'Min Uppercase')" }) }) $vraPasswordComplexityObject | Add-Member -NotePropertyName "Min Unique" $(if ($null -eq $vraPasswordComplexity.'Min Unique') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.'Min Unique').trim() -ne $requiredConfig.minUnique) { "$($vraPasswordComplexity.'Min Unique') [ $($requiredConfig.minUnique) ]" } else { "$($vraPasswordComplexity.'Min Unique')" } } else { "$($vraPasswordComplexity.'Min Unique')" }) }) $vraPasswordComplexityObject | Add-Member -NotePropertyName "Min Length" $(if ($null -eq $vraPasswordComplexity.'Min Length') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.'Min Length').trim() -ne $requiredConfig.minLength) { "$($vraPasswordComplexity.'Min Length') [ $($requiredConfig.minLength) ]" } else { "$($vraPasswordComplexity.'Min Length')" } } else { "$($vraPasswordComplexity.'Min Length')" }) }) $vraPasswordComplexityObject | Add-Member -NotePropertyName "Min Class" $(if ($null -eq $vraPasswordComplexity.'Min Class') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.'Min Class').trim() -ne $requiredConfig.minClass) { "$($vraPasswordComplexity.'Min Class') [ $($requiredConfig.minClass) ]" } else { "$($vraPasswordComplexity.'Min Class')" } } else { "$($vraPasswordComplexity.'Min Class')" }) }) $vraPasswordComplexityObject | Add-Member -NotePropertyName "Min Special" $(if ($null -eq $vraPasswordComplexity.'Min Special') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.'Min Special').trim() -ne $requiredConfig.minSpecial) { "$($vraPasswordComplexity.'Min Special') [ $($requiredConfig.minSpecial) ]" } else { "$($vraPasswordComplexity.'Min Special')" } } else { "$($vraPasswordComplexity.'Min Special')" }) }) $vraPasswordComplexityObject | Add-Member -NotePropertyName "Max Retries" $(if ($null -eq $vraPasswordComplexity.'Max Retries') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.'Max Retries').trim() -ne $requiredConfig.retries) { "$($vraPasswordComplexity.'Max Retries') [ $($requiredConfig.retries) ]" } else { "$($vraPasswordComplexity.'Max Retries')" } } else { "$($vraPasswordComplexity.'Max Retries')" }) }) if ($vraPasswordComplexity -match "Max Repeat") { $vraPasswordComplexityObject | Add-Member -NotePropertyName "Max Repeat" $(if ($null -eq $vraPasswordComplexity.'Max Repeat') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.'Max Repeat').trim() -ne $requiredConfig.maxRepeat) { "$($vraPasswordComplexity.'Max Repeat') [ $($requiredConfig.maxRepeat) ]" } else { "$($vraPasswordComplexity.'Max Repeat')" } } else { "$($vraPasswordComplexity.'Max Repeat')" }) }) } else { $vraPasswordComplexityObject | Add-Member -NotePropertyName "Max Sequence" $(if ($null -eq $vraPasswordComplexity.'Max Sequence') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.'Max Sequence').trim() -ne $requiredConfig.maxSequence) { "$($vraPasswordComplexity.'Max Sequence') [ $($requiredConfig.maxSequence) ]" } else { "$($vraPasswordComplexity.'Max Sequence')" } } else { "$($vraPasswordComplexity.'Max Sequence')" }) }) } $vraPasswordComplexityObject | Add-Member -NotePropertyName "History" $(if ($null -eq $vraPasswordComplexity.History) { Write-Output "Not configured." } else { $(if ($drift) { if (($vraPasswordComplexity.History).trim() -ne $requiredConfig.history) { "$($vraPasswordComplexity.History) [ $($requiredConfig.history) ]" } else { "$($vraPasswordComplexity.History)" } } else { "$($vraPasswordComplexity.History)" }) }) $allvraPasswordComplexityObject += $vraPasswordComplexityObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Automation ($node): PRE_VALIDATION_FAILED" } } return $allvraPasswordComplexityObject } # Workspace ONE Access if ($vidm) { # Directory Users if ($settings -eq 'directory') { if ($vidmdrift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).wsaDirectory.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).wsaDirectory.passwordComplexity } } $vidmnodes = ((Get-vRSLCMProductDetails -productId vidm).nodes | Where-Object { $_.type -ne 'vidm-connector' }).properties.hostName $allvidmPasswordDirectoryComplexityObject = New-Object System.Collections.ArrayList foreach ($node in $vidmnodes) { $vidmdirectorynodedata = ((Get-vRSLCMProductDetails -productId vidm).properties) $vidmdirectoryvmid = $vidmdirectorynodedata.defaultConfigurationPassword.split(':')[2] $vidmdirectorypassword = (Get-vRSLCMProductPassword -productId vidm -vmid $vidmdirectoryvmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vidmdirectoryusername = $vidmdirectorynodedata.defaultConfigurationUsername if (Test-WsaConnection -server $node) { if (Test-WsaAuthentication -server $node -user $vidmdirectoryusername -pass $vidmdirectorypassword.password ) { if ($vidmPasswordDirectoryComplexity = Get-WsaPasswordPolicy) { $vidmPasswordDirectoryComplexityObject = New-Object -TypeName PSObject $vidmPasswordDirectoryComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $node.Split('.')[0] $vidmPasswordDirectoryComplexityObject | Add-Member -NotePropertyName "Min Numerical" $(if ($null -eq $vidmPasswordDirectoryComplexity.minDigit) { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmPasswordDirectoryComplexity.minDigit) -ne $requiredConfig.minNumerical) { "$($vidmPasswordDirectoryComplexity.minDigit) [ $($requiredConfig.minNumerical) ]" } else { "$($vidmPasswordDirectoryComplexity.minDigit)" } } else { "$($vidmPasswordDirectoryComplexity.minDigit)" }) }) $vidmPasswordDirectoryComplexityObject | Add-Member -NotePropertyName "Min Uppercase" $(if ($null -eq $vidmPasswordDirectoryComplexity.minUpper) { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmPasswordDirectoryComplexity.minUpper) -ne $requiredConfig.minUppercase) { "$($vidmPasswordDirectoryComplexity.minUpper) [ $($requiredConfig.minUppercase) ]" } else { "$($vidmPasswordDirectoryComplexity.minUpper)" } } else { "$($vidmPasswordDirectoryComplexity.minUpper)" }) }) $vidmPasswordDirectoryComplexityObject | Add-Member -NotePropertyName "Min Lowercase" $(if ($null -eq $vidmPasswordDirectoryComplexity.minLower) { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmPasswordDirectoryComplexity.minLower) -ne $requiredConfig.minLowercase) { "$($vidmPasswordDirectoryComplexity.minLower) [ $($requiredConfig.minLowercase) ]" } else { "$($vidmPasswordDirectoryComplexity.minLower)" } } else { "$($vidmPasswordDirectoryComplexity.minLower)" }) }) $vidmPasswordDirectoryComplexityObject | Add-Member -NotePropertyName "Max Indentical Characters" $(if ($null -eq $vidmPasswordDirectoryComplexity.maxConsecutiveIdenticalCharacters) { Write-Output "Max Indentical Characters" } else { $(if ($vidmdrift) { if (($vidmPasswordDirectoryComplexity.maxConsecutiveIdenticalCharacters) -ne $requiredConfig.maxIdenticalAdjacent) { "$($vidmPasswordDirectoryComplexity.maxConsecutiveIdenticalCharacters) [ $($requiredConfig.maxIdenticalAdjacent) ]" } else { "$($vidmPasswordDirectoryComplexity.maxConsecutiveIdenticalCharacters)" } } else { "$($vidmPasswordDirectoryComplexity.maxConsecutiveIdenticalCharacters)" }) }) $vidmPasswordDirectoryComplexityObject | Add-Member -NotePropertyName "Min Length" $(if ($null -eq $vidmPasswordDirectoryComplexity.minLen) { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmPasswordDirectoryComplexity.minLen) -ne $requiredConfig.minLength) { "$($vidmPasswordDirectoryComplexity.minLen) [ $($requiredConfig.minLength) ]" } else { "$($vidmPasswordDirectoryComplexity.minLen)" } } else { "$($vidmPasswordDirectoryComplexity.minLen)" }) }) $vidmPasswordDirectoryComplexityObject | Add-Member -NotePropertyName "Min Special" $(if ($null -eq $vidmPasswordDirectoryComplexity.minSpecial) { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmPasswordDirectoryComplexity.minSpecial) -ne $requiredConfig.minSpecial) { "$($vidmPasswordDirectoryComplexity.minSpecial) [ $($requiredConfig.minSpecial) ]" } else { "$($vidmPasswordDirectoryComplexity.minSpecial)" } } else { "$($vidmPasswordDirectoryComplexity.minSpecial)" }) }) $vidmPasswordDirectoryComplexityObject | Add-Member -NotePropertyName "History" $(if ($null -eq $vidmPasswordDirectoryComplexity.History) { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmPasswordDirectoryComplexity.History) -ne $requiredConfig.history) { "$($vidmPasswordDirectoryComplexity.History) [ $($requiredConfig.history) ]" } else { "$($vidmPasswordDirectoryComplexity.History)" } } else { "$($vidmPasswordDirectoryComplexity.History)" }) }) $allvidmPasswordDirectoryComplexityObject += $vidmPasswordDirectoryComplexityObject } } } } return $allvidmPasswordDirectoryComplexityObject } # Local Users if ($settings -eq 'localuser') { if ($vidmdrift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).wsaLocal.passwordComplexity } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).wsaLocal.passwordComplexity } } $vidmnodes = ((Get-vRSLCMProductDetails -productId vidm).nodes | Where-Object { $_.type -ne 'vidm-connector' }).properties.hostName $allvidmPasswordLocalComplexityObject = New-Object System.Collections.ArrayList foreach ($node in $vidmnodes) { $vidmlocalnodedata = ((Get-vRSLCMProductDetails -productId vidm).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.type -ne 'vidm-connector' -and $_.hostName -eq $node }) $vidmlocalvmid = $vidmlocalnodedata.vidmRootPassword.Split(':')[2] $vidmlocalpassword = (Get-vRSLCMProductPassword -productId vidm -vmid $vidmlocalvmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) if ($vidmPasswordLocalComplexity = Get-AriaLocalUserPasswordComplexity -vmName $node.split('.')[0] -guestUser root -guestPassword $vidmlocalpassword.password) { $vidmPasswordLocalComplexityObject = New-Object -TypeName PSObject $vidmPasswordLocalComplexityObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vidmPasswordLocalComplexity.system $vidmPasswordLocalComplexityObject | Add-Member -NotePropertyName "Min Length" $(if ($null -eq $vidmPasswordLocalComplexity.'Min Length') { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmPasswordLocalComplexity.'Min Length') -ne $requiredConfig.minLength) { "$($vidmPasswordLocalComplexity.'Min Length') [ $($requiredConfig.minLength) ]" } else { "$($vidmPasswordLocalComplexity.'Min Length')" } } else { "$($vidmPasswordLocalComplexity.'Min Length')" }) }) $vidmPasswordLocalComplexityObject | Add-Member -NotePropertyName "History" $(if ($null -eq $vidmPasswordLocalComplexity.History) { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmPasswordLocalComplexity.History) -ne $requiredConfig.history) { "$($vidmPasswordLocalComplexity.History) [ $($requiredConfig.history) ]" } else { "$($vidmPasswordLocalComplexity.History)" } } else { "$($vidmPasswordLocalComplexity.History)" }) }) $vidmPasswordLocalComplexityObject | Add-Member -NotePropertyName "Max Retries" $(if ($null -eq $vidmPasswordLocalComplexity.'Max Retries') { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmPasswordLocalComplexity.'Max Retries') -ne $requiredConfig.retries) { "$($vidmPasswordLocalComplexity.'Max Retries') [ $($requiredConfig.retries) ]" } else { "$($vidmPasswordLocalComplexity.'Max Retries')" } } else { "$($vidmPasswordLocalComplexity.'Max Retries')" }) }) $allvidmPasswordLocalComplexityObject += $vidmPasswordLocalComplexityObject } } return $allvidmPasswordLocalComplexityObject } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-AriaLocalUserPasswordComplexity Function Request-AriaLocalUserAccountLockout { <# .SYNOPSIS Retrieves the Aria product password account lockout. .DESCRIPTION The Request-AriaLocalUserAccountLockout cmdlet retrieves the Aria Automation password expiration policy. - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to Aria Suite Lifecycle - Retrieves the password account lockout policy. .EXAMPLE Request-AriaLocalUserAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra This example retrieves the password expiration policy for Aria Automation instances. .EXAMPLE Request-AriaLocalUserAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password expiration policy for Aria Automation instances and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-AriaLocalUserAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -drift This example retrieves the password expiration policy for Aria Automation instances and compares the configuration against the product defaults. .EXAMPLE Request-AriaLocalUserAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -vidm -settings directory This example retrieves the password expiration policy for Workspace ONE Access instances for directory users. .EXAMPLE Request-AriaLocalUserAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -vidm -settings directory -vidmdrift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the password expiration policy for Workspace ONE Access instances for directory users and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-AriaLocalUserAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -vidm -settings directory -vidmdrift This example retrieves the password expiration policy for Workspace ONE Access instances for directory users and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER product. The product to retrieve the password account lockout policy. One of: vrslcm, vrli, vrops, vrni, or vra. .PARAMETER vidm Switch to retrieve the password account lockout policy for Workspace ONE Access. .PARAMETER settings The settings to retrieve the password account lockout policy for Workspace ONE Access. One of: directory, localuser. .PARAMETER vidmdrift Switch to compare the current configuration against the product defaults or a JSON file for Workspace ONE Access. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [CmdletBinding(DefaultParameterSetName = 'novidm')] [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter(ParameterSetName = 'novidm', Mandatory = $false)] [ValidateSet('vrslcm', 'vrops', 'vrli', 'vrni', 'vra')] [String]$product, [Parameter (Mandatory = $false, ParameterSetName = "vidm")] [Switch]$vidm, [Parameter(ParameterSetName = 'vidm', Mandatory = $true)] [ValidateSet('directory', 'localuser')] [String]$settings, [Parameter (Mandatory = $false, ParameterSetName = "vidm")] [ValidateNotNullOrEmpty()] [Switch]$vidmdrift, [Parameter (Mandatory = $false, ParameterSetName = "novidm")] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVrslcmDetails = Get-vRSLCMServerDetail -fqdn $server -username $user -password $pass)) { if (Test-vRSLCMAuthentication -server $vcfVrslcmDetails.fqdn -user $vcfVrslcmDetails.adminUser -pass $vcfVrslcmDetails.adminPass) { $version = Get-VCFManager -version $domain = Get-VCFWorkloadDomain | Select-Object name, type | Where-Object { $_.type -eq "MANAGEMENT" } if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain.name)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { } } } } } } } Try { # Aria Suite Lifecycle if ($product -eq 'vrslcm') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaLifecycle.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaLifecycle.accountLockout } } $allvrslcmAccountLockoutObject = New-Object System.Collections.ArrayList if ($vrslcmAccountLockout = Get-AriaLocalUserAccountLockout -vmName $vcfVrslcmDetails.fqdn.split('.')[0] -guestUser $vcfVrslcmDetails.rootUser -guestPassword $vcfVrslcmDetails.rootPassword ) { $vrslcmAccountLockoutObject = New-Object -TypeName PSObject $vrslcmAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vrslcmAccountLockout.system $vrslcmAccountLockoutObject | Add-Member -NotePropertyName "Maximum Failures" $(if ($null -eq $vrslcmAccountLockout.'Max Failures') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmAccountLockout.'Max Failures').trim() -ne $requiredConfig.maxFailures.trim()) { "$($vrslcmAccountLockout.'Max Failures') [ $($requiredConfig.maxFailures) ]" } else { "$($vrslcmAccountLockout.'Max Failures')" } } else { "$($vrslcmAccountLockout.'Max Failures')" }) }) $vrslcmAccountLockoutObject | Add-Member -NotePropertyName "Unlock Interval" $(if ($null -eq $vrslcmAccountLockout.'Unlock Interval (sec)') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmAccountLockout.'Unlock Interval (sec)').trim() -ne $requiredConfig.unlockInterval.trim()) { "$($vrslcmAccountLockout.'Unlock Interval (sec)') [ $($requiredConfig.unlockInterval) ]" } else { "$($vrslcmAccountLockout.'Unlock Interval (sec)')" } } else { "$($vrslcmAccountLockout.'Unlock Interval (sec)')" }) }) $vrslcmAccountLockoutObject | Add-Member -NotePropertyName "Root Unlock Interval" $(if ($null -eq $vrslcmAccountLockout.'Root Unlock Interval (sec)') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrslcmAccountLockout.'Root Unlock Interval (sec)').trim() -ne $requiredConfig.rootUnlockInterval.trim()) { "$($vrslcmAccountLockout.'Root Unlock Interval (sec)') [ $($requiredConfig.rootUnlockInterval) ]" } else { "$($vrslcmAccountLockout.'Root Unlock Interval (sec)')" } } else { "$($vrslcmAccountLockout.'Root Unlock Interval (sec)')" }) }) $allvrslcmAccountLockoutObject += $vrslcmAccountLockoutObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Suite Lifecycle ($vcfVrslcmDetails.fqdn): PRE_VALIDATION_FAILED" } return $allvrslcmAccountLockoutObject } # Aria Operations if ($product -eq 'vrops') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaOperations.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaOperations.accountLockout } } $vropsnodes = ((Get-vRSLCMProductDetails -productId vrops).nodes).properties.hostName $allvropsAccountLockoutObject = New-Object System.Collections.ArrayList foreach ($node in $vropsnodes) { $vropspassword = (Get-vRSLCMProductPassword -productId vrops -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vropsusername = (Get-vRSLCMLockerPassword -vmid $vropspassword.passwordvmid).userName if ($vropsAccountLockout = Get-AriaLocalUserAccountLockout -vmName $node.split('.')[0] -guestUser $vropsusername -guestPassword $vropspassword.password ) { $vropsAccountLockoutObject = New-Object -TypeName PSObject $vropsAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vropsAccountLockout.system $vropsAccountLockoutObject | Add-Member -NotePropertyName "Maximum Failures" $(if ($null -eq $vropsAccountLockout.'Max Failures') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsAccountLockout.'Max Failures').trim() -ne $requiredConfig.maxFailures.trim()) { "$($vropsAccountLockout.'Max Failures') [ $($requiredConfig.maxFailures) ]" } else { "$($vropsAccountLockout.'Max Failures')" } } else { "$($vropsAccountLockout.'Max Failures')" }) }) $vropsAccountLockoutObject | Add-Member -NotePropertyName "Unlock Interval" $(if ($null -eq $vropsAccountLockout.'Unlock Interval (sec)') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsAccountLockout.'Unlock Interval (sec)').trim() -ne $requiredConfig.unlockInterval.trim()) { "$($vropsAccountLockout.'Unlock Interval (sec)') [ $($requiredConfig.unlockInterval) ]" } else { "$($vropsAccountLockout.'Unlock Interval (sec)')" } } else { "$($vropsAccountLockout.'Unlock Interval (sec)')" }) }) $vropsAccountLockoutObject | Add-Member -NotePropertyName "Root Unlock Interval" $(if ($null -eq $vropsAccountLockout.'Root Unlock Interval (sec)') { Write-Output "Not configured." } else { $(if ($drift) { if (($vropsAccountLockout.'Root Unlock Interval (sec)').trim() -ne $requiredConfig.rootUnlockInterval.trim()) { "$($vropsAccountLockout.'Root Unlock Interval (sec)') [ $($requiredConfig.rootUnlockInterval) ]" } else { "$($vropsAccountLockout.'Root Unlock Interval (sec)')" } } else { "$($vropsAccountLockout.'Root Unlock Interval (sec)')" }) }) $allvropsAccountLockoutObject += $vropsAccountLockoutObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations ($node): PRE_VALIDATION_FAILED" } } return $allvropsAccountLockoutObject } # Aria Operatons for Logs if ($product -eq 'vrli') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaOperationsLogs.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaOperationsLogs.accountLockout } } $vrlinodes = ((Get-vRSLCMProductDetails -productId vrli).nodes).properties.hostName $allvrliAccountLockoutObject = New-Object System.Collections.ArrayList foreach ($node in $vrlinodes) { $vrlipassword = (Get-vRSLCMProductPassword -productId vrli -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) if ($vrliAccountLockout = Get-AriaLocalUserAccountLockout -vmName $node.split('.')[0] -guestUser root -guestPassword $vrlipassword.password ) { $vrliAccountLockoutObject = New-Object -TypeName PSObject $vrliAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vrliAccountLockout.system $vrliAccountLockoutObject | Add-Member -NotePropertyName "Maximum Failures" $(if ($null -eq $vrliAccountLockout.'Max Failures') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliAccountLockout.'Max Failures').trim() -ne $requiredConfig.maxFailures.trim()) { "$($vrliAccountLockout.'Max Failures') [ $($requiredConfig.maxFailures) ]" } else { "$($vrliAccountLockout.'Max Failures')" } } else { "$($vrliAccountLockout.'Max Failures')" }) }) $vrliAccountLockoutObject | Add-Member -NotePropertyName "Unlock Interval" $(if ($null -eq $vrliAccountLockout.'Unlock Interval (sec)') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliAccountLockout.'Unlock Interval (sec)').trim() -ne $requiredConfig.unlockInterval.trim()) { "$($vrliAccountLockout.'Unlock Interval (sec)') [ $($requiredConfig.unlockInterval) ]" } else { "$($vrliAccountLockout.'Unlock Interval (sec)')" } } else { "$($vrliAccountLockout.'Unlock Interval (sec)')" }) }) $vrliAccountLockoutObject | Add-Member -NotePropertyName "Root Unlock Interval" $(if ($null -eq $vrliAccountLockout.'Root Unlock Interval (sec)') { Write-Output "Not configured." } else { $(if ($drift) { if (($vrliAccountLockout.'Root Unlock Interval (sec)').trim() -ne $requiredConfig.rootUnlockInterval.trim()) { "$($vrliAccountLockout.'Root Unlock Interval (sec)') [ $($requiredConfig.rootUnlockInterval) ]" } else { "$($vrliAccountLockout.'Root Unlock Interval (sec)')" } } else { "$($vrliAccountLockout.'Root Unlock Interval (sec)')" }) }) $allvrliAccountLockoutObject += $vrliAccountLockoutObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations for Logs ($node): PRE_VALIDATION_FAILED" } } return $allvrliAccountLockoutObject } # Aria Operations for Networks if ($product -eq 'vrni') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaOperationsNetworks.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaOperationsNetworks.accountLockout } } $vrninodes = ((Get-vRSLCMProductDetails -productId vrni).nodes | Select-Object type -ExpandProperty properties) $allvrniAccountLockoutObject = New-Object System.Collections.ArrayList foreach ($node in $vrninodes) { $vrninodedata = ((Get-vRSLCMProductDetails -productId vrni).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.vmname -eq $node.vmName }) $vrnivmid = $vrninodedata.supportPassword.Split(':')[2] $vrnipassword = (Get-vRSLCMProductPassword -productId vrni -vmid $vrnivmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) if ($vrniAccountLockout = Get-AriaLocalUserAccountLockout -vmName $node.vmname -guestUser support -guestPassword $vrnipassword.password -product vrni ) { $vrniAccountLockoutObject = New-Object -TypeName PSObject $vrniAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vrniAccountLockout.System $vrniAccountLockoutObject | Add-Member -NotePropertyName "Maximum Failures" -NotePropertyValue $(if ($null -eq $vrniAccountLockout.'Max Failures') { "Not configured." } else { $(if ($drift) { if (($vrniAccountLockout.'Max Failures').trim() -ne $requiredConfig.maxFailures.trim()) { "$($vrniAccountLockout.'Max Failures') [ $($requiredConfig.maxFailures) ]" } else { "$($vrniAccountLockout.'Max Failures')" } } else { "$($vrniAccountLockout.'Max Failures')" }) }) $vrniAccountLockoutObject | Add-Member -NotePropertyName "Unlock Interval" -NotePropertyValue $(if ($null -eq $vrniAccountLockout.'Unlock Interval (sec)') { "Not configured." } else { $(if ($drift) { if (($vrniAccountLockout.'Unlock Interval (sec)').trim() -ne $requiredConfig.unlockInterval.trim()) { "$($vrniAccountLockout.'Unlock Interval (sec)') [ $($requiredConfig.unlockInterval) ]" } else { "$($vrniAccountLockout.'Unlock Interval (sec)')" } } else { "$($vrniAccountLockout.'Unlock Interval (sec)')" }) }) $allvrniAccountLockoutObject += $vrniAccountLockoutObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Operations for Networks ($node): PRE_VALIDATION_FAILED" } } return $allvrniAccountLockoutObject } # Aria Automation if ($product -eq 'vra') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).ariaAutomation.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).ariaAutomation.accountLockout } } $vranodes = ((Get-vRSLCMProductDetails -productId vra).nodes).properties.hostName $allvraAccountLockoutObject = New-Object System.Collections.ArrayList foreach ($node in $vranodes) { $vrapassword = (Get-vRSLCMProductPassword -productId vra -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vrausername = (Get-vRSLCMLockerPassword -vmid $vrapassword.passwordvmid).userName if ($vraAccountLockout = Get-AriaLocalUserAccountLockout -vmName $node.split('.')[0] -guestUser $vrausername -guestPassword $vrapassword.password ) { $vraAccountLockoutObject = New-Object -TypeName PSObject $vraAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vraAccountLockout.system $vraAccountLockoutObject | Add-Member -NotePropertyName "Maximum Failures" $(if ($null -eq $vraAccountLockout.'Max Failures') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraAccountLockout.'Max Failures').trim() -ne $requiredConfig.maxFailures.trim()) { "$($vraAccountLockout.'Max Failures') [ $($requiredConfig.maxFailures) ]" } else { "$($vraAccountLockout.'Max Failures')" } } else { "$($vraAccountLockout.'Max Failures')" }) }) $vraAccountLockoutObject | Add-Member -NotePropertyName "Unlock Interval" $(if ($null -eq $vraAccountLockout.'Unlock Interval (sec)') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraAccountLockout.'Unlock Interval (sec)').trim() -ne $requiredConfig.unlockInterval.trim()) { "$($vraAccountLockout.'Unlock Interval (sec)') [ $($requiredConfig.unlockInterval) ]" } else { "$($vraAccountLockout.'Unlock Interval (sec)')" } } else { "$($vraAccountLockout.'Unlock Interval (sec)')" }) }) $vraAccountLockoutObject | Add-Member -NotePropertyName "Root Unlock Interval" $(if ($null -eq $vraAccountLockout.'Root Unlock Interval (sec)') { Write-Output "Not configured." } else { $(if ($drift) { if (($vraAccountLockout.'Root Unlock Interval (sec)').trim() -ne $requiredConfig.rootUnlockInterval.trim()) { "$($vraAccountLockout.'Root Unlock Interval (sec)') [ $($requiredConfig.rootUnlockInterval) ]" } else { "$($vraAccountLockout.'Root Unlock Interval (sec)')" } } else { "$($vraAccountLockout.'Root Unlock Interval (sec)')" }) }) $allvraAccountLockoutObject += $vraAccountLockoutObject } else { Write-Error "Unable to retrieve password expiration policy from Aria Automation ($node): PRE_VALIDATION_FAILED" } } return $allvraAccountLockoutObject } # Workspace ONE Access if ($vidm) { # Directory Users if ($settings -eq 'directory') { if ($drift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).wsaDirectory.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).wsaDirectory.accountLockout } } $vidmnodes = ((Get-vRSLCMProductDetails -productId vidm).nodes | Where-Object { $_.type -ne 'vidm-connector' }).properties.hostName $allvidmDirectoryAccountLockoutObject = New-Object System.Collections.ArrayList foreach ($node in $vidmnodes) { $vidmdirectorynodedata = ((Get-vRSLCMProductDetails -productId vidm).properties) $vidmdirectoryvmid = $vidmdirectorynodedata.defaultConfigurationPassword.split(':')[2] $vidmdirectorypassword = (Get-vRSLCMProductPassword -productId vidm -vmid $vidmdirectoryvmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vidmdirectoryusername = $vidmdirectorynodedata.defaultConfigurationUsername if (Test-WsaConnection -server $node) { if (Test-WsaAuthentication -server $node -user $vidmdirectoryusername -pass $vidmdirectorypassword.password ) { if ($vidmDirectoryAccountLockout = Get-WsaAccountLockout) { $vidmDirectoryAccountLockoutObject = New-Object -TypeName PSObject $vidmDirectoryAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $node.Split('.')[0] $vidmDirectoryAccountLockoutObject | Add-Member -NotePropertyName "Maximum Failures" $(if ($null -eq $vidmDirectoryAccountLockout.numAttempts) { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmDirectoryAccountLockout.numAttempts).trim() -ne $requiredConfig.maxFailures.trim()) { "$($vidmDirectoryAccountLockout.numAttempts) [ $($requiredConfig.maxFailures) ]" } else { "$($vidmDirectoryAccountLockout.numAttempts)" } } else { "$($vidmDirectoryAccountLockout.numAttempts)" }) }) $vidmDirectoryAccountLockoutObject | Add-Member -NotePropertyName "Attempt Interval" $(if ($null -eq $vidmDirectoryAccountLockout.attemptInterval) { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmDirectoryAccountLockout.attemptInterval).trim() -ne $requiredConfig.failedAttemptInterval.trim()) { "$($vidmDirectoryAccountLockout.attemptInterval) [ $($requiredConfig.failedAttemptInterval) ]" } else { "$($vidmDirectoryAccountLockout.attemptInterval)" } } else { "$($vidmDirectoryAccountLockout.attemptInterval)" }) }) $vidmDirectoryAccountLockoutObject | Add-Member -NotePropertyName "Unlock Interval" $(if ($null -eq $vidmDirectoryAccountLockout.unlockInterval) { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmDirectoryAccountLockout.unlockInterval).trim() -ne $requiredConfig.unlockInterval.trim()) { "$($vidmDirectoryAccountLockout.unlockInterval) [ $($requiredConfig.unlockInterval) ]" } else { "$($vidmDirectoryAccountLockout.unlockInterval)" } } else { "$($vidmDirectoryAccountLockout.unlockInterval)" }) }) $allvidmDirectoryAccountLockoutObject += $vidmDirectoryAccountLockoutObject } } } } return $allvidmDirectoryAccountLockoutObject } # Local Users if ($settings -eq 'localuser') { if ($vidmdrift) { if ($PsBoundParameters.ContainsKey("policyFile")) { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).wsaLocal.accountLockout } else { $requiredConfig = (Get-PasswordPolicyConfig -version $version).wsaLocal.accountLockout } } $vidmnodes = ((Get-vRSLCMProductDetails -productId vidm).nodes | Where-Object { $_.type -ne 'vidm-connector' }).properties.hostName $allvidmLocalAccountLockoutObject = New-Object System.Collections.ArrayList foreach ($node in $vidmnodes) { $vidmlocalnodedata = ((Get-vRSLCMProductDetails -productId vidm).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.type -ne 'vidm-connector' -and $_.hostName -eq $node }) $vidmlocalvmid = $vidmlocalnodedata.vidmRootPassword.Split(':')[2] $vidmlocalpassword = (Get-vRSLCMProductPassword -productId vidm -vmid $vidmlocalvmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) if ($vidmLocalAccountLockout = Get-AriaLocalUserAccountLockout -vmName $node.split('.')[0] -guestUser root -guestPassword $vidmlocalpassword.password) { $vidmLocalAccountLockoutObject = New-Object -TypeName PSObject $vidmLocalAccountLockoutObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vidmLocalAccountLockout.system $vidmLocalAccountLockoutObject | Add-Member -NotePropertyName "Maximum Failures" $(if ($null -eq $vidmLocalAccountLockout.'Maximum Failures') { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmLocalAccountLockout.'Maximum Failures').trim() -ne $requiredConfig.maxFailures.trim()) { "$($vidmLocalAccountLockout.'Maximum Failures') [ $($requiredConfig.maxFailures) ]" } else { "$($vidmLocalAccountLockout.'Maximum Failures')" } } else { "$($vrliAccountLockout.'Maximum Failures')" }) }) $vidmLocalAccountLockoutObject | Add-Member -NotePropertyName "Unlock Interval" $(if ($null -eq $vidmLocalAccountLockout.'Unlock Interval (sec)') { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmLocalAccountLockout.'Unlock Interval (sec)').trim() -ne $requiredConfig.unlockInterval.trim()) { "$($vidmLocalAccountLockout.'Unlock Interval (sec)') [ $($requiredConfig.unlockInterval) ]" } else { "$($vidmLocalAccountLockout.'Unlock Interval (sec)')" } } else { "$($vidmLocalAccountLockout.'Unlock Interval (sec)')" }) }) $vidmLocalAccountLockoutObject | Add-Member -NotePropertyName "Root Unlock Interval" $(if ($null -eq $vidmLocalAccountLockout.'Root Unlock Interval (sec)') { Write-Output "Not configured." } else { $(if ($vidmdrift) { if (($vidmLocalAccountLockout.'Root Unlock Interval (sec)').trim() -ne $requiredConfig.rootUnlockInterval.trim()) { "$($vidmLocalAccountLockout.'Root Unlock Interval (sec)') [ $($requiredConfig.rootUnlockInterval) ]" } else { "$($vidmLocalAccountLockout.'Root Unlock Interval (sec)')" } } else { "$($vidmLocalAccountLockout.'Root Unlock Interval (sec)')" }) }) $allvidmLocalAccountLockoutObject += $vidmLocalAccountLockoutObject } } return $allvidmLocalAccountLockoutObject } } } Catch { Write-Error $_.Exception.Message } } Export-ModuleMember -Function Request-AriaLocalUserAccountLockout Function Publish-AriaLocalUserPasswordPolicy { <# .SYNOPSIS Publishes the password policies for Aria product local users. .DESCRIPTION Publish-AriaLocalUserPasswordPolicy cmdlet retrieves the requested password policy for all VAria products and converts the output to HTML. - Validates that network connectivity and authentication is possible to SDDC Manager - Validates which Aria products are installed. .EXAMPLE Publish-AriaLocalUserPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -allDomains This example returns password expiration policy for all Aria products for all domains. .EXAMPLE Publish-AriaLocalUserPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordExpiration -workloadDomain [workload_domain_name] This example returns password expiration policy for all Aria products for the management domain. .EXAMPLE Publish-AriaLocalUserPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordComplexity -allDomains This example returns password complexity policy for all Aria products for all domains. .EXAMPLE Publish-AriaLocalUserPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy PasswordComplexity -workloadDomain [workload_domain_name] This example returns password complexity policy for all Aria products for the management domain. .EXAMPLE Publish-AriaLocalUserPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy AccountLockout -allDomains This example returns password account lockout policy for all Aria products for all domains. .EXAMPLE Publish-AriaLocalUserPasswordPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -policy AccountLockout -workloadDomain [workload_domain_name] This example returns password account lockout policy for all Aria products for the management domain. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER policy The policy to publish. One of: PasswordExpiration, PasswordComplexity, AccountLockout. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateSet('PasswordExpiration', 'PasswordComplexity', 'AccountLockout')] [String]$policy, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain ) $pass = Get-Password -username $user -password $pass Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFAriaLifecycle) { $ariaResources = @('ariaLifecycle') foreach ($resource in $ariaResources) { switch ($resource) { default { $command = "Get-VCF$resource" } 'workspaceOneAccess' { $command = 'Get-VCFWsa'; } } $isEnabled = (Invoke-Expression $command -ErrorAction SilentlyContinue) $resourceTitleCase = switch ($resource) { 'ariaLifecycle' { 'Aria Suite Lifecycle' } } # Checks for VNware Aria Suite Lifecycle in VMware Cloud Foundation mode. if ($isEnabled) { # Aria Suite Lifecycle if ($resourceTitleCase -eq "Aria Suite Lifecycle") { if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-AriaLocalUserPasswordComplexity"; $preHtmlContent = '<a id="vrslcm-local-password-complexity"></a><h3>Aria Suite Lifecycle - Password Complexity</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrslcm " } if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-AriaLocalUserPasswordExpiration"; $preHtmlContent = '<a id="vrslcm-local-password-expiration"></a><h3>Aria Suite Lifecycle - Password Expiration</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrslcm " } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-AriaLocalUserAccountLockout"; $preHtmlContent = '<a id="vrslcm-local-account-lockout"></a><h3>Aria Suite Lifecycle - Account Lockout</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrslcm " } $command = $pvsCmdlet + $commandSwitch + $customSwitch $vrslcmLocalPasswordPolicyObject = Invoke-Expression $command $allVrslcmLocalPasswordPolicyObject += $vrslcmLocalPasswordPolicyObject $allVrslcmLocalPasswordPolicyObject = $allVrslcmLocalPasswordPolicyObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table $allVrslcmLocalPasswordPolicyObject = Convert-CssClassStyle -htmldata $allVrslcmLocalPasswordPolicyObject $allVrslcmLocalPasswordPolicyObject } } # Aria Operations $notVcfEnabledVrops = Get-vRSLCMProductDetails -productId vrops if ($notVcfEnabledVrops) { if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-AriaLocalUserPasswordComplexity"; $preHtmlContent = '<a id="vrops-local-password-complexity"></a><h3>Aria Operations - Password Complexity</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrops " } if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-AriaLocalUserPasswordExpiration"; $preHtmlContent = '<a id="vrops-local-password-expiration"></a><h3>VAria Operations - Password Expiration</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrops" } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-AriaLocalUserAccountLockout"; $preHtmlContent = '<a id="vrops-local-account-lockout"></a><h3>Aria Operations - Account Lockout</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrops " } $command = $pvsCmdlet + $commandSwitch + $customSwitch $vropsLocalPasswordPolicyObject = Invoke-Expression $command $allVropsLocalPasswordPolicyObject += $vropsLocalPasswordPolicyObject $allVropsLocalPasswordPolicyObject = $allVropsLocalPasswordPolicyObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table $allVropsLocalPasswordPolicyObject = Convert-CssClassStyle -htmldata $allVropsLocalPasswordPolicyObject $allVropsLocalPasswordPolicyObject } # Aria Operations for Logs $notVcfEnabledVrli = Get-vRSLCMProductDetails -productId vrli if ($notVcfEnabledVrli) { if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-AriaLocalUserPasswordComplexity"; $preHtmlContent = '<a id="vrli-local-password-complexity"></a><h3>Aria Operations for Logs - Password Complexity</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrli " } if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-AriaLocalUserPasswordExpiration"; $preHtmlContent = '<a id="vrli-local-password-expiration"></a><h3>Aria Operations for Logs - Password Expiration</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrli " } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-AriaLocalUserAccountLockout"; $preHtmlContent = '<a id="vrli-local-account-lockout"></a><h3>Aria Operations for Logs - Account Lockout</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrli " } $command = $pvsCmdlet + $commandSwitch + $customSwitch $vrliLocalPasswordPolicyObject = Invoke-Expression $command $allVrliLocalPasswordPolicyObject += $vrliLocalPasswordPolicyObject $allVrliLocalPasswordPolicyObject = $allVrliLocalPasswordPolicyObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table $allVrliLocalPasswordPolicyObject = Convert-CssClassStyle -htmldata $allVrliLocalPasswordPolicyObject $allVrliLocalPasswordPolicyObject } # Aria Operations for Networks $notVcfEnabledVrni = Get-vRSLCMProductDetails -productId vrni if ($null -ne $notVcfEnabledVrni) { if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-AriaLocalUserPasswordComplexity"; $preHtmlContent = '<a id="vrni-local-password-complexity"></a><h3>Aria Operations for Networks - Password Complexity</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrni " } if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-AriaLocalUserPasswordExpiration"; $preHtmlContent = '<a id="vrni-local-password-expiration"></a><h3>Aria Operations for Networks - Password Expiration</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrni " } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-AriaLocalUserAccountLockout"; $preHtmlContent = '<a id="vrni-local-account-lockout"></a><h3>Aria Operations for Networks - Account Lockout</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vrni " } $command = $pvsCmdlet + $commandSwitch + $customSwitch $vrniLocalPasswordPolicyObject = Invoke-Expression $command $allVrniLocalPasswordPolicyObject += $vrniLocalPasswordPolicyObject $allVrniLocalPasswordPolicyObject = $allVrniLocalPasswordPolicyObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table $allVrniLocalPasswordPolicyObject = Convert-CssClassStyle -htmldata $allVrniLocalPasswordPolicyObject $allVrniLocalPasswordPolicyObject } # Aria Automation $notVcfEnabledVra = Get-vRSLCMProductDetails -productid vra if ($notVcfEnabledVra) { if ($PsBoundParameters.ContainsKey('drift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -drift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -drift" } } else { $commandSwitch = "" } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-AriaLocalUserPasswordComplexity"; $preHtmlContent = '<a id="vra-local-password-complexity"></a><h3>Aria Automation - Password Complexity</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vra " } if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-AriaLocalUserPasswordExpiration"; $preHtmlContent = '<a id="vra-local-password-expiration"></a><h3>Aria Automation - Password Expiration</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vra " } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-AriaLocalUserAccountLockout"; $preHtmlContent = '<a id="vra-local-account-lockout"></a><h3>Aria Automation - Account Lockout</h3>'; $customSwitch = " -server $server -user $user -pass $pass -product vra " } $command = $pvsCmdlet + $commandSwitch + $customSwitch $vraLocalPasswordPolicyObject = Invoke-Expression $command $allVraLocalPasswordPolicyObject += $vraLocalPasswordPolicyObject $allVraLocalPasswordPolicyObject = $allVraLocalPasswordPolicyObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table $allVraLocalPasswordPolicyObject = Convert-CssClassStyle -htmldata $allVraLocalPasswordPolicyObject $allVraLocalPasswordPolicyObject } # Workspace ONE Access $notVcfEnabledWsa = Get-vRSLCMProductDetails -productid vidm if ($notVcfEnabledWsa) { # Runs Workspace ONE Access Directory password policy if ($PsBoundParameters.ContainsKey('vidmdrift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -vidmdrift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -vidmdrift" } } else { $commandSwitch = "" } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-AriaLocalUserPasswordComplexity"; $preHtmlContent = '<a id="wsa-directory-password-complexity"></a><h3>Workspace ONE (Directory) - Password Complexity</h3>'; $customSwitch = " -server $server -user $user -pass $pass -vidm -settings directory " } if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-AriaLocalUserPasswordExpiration"; $preHtmlContent = '<a id="wsa-directory-password-expiration"></a><h3>Workspace ONE (Directory) - Password Expiration</h3>'; $customSwitch = " -server $server -user $user -pass $pass -vidm " } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-AriaLocalUserAccountLockout"; $preHtmlContent = '<a id="wsa-directory-account-lockout"></a><h3>Workspace ONE (Directory) - Account Lockout</h3>'; $customSwitch = " -server $server -user $user -pass $pass -vidm -settings directory " } $command = $pvsCmdlet + $commandSwitch + $customSwitch $wsaDirectoryPasswordPolicyObject = Invoke-Expression $command $allWsaDirectoryPasswordPolicyObject += $wsaDirectoryPasswordPolicyObject $allWsaDirectoryPasswordPolicyObject = $allWsaDirectoryPasswordPolicyObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table $allWsaDirectoryPasswordPolicyObject = Convert-CssClassStyle -htmldata $allWsaDirectoryPasswordPolicyObject $allWsaDirectoryPasswordPolicyObject # Runs Workspace ONE Access Local password policy if ($PsBoundParameters.ContainsKey('vidmdrift')) { if ($PsBoundParameters.ContainsKey('policyFile')) { $commandSwitch = " -vidmdrift -reportPath '$reportPath' -policyFile '$policyFile'" } else { $commandSwitch = " -vidmdrift" } } else { $commandSwitch = "" } if ($policy -eq "PasswordExpiration") { $pvsCmdlet = "Request-AriaLocalUserPasswordExpiration"; $preHtmlContent = '<a id="wsa-local-password-expiration"></a><h3>Workspace ONE (Local) - Password Expiration</h3>'; $customSwitch = " -server $server -user $user -pass $pass -vidm " } if ($policy -eq "PasswordComplexity") { $pvsCmdlet = "Request-AriaLocalUserPasswordComplexity"; $preHtmlContent = '<a id="wsa-local-password-complexity"></a><h3>Workspace ONE (Local) - Password Complexity</h3>'; $customSwitch = " -server $server -user $user -pass $pass -vidm -settings localuser " } if ($policy -eq "AccountLockout") { $pvsCmdlet = "Request-AriaLocalUserAccountLockout"; $preHtmlContent = '<a id="wsa-local-account-lockout"></a><h3>Workspace ONE (Local) - Account Lockout</h3>'; $customSwitch = " -server $server -user $user -pass $pass -vidm -settings localuser " } $command = $pvsCmdlet + $commandSwitch + $customSwitch $wsaLocalPasswordPolicyObject = Invoke-Expression $command $allWsaLocalPasswordPolicyObject +=$wsaLocalPasswordPolicyObject $allWsaLocalPasswordPolicyObject = $allWsaLocalPasswordPolicyObject | Sort-Object 'System' | ConvertTo-Html -Fragment -PreContent $preHtmlContent -As Table $allWsaLocalPasswordPolicyObject = Convert-CssClassStyle -htmldata $allWsaLocalPasswordPolicyObject $allWsaLocalPasswordPolicyObject } } } } } } Catch { Write-Error $_.Exception.Message } } Export-ModuleMember -Function Publish-AriaLocalUserPasswordPolicy Function Update-AriaLocalUserPasswordExpiration { <# .SYNOPSIS Configure password account lockout for local users. .DESCRIPTION The Update-AriaLocalUserPasswordExpiration cmdlet configures the password expiration local users. .EXAMPLE Update-AriaLocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -localuser [local_username] -maxdays 90 -mindays 7 -warndays 7 This example updates the Aria Automation nodes with new values for each element. .EXAMPLE. Update-AriaLocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -json -reportPath [report_path] -policyFile [policy_file].json This example updates the Aria Automation nodes using the JSON file values. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER product The product to configure the password expiration policy. One of: vrslcm, vrli, vrops, vrni, or vra. .PARAMETER localuser The local user to configure. .PARAMETER maxdays The maximum number of days between password change. .PARAMETER mindays The minimum number of days between password change. .PARAMETER warndays The number of days before password expiration that a user is warned that password will expire. .PARAMETER json Use a JSON file to configure the password complexity. .PARAMETER policyPath The path to the policy file. .PARAMETER policyFile The path to the policy file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateSet('vrslcm', 'vrops', 'vrli', 'vrni', 'vra')] [String]$product, [Parameter (Mandatory = $false)] [ValidateSet('root', 'support', 'consoleuser')] [Array]$localuser, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$maxdays, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$mindays, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$warndays, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVrslcmDetails = Get-vRSLCMServerDetail -fqdn $server -username $user -password $pass)) { if (Test-vRSLCMAuthentication -server $vcfVrslcmDetails.fqdn -user $vcfVrslcmDetails.adminUser -pass $vcfVrslcmDetails.adminPass) { $domain = Get-VCFWorkloadDomain | Select-Object name, type | Where-Object { $_.type -eq "MANAGEMENT" } if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain.name)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { } } } } } } } Try { if ($PsBoundParameters.ContainsKey("json")) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { # Aria Suite Lifecycle if ($product -eq "vrslcm") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaLifecycle.passwordExpiration $scriptCheck = "cat /etc/passwd" $checkKeys = Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCheck -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword foreach ($user in $localuser) { if ($checkKeys.ScriptOutput -match $user) { $policies = @{ # maxdays = Maximum number of days between password change. (By default, the password is set to never expire.) maxdays = $requiredConfig.maxDays # mindays = Minimum number of days between password change. (Default = 0) mindays = $requiredConfig.minDays # warndays = Number of days before password expiration that a user is warned that password will expire. (Default = 7) warndays = $requiredConfig.warningDays } foreach ($policy in $policies.GetEnumerator()) { $scriptCommand = "chage --$($policy.Name) $($policy.Value) $user" Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } } else { Write-Output "User $user not found on $node" } } } # Aria Operations if ($product -eq "vrops") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaOperations.passwordExpiration $vropsnodes = ((Get-vRSLCMProductDetails -productid vrops).nodes).properties.hostName $scriptCheck = "cat /etc/passwd" foreach ($node in $vropsnodes) { $vropspassword = (Get-vRSLCMProductPassword -productId vrops -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vropsusername = (Get-vRSLCMLockerPassword -vmid $vropspassword.passwordvmid).userName $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vropsusername -GuestPassword $vropspassword.password foreach ($user in $localuser) { $user if ($checkKeys.ScriptOutput -match $user) { $policies = @{ # maxdays = Maximum number of days between password change. (Default = 365) maxdays = $requiredConfig.maxDays # mindays = Minimum number of days between password change. (Default = 0) mindays = $requiredConfig.minDays # warndays = Number of days before password expiration that a user is warned that password will expire. (Default = 7) warndays = $requiredConfig.warningDays } foreach ($policy in $policies.GetEnumerator()) { $scriptCommand = "chage --$($policy.Name) $($policy.Value) $user" Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } } else { Write-Output "User $user not found on $node" } } } } # Aria Operatons for Logs if ($product -eq 'vrli') { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaOperationsLogs.passwordExpiration $vrlinodes = ((Get-vRSLCMProductDetails -productid vrli).nodes).properties.hostName $scriptCheck = "cat /etc/passwd" foreach ($node in $vrlinodes) { $vrlipassword = (Get-vRSLCMProductPassword -productId vrli -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser root -GuestPassword $vrlipassword.password foreach ($user in $localuser) { if ($checkKeys.ScriptOutput -match $user) { $policies = @{ # maxdays = Maximum number of days between password change. (Default = 365) maxdays = $requiredConfig.maxDays # mindays = Minimum number of days between password change. (Default = 0) mindays = $requiredConfig.minDays # warndays = Number of days before password expiration that a user is warned that password will expire. (Default = 7) warndays = $requiredConfig.warningDays } foreach ($policy in $policies.GetEnumerator()) { $scriptCommand = "chage --$($policy.Name) $($policy.Value) $user" Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } } else { Write-Output "User $user not found on $node" } } } } # Aria Operations for Networks if ($product -eq "vrni") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).ariaOperationsNetworks.passwordExpiration $vrninodes = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties) foreach ($node in $vrninodes) { $scriptCheck = "sudo cat /etc/passwd" $vrninodedata = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.vmname -eq $node.vmName }) $vrnivmid = $vrninodedata.supportPassword.Split(':')[2] $vrnipassword = (Get-vRSLCMProductPassword -productId vrni -vmid $vrnivmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $checkKeys = Invoke-VMScript -VM $node.vmname -ScriptText $scriptCheck -GuestUser support -GuestPassword $vrnipassword.password -Confirm:$false foreach ($user in $localuser) { if ($checkKeys.ScriptOutput -match $user) { $policies = @{ # maxdays = Maximum number of days between password change. (By default, the password is set to never expire.) maxdays = $requiredConfig.maxDays # mindays = Minimum number of days between password change. (Default = 0) mindays = $requiredConfig.minDays # warndays = Number of days before password expiration that a user is warned that password will expire. (Default = 7) warndays = $requiredConfig.warningDays } foreach ($policy in $policies.GetEnumerator()) { $scriptCommand = "sudo chage --$($policy.Name) $($policy.Value) $user" Invoke-VMScript -VM $node.vmname -ScriptText $scriptCommand -GuestUser support -GuestPassword $vrnipassword.password -Confirm:$false | Out-Null } } else { Write-Output "User $user not found on $($node.vmname)" } } } } # Aria Automation if ($product -eq "vra") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaAutomation.passwordExpiration $vranodes = ((Get-vRSLCMProductDetails -productid vra).nodes).properties.hostName $scriptCheck = "cat /etc/passwd" foreach ($node in $vranodes) { $vrapassword = (Get-vRSLCMProductPassword -productId vra -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vrausername = (Get-vRSLCMLockerPassword -vmid $vrapassword.passwordvmid).userName $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vrausername -GuestPassword $vrapassword.password foreach ($user in $localuser) { if ($checkKeys.ScriptOutput -match $user) { $policies = @{ # maxdays = Maximum number of days between password change. (Default = 365) maxdays = $requiredConfig.maxDays # mindays = Minimum number of days between password change. (Default = 0) mindays = $requiredConfig.minDays # warndays = Number of days before password expiration that a user is warned that password will expire. (Default = 7) warndays = $requiredConfig.warningDays } foreach ($policy in $policies.GetEnumerator()) { $scriptCommand = "chage --$($policy.Name) $($policy.Value) $user" Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } } else { Write-Output "User $user not found on $node" } } } } } } if (-not($PsBoundParameters.ContainsKey("json"))) { # Aria Suite Lifecycle if ($product -eq "vrslcm") { $scriptCheck = "cat /etc/passwd" $checkKeys = Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCheck -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword foreach ($user in $localuser) { if ($checkKeys.ScriptOutput -match $user) { $policies = @{ # maxdays = Maximum number of days between password change. (By default, the password is set to never expire.) maxdays = $maxdays # mindays = Minimum number of days between password change. (Default = 0) mindays = $mindays # warndays = Number of days before password expiration that a user is warned that password will expire. (Default = 7) warndays = $warndays } foreach ($policy in $policies.GetEnumerator()) { if ($PsBoundParameters.ContainsKey($policy.Name)) { $scriptCommand = "chage --$($policy.Name) $($policy.Value) $user" Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } } } else { Write-Output "User $user not found on $node" } } } # Aria Operations if ($product -eq "vrops") { $vropsnodes = ((Get-vRSLCMProductDetails -productid vrops).nodes).properties.hostName $scriptCheck = "cat /etc/passwd" foreach ($node in $vropsnodes) { $vropspassword = (Get-vRSLCMProductPassword -productId vrops -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vropsusername = (Get-vRSLCMLockerPassword -vmid $vropspassword.passwordvmid).userName $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vropsusername -GuestPassword $vropspassword.password foreach ($user in $localuser) { if ($checkKeys.ScriptOutput -match $user) { $policies = @{ # maxdays = Maximum number of days between password change. (Default = 365) maxdays = $maxdays # mindays = Minimum number of days between password change. (Default = 0) mindays = $mindays # warndays = Number of days before password expiration that a user is warned that password will expire. (Default = 7) warndays = $warndays } foreach ($policy in $policies.GetEnumerator()) { if ($PsBoundParameters.ContainsKey($policy.Name)) { $scriptCommand = "chage --$($policy.Name) $($policy.Value) $user" Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } } } else { Write-Output "User $user not found on $node" } } } } # Aria Operations for Logs if ($product -eq "vrli") { $vrlinodes = ((Get-vRSLCMProductDetails -productid vrli).nodes).properties.hostName $scriptCheck = "cat /etc/passwd" foreach ($node in $vrlinodes) { $vrlipassword = (Get-vRSLCMProductPassword -productId vrli -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser root -GuestPassword $vrlipassword.password foreach ($user in $localuser) { if ($checkKeys.ScriptOutput -match $user) { $policies = @{ # maxdays = Maximum number of days between password change. (Default = 365) maxdays = $maxdays # mindays = Minimum number of days between password change. (Default = 0) mindays = $mindays # warndays = Number of days before password expiration that a user is warned that password will expire. (Default = 7) warndays = $warndays } foreach ($policy in $policies.GetEnumerator()) { if ($PsBoundParameters.ContainsKey($policy.Name)) { $scriptCommand = "chage --$($policy.Name) $($policy.Value) $user" Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } } } else { Write-Output "User $user not found on $node" } } } } # Aria Operations for Networks if ($product -eq "vrni") { $vrninodes = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties) $scriptCheck = "sudo cat /etc/passwd" foreach ($node in $vrninodes) { $vrninodedata = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.vmname -eq $node.vmName }) $vrnivmid = $vrninodedata.supportPassword.Split(':')[2] $vrnipassword = (Get-vRSLCMProductPassword -productId vrni -vmid $vrnivmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $checkKeys = Invoke-VMScript -VM $node.vmname -ScriptText $scriptCheck -GuestUser support -GuestPassword $vrnipassword.password foreach ($user in $localuser) { if ($checkKeys.ScriptOutput -match $user) { $policies = @{ # maxdays = Maximum number of days between password change. (By default, the password is set to never expire.) maxdays = $maxdays # mindays = Minimum number of days between password change. (Default = 0) mindays = $mindays # warndays = Number of days before password expiration that a user is warned that password will expire. (Default = 7) warndays = $warndays } foreach ($policy in $policies.GetEnumerator()) { if ($PsBoundParameters.ContainsKey($policy.Name)) { $scriptCommand = "sudo chage --$($policy.Name) $($policy.Value) $user" Invoke-VMScript -VM $node.vmname -ScriptText $scriptCommand -GuestUser support -GuestPassword $vrnipassword.password -Confirm:$false | Out-Null } } } else { Write-Output "User $user not found on $node" } } } } # Aria Automation if ($product -eq 'vra') { $vranodes = ((Get-vRSLCMProductDetails -productid vra).nodes).properties.hostName $scriptCheck = "cat /etc/passwd" foreach ($node in $vranodes) { $vrapassword = (Get-vRSLCMProductPassword -productId vra -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vrausername = (Get-vRSLCMLockerPassword -vmid $vrapassword.passwordvmid).userName $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vrausername -GuestPassword $vrapassword.password foreach ($user in $localuser) { if ($checkKeys.ScriptOutput -match $user) { $policies = @{ # maxdays = Maximum number of days between password change. (Default = 365) maxdays = $maxdays # mindays = Minimum number of days between password change. (Default = 0) mindays = $mindays # warndays = Number of days before password expiration that a user is warned that password will expire. (Default = 7) warndays = $warndays } foreach ($policy in $policies.GetEnumerator()) { if ($PsBoundParameters.ContainsKey($policy.Name)) { $scriptCommand = "chage --$($policy.Name) $($policy.Value) $user" Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } } } else { Write-Output "User $user not found on $node" } } } } } } Catch { Write-Error $_.Exception.Message } } Export-ModuleMember -Function Update-AriaLocalUserPasswordExpiration Function Update-AriaLocalUserPasswordComplexity { <# .SYNOPSIS Configure password complexity for local users. .DESCRIPTION The Update-AriaLocalUserPasswordComplexity cmdlet configures the password complexity local users. .EXAMPLE Update-AriaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -minLength 7 -uppercase 1 -lowercase 1 -numerical 1 -special 1 -unique 5 -history 3 -retry 3 -class 3 -sequence 3 This example updates the Aria Automation nodes with new values for each element. .EXAMPLE Update-AriaLocalUserPasswordComplexity -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -json -reportPath [report_path] -policyFile [policy_file].json This example updates Aria Automation using the JSON file values. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER product The product to configure the password complexity policy. One of: vrslcm, vrli, vrops, vrni, or vra. .PARAMETER minLength The minimum number of characters in a password. .PARAMETER uppercase The maximum number of uppercase characters in a password. .PARAMETER lowercase The maximum number of lowercase characters in a password. .PARAMETER numerical The maximum number of numerical characters in a password. .PARAMETER special The maximum number of special characters in a password. .PARAMETER unique The minimum number of unique characters in a password. .PARAMETER history The number of passwords to remember. .PARAMETER retry The number of retries. .PARAMETER class The minimum number of character classes. .PARAMETER sequence The maximum number of repeated characters. .PARAMETER json Use a JSON file to configure the password complexity. .PARAMETER policyPath The path to the policy file. .PARAMETER policyFile The path to the policy file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateSet('vrslcm', 'vrops', 'vrli', 'vrni', 'vra')] [String]$product, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$minLength, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$uppercase, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$lowercase, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$numerical, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$special, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$unique, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$history, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$retry, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$class, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$sequence, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVrslcmDetails = Get-vRSLCMServerDetail -fqdn $server -username $user -password $pass)) { if (Test-vRSLCMAuthentication -server $vcfVrslcmDetails.fqdn -user $vcfVrslcmDetails.adminUser -pass $vcfVrslcmDetails.adminPass) { $domain = Get-VCFWorkloadDomain | Select-Object name, type | Where-Object { $_.type -eq "MANAGEMENT" } if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain.name)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { } } } } } } } $photonScript = "cat /etc/photon-release" Try { if ($PsBoundParameters.ContainsKey("json")) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { # Aria Suite Lifecycle if ($product -eq "vrslcm") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaLifecycle.passwordComplexity $photonRelease = Invoke-VMscript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $photonScript -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/pwquality.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCheck -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword # minlen = Minimum password length (Default = 8) $minLength = $requiredConfig.minLength $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";s/minlen=[-]?[0-9]+/minlen=$minLength/" } $uncommentRegex = "/minlen/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minlen =" -or $checkKeys.ScriptOutput -match "minlen=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$minLengthRegex' $configFile" } else { $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";/pam_cracklib.so/ s/$/ minlen=$minLength/" } $scriptCommand = "sed -E -i.bak '$minLengthRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null # ucredit = Maximum number of uppercase characters that will generate a credit (Default = -1) $uppercase = $requiredConfig.minUppercase $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";s/ucredit=[-]?[0-9]+/ucredit=$uppercase/" } $uncommentRegex = "/ucredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ucredit =" -or $checkKeys.ScriptOutput -match "ucredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uppercaseRegex' $configFile" } else { $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";/pam_cracklib.so/ s/$/ ucredit=$uppercase/" } $scriptCommand = "sed -E -i.bak '$uppercaseRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null # lcredit = Maximum number of lowercase characters that will generate a credit (Default = -1) $lowercase = $requiredConfig.minLowercase $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";s/lcredit=[-]?[0-9]+/lcredit=$lowercase/" } $uncommentRegex = "/lcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# lcredit =" -or $checkKeys.ScriptOutput -match "lcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$lowercaseRegex' $configFile" } else { $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";/pam_cracklib.so/ s/$/ lcredit=$lowercase/" } $scriptCommand = "sed -E -i.bak '$lowercaseRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null # dcredit = Maximum number of digits that will generate a credit (Default = -1) $numerical = $requiredConfig.minNumerical $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";s/dcredit=[-]?[0-9]+/dcredit=$numerical/" } $uncommentRegex = "/dcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# dcredit =" -or $checkKeys.ScriptOutput -match "dcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$numericalRegex' $configFile" } else { $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";/pam_cracklib.so/ s/$/ dcredit=$numerical/" } $scriptCommand = "sed -E -i.bak '$numericalRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null # ocredit = Maximum number of other characters that will generate a credit (Default = -1) $special = $requiredConfig.minSpecial $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";s/ocredit=[-]?[0-9]+/ocredit=$special/" } $uncommentRegex = "/ocredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ocredit =" -or $checkKeys.ScriptOutput -match "ocredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$specialRegex' $configFile" } else { $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";/pam_cracklib.so/ s/$/ ocredit=$special/" } $scriptCommand = "sed -E -i.bak '$specialRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null # difok = Minimum number of characters that must be different from the old password (Default = 4) $unique = $requiredConfig.minUnique $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";s/difok=[-]?[0-9]+/difok=$unique/" } $uncommentRegex = "/difok/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# difok =" -or $checkKeys.ScriptOutput -match "difok=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uniqueRegex' $configFile" } else { $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";/pam_cracklib.so/ s/$/ difok=$unique/" } $scriptCommand = "sed -E -i.bak '$uniqueRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null # minclass = Minimum number of character types that must be used (e.g., uppercase, lowercase, digits, other) (Default = 4) $class = $requiredConfig.minClass $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";s/minclass=[-]?[0-9]+/minclass=$class/" } $uncommentRegex = "/minclass/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minclass =" -or $checkKeys.ScriptOutput -match "minclass=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$classRegex' $configFile" } else { $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";/pam_cracklib.so/ s/$/ minclass=$class/" } $scriptCommand = "sed -E -i.bak '$classRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null # remember = Maximum number of passwords the system remembers (Default = 5) $history = $requiredConfig.history if ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "requisite pam_pwhistory.so enforce_for_root use_authtok" $rememberPattern = "remember=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $rememberPattern) { $historyCommand += ";s/(remember=[-]?[0-9]+)|(remember=)/remember=$history/" } else { $historyCommand += ";/$pamPattern/ s/$/ remember=$history/" } } else { $historyCommand += "/pam_unix.so/i password requisite pam_pwhistory.so use_authtok enforce_for_root remember=$history" } $scriptCommand += $historyCommand if ($product -eq "vrni") { $scriptCommand += "' /etc/pam.d/common-password" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } $checkKeys = Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCheck -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword # retry = Maximum number of retries of password (Default = 3) $retry = $requiredConfig.retries if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# retry =") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "/retry/s/ *# *//g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } else { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += ";s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "requisite pam_pwhistory.so enforce_for_root use_authtok" $retryPattern = "retry=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $retryPattern) { $retryCommand += ";s/retry=[-]?[0-9]+/retry=$retry/" } else { $retryCommand += ";/$pamPattern/ s/$/ retry=$retry/" } } else { $retryCommand += "/pam_unix.so/i password requisite pam_pwhistory.so use_authtok enforce_for_root retry=$retry" } $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } # Aria Operations if ($product -eq "vrops") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaOperations.passwordComplexity $vropsnodes = ((Get-vRSLCMProductDetails -productid vrops).nodes).properties.hostName foreach ($node in $vropsnodes) { $vropspassword = (Get-vRSLCMProductPassword -productId vrops -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vropsusername = (Get-vRSLCMLockerPassword -vmid $vropspassword.passwordvmid).userName $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser $vropsusername -GuestPassword $vropspassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/pwquality.conf; cat /etc/security/pwhistory.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vropsusername -GuestPassword $vropspassword.password # minlen = Minimum password length (Default = 8) $minLength = $requiredConfig.minLength $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";s/minlen=[-]?[0-9]+/minlen=$minLength/" } $uncommentRegex = "/minlen/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minlen =" -or $checkKeys.ScriptOutput -match "minlen=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$minLengthRegex' $configFile" } else { $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";/pam_cracklib.so/ s/$/ minlen=$minLength/" } $scriptCommand = "sed -E -i.bak '$minLengthRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null # ucredit = Maximum number of uppercase characters that will generate a credit (Default = -1) $uppercase = $requiredConfig.minUppercase $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";s/ucredit=[-]?[0-9]+/ucredit=$uppercase/" } $uncommentRegex = "/ucredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ucredit =" -or $checkKeys.ScriptOutput -match "ucredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uppercaseRegex' $configFile" } else { $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";/pam_cracklib.so/ s/$/ ucredit=$uppercase/" } $scriptCommand = "sed -E -i.bak '$uppercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null # lcredit = Maximum number of lowercase characters that will generate a credit (Default = -1) $lowercase = $requiredConfig.minLowercase $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";s/lcredit=[-]?[0-9]+/lcredit=$lowercase/" } $uncommentRegex = "/lcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# lcredit =" -or $checkKeys.ScriptOutput -match "lcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$lowercaseRegex' $configFile" } else { $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";/pam_cracklib.so/ s/$/ lcredit=$lowercase/" } $scriptCommand = "sed -E -i.bak '$lowercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null # dcredit = Maximum number of digits that will generate a credit (Default = -1) $numerical = $requiredConfig.minNumerical $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";s/dcredit=[-]?[0-9]+/dcredit=$numerical/" } $uncommentRegex = "/dcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# dcredit =" -or $checkKeys.ScriptOutput -match "dcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$numericalRegex' $configFile" } else { $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";/pam_cracklib.so/ s/$/ dcredit=$numerical/" } $scriptCommand = "sed -E -i.bak '$numericalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null # ocredit = Maximum number of other characters that will generate a credit (Default = -1) $special = $requiredConfig.minSpecial $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";s/ocredit=[-]?[0-9]+/ocredit=$special/" } $uncommentRegex = "/ocredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ocredit =" -or $checkKeys.ScriptOutput -match "ocredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$specialRegex' $configFile" } else { $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";/pam_cracklib.so/ s/$/ ocredit=$special/" } $scriptCommand = "sed -E -i.bak '$specialRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null # difok = Minimum number of characters that must be different from the old password (Default = 4) $unique = $requiredConfig.minUnique $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";s/difok=[-]?[0-9]+/difok=$unique/" } $uncommentRegex = "/difok/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# difok =" -or $checkKeys.ScriptOutput -match "difok=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uniqueRegex' $configFile" } else { $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";/pam_cracklib.so/ s/$/ difok=$unique/" } $scriptCommand = "sed -E -i.bak '$uniqueRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null # minclass = Minimum number of character types that must be used (e.g., uppercase, lowercase, digits, other) (Default = 4) $class = $requiredConfig.minClass $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";s/minclass=[-]?[0-9]+/minclass=$class/" } $uncommentRegex = "/minclass/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minclass =" -or $checkKeys.ScriptOutput -match "minclass=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$classRegex' $configFile" } else { $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";/pam_cracklib.so/ s/$/ minclass=$class/" } $scriptCommand = "sed -E -i.bak '$classRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null # maxsequence = Maximum number of times a single character may be repeated (Default = 0) $sequence = $requiredConfig.maxSequence $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";s/maxsequence=[-]?[0-9]+/maxsequence=$sequence/" } $uncommentRegex = "/maxrepeat/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# maxrepeat =" -or $checkKeys.ScriptOutput -match "maxsequence=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$sequenceRegex' $configFile" } else { $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";/pam_cracklib.so/ s/$/ maxsequence=$sequence/" } $scriptCommand = "sed -E -i.bak '$sequenceRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null # remember = Maximum number of passwords the system remembers (Default = 5) $history = $requiredConfig.history if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# remember =") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += "/^# remember/s/ *# *//g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } else { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += ";s/remember = [-]?[0-9]+/remember = $history/g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $rememberPattern = "remember=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $rememberPattern) { $historyCommand += ";s/(remember=[-]?[0-9]+)|(remember=)/remember=$history/" } else { $historyCommand += ";/$pamPattern/ s/$/ remember=$history/" } } else { $historyCommand += "/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root remember=$history" } $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vropsusername -GuestPassword $vropspassword.password # retry = Maximum number of retries of password (Default = 3) $retry = $requiredConfig.retries if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# retry =") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "/retry/s/ *# *//g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } else { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += ";s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $retryPattern = "retry=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $retryPattern) { $retryCommand += ";s/retry=[-]?[0-9]+/retry=$retry/" } else { $retryCommand += ";/$pamPattern/ s/$/ retry=$retry/" } } else { $retryCommand += "/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root retry=$retry" } $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } } # Aria Operatons for Logs if ($product -eq 'vrli') { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaOperationsLogs.passwordComplexity $vrlinodes = ((Get-vRSLCMProductDetails -productid vrli).nodes).properties.hostName foreach ($node in $vrlinodes) { $scriptCommand = "sed -E -i.bak '" $vrlipassword = (Get-vRSLCMProductPassword -productId vrli -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser root -GuestPassword $vrlipassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/pwquality.conf; cat /etc/security/pwhistory.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser root -GuestPassword $vrlipassword.password # minlen = Minimum password length (Default = 8) $minLength = $requiredConfig.minLength $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";s/minlen=[-]?[0-9]+/minlen=$minLength/" } $uncommentRegex = "/minlen/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minlen =" -or $checkKeys.ScriptOutput -match "minlen=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$minLengthRegex' $configFile" } else { $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";/pam_cracklib.so/ s/$/ minlen=$minLength/" } $scriptCommand = "sed -E -i.bak '$minLengthRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null # ucredit = Maximum number of uppercase characters that will generate a credit (Default = -1) $uppercase = $requiredConfig.minUppercase $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";s/ucredit=[-]?[0-9]+/ucredit=$uppercase/" } $uncommentRegex = "/ucredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ucredit =" -or $checkKeys.ScriptOutput -match "ucredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uppercaseRegex' $configFile" } else { $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";/pam_cracklib.so/ s/$/ ucredit=$uppercase/" } $scriptCommand = "sed -E -i.bak '$uppercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null # lcredit = Maximum number of lowercase characters that will generate a credit (Default = -1) $lowercase = $requiredConfig.minLowercase $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";s/lcredit=[-]?[0-9]+/lcredit=$lowercase/" } $uncommentRegex = "/lcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# lcredit =" -or $checkKeys.ScriptOutput -match "lcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$lowercaseRegex' $configFile" } else { $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";/pam_cracklib.so/ s/$/ lcredit=$lowercase/" } $scriptCommand = "sed -E -i.bak '$lowercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null # dcredit = Maximum number of digits that will generate a credit (Default = -1) $numerical = $requiredConfig.minNumerical $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";s/dcredit=[-]?[0-9]+/dcredit=$numerical/" } $uncommentRegex = "/dcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# dcredit =" -or $checkKeys.ScriptOutput -match "dcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$numericalRegex' $configFile" } else { $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";/pam_cracklib.so/ s/$/ dcredit=$numerical/" } $scriptCommand = "sed -E -i.bak '$numericalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null # ocredit = Maximum number of other characters that will generate a credit (Default = -1) $special = $requiredConfig.minSpecial $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";s/ocredit=[-]?[0-9]+/ocredit=$special/" } $uncommentRegex = "/ocredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ocredit =" -or $checkKeys.ScriptOutput -match "ocredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$specialRegex' $configFile" } else { $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";/pam_cracklib.so/ s/$/ ocredit=$special/" } $scriptCommand = "sed -E -i.bak '$specialRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null # difok = Minimum number of characters that must be different from the old password (Default = 4) $unique = $requiredConfig.minUnique $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";s/difok=[-]?[0-9]+/difok=$unique/" } $uncommentRegex = "/difok/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# difok =" -or $checkKeys.ScriptOutput -match "difok=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uniqueRegex' $configFile" } else { $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";/pam_cracklib.so/ s/$/ difok=$unique/" } $scriptCommand = "sed -E -i.bak '$uniqueRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null # minclass = Minimum number of character types that must be used (e.g., uppercase, lowercase, digits, other) (Default = 4) $class = $requiredConfig.minClass $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";s/minclass=[-]?[0-9]+/minclass=$class/" } $uncommentRegex = "/minclass/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minclass =" -or $checkKeys.ScriptOutput -match "minclass=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$classRegex' $configFile" } else { $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";/pam_cracklib.so/ s/$/ minclass=$class/" } $scriptCommand = "sed -E -i.bak '$classRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null # maxsequence = Maximum number of times a single character may be repeated (Default = 0) $sequence = $requiredConfig.maxSequence $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";s/maxsequence=[-]?[0-9]+/maxsequence=$sequence/" } $uncommentRegex = "/maxrepeat/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# maxrepeat =" -or $checkKeys.ScriptOutput -match "maxsequence=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$sequenceRegex' $configFile" } else { $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";/pam_cracklib.so/ s/$/ maxsequence=$sequence/" } $scriptCommand = "sed -E -i.bak '$sequenceRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null # remember = Maximum number of passwords the system remembers (Default = 5) $history = $requiredConfig.history if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# remember =") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += "/^# remember/s/ *# *//g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } else { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += ";s/remember = [-]?[0-9]+/remember = $history/g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $rememberPattern = "remember=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $rememberPattern) { $historyCommand += ";s/(remember=[-]?[0-9]+)|(remember=)/remember=$history/" } else { $historyCommand += ";/$pamPattern/ s/$/ remember=$history/" } } else { $historyCommand += "/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root remember=$history" } $scriptCommand += $historyCommand if ($product -eq "vrni") { $scriptCommand += "' /etc/pam.d/common-password" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser root -GuestPassword $vrlipassword.password # retry = Maximum number of retries of password (Default = 3) $retry = $requiredConfig.retries if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# retry =") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "/retry/s/ *# *//g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } else { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += ";s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $retryPattern = "retry=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $retryPattern) { $retryCommand += ";s/retry=[-]?[0-9]+/retry=$retry/" } else { $retryCommand += ";/$pamPattern/ s/$/ retry=$retry/" } } else { $retryCommand += "/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root retry=$retry" } $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } } # Aria Operations for Networks if ($product -eq "vrni") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).ariaOperationsNetworks.passwordComplexity $vrninodes = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties) $scriptCommand = $null foreach ($node in $vrninodes) { $scriptCommand = "sudo sed -E -i.bak '" $scriptCheck = " sudo cat /etc/pam.d/common-password" $vrninodedata = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.vmname -eq $node.vmName }) $vrnivmid = $vrninodedata.supportPassword.Split(':')[2] $vrnipassword = (Get-vRSLCMProductPassword -productId vrni -vmid $vrnivmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $checkKeys = Invoke-VMScript -VM $node.vmname -ScriptText $scriptCheck -GuestUser support -GuestPassword $vrnipassword.password # minlen = Minimum password length (Default = 6) $minLengthCommand = $null $minLength = $requiredConfig.minLength if ($checkKeys.ScriptOutput -match "minlen=") { $minLengthCommand += ";s/minlen=[-]?[0-9]+/minlen=$minLength/" } else { $minLengthCommand += ";/pam_cracklib.so/ s/$/ minlen=$minLength/" } $scriptCommand += $minLengthCommand $uppercase = $requiredConfig.minUppercase # ucredit = Maximum number of uppercase characters that will generate a credit (Default = -1) if ($checkKeys.ScriptOutput -match "ucredit=") { $uppercaseCommand = ";s/ucredit=[-]?[0-9]+/ucredit=$uppercase/" } $scriptCommand += $uppercaseCommand $lowercase = $requiredConfig.minLowercase # lcredit = Maximum number of lowercase characters that will generate a credit (Default = -1) if ($checkKeys.ScriptOutput -match "lcredit=") { $lowercaseCommand = ";s/lcredit=[-]?[0-9]+/lcredit=$lowercase/" } $scriptCommand += $lowercaseCommand $numerical = $requiredConfig.minNumerical # dcredit = Maximum number of digits that will generate a credit (Default = -1) if ($checkKeys.ScriptOutput -match "dcredit=") { $numericalCommand = ";s/dcredit=[-]?[0-9]+/dcredit=$numerical/" } $scriptCommand += $numericalCommand $special = $requiredConfig.minSpecial # ocredit = Maximum number of other characters that will generate a credit (Default = -1) if ($checkKeys.ScriptOutput -match "ocredit=") { $specialCommand = ";s/ocredit=[-]?[0-9]+/ocredit=$special/" } $scriptCommand += $specialCommand $unique = $requiredConfig.minUnique # difok = Minimum number of characters that must be different from the old password (Default = 4) if ($checkKeys.ScriptOutput -match "difok=") { $uniqueCommand = ";s/difok=[-]?[0-9]+/difok=$unique/" } $scriptCommand += $uniqueCommand $class = $requiredConfig.minClass # minclass = Minimum number of character types that must be used (e.g., uppercase, lowercase, digits, other) (Default = 4) if ($checkKeys.ScriptOutput -match "minclass=" ) { $minClassCommand = ";s/minclass=[-]?[0-9]+/minclass=$class/" } $scriptCommand += $minClassCommand $sequence = $requiredConfig.maxSequence # maxrepeat = Maximum number of times a single character may be repeated (Default = 0) if ($checkKeys.ScriptOutput -match "sequence=" ) { $maxSequenceCommand = ";s/maxsequence=[-]?[0-9]+/maxsequence=$sequence/" } $scriptCommand += $maxSequenceCommand $history = $requiredConfig.history # remember = Maximum number of passwords the system remembers (Default = 5) if ($checkKeys.ScriptOutput -match "history=") { $historyCommand += ";s/(remember=[-]?[0-9]+)|(remember=)/remember=$history/" } $scriptCommand += $historyCommand $retry = $requiredConfig.retries # if ($checkKeys.ScriptOutput -match "retry=") { $retryCommand += ";s/retry=[-]?[0-9]+/retry=$retry/" } $scriptCommand += $retryCommand $scriptCommand += "' /etc/pam.d/common-password" Invoke-VMScript -VM $node.vmname -ScriptText $scriptCommand -GuestUser support -GuestPassword $vrnipassword.password -Confirm:$false | Out-Null } } # Aria Automation if ($product -eq "vra") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaAutomation.passwordComplexity $vranodes = ((Get-vRSLCMProductDetails -productid vra).nodes).properties.hostName foreach ($node in $vranodes) { $vrapassword = (Get-vRSLCMProductPassword -productId vra -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vrausername = (Get-vRSLCMLockerPassword -vmid $vrapassword.passwordvmid).userName $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser $vrausername -GuestPassword $vrapassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/pwquality.conf; cat /etc/security/pwhistory.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vrausername -GuestPassword $vrapassword.password # minlen = Minimum password length (Default = 8) $minLength = $requiredConfig.minLength $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";s/minlen=[-]?[0-9]+/minlen=$minLength/" } $uncommentRegex = "/minlen/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minlen =" -or $checkKeys.ScriptOutput -match "minlen=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$minLengthRegex' $configFile" } else { $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";/pam_cracklib.so/ s/$/ minlen=$minLength/" } $scriptCommand = "sed -E -i.bak '$minLengthRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null # ucredit = Maximum number of uppercase characters that will generate a credit (Default = -1) $uppercase = $requiredConfig.minUppercase $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";s/ucredit=[-]?[0-9]+/ucredit=$uppercase/" } $uncommentRegex = "/ucredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ucredit =" -or $checkKeys.ScriptOutput -match "ucredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uppercaseRegex' $configFile" } else { $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";/pam_cracklib.so/ s/$/ ucredit=$uppercase/" } $scriptCommand = "sed -E -i.bak '$uppercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $lowercase = $requiredConfig.minLowercase # lcredit = Maximum number of lowercase characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";s/lcredit=[-]?[0-9]+/lcredit=$lowercase/" } $uncommentRegex = "/lcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# lcredit =" -or $checkKeys.ScriptOutput -match "lcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$lowercaseRegex' $configFile" } else { $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";/pam_cracklib.so/ s/$/ lcredit=$lowercase/" } $scriptCommand = "sed -E -i.bak '$lowercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null # dcredit = Maximum number of digits that will generate a credit (Default = -1) $numerical = $requiredConfig.minNumerical $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";s/dcredit=[-]?[0-9]+/dcredit=$numerical/" } $uncommentRegex = "/dcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# dcredit =" -or $checkKeys.ScriptOutput -match "dcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$numericalRegex' $configFile" } else { $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";/pam_cracklib.so/ s/$/ dcredit=$numerical/" } $scriptCommand = "sed -E -i.bak '$numericalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null # ocredit = Maximum number of other characters that will generate a credit (Default = -1) $special = $requiredConfig.minSpecial $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";s/ocredit=[-]?[0-9]+/ocredit=$special/" } $uncommentRegex = "/ocredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ocredit =" -or $checkKeys.ScriptOutput -match "ocredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$specialRegex' $configFile" } else { $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";/pam_cracklib.so/ s/$/ ocredit=$special/" } $scriptCommand = "sed -E -i.bak '$specialRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null # difok = Minimum number of characters that must be different from the old password (Default = 4) $unique = $requiredConfig.minUnique $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";s/difok=[-]?[0-9]+/difok=$unique/" } $uncommentRegex = "/difok/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# difok =" -or $checkKeys.ScriptOutput -match "difok=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uniqueRegex' $configFile" } else { $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";/pam_cracklib.so/ s/$/ difok=$unique/" } $scriptCommand = "sed -E -i.bak '$uniqueRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null # minclass = Minimum number of character types that must be used (e.g., uppercase, lowercase, digits, other) (Default = 4) $class = $requiredConfig.minClass $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";s/minclass=[-]?[0-9]+/minclass=$class/" } $uncommentRegex = "/minclass/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minclass =" -or $checkKeys.ScriptOutput -match "minclass=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$classRegex' $configFile" } else { $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";/pam_cracklib.so/ s/$/ minclass=$class/" } $scriptCommand = "sed -E -i.bak '$classRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null # maxsequence = Maximum number of times a single character may be repeated (Default = 0) $sequence = $requiredConfig.maxSequence $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";s/maxsequence=[-]?[0-9]+/maxsequence=$sequence/" } $uncommentRegex = "/maxrepeat/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# maxrepeat =" -or $checkKeys.ScriptOutput -match "maxsequence=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$sequenceRegex' $configFile" } else { $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";/pam_cracklib.so/ s/$/ maxsequence=$sequence/" } $scriptCommand = "sed -E -i.bak '$sequenceRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null # remember = Maximum number of passwords the system remembers (Default = 5) $history = $requiredConfig.history if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# remember =") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += "/^# remember/s/ *# *//g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += "s/remember = [-]?[0-9]+/remember = $history/g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } else { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += ";s/remember = [-]?[0-9]+/remember = $history/g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $rememberPattern = "remember=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $rememberPattern) { $historyCommand += ";s/(remember=[-]?[0-9]+)|(remember=)/remember=$history/" } else { $historyCommand += ";/$pamPattern/ s/$/ remember=$history/" } } else { $historyCommand += "/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root remember=$history" } $scriptCommand += $historyCommand if ($product -eq "vrni") { $scriptCommand += "' /etc/pam.d/common-password" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vrausername -GuestPassword $vrapassword.password # retry = Maximum number of retries of password (Default = 3) $retry = $requiredConfig.retries if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# retry =") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "/retry/s/ *# *//g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } $scriptCommand Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } else { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += ";s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $retryPattern = "retry=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $retryPattern) { $retryCommand += ";s/retry=[-]?[0-9]+/retry=$retry/" } else { $retryCommand += ";/$pamPattern/ s/$/ retry=$retry/" } } else { $retryCommand += "/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root retry=$retry" } $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } } } } if (-not($PsBoundParameters.ContainsKey("json"))) { # Aria Suite Lifecycle if ($product -eq "vrslcm") { $photonRelease = Invoke-VMscript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $photonScript -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/pwquality.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCheck -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword if ($PsBoundParameters.ContainsKey("minLength")) { # minlen = Minimum password length (Default = 8) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";s/minlen=[-]?[0-9]+/minlen=$minLength/" } $uncommentRegex = "/minlen/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minlen =" -or $checkKeys.ScriptOutput -match "minlen=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$minLengthRegex' $configFile" } else { $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";/pam_cracklib.so/ s/$/ minlen=$minLength/" } $scriptCommand = "sed -E -i.bak '$minLengthRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("uppercase")) { # ucredit = Maximum number of uppercase characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";s/ucredit=[-]?[0-9]+/ucredit=$uppercase/" } $uncommentRegex = "/ucredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ucredit =" -or $checkKeys.ScriptOutput -match "ucredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uppercaseRegex' $configFile" } else { $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";/pam_cracklib.so/ s/$/ ucredit=$uppercase/" } $scriptCommand = "sed -E -i.bak '$uppercaseRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("lowercase")) { # lcredit = Maximum number of lowercase characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";s/lcredit=[-]?[0-9]+/lcredit=$lowercase/" } $uncommentRegex = "/lcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# lcredit =" -or $checkKeys.ScriptOutput -match "lcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$lowercaseRegex' $configFile" } else { $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";/pam_cracklib.so/ s/$/ lcredit=$lowercase/" } $scriptCommand = "sed -E -i.bak '$lowercaseRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("numerical")) { # dcredit = Maximum number of digits that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";s/dcredit=[-]?[0-9]+/dcredit=$numerical/" } $uncommentRegex = "/dcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# dcredit =" -or $checkKeys.ScriptOutput -match "dcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$numericalRegex' $configFile" } else { $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";/pam_cracklib.so/ s/$/ dcredit=$numerical/" } $scriptCommand = "sed -E -i.bak '$numericalRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("special")) { # ocredit = Maximum number of other characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";s/ocredit=[-]?[0-9]+/ocredit=$special/" } $uncommentRegex = "/ocredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ocredit =" -or $checkKeys.ScriptOutput -match "ocredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$specialRegex' $configFile" } else { $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";/pam_cracklib.so/ s/$/ ocredit=$special/" } $scriptCommand = "sed -E -i.bak '$specialRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("unique")) { # difok = Minimum number of characters that must be different from the old password (Default = 4) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";s/difok=[-]?[0-9]+/difok=$unique/" } $uncommentRegex = "/difok/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# difok =" -or $checkKeys.ScriptOutput -match "difok=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uniqueRegex' $configFile" } else { $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";/pam_cracklib.so/ s/$/ difok=$unique/" } $scriptCommand = "sed -E -i.bak '$uniqueRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("class")) { # minclass = Minimum number of character types that must be used (e.g., uppercase, lowercase, digits, other) (Default = 4) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";s/minclass=[-]?[0-9]+/minclass=$class/" } $uncommentRegex = "/minclass/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minclass =" -or $checkKeys.ScriptOutput -match "minclass=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$classRegex' $configFile" } else { $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";/pam_cracklib.so/ s/$/ minclass=$class/" } $scriptCommand = "sed -E -i.bak '$classRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("history")) { # remember = Maximum number of passwords the system remembers (Default = 5) if ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "requisite pam_pwhistory.so enforce_for_root use_authtok" $rememberPattern = "remember=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $rememberPattern) { $historyCommand += ";s/(remember=[-]?[0-9]+)|(remember=)/remember=$history/" } else { $historyCommand += ";/$pamPattern/ s/$/ remember=$history/" } } else { $historyCommand += "/pam_unix.so/i password requisite pam_pwhistory.so use_authtok enforce_for_root remember=$history" } $scriptCommand += $historyCommand if ($product -eq "vrni") { $scriptCommand += "' /etc/pam.d/common-password" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } } $checkKeys = Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCheck -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword if ($PsBoundParameters.ContainsKey("retry")) { # retry = Maximum number of retries of password (Default = 3) if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# retry =") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "/retry/s/ *# *//g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } else { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += ";s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "requisite pam_pwhistory.so enforce_for_root use_authtok" $retryPattern = "retry=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $retryPattern) { $retryCommand += ";s/retry=[-]?[0-9]+/retry=$retry/" } else { $retryCommand += ";/$pamPattern/ s/$/ retry=$retry/" } } else { $retryCommand += "/pam_unix.so/i password requisite pam_pwhistory.so use_authtok enforce_for_root retry=$retry" } $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } } # Aria Operations if ($product -eq "vrops") { $vropsnodes = ((Get-vRSLCMProductDetails -productid vrops).nodes).properties.hostName foreach ($node in $vropsnodes) { $vropspassword = (Get-vRSLCMProductPassword -productId vrops -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vropsusername = (Get-vRSLCMLockerPassword -vmid $vropspassword.passwordvmid).userName $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser $vropsusername -GuestPassword $vropspassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/pwquality.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vropsusername -GuestPassword $vropspassword.password if ($PsBoundParameters.ContainsKey("minLength")) { # minlen = Minimum password length (Default = 8) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";s/minlen=[-]?[0-9]+/minlen=$minLength/" } $uncommentRegex = "/minlen/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minlen =" -or $checkKeys.ScriptOutput -match "minlen=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$minLengthRegex' $configFile" } else { $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";/pam_cracklib.so/ s/$/ minlen=$minLength/" } $scriptCommand = "sed -E -i.bak '$minLengthRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("uppercase")) { # ucredit = Maximum number of uppercase characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";s/ucredit=[-]?[0-9]+/ucredit=$uppercase/" } $uncommentRegex = "/ucredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ucredit =" -or $checkKeys.ScriptOutput -match "ucredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uppercaseRegex' $configFile" } else { $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";/pam_cracklib.so/ s/$/ ucredit=$uppercase/" } $scriptCommand = "sed -E -i.bak '$uppercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("lowercase")) { # lcredit = Maximum number of lowercase characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";s/lcredit=[-]?[0-9]+/lcredit=$lowercase/" } $uncommentRegex = "/lcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# lcredit =" -or $checkKeys.ScriptOutput -match "lcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$lowercaseRegex' $configFile" } else { $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";/pam_cracklib.so/ s/$/ lcredit=$lowercase/" } $scriptCommand = "sed -E -i.bak '$lowercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("numerical")) { # dcredit = Maximum number of digits that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";s/dcredit=[-]?[0-9]+/dcredit=$numerical/" } $uncommentRegex = "/dcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# dcredit =" -or $checkKeys.ScriptOutput -match "dcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$numericalRegex' $configFile" } else { $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";/pam_cracklib.so/ s/$/ dcredit=$numerical/" } $scriptCommand = "sed -E -i.bak '$numericalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("special")) { # ocredit = Maximum number of other characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";s/ocredit=[-]?[0-9]+/ocredit=$special/" } $uncommentRegex = "/ocredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ocredit =" -or $checkKeys.ScriptOutput -match "ocredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$specialRegex' $configFile" } else { $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";/pam_cracklib.so/ s/$/ ocredit=$special/" } $scriptCommand = "sed -E -i.bak '$specialRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("unique")) { # difok = Minimum number of characters that must be different from the old password (Default = 4) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";s/difok=[-]?[0-9]+/difok=$unique/" } $uncommentRegex = "/difok/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# difok =" -or $checkKeys.ScriptOutput -match "difok=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uniqueRegex' $configFile" } else { $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";/pam_cracklib.so/ s/$/ difok=$unique/" } $scriptCommand = "sed -E -i.bak '$uniqueRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("class")) { # minclass = Minimum number of character types that must be used (e.g., uppercase, lowercase, digits, other) (Default = 4) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";s/minclass=[-]?[0-9]+/minclass=$class/" } $uncommentRegex = "/minclass/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minclass =" -or $checkKeys.ScriptOutput -match "minclass=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$classRegex' $configFile" } else { $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";/pam_cracklib.so/ s/$/ minclass=$class/" } $scriptCommand = "sed -E -i.bak '$classRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("sequence")) { # maxsequence = Maximum number of times a single character may be repeated (Default = 0) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";s/maxsequence=[-]?[0-9]+/maxsequence=$sequence/" } $uncommentRegex = "/maxrepeat/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# maxrepeat =" -or $checkKeys.ScriptOutput -match "maxsequence=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$sequenceRegex' $configFile" } else { $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";/pam_cracklib.so/ s/$/ maxsequence=$sequence/" } $scriptCommand = "sed -E -i.bak '$sequenceRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("history")) { # remember = Maximum number of passwords the system remembers (Default = 5) if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# remember =") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += "/^# remember/s/ *# *//g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } else { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += ";s/(remember = [-]?[0-9]+)|(remember =)/remember = $history/g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $rememberPattern = "remember=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $rememberPattern) { $historyCommand += ";s/remember=[-]?[0-9]+/remember=$history/" } else { $historyCommand += ";/$pamPattern/ s/$/ remember=$history/" } } else { $historyCommand += ";/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root remember=$history" } $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vropsusername -GuestPassword $vropspassword.password if ($PsBoundParameters.ContainsKey("retry")) { # retry = Maximum number of retries of password (Default = 3) if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# retry =") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "/retry/s/ *# *//g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } $scriptCommand Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } else { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += ";s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $retryPattern = "retry=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $retryPattern) { $retryCommand += ";s/retry=[-]?[0-9]+/retry=$retry/" } else { $retryCommand += ";/$pamPattern/ s/$/ retry=$retry/" } } else { $retryCommand += "/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root retry=$retry" } $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } } } # Aria Operations for Logs if ($product -eq "vrli") { $vrlinodes = ((Get-vRSLCMProductDetails -productid vrli).nodes).properties.hostName foreach ($node in $vrlinodes) { $scriptCommand = "sed -E -i.bak '" $vrlipassword = (Get-vRSLCMProductPassword -productId vrli -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser root -GuestPassword $vrlipassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/pwquality.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser root -GuestPassword $vrlipassword.password if ($PsBoundParameters.ContainsKey("minLength")) { # minlen = Minimum password length (Default = 8) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";s/minlen=[-]?[0-9]+/minlen=$minLength/" } $uncommentRegex = "/minlen/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minlen =" -or $checkKeys.ScriptOutput -match "minlen=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$minLengthRegex' $configFile" } else { $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";/pam_cracklib.so/ s/$/ minlen=$minLength/" } $scriptCommand = "sed -E -i.bak '$minLengthRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("uppercase")) { # ucredit = Maximum number of uppercase characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";s/ucredit=[-]?[0-9]+/ucredit=$uppercase/" } $uncommentRegex = "/ucredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ucredit =" -or $checkKeys.ScriptOutput -match "ucredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uppercaseRegex' $configFile" } else { $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";/pam_cracklib.so/ s/$/ ucredit=$uppercase/" } $scriptCommand = "sed -E -i.bak '$uppercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("lowercase")) { # lcredit = Maximum number of lowercase characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";s/lcredit=[-]?[0-9]+/lcredit=$lowercase/" } $uncommentRegex = "/lcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# lcredit =" -or $checkKeys.ScriptOutput -match "lcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$lowercaseRegex' $configFile" } else { $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";/pam_cracklib.so/ s/$/ lcredit=$lowercase/" } $scriptCommand = "sed -E -i.bak '$lowercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("numerical")) { # dcredit = Maximum number of digits that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";s/dcredit=[-]?[0-9]+/dcredit=$numerical/" } $uncommentRegex = "/dcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# dcredit =" -or $checkKeys.ScriptOutput -match "dcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$numericalRegex' $configFile" } else { $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";/pam_cracklib.so/ s/$/ dcredit=$numerical/" } $scriptCommand = "sed -E -i.bak '$numericalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("special")) { # ocredit = Maximum number of other characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";s/ocredit=[-]?[0-9]+/ocredit=$special/" } $uncommentRegex = "/ocredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ocredit =" -or $checkKeys.ScriptOutput -match "ocredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$specialRegex' $configFile" } else { $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";/pam_cracklib.so/ s/$/ ocredit=$special/" } $scriptCommand = "sed -E -i.bak '$specialRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("unique")) { # difok = Minimum number of characters that must be different from the old password (Default = 4) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";s/difok=[-]?[0-9]+/difok=$unique/" } $uncommentRegex = "/difok/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# difok =" -or $checkKeys.ScriptOutput -match "difok=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uniqueRegex' $configFile" } else { $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";/pam_cracklib.so/ s/$/ difok=$unique/" } $scriptCommand = "sed -E -i.bak '$uniqueRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("class")) { # minclass = Minimum number of character types that must be used (e.g., uppercase, lowercase, digits, other) (Default = 4) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";s/minclass=[-]?[0-9]+/minclass=$class/" } $uncommentRegex = "/minclass/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minclass =" -or $checkKeys.ScriptOutput -match "minclass=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$classRegex' $configFile" } else { $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";/pam_cracklib.so/ s/$/ minclass=$class/" } $scriptCommand = "sed -E -i.bak '$classRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("sequence")) { # maxsequence = Maximum number of times a single character may be repeated (Default = 0) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";s/maxsequence=[-]?[0-9]+/maxsequence=$sequence/" } $uncommentRegex = "/maxrepeat/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# maxrepeat =" -or $checkKeys.ScriptOutput -match "maxsequence=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$sequenceRegex' $configFile" } else { $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";/pam_cracklib.so/ s/$/ maxsequence=$sequence/" } $scriptCommand = "sed -E -i.bak '$sequenceRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("history")) { # remember = Maximum number of passwords the system remembers (Default = 5) if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# remember =") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += "/^# remember/s/ *# *//g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } else { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += ";s/(remember = [-]?[0-9]+)|(remember =)/remember = $history/g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $rememberPattern = "remember=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $rememberPattern) { $historyCommand += ";s/(remember=[-]?[0-9]+)|(remember=)/remember=$history/" } else { $historyCommand += ";/$pamPattern/ s/$/ remember=$history/" } } else { $historyCommand += ";/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root remember=$history" } $scriptCommand += $historyCommand if ($product -eq "vrni") { $scriptCommand += "' /etc/pam.d/common-password" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser root -GuestPassword $vrlipassword.password if ($PsBoundParameters.ContainsKey("retry")) { # retry = Maximum number of retries of password (Default = 3) if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# retry =") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "/retry/s/ *# *//g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } $scriptCommand Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } else { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += ";s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $retryPattern = "retry=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $retryPattern) { $retryCommand += ";s/retry=[-]?[0-9]+/retry=$retry/" } else { $retryCommand += ";/$pamPattern/ s/$/ retry=$retry/" } } else { $retryCommand += "/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root retry=$retry" } $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } } } # Aria Operations for Networks if ($product -eq "vrni") { $vrninodes = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties) $scriptCommand = $null foreach ($node in $vrninodes) { $scriptCommand = "sudo sed -E -i.bak '" $scriptCheck = " sudo cat /etc/pam.d/common-password" $vrninodedata = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.vmname -eq $node.vmName }) $vrnivmid = $vrninodedata.supportPassword.Split(':')[2] $vrnipassword = (Get-vRSLCMProductPassword -productId vrni -vmid $vrnivmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $checkKeys = Invoke-VMScript -VM $node.vmname -ScriptText $scriptCheck -GuestUser support -GuestPassword $vrnipassword.password if ($PsBoundParameters.ContainsKey("minLength")) { # minlen = Minimum password length (Default = 6) $minLengthCommand = "" if ($checkKeys.ScriptOutput -match "minlen=") { $minLengthCommand += ";s/minlen=[-]?[0-9]+/minlen=$minLength/" } else { $minLengthCommand += ";/pam_cracklib.so/ s/$/ minlen=$minLength/" } $scriptCommand += $minLengthCommand } if ($PsBoundParameters.ContainsKey("uppercase")) { # ucredit = Maximum number of uppercase characters that will generate a credit (Default = -1) if ($checkKeys.ScriptOutput -match "ucredit=") { $uppercaseCommand = ";s/ucredit=[-]?[0-9]+/ucredit=$uppercase/" } $scriptCommand += $uppercaseCommand } if ($PsBoundParameters.ContainsKey("lowercase")) { # lcredit = Maximum number of lowercase characters that will generate a credit (Default = -1) if ($checkKeys.ScriptOutput -match "lcredit=") { $lowercaseCommand = ";s/lcredit=[-]?[0-9]+/lcredit=$lowercase/" } $scriptCommand += $lowercaseCommand } if ($PsBoundParameters.ContainsKey("numerical")) { # dcredit = Maximum number of digits that will generate a credit (Default = -1) if ($checkKeys.ScriptOutput -match "dcredit=") { $numericalCommand = ";s/dcredit=[-]?[0-9]+/dcredit=$numerical/" } $scriptCommand += $numericalCommand } if ($PsBoundParameters.ContainsKey("special")) { # ocredit = Maximum number of other characters that will generate a credit (Default = -1) if ($checkKeys.ScriptOutput -match "ocredit=") { $specialCommand = ";s/ocredit=[-]?[0-9]+/ocredit=$special/" } $scriptCommand += $specialCommand } if ($PsBoundParameters.ContainsKey("unique")) { # difok = Minimum number of characters that must be different from the old password (Default = 4) if ($checkKeys.ScriptOutput -match "difok=") { $uniqueCommand = ";s/difok=[-]?[0-9]+/difok=$unique/" } $scriptCommand += $uniqueCommand } if ($PsBoundParameters.ContainsKey("class")) { # minclass = Minimum number of character types that must be used (e.g., uppercase, lowercase, digits, other) (Default = 4) if ($checkKeys.ScriptOutput -match "minclass=" ) { $minClassCommand = ";s/minclass=[-]?[0-9]+/minclass=$class/" } $scriptCommand += $minClassCommand } if ($PsBoundParameters.ContainsKey("sequence")) { # maxrepeat = Maximum number of times a single character may be repeated (Default = 0) if ($checkKeys.ScriptOutput -match "sequence=" ) { $maxSequenceCommand = ";s/maxsequence=[-]?[0-9]+/maxsequence=$sequence/" } $scriptCommand += $maxSequenceCommand } if ($PsBoundParameters.ContainsKey("history")) { # remember = Maximum number of passwords the system remembers (Default = 5) if ($checkKeys.ScriptOutput -match "remember=") { $historyCommand += ";s/(remember=[-]?[0-9]+)|(remember=)/remember=$history/" } $scriptCommand += $historyCommand } if ($PsBoundParameters.ContainsKey("retry")) { if ($checkKeys.ScriptOutput -match "retry=") { $retryCommand += ";s/retry=[-]?[0-9]+/retry=$retry/" } $scriptCommand += $retryCommand } $scriptCommand += "' /etc/pam.d/common-password" Invoke-VMScript -VM $node.vmname -ScriptText $scriptCommand -GuestUser support -GuestPassword $vrnipassword.password -Confirm:$false | Out-Null } } # Aria Automation if ($product -eq 'vra') { $vranodes = ((Get-vRSLCMProductDetails -productid vra).nodes).properties.hostName foreach ($node in $vranodes) { $vrapassword = (Get-vRSLCMProductPassword -productId vra -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vrausername = (Get-vRSLCMLockerPassword -vmid $vrapassword.passwordvmid).userName $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser $vrausername -GuestPassword $vrapassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/pwquality.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vrausername -GuestPassword $vrapassword.password if ($PsBoundParameters.ContainsKey("minLength")) { # minlen = Minimum password length (Default = 8) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";s/minlen=[-]?[0-9]+/minlen=$minLength/" } $uncommentRegex = "/minlen/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minlen =" -or $checkKeys.ScriptOutput -match "minlen=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$minLengthRegex' $configFile" } else { $minLengthRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minlen = [-]?[0-9]+/minlen = $minLength/g" } else { ";/pam_cracklib.so/ s/$/ minlen=$minLength/" } $scriptCommand = "sed -E -i.bak '$minLengthRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("uppercase")) { # ucredit = Maximum number of uppercase characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";s/ucredit=[-]?[0-9]+/ucredit=$uppercase/" } $uncommentRegex = "/ucredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ucredit =" -or $checkKeys.ScriptOutput -match "ucredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uppercaseRegex' $configFile" } else { $uppercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ucredit = [-]?[0-9]+/ucredit = $uppercase/g" } else { ";/pam_cracklib.so/ s/$/ ucredit=$uppercase/" } $scriptCommand = "sed -E -i.bak '$uppercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("lowercase")) { # lcredit = Maximum number of lowercase characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";s/lcredit=[-]?[0-9]+/lcredit=$lowercase/" } $uncommentRegex = "/lcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# lcredit =" -or $checkKeys.ScriptOutput -match "lcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$lowercaseRegex' $configFile" } else { $lowercaseRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/lcredit = [-]?[0-9]+/lcredit = $lowercase/g" } else { ";/pam_cracklib.so/ s/$/ lcredit=$lowercase/" } $scriptCommand = "sed -E -i.bak '$lowercaseRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("numerical")) { # dcredit = Maximum number of digits that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";s/dcredit=[-]?[0-9]+/dcredit=$numerical/" } $uncommentRegex = "/dcredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# dcredit =" -or $checkKeys.ScriptOutput -match "dcredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$numericalRegex' $configFile" } else { $numericalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/dcredit = [-]?[0-9]+/dcredit = $numerical/g" } else { ";/pam_cracklib.so/ s/$/ dcredit=$numerical/" } $scriptCommand = "sed -E -i.bak '$numericalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("special")) { # ocredit = Maximum number of other characters that will generate a credit (Default = -1) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";s/ocredit=[-]?[0-9]+/ocredit=$special/" } $uncommentRegex = "/ocredit/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# ocredit =" -or $checkKeys.ScriptOutput -match "ocredit=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$specialRegex' $configFile" } else { $specialRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/ocredit = [-]?[0-9]+/ocredit = $special/g" } else { ";/pam_cracklib.so/ s/$/ ocredit=$special/" } $scriptCommand = "sed -E -i.bak '$specialRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("unique")) { # difok = Minimum number of characters that must be different from the old password (Default = 4) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";s/difok=[-]?[0-9]+/difok=$unique/" } $uncommentRegex = "/difok/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# difok =" -or $checkKeys.ScriptOutput -match "difok=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$uniqueRegex' $configFile" } else { $uniqueRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/difok = [-]?[0-9]+/difok = $unique/g" } else { ";/pam_cracklib.so/ s/$/ difok=$unique/" } $scriptCommand = "sed -E -i.bak '$uniqueRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("class")) { # minclass = Minimum number of character types that must be used (e.g., uppercase, lowercase, digits, other) (Default = 4) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";s/minclass=[-]?[0-9]+/minclass=$class/" } $uncommentRegex = "/minclass/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# minclass =" -or $checkKeys.ScriptOutput -match "minclass=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$classRegex' $configFile" } else { $classRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/minclass = [-]?[0-9]+/minclass = $class/g" } else { ";/pam_cracklib.so/ s/$/ minclass=$class/" } $scriptCommand = "sed -E -i.bak '$classRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("sequence")) { # maxsequence = Maximum number of times a single character may be repeated (Default = 0) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/pwquality.conf" } else { "/etc/pam.d/system-password" } $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";s/maxsequence=[-]?[0-9]+/maxsequence=$sequence/" } $uncommentRegex = "/maxrepeat/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# maxrepeat =" -or $checkKeys.ScriptOutput -match "maxsequence=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$sequenceRegex' $configFile" } else { $sequenceRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/maxrepeat = [-]?[0-9]+/maxrepeat = $sequence/g" } else { ";/pam_cracklib.so/ s/$/ maxsequence=$sequence/" } $scriptCommand = "sed -E -i.bak '$sequenceRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("history")) { # remember = Maximum number of passwords the system remembers (Default = 5) if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# remember =") { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += "/^# remember/s/ *# *//g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += "s/(remember = [-]?[0-9]+)|(remember = )/remember = $history/g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } $scriptCommand Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } else { $scriptCommand = $null $historyCommand = $null $scriptCommand = "sed -E -i.bak '" $historyCommand += ";s/(remember = [-]?[0-9]+)|(remember = )/remember = $history/g" $scriptCommand += $historyCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwhistory.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $historyCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $rememberPattern = "remember=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $rememberPattern) { $historyCommand += ";s/(remember=[-]?[0-9]+) | ( remember= )/remember=$history/" } else { $historyCommand += ";/$pamPattern/ s/$/ remember=$history/" } } else { $historyCommand += ";/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root remember=$history" } $scriptCommand += $historyCommand if ($product -eq "vrni") { $scriptCommand += "' /etc/pam.d/common-password" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vrausername -GuestPassword $vrapassword.password if ($PsBoundParameters.ContainsKey("retry")) { # retry = Maximum number of retries of password (Default = 3) if ($photonRelease.ScriptOutput -match "[4-5].0") { if ($checkKeys.ScriptOutput -match "# retry =") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "/retry/s/ *# *//g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } $scriptCommand Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += "s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } else { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $retryCommand += ";s/retry = [-]?[0-9]+/retry = $retry/g" $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } elseif ($photonRelease.ScriptOutput -match "3.0") { $scriptCommand = $null $retryCommand = $null $scriptCommand = "sed -E -i.bak '" $pamPattern = "required pam_pwhistory.so use_authtok enforce_for_root" $retryPattern = "retry=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $retryPattern) { $retryCommand += ";s/retry=[-]?[0-9]+/retry=$retry/" } else { $retryCommand += ";/$pamPattern/ s/$/ retry=$retry/" } } else { $retryCommand += "/pam_unix.so/i password required pam_pwhistory.so use_authtok enforce_for_root retry=$retry" } $scriptCommand += $retryCommand if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCommand += "' /etc/security/pwquality.conf" } else { $scriptCommand += "' /etc/pam.d/system-password" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null $scriptCommand = $null $retryCommand = $null } } } } } } Catch { Write-Error $_.Exception.Message } } Export-ModuleMember -Function Update-AriaLocalUserPasswordComplexity Function Update-AriaLocalUserPasswordAccountLockout { <# .SYNOPSIS Configure password account lockout for local users. .DESCRIPTION The Update-AriaLocalUserPasswordAccountLockout cmdlet configures the Account Lockout settings for local users. .EXAMPLE Update-AriaLocalUserPasswordAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -failures 5 -unlockInterval 900 -rootUnlockInterval 900 This example updates the Aria Automation nodes with new values for each element. .EXAMPLE Update-AriaLocalUserPasswordAccountLockout -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -product vra -json -reportPath [report_path] -policyFile [policy_file].json This example updates Aria Automation nodes using the JSON file values. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER product The product to configure the password account lockout policy. One of: vrslcm, vrli, vrops, vrni, or vra. .PARAMETER failures The number of failed login attempts before the account is locked. .PARAMETER unlockInterval The number of seconds before a locked out account is unlocked. .PARAMETER rootUnlockInterval The number of seconds before a locked out root account is unlocked. .PARAMETER json Use a JSON file to configure the password complexity. .PARAMETER policyPath The path to the policy file. .PARAMETER policyFile The path to the policy file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateSet('vrslcm', 'vrops', 'vrli', 'vrni', 'vra')] [String]$product, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$failures, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$unlockInterval, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int]$rootUnlockInterval, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (($vcfVrslcmDetails = Get-vRSLCMServerDetail -fqdn $server -username $user -password $pass )) { if (Test-vRSLCMAuthentication -server $vcfVrslcmDetails.fqdn -user $vcfVrslcmDetails.adminUser -pass $vcfVrslcmDetails.adminPass) { $domain = Get-VCFWorkloadDomain | Select-Object name, type | Where-Object { $_.type -eq "MANAGEMENT" } if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain.name)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { } } } } } } } $photonScript = "cat /etc/photon-release" Try { if ($PsBoundParameters.ContainsKey("json")) { $version = Get-VCFManager -version if ($PsBoundParameters.ContainsKey("policyFile")) { # Aria Suite Lifecycle if ($product -eq "vrslcm") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaLifecycle.accountLockout $photonRelease = Invoke-VMscript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $photonScript -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/faillock.conf" } else { $scriptCheck = " cat /etc/pam.d/system-auth" } $checkKeys = Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCheck -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword # failures = Maximum number of authentication failures before the account is locked (Default = 3) $failures = $requiredConfig.maxFailures $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $uncommentRegex = "/deny/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# deny =" -or $checkKeys.ScriptOutput -match "deny=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$failuresRegex' $configFile" } else { $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $scriptCommand = "sed -E -i.bak '$failuresRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null # unlock_time = Amount of time in seconds that the account remains locked (Default = 900) $unlockInterval = $requiredConfig.unlockInterval $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/unlock_time=[-]?[0-9]+/unlock_time=$unlockInterval/g" } $uncommentRegex = "/unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$unlockIntervalRegex' $configFile" } else { $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/(^| )unlock_time=[-]?[0-9]+/\1unlock_time=$unlockInterval/g" } $scriptCommand = "sed -E -i.bak '$unlockIntervalRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null # root_unlock_time = Amount of time in seconds that the root account remains locked (Default = 900) $rootUnlockInterval = $requiredConfig.rootUnlockInterval $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/root_unlock_time= [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/root_unlock_time=[-]?[0-9]+/root_unlock_time=$rootUnlockInterval/" } $uncommentRegex = "/root_unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# root_unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "root_unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$rootUnlockIntervalRegex' $configFile" } else { $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^root_unlock_time = [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/(^| )root_unlock_time=[-]?[0-9]+/\1root_unlock_time=$rootUnlockInterval/g" } $scriptCommand = "sed -E -i.bak '$rootUnlockIntervalRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } # Aria Operations if ($product -eq "vrops") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaOperations.accountLockout $vropsnodes = ((Get-vRSLCMProductDetails -productid vrops).nodes).properties.hostName foreach ($node in $vropsnodes) { $vropspassword = (Get-vRSLCMProductPassword -productId vrops -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vropsusername = (Get-vRSLCMLockerPassword -vmid $vropspassword.passwordvmid).userName $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser $vropsusername -GuestPassword $vropspassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/faillock.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vropsusername -GuestPassword $vropspassword.password # failures = Maximum number of authentication failures before the account is locked (Default = 3) $failures = $requiredConfig.maxFailures $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { } $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $uncommentRegex = "/deny/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# deny =" -or $checkKeys.ScriptOutput -match "deny=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$failuresRegex' $configFile" } else { $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $scriptCommand = "sed -E -i.bak '$failuresRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null # unlock_time = Amount of time in seconds that the account remains locked (Default = 900) $unlockInterval = $requiredConfig.unlockInterval $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/unlock_time=[-]?[0-9]+/unlock_time=$unlockInterval/g" } $uncommentRegex = "/unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$unlockIntervalRegex' $configFile" } else { $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/(^| )unlock_time=[-]?[0-9]+/\1unlock_time=$unlockInterval/g" } $scriptCommand = "sed -E -i.bak '$unlockIntervalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null # root_unlock_time = Amount of time in seconds that the root account remains locked (Default = 900) $rootUnlockInterval = $requiredConfig.rootUnlockInterval $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/root_unlock_time= [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/root_unlock_time=[-]?[0-9]+/root_unlock_time=$rootUnlockInterval/" } $uncommentRegex = "/root_unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# root_unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "root_unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$rootUnlockIntervalRegex' $configFile" } else { $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^root_unlock_time = [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/(^| )root_unlock_time=[-]?[0-9]+/\1root_unlock_time=$rootUnlockInterval/g" } $scriptCommand = "sed -E -i.bak '$rootUnlockIntervalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } } # Aria Operatons for Logs if ($product -eq 'vrli') { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaOperationsLogs.accountLockout $vrlinodes = ((Get-vRSLCMProductDetails -productid vrli).nodes).properties.hostName foreach ($node in $vrlinodes) { $vrlipassword = (Get-vRSLCMProductPassword -productId vrli -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser root -GuestPassword $vrlipassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/faillock.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser root -GuestPassword $vrlipassword.password # failures = Maximum number of authentication failures before the account is locked (Default = 3) $failures = $requiredConfig.maxFailures $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $uncommentRegex = "/deny/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# deny =" -or $checkKeys.ScriptOutput -match "deny=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$failuresRegex' $configFile" } else { $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $scriptCommand = "sed -E -i.bak '$failuresRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null # unlock_time = Amount of time in seconds that the account remains locked (Default = 900) $unlockInterval = $requiredConfig.unlockInterval $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/unlock_time=[-]?[0-9]+/unlock_time=$unlockInterval/g" } $uncommentRegex = "/unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$unlockIntervalRegex' $configFile" } else { $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/(^| )unlock_time=[-]?[0-9]+/\1unlock_time=$unlockInterval/g" } $scriptCommand = "sed -E -i.bak '$unlockIntervalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null # root_unlock_time = Amount of time in seconds that the root account remains locked (Default = 900) $rootUnlockInterval = $requiredConfig.rootUnlockInterval $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/root_unlock_time= [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/root_unlock_time=[-]?[0-9]+/root_unlock_time=$rootUnlockInterval/" } $uncommentRegex = "/root_unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# root_unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "root_unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$rootUnlockIntervalRegex' $configFile" } else { $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^root_unlock_time = [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/(^| )root_unlock_time=[-]?[0-9]+/\1root_unlock_time=$rootUnlockInterval/g" } $scriptCommand = "sed -E -i.bak '$rootUnlockIntervalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } } # Aria Operations for Networks if ($product -eq "vrni") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).ariaOperationsNetworks.accountLockout $scriptCommand = $null $vrninodes = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties) foreach ($node in $vrninodes) { $scriptCheck = " sudo cat /etc/pam.d/common-auth" $vrninodedata = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.vmname -eq $node.vmName }) $vrnivmid = $vrninodedata.supportPassword.Split(':')[2] $vrnipassword = (Get-vRSLCMProductPassword -productId vrni -vmid $vrnivmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $checkKeys = Invoke-VMScript -VM $node.vmname -ScriptText $scriptCheck -GuestUser support -GuestPassword $vrnipassword.password # failures = Maximum number of authentication failures before the account is locked (Default = 5) $failuresCommand = $null $failures = $requiredConfig.maxFailures $scriptCommand = "sudo sed -E -i.bak '" $pamPattern = "auth\s+required\s+pam_tally2\.so\s+onerr=fail" $denyPattern = "deny=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $denyPattern) { $failuresCommand += ";s/deny=[-]?[0-9]+/deny=$failures/" } else { $failuresCommand += ";/$pamPattern/ s/$/ deny=$failures/" } } else { $failuresCommand += "/pam_deny.so/a auth required pam_tally2.so onerr=fail deny=$failures" } $scriptCommand += $failuresCommand $scriptCommand += "' /etc/pam.d/common-auth" Invoke-VMScript -VM $node.vmname -ScriptText $scriptCommand -GuestUser support -GuestPassword $vrnipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $checkKeys = Invoke-VMScript -VM $node.vmname -ScriptText $scriptCheck -GuestUser support -GuestPassword $vrnipassword.password # unlock_time = Amount of time in seconds that the account remains locked (Default = 15) $unlockInterval = $requiredConfig.unlockInterval $unlockIntervalCommand = $null $scriptCommand = "sudo sed -E -i.bak '" $pamPattern = "auth\s+required\s+pam_tally2\.so\s+onerr=fail" $unlockIntervalPattern = "unlock_time=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $unlockIntervalPattern) { $unlockIntervalCommand += ";s/unlock_time=[-]?[0-9]+/unlock_time=$unlockInterval/" } else { $unlockIntervalCommand += ";/$pamPattern/ s/$/ unlock_time=$unlockInterval/" } } else { $unlockIntervalCommand += "/pam_deny.so/a auth required pam_tally2.so onerr=fail unlock_time=$unlockInterval" } $scriptCommand += $unlockIntervalCommand $scriptCommand += "' /etc/pam.d/common-auth" Invoke-VMScript -VM $node.vmname -ScriptText $scriptCommand -GuestUser support -GuestPassword $vrnipassword.password -Confirm:$false | Out-Null $scriptCommand = $null } } # Aria Automation if ($product -eq "vra") { $requiredConfig = (Get-PasswordPolicyConfig -version $version -reportPath $policyPath -policyFile $policyFile ).AriaAutomation.accountLockout $vranodes = ((Get-vRSLCMProductDetails -productid vra).nodes).properties.hostName foreach ($node in $vranodes) { $vrapassword = (Get-vRSLCMProductPassword -productId vra -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vrausername = (Get-vRSLCMLockerPassword -vmid $vrapassword.passwordvmid).userName $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser $vrausername -GuestPassword $vrapassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/faillock.conf" } else { $scriptCheck = " cat /etc/pam.d/system-auth" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vrausername -GuestPassword $vrapassword.password # failures = Maximum number of authentication failures before the account is locked (Default = 3) $failures = $requiredConfig.maxFailures $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } if ($checkKeys.ScriptOutput -match "# deny =" -or $checkKeys.ScriptOutput -match "deny=") { } else { $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $scriptCommand = "sed -E -i.bak '$failuresRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null # unlock_time = Amount of time in seconds that the account remains locked (Default = 86400) $unlockInterval = $requiredConfig.unlockInterval $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/unlock_time=[-]?[0-9]+/unlock_time=$unlockInterval/g" } $uncommentRegex = "/unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$unlockIntervalRegex' $configFile" } else { $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/(^| )unlock_time=[-]?[0-9]+/\1unlock_time=$unlockInterval/g" } $scriptCommand = "sed -E -i.bak '$unlockIntervalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null # root_unlock_time = Amount of time in seconds that the root account remains locked (Default = 300) $rootUnlockInterval = $requiredConfig.rootUnlockInterval $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/root_unlock_time= [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/root_unlock_time=[-]?[0-9]+/root_unlock_time=$rootUnlockInterval/" } $uncommentRegex = "/root_unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# root_unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "root_unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$rootUnlockIntervalRegex' $configFile" } else { $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^root_unlock_time = [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/(^| )root_unlock_time=[-]?[0-9]+/\1root_unlock_time=$rootUnlockInterval/g" } $scriptCommand = "sed -E -i.bak '$rootUnlockIntervalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } } } } if (-not($PsBoundParameters.ContainsKey("json"))) { # Aria Suite Lifecycle if ($product -eq "vrslcm") { $photonRelease = Invoke-VMscript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $photonScript -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/pwquality.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCheck -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword if ($PsBoundParameters.ContainsKey("failures")) { # failures = Maximum number of authentication failures before the account is locked (Default = 3) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $uncommentRegex = "/deny/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# deny =" -or $checkKeys.ScriptOutput -match "deny=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$failuresRegex' $configFile" } else { $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $scriptCommand = "sed -E -i.bak '$failuresRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("unlockInterval")) { # unlock_time = Amount of time in seconds that the account remains locked (Default = 900) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/unlock_time=[-]?[0-9]+/unlock_time=$unlockInterval/g" } $uncommentRegex = "/unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$unlockIntervalRegex' $configFile" } else { $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/(^| )unlock_time=[-]?[0-9]+/\1unlock_time=$unlockInterval/g" } $scriptCommand = "sed -E -i.bak '$unlockIntervalRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("rootUnlockInterval")) { # root_unlock_time = Amount of time in seconds that the root account remains locked (Default = 900) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/root_unlock_time= [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/root_unlock_time=[-]?[0-9]+/root_unlock_time=$rootUnlockInterval/" } $uncommentRegex = "/root_unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# root_unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "root_unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$rootUnlockIntervalRegex' $configFile" } else { $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^root_unlock_time = [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/(^| )root_unlock_time=[-]?[0-9]+/\1root_unlock_time=$rootUnlockInterval/g" } $scriptCommand = "sed -E -i.bak '$rootUnlockIntervalRegex' $configFile" } Invoke-VMScript -VM $vcfVrslcmDetails.fqdn.split('.')[0] -ScriptText $scriptCommand -GuestUser $vcfVrslcmDetails.rootUser -GuestPassword $vcfVrslcmDetails.rootPassword -Confirm:$false | Out-Null } } # Aria Operations if ($product -eq "vrops") { $vropsnodes = ((Get-vRSLCMProductDetails -productid vrops).nodes).properties.hostName foreach ($node in $vropsnodes) { $vropspassword = (Get-vRSLCMProductPassword -productId vrops -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vropsusername = (Get-vRSLCMLockerPassword -vmid $vropspassword.passwordvmid).userName $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser $vropsusername -GuestPassword $vropspassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/pwquality.conf" } else { $scriptCheck = " cat /etc/pam.d/system-password" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vropsusername -GuestPassword $vropspassword.password if ($PsBoundParameters.ContainsKey("failures")) { # failures = Maximum number of authentication failures before the account is locked (Default = 3) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $uncommentRegex = "/deny/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# deny =" -or $checkKeys.ScriptOutput -match "deny=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$failuresRegex' $configFile" } else { $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $scriptCommand = "sed -E -i.bak '$failuresRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("unlockInterval")) { # unlock_time = Amount of time in seconds that the account remains locked (Default = 900) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/unlock_time=[-]?[0-9]+/unlock_time=$unlockInterval/g" } $uncommentRegex = "/unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$unlockIntervalRegex' $configFile" } else { $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/(^| )unlock_time=[-]?[0-9]+/\1unlock_time=$unlockInterval/g" } $scriptCommand = "sed -E -i.bak '$unlockIntervalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("rootUnlockInterval")) { # root_unlock_time = Amount of time in seconds that the root account remains locked (Default = 900) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/root_unlock_time= [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/root_unlock_time=[-]?[0-9]+/root_unlock_time=$rootUnlockInterval/" } $uncommentRegex = "/root_unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# root_unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "root_unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$rootUnlockIntervalRegex' $configFile" } else { $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^root_unlock_time = [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/(^| )root_unlock_time=[-]?[0-9]+/\1root_unlock_time=$rootUnlockInterval/g" } $scriptCommand = "sed -E -i.bak '$rootUnlockIntervalRegex' $configFile" } $scriptCommand Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vropsusername -GuestPassword $vropspassword.password -Confirm:$false | Out-Null } } } # Aria Operations for Logs if ($product -eq "vrli") { $vrlinodes = ((Get-vRSLCMProductDetails -productid vrli).nodes).properties.hostName foreach ($node in $vrlinodes) { $vrlipassword = (Get-vRSLCMProductPassword -productId vrli -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser root -GuestPassword $vrlipassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/faillock.conf" } else { $scriptCheck = " cat /etc/pam.d/system-auth" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser root -GuestPassword $vrlipassword.password if ($PsBoundParameters.ContainsKey("failures")) { # failures = Maximum number of authentication failures before the account is locked (Default = 3) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $uncommentRegex = "/deny/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# deny =" -or $checkKeys.ScriptOutput -match "deny=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$failuresRegex' $configFile" } else { $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $scriptCommand = "sed -E -i.bak '$failuresRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("unlockInterval")) { # unlock_time = Amount of time in seconds that the account remains locked (Default = 900) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/unlock_time=[-]?[0-9]+/unlock_time=$unlockInterval/g" } $uncommentRegex = "/unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$unlockIntervalRegex' $configFile" } else { $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/(^| )unlock_time=[-]?[0-9]+/\1unlock_time=$unlockInterval/g" } $scriptCommand = "sed -E -i.bak '$unlockIntervalRegex' $configFile" } $scriptCommand Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("rootUnlockInterval")) { # root_unlock_time = Amount of time in seconds that the root account remains locked (Default = 900) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/root_unlock_time= [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/root_unlock_time=[-]?[0-9]+/root_unlock_time=$rootUnlockInterval/" } $uncommentRegex = "/root_unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# root_unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "root_unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$rootUnlockIntervalRegex' $configFile" } else { $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^root_unlock_time = [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/(^| )root_unlock_time=[-]?[0-9]+/\1root_unlock_time=$rootUnlockInterval/g" } $scriptCommand = "sed -E -i.bak '$rootUnlockIntervalRegex' $configFile" } $scriptCommand Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser root -GuestPassword $vrlipassword.password -Confirm:$false | Out-Null } } } # Aria Operations for Networks if ($product -eq "vrni") { $vrninodes = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties) $scriptCommand = $null foreach ($node in $vrninodes) { $scriptCheck = " sudo cat /etc/pam.d/common-auth" $vrninodedata = ((Get-vRSLCMProductDetails -productid vrni).nodes | Select-Object type -ExpandProperty properties | Where-Object { $_.vmname -eq $node.vmName }) $vrnivmid = $vrninodedata.supportPassword.Split(':')[2] $vrnipassword = (Get-vRSLCMProductPassword -productId vrni -vmid $vrnivmid -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $checkKeys = Invoke-VMScript -VM $node.vmname -ScriptText $scriptCheck -GuestUser support -GuestPassword $vrnipassword.password if ($PsBoundParameters.ContainsKey("failures")) { # failures = Maximum number of authentication failures before the account is locked (Default = 5) $scriptCommand = $null $failuresCommand = $null $scriptCommand = "sudo sed -E -i.bak '" $pamPattern = "auth\s+required\s+pam_tally2\.so\s+onerr=fail" $denyPattern = "deny=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $denyPattern) { $failuresCommand += ";s/deny=[-]?[0-9]+/deny=$failures/" } else { $failuresCommand += ";/$pamPattern/ s/$/ deny=$failures/" } } else { $failuresCommand += "/pam_deny.so/a auth required pam_tally2.so onerr=fail deny=$failures" } $scriptCommand += $failuresCommand $scriptCommand += "' /etc/pam.d/common-auth" Invoke-VMScript -VM $node.vmname -ScriptText $scriptCommand -GuestUser support -GuestPassword $vrnipassword.password -Confirm:$false | Out-Null $scriptCommand = $null $failuresCommand = $null } $checkKeys = Invoke-VMScript -VM $node.vmname -ScriptText $scriptCheck -GuestUser support -GuestPassword $vrnipassword.password if ($PsBoundParameters.ContainsKey("unlockInterval")) { # unlock_time = Amount of time in seconds that the account remains locked (Default = 15) $unlockIntervalCommand = $null $scriptCommand = "sudo sed -E -i.bak '" $pamPattern = "auth\s+required\s+pam_tally2\.so\s+onerr=fail" $unlockIntervalPattern = "unlock_time=" if ($checkKeys.ScriptOutput -match $pamPattern) { if ($checkKeys.ScriptOutput -match $unlockIntervalPattern) { $unlockIntervalCommand += ";s/unlock_time=[-]?[0-9]+/unlock_time=$unlockInterval/" } else { $unlockIntervalCommand += ";/$pamPattern/ s/$/ unlock_time=$unlockInterval/" } } else { $unlockIntervalCommand += "/pam_deny.so/a auth required pam_tally2.so onerr=fail unlock_time=$unlockInterval" } $scriptCommand += $unlockIntervalCommand $scriptCommand += "' /etc/pam.d/common-auth" Invoke-VMScript -VM $node.vmname -ScriptText $scriptCommand -GuestUser support -GuestPassword $vrnipassword.password -Confirm:$false | Out-Null $scriptCommand = $null } if ($PsBoundParameters.ContainsKey("rootUnlockInterval")) { Write-Output "The root unlock interval is not supported for Aria Operations for Networks." } } } # Aria Automation if ($product -eq 'vra') { $vranodes = ((Get-vRSLCMProductDetails -productid vra).nodes).properties.hostName foreach ($node in $vranodes) { $vrapassword = (Get-vRSLCMProductPassword -productId vra -nodeFqdn $node -vrslcmRootPass $vcfVrslcmDetails.rootPassword) $vrausername = (Get-vRSLCMLockerPassword -vmid $vrapassword.passwordvmid).userName $photonRelease = Invoke-VMscript -VM $node.split('.')[0] -ScriptText $photonScript -GuestUser $vrausername -GuestPassword $vrapassword.password if ($photonRelease.ScriptOutput -match "[4-5].0") { $scriptCheck = " cat /etc/security/faillock.conf" } else { $scriptCheck = " cat /etc/pam.d/system-auth" } $checkKeys = Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCheck -GuestUser $vrausername -GuestPassword $vrapassword.password if ($PsBoundParameters.ContainsKey("failures")) { # failures = Maximum number of authentication failures before the account is locked (Default = 3) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $uncommentRegex = "/deny/s/ *# *//g" if ($checkKeys.ScriptOutput -match "# deny =" -or $checkKeys.ScriptOutput -match "deny=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$failuresRegex' $configFile" } else { $failuresRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/deny = [-]?[0-9]+/deny = $failures/g" } else { ";s/deny=[-]?[0-9]+/deny=$failures/" } $scriptCommand = "sed -E -i.bak '$failuresRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("unlockInterval")) { # unlock_time = Amount of time in seconds that the account remains locked (Default = 86400) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/unlock_time=[-]?[0-9]+/unlock_time=$unlockInterval/g" } $uncommentRegex = "/unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$unlockIntervalRegex' $configFile" } else { $unlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^unlock_time = [-]?[0-9]+/unlock_time = $unlockInterval/g" } else { ";s/(^| )unlock_time=[-]?[0-9]+/\1unlock_time=$unlockInterval/g" } $scriptCommand = "sed -E -i.bak '$unlockIntervalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } if ($PsBoundParameters.ContainsKey("rootUnlockInterval")) { # root_unlock_time = Amount of time in seconds that the root account remains locked (Default = 300) $configFile = if ($photonRelease.ScriptOutput -match "[4-5].0") { "/etc/security/faillock.conf" } else { "/etc/pam.d/system-auth" } $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { "s/root_unlock_time= [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/root_unlock_time=[-]?[0-9]+/root_unlock_time=$rootUnlockInterval/" } $uncommentRegex = "/root_unlock_time/s/ *# *//g" if ($checkKeys.ScriptOutput -match "^# root_unlock_time =" -or $checkKeys.ScriptOutput.Trim() -eq "root_unlock_time=") { $scriptCommand = "sed -E -i.bak '$uncommentRegex;$rootUnlockIntervalRegex' $configFile" } else { $rootUnlockIntervalRegex = if ($photonRelease.ScriptOutput -match "[4-5].0") { ";s/^root_unlock_time = [-]?[0-9]+/root_unlock_time = $rootUnlockInterval/g" } else { ";s/(^| )root_unlock_time=[-]?[0-9]+/\1root_unlock_time=$rootUnlockInterval/g" } $scriptCommand = "sed -E -i.bak '$rootUnlockIntervalRegex' $configFile" } Invoke-VMScript -VM $node.split('.')[0] -ScriptText $scriptCommand -GuestUser $vrausername -GuestPassword $vrapassword.password -Confirm:$false | Out-Null } } } } } Catch { Write-Error $_.Exception.Message } } Export-ModuleMember -Function Update-AriaLocalUserPasswordAccountLockout #EndRegion End Aria Product Password Password Management Functions ###### ########################################################################## ########################################################################## #Region Begin Shared Password Management Functions ###### Function Request-LocalUserPasswordExpiration { <# .SYNOPSIS Retrieves the password expiration policy for the specified local user. .DESCRIPTION The Request-LocalUserPasswordExpiration cmdlet retrieves a local user password expiration policy. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Retrieves the password expiration policy for the specified local user. .EXAMPLE Request-LocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -product vcenterServer -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -localUser [local_username] This example retrieves the global password expiration policy for a vCenter instance. .EXAMPLE Request-LocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -product vcenterServer -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -localUser [local_username] -drift -reportPath [report_path] -policyFile [policy_file].json This example retrieves the global password expiration policy for a vCenter instance and checks the configuration drift using the provided configuration JSON. .EXAMPLE Request-LocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -product vcenterServer -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -localUser [local_username] -drift This example retrieves the global password expiration policy for a vCenter instance and compares the configuration against the product defaults. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain which the product is deployed for. .PARAMETER vmName The name of the virtual machine to retrieve the policy from. .PARAMETER guestUser The username to authenticate to the virtual machine guest operating system. .PARAMETER guestPassword The password to authenticate to the virtual machine guest operating system. .PARAMETER localUser The local user to retrieve the password expiration policy for. .PARAMETER product The product to retrieve the password expiration policy for. One of: sddcManager, vcenterServer, nsxManager, nsxEdge, wsaLocal. .PARAMETER drift Switch to compare the current configuration against the product defaults or a JSON file. .PARAMETER reportPath The path to save the policy report. .PARAMETER policyFile The path to the policy configuration file. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$vmName, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$guestUser, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$guestPassword, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Array]$localUser, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateSet('sddcManager', 'vcenterServer', 'nsxManager', 'nsxEdge', 'wsaLocal')] [String]$product, [Parameter (Mandatory = $false, ParameterSetName = 'drift')] [ValidateNotNullOrEmpty()] [Switch]$drift, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$reportPath, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$policyFile ) $pass = Get-Password -username $user -password $pass $guestPassword = Get-Password -username $guestUser -password $guestPassword Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if ($drift) { if ($PsBoundParameters.ContainsKey('policyFile')) { $version = Get-VCFManager -version $command = "(Get-PasswordPolicyConfig -version $version -reportPath $reportPath -policyFile $policyFile ).$product.passwordExpiration" } else { $version = Get-VCFManager -version $command = "(Get-PasswordPolicyConfig -version $version).$product.passwordExpiration" } $requiredConfig = Invoke-Expression $command } if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { $vcenterDomain = $vcfVcenterDetails.type if ($vcenterDomain -ne "MANAGEMENT") { if (Get-VCFWorkloadDomain | Where-Object { $_.type -eq "MANAGEMENT" }) { if (($vcfMgmtVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType "Management")) { if (Test-vSphereConnection -server $($vcfMgmtVcenterDetails.fqdn)) { if (-not (Test-vSphereAuthentication -server $vcfMgmtVcenterDetails.fqdn -user $vcfMgmtVcenterDetails.ssoAdmin -pass $vcfMgmtVcenterDetails.ssoAdminPass)) { return } } } } else { Write-Error "Unable to find Workload Domain typed (MANAGEMENT) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } $allLocalUserExpirationObject = New-Object System.Collections.ArrayList foreach ($user in $localUser) { if ($localUserPasswordExpiration = Get-LocalUserPasswordExpiration -vmName $vmName -guestUser $guestUser -guestPassword $guestPassword -localUser $user) { $localUserExpirationObject = New-Object -TypeName PSObject $localUserExpirationObject | Add-Member -NotePropertyName "Workload Domain" -NotePropertyValue $domain $localUserExpirationObject | Add-Member -NotePropertyName "System" -NotePropertyValue $vmName $localUserExpirationObject | Add-Member -NotePropertyName "User" -NotePropertyValue $user $localUserExpirationObject | Add-Member -NotePropertyName "Min Days" -NotePropertyValue $(if ($drift) { if ($(($localUserPasswordExpiration | Where-Object { $_.Setting -match "Minimum number of days between password change" }).Value.Trim()) -ne $requiredConfig.minDays) { "$(($localUserPasswordExpiration | Where-Object {$_.Setting -match "Minimum number of days between password change"}).Value.Trim()) [ $($requiredConfig.minDays) ]" } else { "$(($localUserPasswordExpiration | Where-Object {$_.Setting -match "Minimum number of days between password change"}).Value.Trim())" } } else { "$(($localUserPasswordExpiration | Where-Object {$_.Setting -match "Minimum number of days between password change"}).Value.Trim())" }) $localUserExpirationObject | Add-Member -NotePropertyName "Max Days" -NotePropertyValue $(if ($drift) { if ($(($localUserPasswordExpiration | Where-Object { $_.Setting -match "Maximum number of days between password change" }).Value.Trim()) -ne $requiredConfig.maxDays) { "$(($localUserPasswordExpiration | Where-Object {$_.Setting -match "Maximum number of days between password change"}).Value.Trim()) [ $($requiredConfig.maxDays) ]" } else { "$(($localUserPasswordExpiration | Where-Object {$_.Setting -match "Maximum number of days between password change"}).Value.Trim())" } } else { "$(($localUserPasswordExpiration | Where-Object {$_.Setting -match "Maximum number of days between password change"}).Value.Trim())" }) $localUserExpirationObject | Add-Member -NotePropertyName "Warning Days" -NotePropertyValue $(if ($drift) { if ($(($localUserPasswordExpiration | Where-Object { $_.Setting -match "Number of days of warning before password expires" }).Value.Trim()) -ne $requiredConfig.warningDays) { "$(($localUserPasswordExpiration | Where-Object {$_.Setting -match "Number of days of warning before password expires"}).Value.Trim()) [ $($requiredConfig.warningDays) ]" } else { "$(($localUserPasswordExpiration | Where-Object {$_.Setting -match "Number of days of warning before password expires"}).Value.Trim())" } } else { "$(($localUserPasswordExpiration | Where-Object {$_.Setting -match "Number of days of warning before password expires"}).Value.Trim())" }) $allLocalUserExpirationObject += $localUserExpirationObject } else { Write-Error "Unable to retrieve password expiration policy for local user ($user) from Virtual Machine ($vmName): PRE_VALIDATION_FAILED" } } return $allLocalUserExpirationObject } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Request-LocalUserPasswordExpiration Function Update-LocalUserPasswordExpiration { <# .SYNOPSIS Updates a local user password expiration period in days. .DESCRIPTION The Update-LocalUserPasswordExpiration cmdlet configures a local user password expiration policy. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager - Validates that network connectivity and authentication is possible to vCenter. - Configures the local user password expiration policy. .EXAMPLE Update-LocalUserPasswordExpiration -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -vmName [vm_name] -guestUser [guest_username] -guestPassword [guest_password] -localUser [local_username],[ssh_username] -minDays 0 -maxDays 999 -warnDays 14 This example updates the password expiration policy for the specified local users on the specified virtual machine. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain which the product is deployed for. .PARAMETER vmName The name of the virtual machine to retrieve the policy from. .PARAMETER guestUser The username to authenticate to the virtual machine guest operating system. .PARAMETER guestPassword The password to authenticate to the virtual machine guest operating system. .PARAMETER localUser The local user to retrieve the password expiration policy for. .PARAMETER minDays The minimum number of days between password changes. .PARAMETER maxDays The maximum number of days between password changes. .PARAMETER warnDays The number of days of warning before password expires. .PARAMETER detail Return the details of the policy. One of true or false. Default is true. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$vmName, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$guestUser, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$guestPassword, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [Array]$localUser, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$minDays, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$maxDays, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$warnDays, [Parameter (Mandatory = $false)] [ValidateSet("true", "false")] [String]$detail = "true" ) $pass = Get-Password -username $user -password $pass $guestPassword = Get-Password -username $guestUser -password $guestPassword Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { if (Get-VCFWorkloadDomain | Where-Object { $_.name -eq $domain }) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { if (Test-vSphereConnection -server $($vcfVcenterDetails.fqdn)) { if (Test-vSphereAuthentication -server $vcfVcenterDetails.fqdn -user $vcfVcenterDetails.ssoAdmin -pass $vcfVcenterDetails.ssoAdminPass) { if (($vcfVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domain $domain)) { $vcenterDomain = $vcfVcenterDetails.type if ($vcenterDomain -ne "MANAGEMENT") { if (Get-VCFWorkloadDomain | Where-Object { $_.type -eq "MANAGEMENT" }) { if (($vcfMgmtVcenterDetails = Get-vCenterServerDetail -server $server -user $user -pass $pass -domainType "Management")) { if (Test-vSphereConnection -server $($vcfMgmtVcenterDetails.fqdn)) { if (-not (Test-vSphereAuthentication -server $vcfMgmtVcenterDetails.fqdn -user $vcfMgmtVcenterDetails.ssoAdmin -pass $vcfMgmtVcenterDetails.ssoAdminPass)) { return } } } } else { Write-Error "Unable to find Workload Domain typed (MANAGEMENT) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } foreach ($user in $localUser) { $existingConfiguration = Get-LocalUserPasswordExpiration -vmName $vmName -guestUser $guestUser -guestPassword $guestPassword -localUser $user $currentMinDays = ($existingConfiguration | Where-Object { $_.Setting -match "Minimum number of days between password change" }).Value.Trim() $currentMaxDays = ($existingConfiguration | Where-Object { $_.Setting -match "Maximum number of days between password change" }).Value.Trim() $currentWarnDays = ($existingConfiguration | Where-Object { $_.Setting -match "Number of days of warning before password expires" }).Value.Trim() if ($currentMinDays -ne $minDays -or $currentMaxDays -ne $maxDays -or $currentWarnDays -ne $warnDays) { Set-LocalUserPasswordExpiration -vmName $vmName -guestUser $guestUser -guestPassword $guestPassword -localUser $user -minDays $minDays -maxDays $maxDays -warnDays $warnDays $updatedConfiguration = Get-LocalUserPasswordExpiration -vmName $vmName -guestUser $guestUser -guestPassword $guestPassword -localUser $user $updatedMinDays = ($updatedConfiguration | Where-Object { $_.Setting -match "Minimum number of days between password change" }).Value.Trim() $updatedMaxDays = ($updatedConfiguration | Where-Object { $_.Setting -match "Maximum number of days between password change" }).Value.Trim() $updatedWarnDays = ($updatedConfiguration | Where-Object { $_.Setting -match "Number of days of warning before password expires" }).Value.Trim() if ($updatedMinDays -eq $minDays -or $updatedMaxDays -eq $maxDays -or $updatedWarnDays -eq $warnDays) { if ($detail -eq "true") { Write-Output "Update Local User ($user) Password Expiration Policy on Virtual Machine ($vmName): SUCCESSFUL" } } else { Write-Error "Update Local User ($user) Password Expiration Policy on Virtual Machine ($vmName): POST_VALIDATION_FAILED" } } else { if ($detail -eq "true") { Write-Warning "Update Local User ($user) Password Expiration Policy on Virtual Machine ($vmName), already set: SKIPPED" } } } if ($detail -eq "false") { Write-Output "Update Local Users to Max Days ($maxDays), Min Days ($minDays) and Warn Days ($warnDays) on Virtual Machine ($vmName): SUCCESSFUL" } } } } } else { Write-Error "Unable to find Workload Domain named ($domain) in the inventory of SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } } Catch { Debug-ExceptionWriter -object $_ } Finally { if ($global:DefaultVIServers) { Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$false } } } Export-ModuleMember -Function Update-LocalUserPasswordExpiration Function Publish-PasswordRotationPolicy { <# .SYNOPSIS Publishes the credential password rotation settings for credentials managed by SDDC Manager based on the resource type for a specified workload domain. .DESCRIPTION The Publish-PasswordRotationPolicy cmdlet retrieves the credential password rotation settings for accounts managed by SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager. - Retrieves the credentialg password rotation settings based on the criteria specified by the -domain and -resource values or all resource types for all workload domains if no values are specified. .EXAMPLE Publish-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains This example publishes the credential password rotation settings for all resource types managed by SDDC Manager for all workload domains. .EXAMPLE Publish-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] This example publishes the credential password rotation settings for all resource types managed by SDDC Manager for the workload domain. .EXAMPLE Publish-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -resource nsxManager This example publishes the credential password rotation settings for the NSX Manager accounts managed by SDDC Manager for all workload domains. .EXAMPLE Publish-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -workloadDomain [workload_domain_name] -resource nsxManager This example publishes the credential password rotation settings for the NSX Manager accounts managed by SDDC Manager for the workload domain. .EXAMPLE Publish-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -allDomains -json This example publishes the credential password rotation settings for all resource types managed by SDDC Manager for all workload domains in JSON format. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER allDomains Switch to publish the policy for all workload domains. .PARAMETER workloadDomain Switch to publish the policy for a specific workload domain. .PARAMETER resource The resource type to publish the policy for. One of: sso, vcenterServer, nsxManager, nsxEdge, ariaLifecycle, ariaOperations, ariaOperationsLogs, ariaAutomation, workspaceOneAccess, backup. .PARAMETER json Switch to publish the policy in JSON format. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (ParameterSetName = 'All-WorkloadDomains', Mandatory = $true)] [ValidateNotNullOrEmpty()] [Switch]$allDomains, [Parameter (ParameterSetName = 'Specific-WorkloadDomain', Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$workloadDomain, [Parameter (Mandatory = $false)] [ValidateSet('sso', 'vcenterServer', 'nsxManager', 'nsxEdge', 'ariaLifecycle', 'ariaOperations', 'ariaOperationsLogs', 'ariaAutomation', 'workspaceOneAccess', 'backup')] [String]$resource, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [Switch]$json ) $pass = Get-Password -username $user -password $pass # Determine the resource type. if ($resource) { switch ($resource) { 'sso' { $resourceName = 'vCenter Single Sign-On' } 'vcenterServer' { $resourceName = 'vCenter' } 'nsxManager' { $resourceName = 'NSX Manager' } 'nsxEdge' { $resourceName = 'NSX Edge' } 'ariaLifecycle' { $resourceName = 'Aria Suite Lifecycle' } 'ariaOperationsLogs' { $resourceName = 'Aria Operations for Logs' } 'ariaOperations' { $resourceName = 'Aria Operations' } 'ariaAutomation' { $resourceName = 'Aria Automation' } 'workspaceOneAccess' { $resourceName = 'Workspace ONE Access' } 'backup' { $resourceName = 'SDDC Manager' } } } else { # If no resource type is specified, retrieve all resource types. $resourceName = 'All Resources' } Try { if (Test-VCFConnection -server $server) { if (Test-VCFAuthentication -server $server -user $user -pass $pass) { $passwordRotationObject = New-Object System.Collections.ArrayList if ($PsBoundParameters.ContainsKey('workloadDomain')) { # Get the credential password rotation policy for a specific workload domain $command = "Request-PasswordRotationPolicy -server $server -user $user -pass $pass -domain $workloadDomain" # If the resource parameter is specified, add it to the command. if ($PsBoundParameters.ContainsKey('resource')) { $command += " -resource $resource" } # Invoke the command and add the results to the array. $passwordRotation = Invoke-Expression $command ; $passwordRotationObject += $passwordRotation } elseif ($PsBoundParameters.ContainsKey('allDomains')) { # Get the credential password rotation policy for all workload domains. $allWorkloadDomains = Get-VCFWorkloadDomain # For each workload domain, get the credential password rotation policy. foreach ($domain in $allWorkloadDomains ) { # Get the credential password rotation policy for a specific workload domain. $command = "Request-PasswordRotationPolicy -server $server -user $user -pass $pass -domain $($domain.name)" # If the resource parameter is specified, add it to the command. if ($PsBoundParameters.ContainsKey('resource')) { $command += " -resource $resource" } # Invoke the command and add the results to the array. $passwordRotation = Invoke-Expression $command ; $passwordRotationObject += $passwordRotation } } # Define the custom sort order for resourceType $resourceTypeOrder = @('SDDC Manager', 'vCenter Single Sign-On', 'vCenter', 'NSX Manager', 'NSX Edge', 'Aria Suite Lifecycle', 'Aria Operations for Logs', 'Aria Operations', 'Aria Automation', 'Workspace ONE Access') # Sort the array by resourceType using the custom sort order $passwordRotationObject = $passwordRotationObject | Sort-Object -Property 'Workload Domain', @{Expression = { $resourceTypeOrder.IndexOf($_.Resource) } }, 'System', 'User' # If the json parameter is specified, return the results as JSON. if ($PsBoundParameters.ContainsKey('json')) { $passwordRotationObject | ConvertTo-Json -Depth 10 } else { # Otherwise, return the results as HTML. # Return the results as HTML but create an anchor for each resource type. if ($passwordRotationObject) { # Check if the $passwordRotationObject variable has any items. if (($passwordRotationObject | Measure-Object).Count -gt 0) { # Return the results as HTML but create an anchor for each resource type. $passwordRotationObject = $passwordRotationObject | ConvertTo-Html -Fragment -PreContent "<a id=$($resourceName.ToLower() -replace ' ', '-')-password-rotation></a><h3>$($resourceName)</h3>" -As Table $passwordRotationObject = Convert-CssClassStyle -htmldata $passwordRotationObject } else { # Display a message indicating that there are no results. $passwordRotationObject = "<a id=$($resourceName.ToLower() -replace ' ', '-')-password-rotation></a><h3>$($resourceName)</h3><p>No password rotation policy data available for $($resourceName).</p>" } } else { # Display a message indicating that there are no results. $passwordRotationObject = "<a id=$($resourceName.ToLower() -replace ' ', '-')-password-rotation></a><h3>$($resourceName)</h3><p>No password rotation policy data available for $($resourceName).</p>" } $passwordRotationObject } } } } Catch { Debug-CatchWriter -object $_ } } Export-ModuleMember -Function Publish-PasswordRotationPolicy Function Request-PasswordRotationPolicy { <# .SYNOPSIS Retrieves the credential password rotation settings for credentials managed by SDDC Manager based on the resource type for a specified workload domain. .DESCRIPTION The Request-PasswordRotationPolicy cmdlet retrieves the credential password rotation settings for credentials managed by SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager. - Retrieves the credential password rotation settings based on the criteria specified by the -domain and -resource values or all resource types for all workload domains if no values are specified. .EXAMPLE Request-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] This example retrieves the credential password rotation settings for all resource types managed by SDDC Manager for all workload domains. .EXAMPLE Request-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] This example retrieves the credential password rotation settings for all resource types managed by SDDC Manager for the workload domain. .EXAMPLE Request-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -resource nsxManager This example retrieves the credential password rotation settings for the NSX Manager accounts managed by SDDC Manager for all workload domains. .EXAMPLE Request-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -resource nsxManager This example retrieves the credential password rotation settings for the NSX Manager accounts managed by SDDC Manager for the workload domain. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the credential password rotation settings for. .PARAMETER resource The resource type to retrieve the credential password rotation settings for. One of: sso, vcenterServer, nsxManager, nsxEdge, ariaLifecycle, ariaOperations, ariaOperationsLogs, ariaAutomation, workspaceOneAccess, backup. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $false)] [ValidateSet('sso', 'vcenterServer', 'nsxManager', 'nsxEdge', 'ariaLifecycle', 'ariaOperations', 'ariaOperationsLogs', 'ariaAutomation', 'workspaceOneAccess', 'backup')] [String]$resource ) $pass = Get-Password -username $user -password $pass # Determine the resource type. if ($resource) { switch ($resource) { 'sso' { $resourceType = 'PSC' } 'vcenterServer' { $resourceType = 'VCENTER' } 'nsxManager' { $resourceType = 'NSXT_MANAGER' } 'nsxEdge' { $resourceType = 'NSXT_EDGE' } 'ariaLifecycle' { $resourceType = 'VRSLCM' } 'ariaOperationsLogs' { $resourceType = 'VRLI' } 'ariaOperations' { $resourceType = 'VROPS' } 'ariaAutomation' { $resourceType = 'VRA' } 'workspaceOneAccess' { $resourceType = 'WSA' } 'backup' { $resourceType = 'BACKUP' } } } else { # If no resource type is specified, retrieve all resource types. $resourceType = '*' } Try { # Validate that network connectivity and authentication is possible to SDDC Manager. if (Test-VCFConnection -server $server) { # Validate that authentication is possible to SDDC Manager. if (Test-VCFAuthentication -server $server -user $user -pass $pass) { # Retrieve the credential password rotation settings for the specified resource type on the specified workload domain, if specified. # ESX host are ineligible for automated password rotation. $passwordRotations = Get-VCFCredentialExpiry | Where-Object { $_.resource.resourceType -like $resourceType -and (!$domain -or $_.resource.domainName -eq $domain -and $_.resource.resourceType -notlike "ESXI") } # Iterate through the credential password rotation settings. $passwordRotationObject = foreach ($passwordRotation in $passwordRotations) { # Determine the resource name based on the resource type. switch ($passwordRotation.resource.resourceType) { 'PSC' { $resourceName = 'vCenter Single Sign-On' } 'VCENTER' { $resourceName = 'vCenter' } 'NSXT_MANAGER' { $resourceName = 'NSX Manager' } 'NSXT_EDGE' { $resourceName = 'NSX Edge' } 'VRSLCM' { $resourceName = 'Aria Suite Lifecycle' } 'VRLI' { $resourceName = 'Aria Operations for Logs' } 'VROPS' { $resourceName = 'Aria Operations' } 'VRA' { $resourceName = 'Aria Automation' } 'WSA' { $resourceName = 'Workspace ONE Access' } 'BACKUP' { $resourceName = 'SDDC Manager' } } # Determine the frequency and next schedule based on the credential password rotation settings. if (!$passwordRotation.autoRotatePolicy) { # If the credential password rotation settings are not configured, set the frequency and next schedule to disabled. $frequencyInDays = 'Disabled' $nextSchedule = 'Disabled' } else { # If the credential password rotation settings are configured, set the frequency and next schedule to the configured values. $frequencyInDays = $passwordRotation.autoRotatePolicy.frequencyInDays $nextSchedule = $passwordRotation.autoRotatePolicy.nextSchedule } # Determine the alert color and message based on the credential password rotation status. # Check if the credential password rotation settings are configured. if ($nextSchedule -eq 'Disabled' -and $frequencyInDays -eq 'Disabled') { # If the credential password rotation settings are not configured, set the alert to green and the message to disabled. $message = 'Automated password rotation is disabled.' $alert = 'GREEN' } elseif ($passwordRotation.expiry.expiryDate -lt $nextSchedule -and $passwordRotation.expiry.connectivityStatus -ne 'ERROR') { # If the password will expire before the scheduled rotation and the connectivity status is not error, set the alert to yellow and the message to will expire before the scheduled rotation. $message = 'Password will expire before the scheduled rotation.' $alert = 'RED' } else { # If the credential password rotation settings are configured, set the alert to green and the message to enabled. $message = 'Automated password rotation is enabled.' $alert = 'GREEN' } # Check if the password is expiring or in an unknown state. if ($passwordRotation.expiry.status -eq 'EXPIRING') { # If the password is expiring, set the alert to yellow and the message to expiring. $message = 'Password is approaching expiration.' $alert = 'YELLOW' } elseif ($passwordRotation.expiry.status -eq 'UNKNOWN' -and $passwordRotation.expiry.connectivityStatus -ne 'ERROR') { # If the password status is unknown and the connectivity status is not error, set the alert to yellow and the message to unknown. $message = 'The resource is in an unknown state.' $alert = 'YELLOW' } if ($null -eq $passwordRotation.expiry.expiryDate) { # If the password is null set the alert to red and the message to unknown. $message = 'Password expiration date is unknown or the password has already expired.' $alert = 'RED' } elseif ($passwordRotation.expiry.connectivityStatus -eq 'ERROR') { # If the connectivity status is error, set the alert to red and the message to error. $message = 'The resource is in an error state.' $alert = 'RED' } elseif ($passwordRotation.expiry.expiryDate -le (Get-Date).AddDays(7)) { # If the is expiring in the next 7 days, set the alert to red and the message to expiring in the next 7 days. $message = 'Password is expiring in next 7 days.' $alert = 'RED' } elseif ($passwordRotation.expiry.expiryDate -le (Get-Date)) { # If the password is expired, set the alert to red and the message to expired. $message = 'Password is expired.' $alert = 'RED' } Try { $nextSchedule = [DateTime]::ParseExact($nextSchedule, 'yyyy-MM-ddTHH:mm:ss.fffZ', [System.Globalization.CultureInfo]::InvariantCulture) } Catch { } $passwordRotationExpiryDate = $passwordRotation.expiry.expiryDate Try { $passwordRotationExpiryDate = [DateTime]::ParseExact($passwordRotation.expiry.expiryDate, 'yyyy-MM-ddTHH:mm:ss.fffZ', [System.Globalization.CultureInfo]::InvariantCulture) } Catch { } [PSCustomObject]@{ 'Workload Domain' = $passwordRotation.resource.domainName 'System' = $passwordRotation.resource.resourceName 'Resource' = $resourceName 'Type' = $passwordRotation.credentialType 'User' = $passwordRotation.username 'Frequency Days' = $frequencyInDays 'Next Schedule' = $nextSchedule 'Expiration' = $passwordRotationExpiryDate 'Connection' = $passwordRotation.expiry.connectivityStatus 'Status' = $passwordRotation.expiry.status 'Alert' = $alert 'Message' = $message } } # Define the custom sort order for resourceType $resourceTypeOrder = @('SDDC Manager', 'vCenter Single Sign-On', 'vCenter', 'NSX Manager', 'NSX Edge', 'Aria Suite Lifecycle', 'Aria Operations for Logs', 'Aria Operations', 'Aria Automation', 'Workspace ONE Access') # Sort the $passwordRotationObjects array by resourceType using the custom sort order $passwordRotationObject = $passwordRotationObject | Sort-Object -Property 'Workload Domain', @{Expression = { $resourceTypeOrder.IndexOf($_.Resource) } }, 'System', 'Type', 'User' # Return the credential password rotation objects. return $passwordRotationObject } else { Write-Error "Unable to retrieve password rotation policy for credentials managed by SDDC Manager ($server): PRE_VALIDATION_FAILED" } } } Catch { Debug-ExceptionWriter -object $_ } } Export-ModuleMember -Function Request-PasswordRotationPolicy Function Update-PasswordRotationPolicy { <# .SYNOPSIS Updates the credential password rotation settings for a credential managed by SDDC Manager. .DESCRIPTION The Update-PasswordRotationPolicy cmdlet updates the credential password rotation settings for a credential managed by SDDC Manager. The cmdlet connects to the SDDC Manager using the -server, -user, and -pass values: - Validates that network connectivity and authentication is possible to SDDC Manager. - Updates the credential password rotation settings based on the credential criteria specified. .EXAMPLE Update-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -resource vcenterServer -resourceName [resource_fqdn] -credential SSH -credentialName root -autoRotate disabled This example disables the credential password rotation settings for a credential managed by SDDC Manager. .EXAMPLE Update-PasswordRotationPolicy -server [sddc_manager_fqdn] -user [admin_username] -pass [admin_password] -domain [workload_domain_name] -resource vcenterServer -resourceName [resource_fqdn] -credential SSH -credentialName root -autoRotate enabled -frequencyInDays 90 This example enables the credential password rotation settings for a credential managed by SDDC Manager. .PARAMETER server The fully qualified domain name of the SDDC Manager instance. .PARAMETER user The username to authenticate to the SDDC Manager instance. .PARAMETER pass The password to authenticate to the SDDC Manager instance. .PARAMETER domain The name of the workload domain to retrieve the credential password rotation settings for. .PARAMETER resource The resource type to retrieve the credential password rotation settings for. One of: sso, vcenterServer, nsxManager, nsxEdge, ariaLifecycle, ariaOperations, ariaOperationsLogs, ariaAutomation, workspaceOneAccess, backup. .PARAMETER resourceName The name of the resource to retrieve the credential password rotation settings for. .PARAMETER credential The credential type to retrieve the user password rotation settings for. One of: ssh, api, audit, sso. .PARAMETER credentialName The name of the credential to retrieve the user password rotation settings for. .PARAMETER autoRotate Enable or disable the credential password rotation policy for the credential by SDDC Manager. One of: enabled, disabled. .PARAMETER frequencyInDays The number of days of warning before credential's password will be automatically rotated by SDDC Manager. #> Param ( [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$server, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$user, [Parameter (Mandatory = $false)] [ValidateNotNullOrEmpty()] [String]$pass, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$domain, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('sso', 'vcenterServer', 'nsxManager', 'nsxEdge', 'ariaLifecycle', 'ariaOperations', 'ariaOperationsLogs', 'ariaAutomation', 'workspaceOneAccess', 'backup')] [String]$resource, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$resourceName, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('ssh', 'api', 'audit', 'sso')] [String]$credential, [Parameter (Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$credentialName, [Parameter (Mandatory = $true)] [ValidateSet('enabled', 'disabled')] [String]$autoRotate, [Parameter (Mandatory = $false)] [ValidateScript({ $autoRotate -eq 'ENABLED' -or $_ -eq $null })] [Int]$frequencyInDays ) $pass = Get-Password -username $user -password $pass # Set the resource type. switch ($resource) { 'sso' { $resourceType = 'PSC'; $resourceDescription = 'vCenter Single Sign-On' } 'vcenterServer' { $resourceType = 'VCENTER'; $resourceDescription = 'vCenter' } 'nsxManager' { $resourceType = 'NSXT_MANAGER'; $resourceDescription = 'NSX Manager' } 'nsxEdge' { $resourceType = 'NSXT_EDGE'; $resourceDescription = 'NSX Edge' } 'ariaLifecycle' { $resourceType = 'VRSLCM'; $resourceDescription = 'Aria Suite Lifecycle' } 'ariaOperationsLogs' { $resourceType = 'VRLI'; $resourceDescription = 'Aria Operations for Logs' } 'ariaOperations' { $resourceType = 'VROPS'; $resourceDescription = 'Aria Operations' } 'ariaAutomation' { $resourceType = 'VRA'; $resourceDescription = 'Aria Automation' } 'workspaceOneAccess' { $resourceType = 'WSA'; $resourceDescription = 'Workspace ONE Access' } 'backup' { $resourceType = 'BACKUP'; $resourceDescription = 'SDDC Manager' } } # Set the credential type. switch ($credential) { 'ssh' { $credentialType = $credential.ToUpper() } 'api' { $credentialType = $credential.ToUpper() } 'audit' { $credentialType = $credential.ToUpper() } 'sso' { $credentialType = $credential.ToUpper() } } # Set the username. $username = $credentialName Try { # Validate that network connectivity and authentication is possible to SDDC Manager. if (Test-VCFConnection -server $server) { # Validate that authentication is possible to SDDC Manager. if (Test-VCFAuthentication -server $server -user $user -pass $pass) { # Set the status messages. $message = "password rotation policy for $credentialType credential ($credentialName) for workload domain ($domain) $resourceDescription resource ($resourceName) managed by SDDC Manager ($server)" $updateMessage = "Updating $message" $locateMessage = "Locating $message" # Update the credential password rotation settings for a credential managed by SDDC Manager. $credentialExpiry = Get-VCFCredentialExpiry | Where-Object { $_.resource.resourceType -eq $resourceType -and $_.resource.resourceName -eq $resourceName -and $_.resource.domainName -eq $domain -and $_.credentialType -eq $credentialType -and $_.username -eq $username } if ($credentialExpiry) { if (!$credentialExpiry.autoRotatePolicy -and $autoRotate -eq 'disabled') { Write-Warning "${updateMessage}: ${skippedStatus}" } elseif ($credentialExpiry.autoRotatePolicy -and $autoRotate -eq 'enabled' -and $credentialExpiry.autoRotatePolicy.frequencyInDays -eq $frequencyInDays) { Write-Warning "${updateMessage}: ${skippedStatus}" } else { if ($autoRotate -eq 'disabled') { Set-VCFCredentialAutoRotatePolicy -resourceName $resourceName -resourceType $resourceType -credentialType $credentialType -username $username -autoRotate $autoRotate } else { Set-VCFCredentialAutoRotatePolicy -resourceName $resourceName -resourceType $resourceType -credentialType $credentialType -username $username -autoRotate $autoRotate -frequencyInDays $frequencyInDays } if (Get-VCFCredentialExpiry | Where-Object { $_.resource.resourceType -eq $resourceType -and $_.resource.resourceName -eq $resourceName -and $_.resource.domainName -eq $domain -and $_.credentialType -eq $credentialType -and $_.username -eq $username }) { Write-Output "${updateMessage}: ${successStatus}" } else { Write-Error "${updateMessage}: ${failureStatus}" } } } else { Write-Error "${locateMessage}: ${preValidationFailureStatus}" } } else { Write-Error "${updateMessage}: ${preValidationFailureStatus}" } } } Catch { Write-Error $_.Exception.Message } } Export-ModuleMember -Function Update-PasswordRotationPolicy #EndRegion End Shared Password Management Functions ###### ########################################################################## ########################################################################## #Region Begin Supporting Functions ###### Function Test-VcfPasswordManagementPrereq { <# .SYNOPSIS Verifies that the minimum dependencies are met to run the PowerShell module. .DESCRIPTION The Test-VcfPasswordManagementPrereq cmdlet verifies that the minimum dependencies are met to run the the PowerShell module. .EXAMPLE Test-VcfPasswordManagementPrereq This example shows how to verify that the minimum dependencies are met to run the PowerShell module. #> Try { $moduleName = $myInvocation.myCommand.ModuleName $moduleData = (Get-Module -Name $moduleName) $moduleManifestPath = Join-Path $moduleData.ModuleBase ($moduleData.Name + '.psd1') $moduleManifest = Import-PowerShellDataFile -Path $moduleManifestPath $requiredModules = $moduleManifest.RequiredModules foreach ($module in $requiredModules) { $moduleName = $module.ModuleName $requiredVersion = $module.ModuleVersion $installedModule = Get-Module -ListAvailable -Name $moduleName if ($installedModule) { $installedVersion = $installedModule.Version | Sort-Object -Descending $installedVersion = $installedVersion[0] if ($installedVersion -lt $requiredVersion) { $message = "$($moduleName) $($installedVersion) is installed. Install $($moduleName) $($requiredVersion) or higher." Show-PasswordManagementOutput -type ERROR -message $message } elseif ($installedVersion -ge $requiredVersion) { $message = "$($moduleName) $($installedVersion) is installed version and meets the minimum required version of $($moduleName) $($requiredVersion)." Show-PasswordManagementOutput -type INFO -message $message } } else { $message = "$($moduleName) is not installed. Install $($moduleName) $($requiredVersion) or higher." Show-PasswordManagementOutput -type ERROR -message $message } } } Catch { Write-Error $_.Exception.Message } } Export-ModuleMember -Function Test-VcfPasswordManagementPrereq Function Show-PasswordManagementOutput { Param ( [Parameter (Mandatory = $true)] [AllowEmptyString()] [String]$message, [Parameter (Mandatory = $false)] [ValidateSet("INFO", "ERROR", "WARNING", "EXCEPTION", "ADVISORY", "NOTE", "QUESTION", "WAIT")] [String]$type = "INFO", [Parameter (Mandatory = $false)] [Switch]$skipnewline ) If ($type -eq "INFO") { $messageColour = "92m" #Green } elseif ($type -in "ERROR", "EXCEPTION") { $messageColour = "91m" # Red } elseif ($type -in "WARNING", "ADVISORY", "QUESTION") { $messageColour = "93m" #Yellow } elseif ($type -in "NOTE", "WAIT") { $messageColour = "97m" # White } $ESC = [char]0x1b $timestampColour = "97m" $timeStamp = Get-Date -Format "MM-dd-yyyy_HH:mm:ss" If ($skipnewline) { Write-Host -NoNewline "$ESC[${timestampcolour} [$timestamp]$ESC[${threadColour} $ESC[${messageColour} [$type] $message$ESC[0m" } else { Write-Host "$ESC[${timestampcolour} [$timestamp]$ESC[${threadColour} $ESC[${messageColour} [$type] $message$ESC[0m" } } Export-ModuleMember -Function Show-PasswordManagementOutput #EndRegion End Supporting Functions ###### ########################################################################## |