Powershellスクリプトでユーザーのパスワード入力が有効かどうかを確認します


30

ドメイン内のシステムにスケジュールされたタスクを追加するPowershellスクリプトを使用しています。このスクリプトを実行すると、パスワードの入力が求められます。私は時々パスワードを太らせるとプロセスが開始され、それが私のアカウントをロックアウトします。入力した内容がドメインで検証されることを確認するために、資格情報を確認する方法はありますか?

ドメインコントローラーを照会する方法を見つけたいです。Google検索をいくつか行ったので、WMIクエリを実行してエラーをトラップできるはずです。可能であれば、そのスタイルの検証は避けたいと思います。

何か案は?前もって感謝します。

回答:


26

私のライブラリにこれがあります:

$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
間違っていない場合、これはネットワーク経由でパスワードをプレーンテキストで送信することになりますか?もしそうなら、それはそうでAccountManagement.PrincipalContext.ValidateCredentials()はないと仮定するのは正しいでしょうか(パスワードにセキュアストリングを提供する場合)?
コードジョッキー

ActiveDirectoryモジュールを使用してLDAPクエリを実行しないのはなぜですか?
コロブキャニオン

6年前、Active Directoryモジュールはありませんでした
Jim B

このスクリプトは、何らかの理由でAD PowerShellモジュールをインストールできない場合にも役立ちます。
ドッジジャクマ18

16

これは私が過去に使用したものです。ローカルマシンアカウントと「アプリケーションディレクトリ」で機能するはずですが、これまでのところ、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)
    }
}

誰かがこれに気付いたら聞いてみたい-私はValidateCredentials()を間違ったパスワードでこのように使用すると、2回の間違ったパスワード試行をトリガーするようだと思う-試行回数のしきい値を制御できない私たちのドメインで、それは低いので、私は単一の通話をしているときに2回悪い試みをしないことを望みます...誰もこれを見ることができますか?
コードジョッキー

domain \ userまたはUPN(user @ domain)形式を使用していますか?私はこれを再現する立場にありませんが、次のURLは同様の問題を説明しています。social.msdn.microsoft.com
vstudio

$context引数としてコンストラクターに渡すことができるはずです。PowerShellは自動的に文字列を列挙型に変換します。さらに良いのは、[System.DirectoryServices.AccountManagement.ContextType]のタイプを作成するだけです$context。また、なぜあなたはここで使用beginしていprocessますか?パイプラインは、この関数を使用する奇妙な方法のようです。
jpmc26

@ jpmc26:関数の本体が実行されるまで、含まれるアセンブリはロードされないため、$contextパラメーターを入力すること[System.DirectoryServices.AccountManagement.ContextType]はオプションではありません。複数の資格情報を検証する場合は、パイプラインを使用すると便利です。
mklement

@mklement Add-Type定義を実行する前に、関数の外部に呼び出しを移動できない理由はありません。Add-Typeとにかく、関数が既に読み込まれている場合でも、関数内で呼び出しを無条件に繰り返し実行するのをためらっています。複数の資格情報を同時に検証することは、そもそも奇妙な状況のように思えます。まれなケースですが、それはあなたが望むものです、あなたは簡単に呼び出しをラップすることができますForEach-Objectので、私はそれで関数を複雑にする理由がわかりません。
jpmc26

1

この投稿は役に立ちましたが、ローカル管理者アカウントでログオンしてスクリプトから実行しようとしていたため、問題は解決しませんでした。ローカル管理者として機能しないようです(ドメインユーザーとしてログオンした場合のみ)。

しかし、私はついに実用的なソリューションを手に入れることができました。それは非常に面倒だったので、ここでそれを共有すると思ったので、この問題を抱える誰もがここで答えを持っています。ニーズに応じて、1つのページで両方の回答が得られます。

sciptの上位(これはget-credentialsセクションであるため、ここには含まれません)powerguiがインストールされ、以下のこのコードの要件であることに注意してください(「Add-PSSnapin Quest.ActiveRoles.ADManagement」行も同様)。powerguiが何をするのかはわかりませんが、他の誰も私に伝えることができず、動作します。

「domain_name」セクションで独自のドメイン名を置き換えます。

#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

(まだ)別のバージョン:

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
}

そして

.\TestCredentials.ps1 -preloadServiceAccountUserName "mydomain\myusername"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.