Controlla se l'immissione della password utente è valida nello script Powershell


30

Sto lavorando con uno script Powershell che aggiunge attività pianificate ai sistemi nel nostro dominio. Quando eseguo questo script, mi verrà richiesta la mia password. A volte cerco la password e il processo inizia, il che blocca il mio account. C'è un modo per verificare le mie credenziali per assicurarsi che ciò che ho digitato verrà convalidato con il dominio?

Vorrei trovare un modo per interrogare il controller di dominio. Ho fatto alcune ricerche su Google e dovrei essere in grado di eseguire una query WMI e intercettare un errore. Vorrei evitare quello stile di convalida, se possibile.

Qualche idea? Grazie in anticipo.

Risposte:


26

Ho questo nella mia biblioteca:

$cred = Get-Credential #Read credentials
 $username = $cred.username
 $password = $cred.GetNetworkCredential().password

 # Get current domain using logged-on user's credentials
 $CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
 $domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$UserName,$Password)

if ($domain.name -eq $null)
{
 write-host "Authentication failed - please verify your username and password."
 exit #terminate the script.
}
else
{
 write-host "Successfully authenticated with domain $domain.name"
}

1
Se non sbaglio, questo finirebbe per inviare la password in testo semplice attraverso la rete, giusto? In caso affermativo, allora ho ragione nel dare per scontato AccountManagement.PrincipalContext.ValidateCredentials()(se fornite una password per la password)?
Codice Jockey

Perché non stai usando il ActiveDirectorymodulo per fare la tua query LDAP?
Kolob Canyon,

6 anni fa non esisteva un modulo di directory attiva
Jim B,

Questo script aiuta anche in situazioni in cui non è possibile installare i moduli di AD PowerShell per un motivo o per l'altro.
Dodzi Dzakuma,

16

Questo è quello che ho usato in passato; dovrebbe funzionare per gli account dei computer locali e la 'directory dell'applicazione', ma finora l'ho usato solo con successo con le credenziali AD:

    function Test-Credential {
    <#
    .SYNOPSIS
        Takes a PSCredential object and validates it against the domain (or local machine, or ADAM instance).

    .PARAMETER cred
        A PScredential object with the username/password you wish to test. Typically this is generated using the Get-Credential cmdlet. Accepts pipeline input.

    .PARAMETER context
        An optional parameter specifying what type of credential this is. Possible values are 'Domain','Machine',and 'ApplicationDirectory.' The default is 'Domain.'

    .OUTPUTS
        A boolean, indicating whether the credentials were successfully validated.

    #>
    param(
        [parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [System.Management.Automation.PSCredential]$credential,
        [parameter()][validateset('Domain','Machine','ApplicationDirectory')]
        [string]$context = 'Domain'
    )
    begin {
        Add-Type -assemblyname system.DirectoryServices.accountmanagement
        $DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::$context) 
    }
    process {
        $DS.ValidateCredentials($credential.UserName, $credential.GetNetworkCredential().password)
    }
}

Mi piacerebbe sapere se qualcuno lo nota - credo che quando uso ValidateCredentials () in questo modo con una password errata, sembra innescare due (2) tentativi di password errata - Non riesco a controllare la soglia del numero di tentativi sul nostro dominio, ed è basso, quindi preferirei non fare due brutti tentativi quando faccio una sola chiamata ... qualcuno può vedere anche questo?
Codice Jockey

Stai utilizzando il formato dominio \ utente o UPN (utente @ dominio)? Non sono in grado di replicarlo, ma il seguente URL descrive un problema simile: social.msdn.microsoft.com/Forums/vstudio/en-US/…
jbsmith

Dovresti essere in grado di passare $contextcome argomento al costruttore. PowerShell converte automaticamente le stringhe in un enum. Meglio ancora, basta fare [System.DirectoryServices.AccountManagement.ContextType]il tipo di $context. Inoltre, perché stai usando begine processqui? La pipeline sembra un modo strano di usare questa funzione.
jpmc26

@ jpmc26: la digitazione del $contextparametro [System.DirectoryServices.AccountManagement.ContextType]non è un'opzione, poiché l'assembly contenente non viene caricato fino all'esecuzione del corpo della funzione ; l'utilizzo della pipeline è utile se si desidera convalidare più credenziali.
mklement

@mklement Non c'è motivo per cui la Add-Typechiamata non possa essere spostata all'esterno della funzione, prima che venga eseguita la sua definizione. Sono titubante ad avere una Add-Typechiamata eseguita incondizionatamente ripetutamente all'interno della funzione anche se è già caricata, comunque. La convalida di più credenziali contemporaneamente sembra in primo luogo una situazione strana. Nel raro caso è quello che vuoi, puoi facilmente avvolgere la chiamata ForEach-Object, quindi non vedo un motivo per complicare la funzione con esso.
jpmc26

1

Ho trovato utile questo post ma non ha risolto il mio problema mentre stavo cercando di eseguirlo da uno script con l'account amministratore locale connesso. Non sembra funzionare come amministratore locale (solo quando si accede come utente di dominio).

Tuttavia, alla fine sono riuscito a ottenere una soluzione funzionante e dato che era un così grande problema, ho pensato di condividerlo qui, così chiunque altro con questo problema avrà la risposta proprio qui. Entrambe le risposte in un'unica pagina a seconda delle tue esigenze.

Si noti che più in alto nello scipt (non incluso qui in quanto questa è solo la sezione get-credentials) è installato powergui ed è un requisito per questo codice qui sotto (così come la riga "Add-PSSnapin Quest.ActiveRoles.ADManagement"). Non sono sicuro di ciò che fa powergui che è diverso, ma nessun altro potrebbe dirmi e funziona.

Sostituisci il tuo nome di dominio nelle sezioni "nome_dominio".

#Get credentials
$credential_ok = 0
while ($credential_ok -ne 1)
{
    $credential = get-credential
    $result = connect-qadservice -service *domain_name* -credential $credential
    [string]$result_string = $result.domain
    if ($result_string -eq "*domain_name*")
    {
        $credential_ok = 1
        #authenticated
    }
    else
    {
        #failed
    }     
}
$username = $credential.username 
$password = $credential.GetNetworkCredential().password 

$date = get-date
Add-Content "c:\lbin\Install_log.txt" "Successfully authenticated XP script as $username $date"

1

(ancora) Un'altra versione:

param([string]$preloadServiceAccountUserName = "")

function HarvestCredentials()
{

        [System.Management.Automation.PSCredential]$credentialsOfCurrentUser = Get-Credential -Message "Please enter your username & password" -UserName $preloadServiceAccountUserName

        if ( $credentialsOfCurrentUser )
        {
            $credentialsOfCurrentUser = $credentialsOfCurrentUser
        }
        else
        {
            throw [System.ArgumentOutOfRangeException] "Gui credentials not entered correctly"          
        }

    Try
    {


        # see https://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.path(v=vs.110).aspx
        # validate the credentials are legitimate
        $validateCredentialsTest = (new-object System.DirectoryServices.DirectoryEntry ("WinNT://"+$credentialsOfCurrentUser.GetNetworkCredential().Domain), $credentialsOfCurrentUser.GetNetworkCredential().UserName, $credentialsOfCurrentUser.GetNetworkCredential().Password).psbase.name
        if ( $null -eq  $validateCredentialsTest)
        {
            throw [System.ArgumentOutOfRangeException] "Credentials are not valid.  ('" + $credentialsOfCurrentUser.GetNetworkCredential().Domain + '\' + $credentialsOfCurrentUser.GetNetworkCredential().UserName + "')"
        }
        else
        {
            $t = $host.ui.RawUI.ForegroundColor
            $host.ui.RawUI.ForegroundColor = "Magenta"
            Write-Output "GOOD CREDENTIALS"
            $host.ui.RawUI.ForegroundColor = $t
        }
    }
    Catch
    {

        $ErrorMessage = $_.Exception.Message
        $FailedItem = $_.Exception.ItemName
        $StackTrace = $_.Exception.StackTrace

        $t = $host.ui.RawUI.ForegroundColor
        $host.ui.RawUI.ForegroundColor = "Red"

        Write-Output "Exception - $ErrorMessage"
        Write-Output "Exception - $FailedItem"
        Write-Output "Exception - $StackTrace"

        $host.ui.RawUI.ForegroundColor = $t

        throw [System.ArgumentOutOfRangeException] "Attempt to create System.DirectoryServices.DirectoryEntry failed.  Most likely reason is that credentials are not valid."
    }

}


Try
{

    HarvestCredentials

}
Catch
{
    $ErrorMessage = $_.Exception.Message
    $FailedItem = $_.Exception.ItemName
    $StackTrace = $_.Exception.StackTrace

    $t = $host.ui.RawUI.ForegroundColor
    $host.ui.RawUI.ForegroundColor = "Red"

    Write-Output "Exception - " + $ErrorMessage
    Write-Output "Exception - " + $FailedItem
    Write-Output "Exception - " + $StackTrace

    $host.ui.RawUI.ForegroundColor = $t

    Break
}
Finally
{
    $Time=Get-Date
    Write-Output "Done - " + $Time
}

e

.\TestCredentials.ps1 -preloadServiceAccountUserName "mydomain\myusername"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.