Pages/Dynamic/PSRemotingCredsPage.ps1

#region >> PSRemoting Creds Page

$PSRemotingCredsPageContent = {
    param($RemoteHost)

    New-UDColumn -Endpoint {$Session:ThisRemoteHost = $RemoteHost}

    # Add the SyncHash to the Page so that we can pass output to other pages
    $PUDRSSyncHT = $global:PUDRSSyncHT

    # Load PUDAdminCenter Module Functions Within ScriptBlock
    $ThisModuleFunctionsStringArray | Where-Object {$_ -ne $null} | foreach {Invoke-Expression $_ -ErrorAction SilentlyContinue}

    #region >> Ensure $RemoteHost is Valid

    if ($PUDRSSyncHT.RemoteHostList.HostName -notcontains $RemoteHost) {
        $ErrorText = "The Remote Host $($RemoteHost.ToUpper()) is not a valid Host Name!"
    }

    if ($ErrorText) {
        New-UDRow -Columns {
            New-UDColumn -Size 4 -Content {
                New-UDHeading -Text ""
            }
            New-UDColumn -Size 4 -Content {
                New-UDHeading -Text $ErrorText -Size 6
            }
            New-UDColumn -Size 4 -Content {
                New-UDHeading -Text ""
            }
        }
    }

    # If $RemoteHost isn't valid, don't load anything else
    if ($ErrorText) {
        return
    }

    #endregion >> Ensure $RemoteHost is Valid

    #region >> Loading Indicator

    New-UDRow -Columns {
        New-UDColumn -Endpoint {
            $Session:PSRemotingPageLoadingTracker = [System.Collections.ArrayList]::new()
            #$PUDRSSyncHT.PSRemotingPageLoadingTracker = $Session:HomePageLoadingTracker
            $Session:NoCredsEntered = $False
            $Session:InvalidSSHPubCert = $False
            $Session:SSHRemotingMethodNoCert = $False
            $Session:DomainRemotingMethodNoCreds = $False
            $Session:LocalRemotingMethodNoCreds = $False
            $Session:UserNameAndPasswordRequired = $False
            $Session:BadFormatDomainUserName = $False
            $Session:EnableWinRMFailure = $False
            $Session:GetWorkingCredsFailure = $False
            $Session:InvalidCreds = $False
            $Session:CheckingCredentials = $False
        }
        New-UDHeading -Text "Set Credentials for $($RemoteHost.ToUpper())" -Size 4
    }

    New-UDRow -Columns {
        New-UDColumn -AutoRefresh -RefreshInterval 1 -Endpoint {
            if ($Session:PSRemotingPageLoadingTracker -notcontains "FinishedLoading") {
                New-UDHeading -Text "Loading...Please wait..." -Size 5
                New-UDPreloader -Size small
            }
        }

        New-UDColumn -AutoRefresh -RefreshInterval 1 -Endpoint {
            New-UDElement -Id "CheckingCredentials" -Tag div -EndPoint {
                if ($Session:CheckingCredentials) {
                    New-UDHeading -Text "Checking Credentials for $Session:ThisRemoteHost...Please wait..." -Size 5
                    New-UDPreloader -Size small
                }
            }
        }

        New-UDColumn -EndPoint {
            New-UDElement -Id "ValidateCredsMsg" -Tag div -EndPoint {
                #New-UDHeading -Text "RemoteHost is $Session:ThisRemoteHost!" -Size 6 -Color red

                if ($Session:NoCredsEntered) {
                    New-UDHeading -Text "You MUST enter UserName/Password for either a Local User or Domain User with access to $Session:ThisRemoteHost!" -Size 6 -Color red
                    $Session:NoCredsEntered = $False
                }
                if ($Session:InvalidSSHPubCert) {
                    New-UDHeading -Text "The string provided is not a valid SSH Public Certificate!" -Size 6 -Color red
                    $Session:InvalidSSHPubCert = $False
                }
                if ($Session:SSHRemotingMethodNoCert) {
                    New-UDHeading -Text "You indicated that SSH is your Preferred_PSRemotingMethod, however, you did not provide a value for Path_To_SSH_Public_Cert!" -Size 6 -Color red
                    $Session:SSHRemotingMethodNoCert = $False
                }
                if ($Session:DomainRemotingMethodNoCreds) {
                    New-UDHeading -Text "You indicated that 'Domain' was your Preferred_PSRemotingCredType, however, you did not provide Domain Credentials!" -Size 6 -Color red
                    $Session:DomainRemotingMethodNoCreds = $False
                }
                if ($Session:LocalRemotingMethodNoCreds) {
                    New-UDHeading -Text "You indicated that 'Local' was your Preferred_PSRemotingCredType, however, you did not provide Local Credentials!" -Size 6 -Color red
                    $Session:LocalRemotingMethodNoCreds = $False
                }
                if ($Session:UserNameAndPasswordRequired) {
                    New-UDHeading -Text "Please enter both a UserName and a Password!" -Size 6 -Color red
                    $Session:UserNameAndPasswordRequired = $False
                }
                if ($Session:BadFormatDomainUserName) {
                    New-UDHeading -Text "Domain_UserName must be in format 'Domain\DomainUser'!" -Size 6 -Color red
                    $Session:BadFormatDomainUserName = $False
                }
                if ($Session:EnableWinRMFailure) {
                    New-UDHeading -Text "Unable to Enable WinRM on $Session:ThisRemoteHost via Invoke-WmiMethod over RPC! Please check your credentials." -Size 6 -Color red
                    $Session:EnableWinRMFailure = $False
                }
                if ($Session:GetWorkingCredsFailure) {
                    New-UDHeading -Text "Unable to test Credentials! Please try again." -Size 6 -Color red
                    $Session:GetWorkingCredsFailure = $False
                }
                if ($Session:InvalidCreds) {
                    New-UDHeading -Text "Invalud Credentials! Please try again." -Size 6 -Color red
                    $Session:InvalidCreds = $False
                }
            }
        }
    }

    #endregion >> Loading Indicator

    <#
    New-UDRow -Endpoint {
        New-UDColumn -Size 2 -Content {}
        New-UDColumn -Size 8 -Endpoint {
            New-UDRow -Endpoint {
                New-UDTextbox -Id "LocalUserName" -Label "Local UserName" -Type text
                New-UDTextbox -Id "LocalPassword" -Label "Local Password" -Type password
                New-UDTextbox -Id "DomainUserName" -Label "Domain UserName" -Type text
                New-UDTextbox -Id "DomainPassword" -Label "Domain Password" -Type password
                New-UDTextbox -Id "SSHPublicCert" -Label "SSH Public Certificate" -Type text
                New-UDSelect -Id "PreferredPSRemotingCredType" -Label "Credential Type" -Option {
                    New-UDSelectOption -Name "Domain" -Value "Domain" -Selected
                    New-UDSelectOption -Name "Local" -Value "Local"
                }
                New-UDSelect -Id "PreferredPSRemotingMethod" -Label "PSRemoting Method" -Option {
                    New-UDSelectOption -Name "WinRM" -Value "WinRM" -Selected
                    New-UDSelectOption -Name "SSH" -Value "SSH"
                }
            }
            New-UDRow -EndPoint {
                New-UDButton -Text "Set Credentials" -OnClick {
                    $PUDRSSyncHT = $global:PUDRSSyncHT

                    $Session:CheckingCredentials = $True
                    Sync-UDElement -Id "CheckingCredentials"

                    $LocalUserNameTextBox = Get-UDElement -Id "LocalUserName"
                    $LocalPasswordTextBox = Get-UDElement -Id "LocalPassword"
                    $DomainUserNameTextBox = Get-UDElement -Id "DomainUserName"
                    $DomainPasswordTextBox = Get-UDElement -Id "DomainPassword"
                    $SSHPublicCertTextBox = Get-UDElement -Id "SSHPublicCert"
                    $PrefCredTypeSelection = Get-UDElement -Id "PreferredPSRemotingCredType"
                    $PrefRemotingMethodSelection = Get-UDElement -Id "PreferredPSRemotingMethod"
                    
                    $Local_UserName = $LocalUserNameTextBox.Attributes['value']
                    $Local_Password = $LocalPasswordTextBox.Attributes['value']
                    $Domain_UserName = $DomainUserNameTextBox.Attributes['value']
                    $Domain_Password = $DomainPasswordTextBox.Attributes['value']
                    $VaultServerUrl = $SSHPublicCertTextBox.Attributes['value']
                    $Preferred_PSRemotingCredType = $($PrefCredTypeSelection.Content | foreach {
                        $_.ToString() | ConvertFrom-Json
                    } | Where-Object {$_.attributes.selected.isPresent}).attributes.value
                    $Preferred_PSRemotingMethod = $($PrefRemotingMethodSelection.Content | foreach {
                        $_.ToString() | ConvertFrom-Json
                    } | Where-Object {$_.attributes.selected.isPresent}).attributes.value

                    $TestingCredsObj = [pscustomobject]@{
                        LocalUserNameTextBox = $LocalUserNameTextBox
                        LocalPasswordTextBox = $LocalPasswordTextBox
                        DomainUserNameTextBox = $DomainUserNameTextBox
                        DomainPasswordTextBox = $DomainPasswordTextBox
                        SSHPublicCertTextBox = $SSHPublicCertTextBox
                        PrefCredTypeSelection = $PrefCredTypeSelection
                        PrefRemotingMethodSelection = $PrefRemotingMethodSelection
                        Local_UserName = $Local_UserName
                        Local_Password = $Local_Password
                        Domain_UserName = $Domain_UserName
                        Domain_Password = $Domain_Password
                        VaultServerUrl = $VaultServerUrl
                        Preferred_PSRemotingCredType = $Preferred_PSRemotingCredType
                        Preferred_PSRemotingMethod = $Preferred_PSRemotingMethod
                        RemoteHost = $Session:ThisRemoteHost
                    }

                    if ($Session:CredentialHT.Keys -notcontains $Session:ThisRemoteHost) {
                        #New-UDInputAction -Toast "`$Session:CredentialHT is not defined!" -Duration 10000
                        $Session:CredentialHT = @{}
                        $RHostCredHT = @{
                            DomainCreds = $null
                            LocalCreds = $null
                            VaultServerUrl = $null
                            PSRemotingCredType = $null
                            PSRemotingMethod = $null
                            PSRemotingCreds = $null
                        }
                        $Session:CredentialHT.Add($Session:ThisRemoteHost,$RHostCredHT)

                        # TODO: Need to remove this when finished testing
                        $PUDRSSyncHT."$Session:ThisRemoteHost`Info".CredHT = $Session:CredentialHT

                        #New-UDInputAction -Toast "`$Session:CredentialHT was null" -Duration 10000
                    }

                    # In case this page was refreshed or redirected to from itself, check $Session:CredentialHT for existing values
                    if (!$Local_UserName -and $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds -ne $null) {
                        $Local_UserName = $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds.UserName
                    }
                    if (!$Local_Password -and $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds -ne $null) {
                        $Local_Password = $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds.GetNetworkCredential().Password
                    }
                    if (!$Domain_UserName -and $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds -ne $null) {
                        $Domain_UserName = $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds.UserName
                    }
                    if (!$Domain_Password -and $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds -ne $null) {
                        $Domain_Password = $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds.GetNetworkCredential().Password
                    }
                    if (!$VaultServerUrl -and $Session:CredentialHT.$Session:ThisRemoteHost.VaultServerUrl -ne $null) {
                        $VaultServerUrl = $Session:CredentialHT.$Session:ThisRemoteHost.VaultServerUrl
                    }
                    if (!$Preferred_PSRemotingCredType -and $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCredType -ne $null) {
                        $Preferred_PSRemotingCredType = $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCredType
                    }
                    if (!$Preferred_PSRemotingMethod -and $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingMethod -ne $null) {
                        $Preferred_PSRemotingMethod = $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingMethod
                    }

                    if (!$Local_UserName -and !$Local_Password -and !$Domain_UserName -and !$Domain_Password -and !$VaultServerUrl) {
                        $Session:NoCredsEntered = $True
                        Sync-UDElement -Id "ValidateCredsMsg"
                        $Session:CheckingCredentials = $False
                        Sync-UDElement -Id "CheckingCredentials"
                        return
                    }

                    if ($VaultServerUrl) {
                        # TODO: Validate the provided string is a SSH Public Cert
                        if ($BadSSHPubCert) {
                            $Session:InvalidSSHPubCert = $True
                            Sync-UDElement -Id "ValidateCredsMsg"
                            $Session:CheckingCredentials = $False
                            Sync-UDElement -Id "CheckingCredentials"
                            return
                        }
                    }

                    if (!$Preferred_PSRemotingMethod -and $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingMethod) {
                        $Preferred_PSRemotingMethod = $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingMethod
                    }
                    if ($Preferred_PSRemotingMethod -eq "SSH" -and !$VaultServerUrl) {
                        $Session:SSHRemotingMethodNoCert = $True
                        Sync-UDElement -Id "ValidateCredsMsg"
                        $Session:CheckingCredentials = $False
                        Sync-UDElement -Id "CheckingCredentials"
                        return
                    }

                    if (!$Preferred_PSRemotingCredType -and $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCredType) {
                        $Preferred_PSRemotingCredType = $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCredType
                    }
                    if ($Preferred_PSRemotingCredType -eq "Domain" -and $(!$Domain_UserName -or !$Domain_Password)) {
                        $Session:DomainRemotingMethodNoCreds = $True
                        Sync-UDElement -Id "ValidateCredsMsg"
                        $Session:CheckingCredentials = $False
                        Sync-UDElement -Id "CheckingCredentials"
                        return
                    }

                    if ($Preferred_PSRemotingCredType -eq "Local" -and $(!$Local_UserName -or !$Local_Password)) {
                        $Session:LocalRemotingMethodNoCreds = $True
                        Sync-UDElement -Id "ValidateCredsMsg"
                        $Session:CheckingCredentials = $False
                        Sync-UDElement -Id "CheckingCredentials"
                        return
                    }

                    if ($($Local_UserName -and !$Local_Password) -or $(!$Local_UserName -and $Local_Password) -or
                    $($Domain_UserName -and !$Domain_Password) -or $(!$Domain_UserName -and $Domain_Password)
                    ) {
                        $Session:UserNameAndPasswordRequired = $True
                        Sync-UDElement -Id "ValidateCredsMsg"
                        $Session:CheckingCredentials = $False
                        Sync-UDElement -Id "CheckingCredentials"
                        return
                    }

                    if ($Local_UserName -and $Local_Password) {
                        # Make sure the $Local_UserName is in format $Session:ThisRemoteHost\$Local_UserName
                        if ($Local_UserName -notmatch "^$Session:ThisRemoteHost\\[a-zA-Z0-9]+$") {
                            $Local_UserName = "$Session:ThisRemoteHost\$Local_UserName"
                        }

                        $LocalPwdSecureString = ConvertTo-SecureString $Local_Password -AsPlainText -Force
                        $LocalAdminCreds = [pscredential]::new($Local_UserName,$LocalPwdSecureString)
                    }

                    if ($Domain_UserName -and $Domain_Password) {
                        $DomainShortName = $($PUDRSSyncHT."$Session:ThisRemoteHost`Info".NetworkInfo.Domain -split "\.")[0]
                        # Make sure the $Domain_UserName is in format $Session:ThisRemoteHost\$Domain_UserName
                        if ($Domain_UserName -notmatch "^$DomainShortName\\[a-zA-Z0-9]+$") {
                            $Session:BadFormatDomainUserName = $True
                            Sync-UDElement -Id "ValidateCredsMsg"
                            $Session:CheckingCredentials = $False
                            Sync-UDElement -Id "CheckingCredentials"
                            return
                        }

                        $DomainPwdSecureString = ConvertTo-SecureString $Domain_Password -AsPlainText -Force
                        $DomainAdminCreds = [pscredential]::new($Domain_UserName,$DomainPwdSecureString)
                    }

                    # Test the Credentials
                    [System.Collections.ArrayList]$CredentialsToTest = @()
                    if ($LocalAdminCreds) {
                        $PSObj = [pscustomobject]@{CredType = "LocalUser"; PSCredential = $LocalAdminCreds}
                        $null = $CredentialsToTest.Add($PSObj)
                    }
                    if ($DomainAdminCreds) {
                        $PSObj = [pscustomobject]@{CredType = "DomainUser"; PSCredential = $DomainAdminCreds}
                        $null = $CredentialsToTest.Add($PSObj)
                    }

                    [System.Collections.ArrayList]$FailedCredentialsA = @()
                    foreach ($CredObj in $CredentialsToTest) {
                        try {
                            $GetWorkingCredsResult = GetWorkingCredentials -RemoteHostNameOrIP $Session:ThisRemoteHost -AltCredentials $CredObj.PSCredential -ErrorAction Stop
            
                            if ($GetWorkingCredsResult.DeterminedCredsThatWorkedOnRemoteHost) {
                                if ($GetWorkingCredsResult.WorkingCredentials.GetType().FullName -ne "System.Management.Automation.PSCredential") {
                                    $null = $FailedCredentialsA.Add($CredObj)
                                }
                            }
                            else {
                                $null = $FailedCredentialsA.Add($CredObj)
                            }
                        }
                        catch {}
                    }

                    if ($($CredentialsToTest.Count -eq 2 -and $FailedCredentialsA.Count -eq 2) -or
                    $($CredentialsToTest.Count -eq 1 -and $FailedCredentialsA.Count -eq 1)
                    ) {
                        # Since WinRM failed, try and enable WinRM Remotely via Invoke-WmiMethod over RPC Port 135 (if it's open)
                        $RPCPortOpen = $(TestPort -HostName $Session:ThisRemoteHost -Port 135).Open

                        [System.Collections.ArrayList]$EnableWinRMSuccess = @()
                        foreach ($CredObj in $CredentialsToTest) {
                            if ($RPCPortOpen) {
                                try {
                                    $null = EnableWinRMViaRPC -RemoteHostNameOrIP $Session:ThisRemoteHost -Credential $CredObj.PSCredential
                                    $null = $EnableWinRMSuccess.Add($CredObj)
                                    break
                                }
                                catch {
                                    #New-UDInputAction -Toast "Failed to enable WinRM Remotely using Credentials $($CredObj.PSCredential.UserName)" -Duration 10000
                                }
                            }
                        }

                        if ($EnableWinRMSuccess.Count -eq 0) {
                            $Session:EnableWinRMFailure = $True
                            Sync-UDElement -Id "ValidateCredsMsg"
                            $Session:CheckingCredentials = $False
                            Sync-UDElement -Id "CheckingCredentials"
                            return
                        }
                        else {
                            [System.Collections.ArrayList]$FailedCredentialsB = @()
                            foreach ($CredObj in $CredentialsToTest) {
                                try {
                                    $GetWorkingCredsResult = GetWorkingCredentials -RemoteHostNameOrIP $Session:ThisRemoteHost -AltCredentials $CredObj.PSCredential -ErrorAction Stop
                    
                                    if ($GetWorkingCredsResult.WorkingCredentials.GetType().FullName -ne "System.Management.Automation.PSCredential") {
                                        #New-UDInputAction -Toast "$($CredObj.CredType) Credentials are not valid! Please try again." -Duration 10000
                                        $null = $FailedCredentialsB.Add($CredObj)
                                    }
                                }
                                catch {
                                    $Session:GetWorkingCredsFailure = $True
                                    Sync-UDElement -Id "ValidateCredsMsg"
                                    $Session:CheckingCredentials = $False
                                    Sync-UDElement -Id "CheckingCredentials"
                                    return
                                    
                                    #Show-UDToast -Message $_.Exception.Message -Duration 10
                                }
                            }
                        }
                    }

                    if ($FailedCredentialsA.Count -gt 0 -or $FailedCredentialsB.Count -gt 0) {
                        if ($FailedCredentialsB.Count -gt 0) {
                            foreach ($CredObj in $FailedCredentialsB) {
                                $Session:GetWorkingCredsFailure = $True
                                Sync-UDElement -Id "ValidateCredsMsg"
                                #$Session:CredentialHT.$Session:ThisRemoteHost."$CredType`Creds" = $null
                            }
                            $Session:CheckingCredentials = $False
                            Sync-UDElement -Id "CheckingCredentials"
                            return
                        }
                        if ($FailedCredentialsA.Count -gt 0 -and $FailedCredentialsB.Count -eq 0) {
                            foreach ($CredObj in $FailedCredentialsA) {
                                $Session:GetWorkingCredsFailure = $True
                                Sync-UDElement -Id "ValidateCredsMsg"
                            }
                            $Session:CheckingCredentials = $False
                            Sync-UDElement -Id "CheckingCredentials"
                            return
                        }
                    }

                    if ($DomainAdminCreds) {
                        $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds = $DomainAdminCreds
                    }
                    if ($LocalAdminCreds) {
                        $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds = $LocalAdminCreds
                    }
                    if ($VaultServerUrl) {
                        $Session:CredentialHT.$Session:ThisRemoteHost.VaultServerUrl = $VaultServerUrl
                    }
                    if ($Preferred_PSRemotingCredType) {
                        $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCredType = $Preferred_PSRemotingCredType
                    }
                    if ($Preferred_PSRemotingMethod) {
                        $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingMethod = $Preferred_PSRemotingMethod
                    }

                    # Determine $PSRemotingCreds
                    if ($Preferred_PSRemotingCredType -eq "Local") {
                        $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCreds = $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds
                    }
                    if ($Preferred_PSRemotingCredType -eq "Domain") {
                        $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCreds = $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds
                    }

                    Invoke-UDRedirect -Url "/ToolSelect/$Session:ThisRemoteHost"
                }
            }
            New-UDColumn -AutoRefresh -RefreshInterval 1 -Endpoint {
                try {
                    $null = $Session:PSRemotingPageLoadingTracker.Add("FinishedLoading")
                }
                catch {
                    Write-Verbose "`$Session:PSRemotingPageLoadingTracker hasn't been set yet..."
                }
            }
        }
        New-UDColumn -Size 2 -Content {}
    }
    #>


    New-UDRow -Endpoint {
        New-UDColumn -Size 2 -EndPoint {}
        New-UDColumn -Size 8 -EndPoint {
            $PUDRSSyncHT = $global:PUDRSSyncHT

            $Cache:CredsForm = New-UDInput -SubmitText "Set Credentials" -Id "CredsForm" -Content {
                New-UDInputField -Type textbox -Name 'Local_UserName' -Value $null
                New-UDInputField -Type password -Name 'Local_Password' -Value $null
                New-UDInputField -Type textbox -Name 'Domain_UserName' -Value $null
                New-UDInputField -Type password -Name 'Domain_Password' -Value $null
                New-UDInputField -Type textbox -Name 'VaultServerUrl' -Value $null
                New-UDInputField -Type select -Name 'Preferred_PSRemotingCredType' -Values @("Local","Domain","SSHCertificate") -DefaultValue "Domain"

                [System.Collections.ArrayList]$PSRemotingMethodValues = @("WinRM")
                if ($PUDRSSyncHT."$Session:ThisRemoteHost`Info".RHostTableData.SSH -eq "Available") {
                    $null = $PSRemotingMethodValues.Add("SSH")
                }
                New-UDInputField -Type select -Name 'Preferred_PSRemotingMethod' -Values @("WinRM","SSH") -DefaultValue "WinRM"
            } -Endpoint {
                param(
                    [string]$Local_UserName,
                    [string]$Local_Password,
                    [string]$Domain_UserName,
                    [string]$Domain_Password,
                    [string]$VaultServerUrl,
                    [string]$Preferred_PSRemotingCredType,
                    [string]$Preferred_PSRemotingMethod
                )

                # Add the SyncHash to the Page so that we can pass output to other pages
                $PUDRSSyncHT = $global:PUDRSSyncHT

                # Load PUDAdminCenter Module Functions Within ScriptBlock
                $Cache:ThisModuleFunctionsStringArray | Where-Object {$_ -ne $null} | foreach {Invoke-Expression $_ -ErrorAction SilentlyContinue}

                try {
                    if ($Session:CredentialHT.GetType().FullName -ne "System.Collections.Hashtable") {
                        $Session:CredentialHT = @{}
                    }
                }
                catch {
                    $Session:CredentialHT = @{}
                }

                if ($Session:CredentialHT.Keys -notcontains $Session:ThisRemoteHost) {
                    $RHostCredHT = @{
                        DomainCreds         = $null
                        LocalCreds          = $null
                        VaultServerUrl      = $null
                        PSRemotingCredType  = $null
                        PSRemotingMethod    = $null
                        PSRemotingCreds     = $null
                    }
                    $Session:CredentialHT.Add($Session:ThisRemoteHost,$RHostCredHT)
                }

                # TODO: Need to remove this when finished testing
                $PUDRSSyncHT."$Session:ThisRemoteHost`Info".CredHT = $Session:CredentialHT

                # In case this page was refreshed or redirected to from itself, check $Session:CredentialHT for existing values
                if (!$Local_UserName -and $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds -ne $null) {
                    $Local_UserName = $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds.UserName
                }
                if (!$Local_Password -and $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds -ne $null) {
                    $Local_Password = $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds.GetNetworkCredential().Password
                }
                if (!$Domain_UserName -and $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds -ne $null) {
                    $Domain_UserName = $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds.UserName
                }
                if (!$Domain_Password -and $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds -ne $null) {
                    $Domain_Password = $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds.GetNetworkCredential().Password
                }
                if (!$VaultServerUrl -and $Session:CredentialHT.$Session:ThisRemoteHost.VaultServerUrl -ne $null) {
                    $VaultServerUrl = $Session:CredentialHT.$Session:ThisRemoteHost.VaultServerUrl
                }
                if (!$Preferred_PSRemotingCredType -and $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCredType -ne $null) {
                    $Preferred_PSRemotingCredType = $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCredType
                }
                if (!$Preferred_PSRemotingMethod -and $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingMethod -ne $null) {
                    $Preferred_PSRemotingMethod = $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingMethod
                }

                # Make sure *Something* is filled out...
                if (!$Local_UserName -and !$Local_Password -and !$Domain_UserName -and !$Domain_Password -and !$VaultServerUrl) {
                    New-UDInputAction -Toast "You MUST enter UserName/Password for either a Local User or Domain User with access to $Session:ThisRemoteHost!" -Duration 10000
                    Sync-UDElement -Id "CredsForm"
                    return
                }

                <#
                # Set/Check $Preferred_PSRemotingCredType...
                if (!$Preferred_PSRemotingCredType -and $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCredType) {
                    $Preferred_PSRemotingCredType = $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCredType
                }
                # Set/Check $Preferred_PSRemotingMethod...
                if (!$Preferred_PSRemotingMethod -and $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingMethod) {
                    $Preferred_PSRemotingMethod = $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingMethod
                }
                #>

                
                if ($Preferred_PSRemotingMethod -eq "SSH") {
                    if ($Preferred_PSRemotingCredType -ne "SSHCertificate") {
                        $Preferred_PSRemotingCredType = "SSHUserNameAndPassword"
                    }
                    
                    if ($Preferred_PSRemotingCredType -eq "Domain") {
                        if ($Local_UserName -or $Local_Password) {
                            New-UDInputAction -Toast "You specifed your Preferred_PSRemotingCredType as '$Preferred_PSRemotingCredType', but you provided Local_UserName or Local_Password!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }
                        if ($VaultServerUrl) {
                            New-UDInputAction -Toast "You specifed your Preferred_PSRemotingCredType as '$Preferred_PSRemotingCredType', but you provided VaultServerUrl!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }

                        if (!$Domain_UserName -or !$Domain_Password) {
                            New-UDInputAction -Toast "You must provide a Domain_UserName AND Domain_Password in order to use PowerShell Remoting over SSH!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }

                        # Make sure the $Domain_UserName is in format $Session:ThisRemoteHost\$Domain_UserName
                        if ($Domain_UserName -and $Domain_Password) {
                            $DomainShortName = $($PUDRSSyncHT."$Session:ThisRemoteHost`Info".NetworkInfo.Domain -split "\.")[0]
                            if ($Domain_UserName -notmatch "^$DomainShortName\\[a-zA-Z0-9]+$") {
                                New-UDInputAction -Toast "Domain_UserName must be in format 'Domain\DomainUser'!" -Duration 10000
                                Sync-UDElement -Id "CredsForm"
                                return
                            }
        
                            $DomainPwdSecureString = ConvertTo-SecureString $Domain_Password -AsPlainText -Force
                            $DomainAdminCreds = [pscredential]::new($Domain_UserName,$DomainPwdSecureString)
                        }
                    }
                    if ($Preferred_PSRemotingCredType -eq "Local") {
                        if ($Domain_UserName -or $Domain_Password) {
                            New-UDInputAction -Toast "You specifed your Preferred_PSRemotingCredType as '$Preferred_PSRemotingCredType', but you provided Domain_UserName or Domain_Password!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }
                        if ($VaultServerUrl) {
                            New-UDInputAction -Toast "You specifed your Preferred_PSRemotingCredType as '$Preferred_PSRemotingCredType', but you provided VaultServerUrl!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }

                        if (!$Local_UserName -or !$Local_Password) {
                            New-UDInputAction -Toast "You must provide a Local_UserName AND Local_Password in order to use PowerShell Remoting over SSH!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }

                        # Make sure the $Local_UserName is in format $Session:ThisRemoteHost\$Local_UserName
                        if ($Local_UserName -and $Local_Password) {
                            if ($Local_UserName -notmatch "^$Session:ThisRemoteHost\\[a-zA-Z0-9]+$") {
                                $Local_UserName = "$Session:ThisRemoteHost\$Local_UserName"
                            }
        
                            $LocalPwdSecureString = ConvertTo-SecureString $Local_Password -AsPlainText -Force
                            $LocalAdminCreds = [pscredential]::new($Local_UserName,$LocalPwdSecureString)
                        }
                    }
                    if ($Preferred_PSRemotingCredType -eq "SSHUserNameAndPassword") {
                        if (!$($Domain_UserName -and $Domain_Password) -and !$($Local_UserName -and $Local_Password)) {
                            New-UDInputAction -Toast "Since you specifed your Preferred_PSRemotingCredType as '$Preferred_PSRemotingCredType', you MUST provide a Domain_UserName and Domain_Password or Local_UserName and Local_Password!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }

                        # Make sure the $Local_UserName is in format $Session:ThisRemoteHost\$Local_UserName
                        if ($Local_UserName -and $Local_Password) {
                            if ($Local_UserName -notmatch "^$Session:ThisRemoteHost\\[a-zA-Z0-9]+$") {
                                $Local_UserName = "$Session:ThisRemoteHost\$Local_UserName"
                            }
        
                            $LocalPwdSecureString = ConvertTo-SecureString $Local_Password -AsPlainText -Force
                            $LocalAdminCreds = [pscredential]::new($Local_UserName,$LocalPwdSecureString)
                        }

                        # Make sure the $Domain_UserName is in format $Session:ThisRemoteHost\$Domain_UserName
                        if ($Domain_UserName -and $Domain_Password) {
                            $DomainShortName = $($PUDRSSyncHT."$Session:ThisRemoteHost`Info".NetworkInfo.Domain -split "\.")[0]
                            if ($Domain_UserName -notmatch "^$DomainShortName\\[a-zA-Z0-9]+$") {
                                New-UDInputAction -Toast "Domain_UserName must be in format 'Domain\DomainUser'!" -Duration 10000
                                Sync-UDElement -Id "CredsForm"
                                return
                            }
        
                            $DomainPwdSecureString = ConvertTo-SecureString $Domain_Password -AsPlainText -Force
                            $DomainAdminCreds = [pscredential]::new($Domain_UserName,$DomainPwdSecureString)
                        }
                    }
                    if ($Preferred_PSRemotingCredType -eq "SSHCertificate") {
                        if (!$Domain_UserName -or !$Domain_Password) {
                            New-UDInputAction -Toast "You specifed your Preferred_PSRemotingCredType as '$Preferred_PSRemotingCredType', which means you must provide Domain_UserName and Domain_Password!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }
                        if (!$VaultServerUrl) {
                            New-UDInputAction -Toast "You must provide the VaultServerUrl in order to generate/request/receive a new SSH Certificate!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }

                        # Make sure the $Domain_UserName is in format $Session:ThisRemoteHost\$Domain_UserName
                        if ($Domain_UserName -and $Domain_Password) {
                            $DomainShortName = $($PUDRSSyncHT."$Session:ThisRemoteHost`Info".NetworkInfo.Domain -split "\.")[0]
                            if ($Domain_UserName -notmatch "^$DomainShortName\\[a-zA-Z0-9]+$") {
                                New-UDInputAction -Toast "Domain_UserName must be in format 'Domain\DomainUser'!" -Duration 10000
                                Sync-UDElement -Id "CredsForm"
                                return
                            }
        
                            $DomainPwdSecureString = ConvertTo-SecureString $Domain_Password -AsPlainText -Force
                            $DomainAdminCreds = [pscredential]::new($Domain_UserName,$DomainPwdSecureString)
                        }

                        if ($VaultServerUrl) {
                            [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"

                            # Make sure we can reach the Vault Server and that is in a state where we can actually use it.
                            try {
                                $VaultServerUpAndUnsealedCheck = Invoke-RestMethod "$VaultServerUrl/sys/health"
                                if (!$VaultServerUpAndUnsealedCheck -or $VaultServerUpAndUnsealedCheck.initialized -ne $True -or
                                $VaultServerUpAndUnsealedCheck.sealed -ne $False -or $VaultServerUpAndUnsealedCheck.standby -ne $False) {
                                    throw "The Vault Server is either not reachable or in a state where it cannot be used! Halting!"
                                }
                            }
                            catch {
                                New-UDInputAction -Toast $_.Exception.Message -Duration 10000
                                Sync-UDElement -Id "CredsForm"
                                return
                            }
                        }
                    }

                    try {
                        # Make sure we have the WinSSH Module Available
                        if ($(Get-Module -ListAvailable).Name -notcontains "WinSSH") {$null = Install-Module WinSSH -ErrorAction Stop}
                        if ($(Get-Module).Name -notcontains "WinSSH") {$null = Import-Module WinSSH -ErrorAction Stop}

                        # Make sure we have the VaultServer Module Available
                        if ($(Get-Module -ListAvailable).Name -notcontains "VaultServer") {$null = Install-Module VaultServer -ErrorAction Stop}
                        if ($(Get-Module).Name -notcontains "VaultServer") {$null = Import-Module VaultServer -ErrorAction Stop}
                    }
                    catch {
                        New-UDInputAction -Toast $_.Exception.Message -Duration 10000
                        Sync-UDElement -Id "CredsForm"
                        return
                    }

                    if ($(Get-Module).Name -notcontains "WinSSH") {
                        New-UDInputAction -Toast "The WinSSH Module is not available! Halting!" -Duration 10000
                        Sync-UDElement -Id "CredsForm"
                        return
                    }
                    if ($(Get-Module).Name -notcontains "VaultServer") {
                        New-UDInputAction -Toast "The VaultServer Module is not available! Halting!" -Duration 10000
                        Sync-UDElement -Id "CredsForm"
                        return
                    }

                    # Install OpenSSH-Win64 if it isn't already
                    if (!$(Test-Path "$env:ProgramFiles\OpenSSH-Win64\ssh.exe")) {
                        Install-WinSSH -GiveWinSSHBinariesPathPriority -ConfigureSSHDOnLocalHost -DefaultShell pwsh
                    }
                    else {
                        if (!$(Get-Command ssh -ErrorAction SilentlyContinue)) {
                            $OpenSSHDir ="$env:ProgramFiles\OpenSSH-Win64"
                            # Update PowerShell $env:Path
                            [System.Collections.Arraylist][array]$CurrentEnvPathArray = $env:Path -split ';' | Where-Object {![System.String]::IsNullOrWhiteSpace($_)} | Sort-Object | Get-Unique
                            if ($CurrentEnvPathArray -notcontains $OpenSSHDir) {
                                $CurrentEnvPathArray.Insert(0,$OpenSSHDir)
                                $env:Path = $CurrentEnvPathArray -join ';'
                            }
                            
                            # Update SYSTEM Path
                            $RegistrySystemPath = 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment'
                            $CurrentSystemPath = $(Get-ItemProperty -Path $RegistrySystemPath -Name PATH).Path
                            [System.Collections.Arraylist][array]$CurrentSystemPathArray = $CurrentSystemPath -split ";" | Where-Object {![System.String]::IsNullOrWhiteSpace($_)} | Sort-Object | Get-Unique
                            if ($CurrentSystemPathArray -notcontains $OpenSSHDir) {
                                $CurrentSystemPathArray.Insert(0,$OpenSSHDir)
                                $UpdatedSystemPath = $CurrentSystemPathArray -join ";"
                                Set-ItemProperty -Path $RegistrySystemPath -Name PATH -Value $UpdatedSystemPath
                            }
                        }
                        if (!$(Get-Command ssh -ErrorAction SilentlyContinue)) {
                            New-UDInputAction -Toast "Unable to find ssh.exe on $env:ComputerName!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }
                    }

                    if ($Preferred_PSRemotingCredType -eq "SSHCertificate") {
                        # Use Domain Credentials to get a new Vault Server Authentication Token, generate new SSH Keys on the PUDAdminCenter Server,
                        # have the Vault Server sign them, add the new private key to the ssh-agent, and output an SSH Public Certificate to $HOME\.ssh
                        # NOTE: The SSH Keys will expire in 24 hours
                        $NewSSHKeyName = $($DomainAdminCreds.UserName -split "\\")[-1] + "_" + $(Get-Date -Format MM-dd-yy_hhmmsstt)
                        $NewSSHCredentialsSplatParams = @{
                            VaultServerBaseUri                  = $VaultServerUrl
                            DomainCredentialsWithAccessToVault  = $DomainAdminCreds
                            NewSSHKeyName                       = $NewSSHKeyName
                            BlankSSHPrivateKeyPwd               = $True
                            AddToSSHAgent                       = $True
                            RemovePrivateKey                    = $True # Removes the Private Key from the filesystem
                            #SSHAgentExpiry = 86400 # 24 hours in seconds # Don't use because this makes ALL keys in ssh-agent expire in 24 hours
                        }

                        try {
                            $NewSSHCredsResult = New-SSHCredentials @NewSSHCredentialsSplatParams -ErrorAction Stop
                            $NewSSHCredsResult | Add-Member -Name "PrivateKeyPath" -Value $($NewSSHCredsResult.PublicKeyPath -replace "\.pub","") -MemberType NoteProperty
                        }
                        catch {
                            New-UDInputAction -Toast $_.Exception.Message -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }

                        if ($PUDRSSyncHT.Keys -contains "NewSSHCredsResult") {
                            $PUDRSSyncHT.NewSSHCredsResult = $NewSSHCredsResult
                        }
                        else {
                            $PUDRSSyncHT.Add("NewSSHCredsResult",$NewSSHCredsResult)
                        }

                        # $NewSSHCredsResult (and $GetSSHAuthSanity later on) is a pscustomobject with the following content:
                        <#
                            PublicKeyCertificateAuthShouldWork : True
                            FinalSSHExeCommand : ssh zeroadmin@zero@<RemoteHost>
                            PublicKeyPath : C:\Users\zeroadmin\.ssh\zeroadmin_071918.pub
                            PublicCertPath : C:\Users\zeroadmin\.ssh\zeroadmin_071918-cert.pub
                        #>


                        # If $NewSSHCredsResult.FinalSSHExeCommand looks like...
                        # ssh -o "IdentitiesOnly=true" -i "C:\Users\zeroadmin\.ssh\zeroadmin_071718" -i "C:\Users\zeroadmin\.ssh\zeroadmin_071718-cert.pub" zeroadmin@zero@<RemoteHost>
                        # ...or...
                        # ssh <user>@<RemoteHost>
                        # ...then there are too many identities loaded in the ssh-agent service, which means we need to get the private key from the registry and write it to a file
                        # See: https://blog.ropnop.com/extracting-ssh-private-keys-from-windows-10-ssh-agent/
                        if (!$NewSSHCredsResult.PublicKeyCertificateAuthShouldWork -or 
                        $NewSSHCredsResult.FinalSSHExeCommand -eq "ssh <user>@<RemoteHost>" -or
                        $NewSSHCredsResult.FinalSSHExeCommand -match "IdentitiesOnly=true"
                        ) {
                            # NOTE: Extract-SSHPrivateKeysFromRegistry is from the WinSSH Module and provides output like:
                            <#
                                OriginalPrivateKeyFilePath = $OriginalPrivateKeyFilePath
                                PrivateKeyContent = $PrivateKeyContent
                            #>

                            # This should only really be necessary if the ssh-agent has more than 5 entries in it (and the needed key isn't within one of the first 5) and
                            # the RSA Private Key isn't on the filesystem under "$HOME\.ssh". The Get-SSHClientAuthSanity function figures that out for us.
                            $ExtractedPrivateKeys = Extract-SSHPrivateKeysFromRegistry
                            $OriginalPrivateKeyPath = $NewSSHCredsResult.PublicKeyPath -replace "\.pub",""
                            $PrivateKeyContent = $($ExtractedPrivateKeys | Where-Object {$_.OriginalPrivateKeyFilePath -eq $OriginalPrivateKeyPath}).PrivateKeyContent

                            if ($PrivateKeyContent.Count -gt 0) {
                                Set-Content -Path $OriginalPrivateKeyPath -Value $PrivateKeyContent
                                $NeedToRemovePrivateKey = $True
                                $GetSSHAuthSanityCheck = Get-SSHClientAuthSanity -SSHPublicKeyFilePath $NewSSHCredsResult.PublicKeyPath
                                if ($GetSSHAuthSanityCheck.PublicKeyCertificateAuthShouldWork) {
                                    $GetSSHAuthSanity = [pscustomobject]@{
                                        PublicKeyCertificateAuthShouldWork  = $True
                                        FinalSSHExeCommand                  = $GetSSHAuthSanityCheck.FinalSSHExeCommand
                                        PrivateKeyPath                      = $OriginalPrivateKeyPath
                                        PublicKeyPath                       = $NewSSHCredsResult.PublicKeyPath
                                        PublicCertPath                      = $NewSSHCredsResult.PublicKeyPath + '-cert.pub'
                                    }
                                }
                                
                                # The below $FinalSSHExeCommand string should look like:
                                # ssh -o "IdentitiesOnly=true" -i "$OriginalPrivateKeyPath" -i "$($NewSSHCredsResult.PublicCertPath)" zeroadmin@zero@<RemoteHost>
                                $FinalSSHExeCommand = $GetSSHAuthSanity.FinalSSHExeCommand

                                if (!$GetSSHAuthSanity.PublicKeyCertificateAuthShouldWork) {
                                    $UserNamePasswordRequired = $True
                                    $ToastMsg = "Unable to use SSH Certificate Authentication because the user ssh private key is not available on the " +
                                    "filesystem or in the ssh-agent. Trying UserName/Password SSH Authentication..."
                                    New-UDInputAction -Toast $ToastMsg -Duration 10000
                                    #Sync-UDElement -Id "CredsForm"
                                    #return
                                }
                            }
                            else {
                                $UserNamePasswordRequired = $True
                                $ToastMsg = "Unable to use SSH Certificate Authentication because the user ssh keys and/or " +
                                "ssh cert and/or ssh-agent is not configured properly! Trying UserName/Password SSH Authentication..."
                                New-UDInputAction -Toast $ToastMsg -Duration 10000
                                #Sync-UDElement -Id "CredsForm"
                                #return
                            }
                        }
                        else {
                            $GetSSHAuthSanity = $NewSSHCredsResult
                            
                            # The below $FinalSSHExeCommand string should look like:
                            # ssh zeroadmin@zero@<RemoteHost>
                            $FinalSSHExeCommand = $GetSSHAuthSanity.FinalSSHExeCommand
                        }

                        $SSHCertificate = Get-Content $GetSSHAuthSanity.PublicCertPath

                        if ($PUDRSSyncHT.Keys -contains "GetSSHAuthSanity") {
                            $PUDRSSyncHT.GetSSHAuthSanity = $GetSSHAuthSanity
                        }
                        else {
                            $PUDRSSyncHT.Add("GetSSHAuthSanity",$GetSSHAuthSanity)
                        }
                    }
                }
                if ($Preferred_PSRemotingMethod -eq "WinRM") {
                    if ($VaultServerUrl) {
                        New-UDInputAction -Toast "You provided a Vault Server Url, however, your Preferred_PSRemotingMethod is not SSH!" -Duration 10000
                        Sync-UDElement -Id "CredsForm"
                        return
                    }

                    if ($($Local_UserName -and !$Local_Password) -or $(!$Local_UserName -and $Local_Password) -or
                    $($Domain_UserName -and !$Domain_Password) -or $(!$Domain_UserName -and $Domain_Password)
                    ) {
                        New-UDInputAction -Toast "Please enter both a UserName and a Password!" -Duration 10000
                        Sync-UDElement -Id "CredsForm"
                        return
                    }

                    # Make sure the $Local_UserName is in format $Session:ThisRemoteHost\$Local_UserName
                    if ($Local_UserName -and $Local_Password) {
                        if ($Local_UserName -notmatch "^$Session:ThisRemoteHost\\[a-zA-Z0-9]+$") {
                            $Local_UserName = "$Session:ThisRemoteHost\$Local_UserName"
                        }
    
                        $LocalPwdSecureString = ConvertTo-SecureString $Local_Password -AsPlainText -Force
                        $LocalAdminCreds = [pscredential]::new($Local_UserName,$LocalPwdSecureString)
                    }

                    # Make sure the $Domain_UserName is in format $Session:ThisRemoteHost\$Domain_UserName
                    if ($Domain_UserName -and $Domain_Password) {
                        $DomainShortName = $($PUDRSSyncHT."$Session:ThisRemoteHost`Info".NetworkInfo.Domain -split "\.")[0]
                        if ($Domain_UserName -notmatch "^$DomainShortName\\[a-zA-Z0-9]+$") {
                            New-UDInputAction -Toast "Domain_UserName must be in format 'Domain\DomainUser'!" -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }
    
                        $DomainPwdSecureString = ConvertTo-SecureString $Domain_Password -AsPlainText -Force
                        $DomainAdminCreds = [pscredential]::new($Domain_UserName,$DomainPwdSecureString)
                    }
                }

                ##### Test the Credentials #####

                # IMPORTANT NOTE: OpenSSH-Win64's implementation of 'ssh.exe -t' does not work properly...If it did, the TestSSH Private function would be a lot simpler
                            
                # NOTE: The Principal(s) on the SSH Certificate do NOT determine who you are on the Remote Host. What DOES determine who you are on the Remote Host is
                # 1) The UserName specified via -UserName with *-PSSession cmdlets
                # 2) The UserName specified via <UserName>@<DomainShortName>@<RemoteHost> with ssh.exe

                if ($Preferred_PSRemotingMethod -eq "SSH") {
                    # Make sure we have pwsh
                    if (!$(Get-Command pwsh -ErrorAction SilentlyContinue)) {
                        $InstallPwshResult = Install-Program -ProgramName powershell-core -CommandName pwsh.exe -ExpectedInstallLocation "C:\Program Files\PowerShell"
                    }
                    
                    # NOTE: The Await Module comes with the WinSSH Module that we made sure was installed/imported earlier
                    try {
                        Import-Module "$($(Get-Module WinSSH).ModuleBase)\Await\Await.psd1" -ErrorAction Stop
                    }
                    catch {
                        New-UDInputAction -Toast "Unable to load the Await Module! Halting!" -Duration 10000
                        Sync-UDElement -Id "CredsForm"
                        return
                    }

                    if ($Preferred_PSRemotingCredType -eq "SSHCertificate") {
                        # Determine if we're going to do UserName/Password Auth or SSH Certificate Auth
                        if (!$UserNamePasswordRequired) {
                            # We need to get the UserName from the SSHCertificate
                            [System.Collections.ArrayList][array]$SSHCertInfo = ssh-keygen -L -f $GetSSHAuthSanity.PublicCertPath
                            $PrincipalsLine = $SSHCertInfo | Where-Object {$_ -match "Principals:"}
                            $PrincipalsLineIndex = $SSHCertInfo.IndexOf($PrincipalsLine)
                            $CriticalOptionsLine = $SSHCertInfo | Where-Object {$_ -match "Critical Options:"}
                            $CriticalOptionsLineIndex = $SSHCertInfo.IndexOf($CriticalOptionsLine)
                            [array]$PrincipalsList = @($SSHCertInfo[$PrincipalsLineIndex..$CriticalOptionsLineIndex] | Where-Object {$_ -notmatch "Principals:|Critical Options:"} | foreach {$_.Trim()})
                            $SSHCertUser = $($PrincipalsList[0] -split '@')[0].Trim()
                            $ShortUserName = $SSHCertUser
                            $DomainShortName = $($($PUDRSSyncHT.RemoteHostList | Where-Object {$_.HostName -eq $Session:ThisRemoteHost}).Domain -split "\.")[0]
                            $Domain_UserName = "$DomainShortName\$ShortUserName"
                        }
                    }

                    $OSGuess = $PUDRSSyncHT."$Session:ThisRemoteHost`Info".RHostTableData.OS_Guess
                    if ($OSGuess) {
                        if ($OSGuess -match "Windows|Microsoft") {
                            $UpdatedOSGuess = "Windows"
                        }
                        elseif ($OSGuess -match "Linux") {
                            $UpdatedOSGuess = "Linux"
                        }
                        else {
                            $UpdatedOSGuess = "Windows"
                        }
                    }
                    if (!$OSGuess) {
                        $UpdatedOSGuess = "Windows"
                    }

                    $SSHTestSplatParams = @{
                        OSGuess                 = $UpdatedOSGuess
                        RemoteHostNetworkInfo   = $PUDRSSyncHT.RemoteHostList | Where-Object {$_.HostName -eq $Session:ThisRemoteHost}
                        OutputTracker           = $PUDRSSyncHT
                    }
                    if ($Local_UserName -and $Local_Password) {
                        $SSHTestSplatParams.Add("LocalUserName",$Local_UserName)
                        $SSHTestSplatParams.Add("LocalPassword",$Local_Password)
                    }
                    if ($Domain_UserName -and $DOmain_Password) {
                        $SSHTestSplatParams.Add("DomainUserName",$Domain_UserName)
                        $SSHTestSplatParams.Add("DomainPassword",$Domain_Password)
                    }
                    if ($GetSSHAuthSanity.PublicCertPath) {
                        $SSHTestSplatParams.Add("PublicCertPath",$GetSSHAuthSanity.PublicCertPath)
                    }
                    # IMPORTANT NOTE: The SSHTest function outputs some UDDashboard objects and sets $script:SSHCheckAsJson as well as $script:SSHOutputPrep
                    # For these reasons, we are assigning SSHTest output to a variable
                    TestSSH @SSHTestSplatParams

                    if ($SSHCheckAsJson.Output -ne "ConnectionSuccessful" -and ![bool]$($($SSHOutputPrep -split "`n") -match "^ConnectionSuccessful")) {
                        New-UDInputAction -Toast "SSH attempts via PowerShell Core 'Invoke-Command' and ssh.exe have failed!" -Duration 10000
                        Sync-UDElement -Id "CredsForm"
                        return
                    }
                }
                if ($Preferred_PSRemotingMethod -eq "WinRM") {
                    [System.Collections.ArrayList]$CredentialsToTest = @()
                    if ($LocalAdminCreds) {
                        $PSObj = [pscustomobject]@{CredType = "LocalUser"; PSCredential = $LocalAdminCreds}
                        $null = $CredentialsToTest.Add($PSObj)
                    }
                    if ($DomainAdminCreds) {
                        $PSObj = [pscustomobject]@{CredType = "DomainUser"; PSCredential = $DomainAdminCreds}
                        $null = $CredentialsToTest.Add($PSObj)
                    }

                    [System.Collections.ArrayList]$FailedCredentialsA = @()
                    foreach ($CredObj in $CredentialsToTest) {
                        try {
                            $GetWorkingCredsResult = GetWorkingCredentials -RemoteHostNameOrIP $Session:ThisRemoteHost -AltCredentials $CredObj.PSCredential -ErrorAction Stop
            
                            if ($GetWorkingCredsResult.DeterminedCredsThatWorkedOnRemoteHost) {
                                if ($GetWorkingCredsResult.WorkingCredentials.GetType().FullName -ne "System.Management.Automation.PSCredential") {
                                    #New-UDInputAction -Toast "$($CredObj.CredType) Credentials are not valid! Please try again." -Duration 10000
                                    $null = $FailedCredentialsA.Add($CredObj)
                                }
                            }
                            else {
                                $null = $FailedCredentialsA.Add($CredObj)
                            }
                        }
                        catch {
                            #New-UDInputAction -Toast $_.Exception.Message -Duration 10000
                            #New-UDInputAction -Toast "Unable to test $($CredObj.CredType) Credentials! Refreshing page..." -Duration 10000
                            #New-UDInputAction -RedirectUrl "/PSRemotingCreds/$Session:ThisRemoteHost"
                        }
                    }

                    if ($($CredentialsToTest.Count -eq 2 -and $FailedCredentialsA.Count -eq 2) -or 
                    $($CredentialsToTest.Count -eq 1 -and $FailedCredentialsA.Count -eq 1)
                    ) {
                        # Since WinRM failed, try and enable WinRM Remotely via Invoke-WmiMethod over RPC Port 135 (if it's open)
                        $RPCPortOpen = $(TestPort -HostName $Session:ThisRemoteHost -Port 135).Open

                        [System.Collections.ArrayList]$EnableWinRMSuccess = @()
                        foreach ($CredObj in $CredentialsToTest) {
                            if ($RPCPortOpen) {
                                try {
                                    $null = EnableWinRMViaRPC -RemoteHostNameOrIP $Session:ThisRemoteHost -Credential $CredObj.PSCredential
                                    $null = $EnableWinRMSuccess.Add($CredObj)
                                    break
                                }
                                catch {
                                    #New-UDInputAction -Toast "Failed to enable WinRM Remotely using Credentials $($CredObj.PSCredential.UserName)" -Duration 10000
                                }
                            }
                        }

                        if ($EnableWinRMSuccess.Count -eq 0) {
                            New-UDInputAction -Toast "Unable to Enable WinRM on $Session:ThisRemoteHost via Invoke-WmiMethod over RPC! Please check your credentials." -Duration 10000
                            Sync-UDElement -Id "CredsForm"
                            return
                        }
                        else {
                            [System.Collections.ArrayList]$FailedCredentialsB = @()
                            foreach ($CredObj in $CredentialsToTest) {
                                try {
                                    $GetWorkingCredsResult = GetWorkingCredentials -RemoteHostNameOrIP $Session:ThisRemoteHost -AltCredentials $CredObj.PSCredential -ErrorAction Stop
                    
                                    if ($GetWorkingCredsResult.WorkingCredentials.GetType().FullName -ne "System.Management.Automation.PSCredential") {
                                        #New-UDInputAction -Toast "$($CredObj.CredType) Credentials are not valid! Please try again." -Duration 10000
                                        $null = $FailedCredentialsB.Add($CredObj)
                                    }
                                }
                                catch {
                                    New-UDInputAction -Toast $_.Exception.Message -Duration 10000
                                    New-UDInputAction -Toast "Unable to test $($CredObj.CredType) Credentials! Please try again." -Duration 10000
                                    Sync-UDElement -Id "CredsForm"
                                    return
                                }
                            }
                        }
                    }

                    if ($FailedCredentialsA.Count -gt 0 -or $FailedCredentialsB.Count -gt 0) {
                        if ($FailedCredentialsB.Count -gt 0) {
                            foreach ($CredObj in $FailedCredentialsB) {
                                New-UDInputAction -Toast "$($CredObj.CredType) Credentials are not valid! Please try again." -Duration 10000
                                $Session:CredentialHT.$Session:ThisRemoteHost."$CredType`Creds" = $null
                            }
                            Sync-UDElement -Id "CredsForm"
                            return
                        }
                        if ($FailedCredentialsA.Count -gt 0 -and $FailedCredentialsB.Count -eq 0) {
                            foreach ($CredObj in $FailedCredentialsA) {
                                New-UDInputAction -Toast "$($CredObj.CredType) Credentials are not valid! Please try again." -Duration 10000
                                $Session:CredentialHT.$Session:ThisRemoteHost."$CredType`Creds" = $null
                            }
                            Sync-UDElement -Id "CredsForm"
                            return
                        }
                    }
                }

                if ($DomainAdminCreds) {
                    $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds = $DomainAdminCreds
                }
                if ($LocalAdminCreds) {
                    $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds = $LocalAdminCreds
                }
                if ($VaultServerUrl) {
                    $Session:CredentialHT.$Session:ThisRemoteHost.VaultServerUrl = $VaultServerUrl
                }
                if ($Preferred_PSRemotingCredType) {
                    $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCredType = $Preferred_PSRemotingCredType
                }
                if ($Preferred_PSRemotingMethod) {
                    $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingMethod = $Preferred_PSRemotingMethod
                }

                # Determine $PSRemotingCreds
                if ($Preferred_PSRemotingCredType -eq "Local") {
                    $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCreds = $Session:CredentialHT.$Session:ThisRemoteHost.LocalCreds
                }
                if ($Preferred_PSRemotingCredType -eq "Domain") {
                    $Session:CredentialHT.$Session:ThisRemoteHost.PSRemotingCreds = $Session:CredentialHT.$Session:ThisRemoteHost.DomainCreds
                }

                if ($Preferred_PSRemotingMethod -eq "SSH") {
                    New-UDInputAction -Toast "SSH was SUCCESSFUL, however, ssh functionality has not been fully implemented yet. Please use WinRM instead." -Duration 10000
                    Sync-UDElement -Id "CredsForm"
                    return
                }

                New-UDInputAction -RedirectUrl "/ToolSelect/$Session:ThisRemoteHost"
            }
            $Cache:CredsForm

            New-UDColumn -AutoRefresh -RefreshInterval 1 -Endpoint {
                try {
                    $null = $Session:PSRemotingPageLoadingTracker.Add("FinishedLoading")
                }
                catch {
                    Write-Verbose "`$Session:PSRemotingPageLoadingTracker hasn't been set yet..."
                }
            }
        }
        New-UDColumn -Size 2 -EndPoint {}
    }
}
$Page = New-UDPage -Url "/PSRemotingCreds/:RemoteHost" -Endpoint $PSRemotingCredsPageContent
$null = $Pages.Add($Page)