BetterCredentials
BetterCredentials copied to clipboard
Possibly allow a validation of credentials when retrieved, possibly by a switch
Like many admins I use very long secure credentials, which are subject to all kinds of typo errors. I'd like to see a switch added to Get-Credential that would validate a credential that was inputted.
I created this function to validate credentials when they are entered (and I use it day to day for this type of functionality). It leverages the AccountManagement namespace as described Richard Siddaway's blog post: https://richardspowershellblog.wordpress.com/2008/05/25/system-directoryservices-accountmanagement/. I'd like to see the functionality added in.
Here is my function:
Function Get-ValidatedCredential
{
<#
.SYNOPSIS
Retrieves a credential from the user with the standard Windows dialog, and
then it validates that the password is correct for the account.
.DESCRIPTION
Uses the standard dialog with the option to customize the title, the prompt text, and
to prefill a domain name and user name. The credential is then tested against the
domain to validate that the password is correct. If it is not, the user is prompted again.
The user does have the option to click Cancel and exit this function.
.PARAMETER DomainName
The domain name of the user to validate
.PARAMETER DomainUser
The username (sAMAccountName) of the user to validate
.PARAMETER DialogTitle
The title of the dialog presented to request credentials
.PARAMETER DialogPrompt
The prompt of the dialog presented to request credentials
.EXAMPLE
PS C:\> Get-ValidatedCredential -DomainName $env:USERDOMAIN -DomainUser MyServiceAccount -DialogTitle 'Enter credentials' -DialogPrompt 'Enter the credentials for the service account to use'
.NOTES
This script is based on Richard Siddaway's blog about the System.DirectoryServices.AccountManagement namespace.
https://richardspowershellblog.wordpress.com/2008/05/25/system-directoryservices-accountmanagement/
.INPUTS
[system.string]
.OUTPUTS
[pscredential]
#>
[cmdletbinding()]
param(
[parameter(Mandatory = $true, HelpMessage='The domain name of the account to be validated', ValueFromPipelineByPropertyName = $true)]
[string]$DomainName,
[parameter(Mandatory = $true, HelpMessage = 'The user name of the account to be validated', ValueFromPipelineByPropertyName = $true)]
[string]$DomainUser,
[parameter(ValueFromPipelineByPropertyName = $true)]
[string]$DialogTitle = 'Enter credentials',
[parameter(ValueFromPipelineByPropertyName = $true)]
[string]$DialogPrompt = 'Enter the credentials to be validated'
)
$MyName = $MyInvocation.InvocationName
Write-Verbose -Message ('[{0}] Starting {1}' -f [DateTime]::Now, $MyName)
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$HaveValidCredentials = $false
do
{
$Credential = $Host.UI.PromptForCredential($DialogTitle, $DialogPrompt, ('{0}\{1}' -f $DomainName, $DomainUser), $DomainName)
if ($Credential -eq $null)
{
#Throw 'User clicked cancel, exiting the script'
Write-Verbose -Message ('[{0}] Cancel was clicked, exiting this function quietly' -f $MyName)
if (Test-Path -Path variable:\Context)
{
$Context.Dispose()
}
return $null
}
$Context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList ([System.DirectoryServices.AccountManagement.ContextType]::Domain, $DomainName)
if ($Context.ValidateCredentials($DomainUser, $Credential.GetNetworkCredential().Password))
{
$HaveValidCredentials = $true
Write-Verbose -Message ('[{0}] Current provided credentials are valid, and password is correct, continuing with the installation' -f $MyName)
}
}
until ($HaveValidCredentials)
$Context.Dispose()
$Credential
}