タイトルの調査を行うにあたって、久しぶりに情報を確認する機会があったのでメモとして。
コンピューターアカウントのパスワードをユーザーが直接操作することはないですが、コンピューターアカウントのパスワード同期に伴う問題について調査をする際には次のような情報を一読しておくとよいかと思いました。
- Machine Account Password Process
- Machine Account (AD Computer Object) Password Updates
- Ldifde でユーザーのパスワードを設定する方法
- Active Directory レプリケーション エラー -2146893022: ターゲット プリンシパル名が正しくありません
- FailoverClustering のイベント ID 1206 が記録される現象
- コンピューター オブジェクトを変更するときにクラスター サービス アカウントをトラブルシューティングする方法
- グループポリシー
- ドメイン メンバー: コンピューター アカウント パスワード: 定期的な変更を無効にする
- 実際に無効にすることはなく、どのポリシーで制御がされているかの確認のために記載しています
- ドメイン メンバー: コンピューター アカウント パスワード: 定期的な変更を無効にする
コンピューターアカウントのパスワードの格納場所
コンピューターアカウントのパスワードはローカルコンピューター上と Active Directory の 2 箇所に保存がされており、起点はローカルコンピューターとなり、ドメインと通信ができなければ変更は行われないという認識です。
- ローカルコンピューター
- 次のレジストリに格納されている
- HKLM\SECURITY\Policy\Secrets\$machine.ACC
- CurrVal
- OldVal
- Active Directory
- 次の属性に格納されている (実際の値は参照不可)
コンピューターアカウントのパスワード変更が行われる際には、これらの情報の整合性がポイントとなります。
検証のために AD 側の情報の書き換え
検証のため、クラスターのコンピューターアカウント (仮想コンピューターオブジェクト: VCO) について、「ローカルと Active Directory のパスワードに矛盾が発生している」状態を作り出す必要がありました。
クラスターのコンピューターアカウントのパスワードについては、HKLM の $machine.ACC ではなく、クラスターリソースの ResourceData 辺りに格納しているのではと思っているのですが、これをピンポイントで書き換えるのは大変そうだったので、次のようなスクリプトを実行して、AD 側の属性を変更して、検証ができる状態を作り出してみました。
repadmin /showobjmeta AD-01 CN=SQL-CL-DTC,OU=WSFC,DC=xxxxx,DC=com 1..5 |%{ $basePwd = ('"{0}"' -f (New-Guid)) $unicodePwd = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($basePwd)) $ldf = @" dn: CN=SQL-CL-DTC,OU=WSFC,DC=xxxxx,DC=com changetype: modify replace: unicodePwd unicodePwd:: {0} - "@ -f $unicodePwd $ldf | Out-File -FilePath "C:\Work\ldif.ldf" -Force ldifde -i -f "C:\Work\ldif.ldf" -h -s AD-01 } repadmin /showobjmeta AD-01 CN=SQL-CL-DTC,OU=WSFC,DC=xxxxx,DC=com
lmPwdHistory については直接書き換えることができなったのですが、unicodePwd については ldifde で書き換える ことができるのでこの項目を複数回変更することで、履歴についても書き換わるようにしています。
変更状況の確認については、repadmin を実行して、該当の属性のバージョンから判断をすることができるのではないでしょうか。
クラスターリソースのコンピューターアカウントへの操作状況
クラスターリソースの CNO (Computer Name Object) は AD 上はコンピューターアカウントとなり、クラスターリソースの正常性確認を含めて、様々な操作が行われてます。
これらの操作は、リソースがオンラインになった際や、3,600,000 msec (60 分 = 1 時間) 間隔というようなトリガーがあるようでした。
クラスターの各種操作についてはクラスターログに記録が行われますので、直近の操作からコンピューターアカウントのパスワードの操作状況を確認する場合などは次のようなコマンドを使用することができます。
get-clusterlog -UseLocalTime -TimeSpan 120;Get-Content C:\Windows\Cluster\Reports\Cluster.log | Select-String "password" | ft
パスワードの変更が実行できていない場合などは、次のようなログが出力されます。
00003168.000024b4::2022/11/30-17:13:12.721 INFO [RES] Network Name <SQL Network Name (SQL-CL-FCI)>: AccountAD: CheckIfPasswordIsInSync for SQL-CL-FCI returned 0 00003168.0000236c::2022/11/30-17:31:36.818 WARN [RES] Network Name: [NNLIB] LogonUserExEx fails for user SQL-CL-DTC$: 1326 (useSecondaryPassword: 0) 00003168.000018e4::2022/11/30-17:31:36.838 INFO [RES] Network Name <SQL-CL-DTC>: AccountAD: CheckIfPasswordIsInSync for SQL-CL-DTC returned 0 00003168.0000236c::2022/11/30-17:31:36.855 WARN [RES] Network Name: [NNLIB] LogonUserExEx fails for user SQL-CL-DTC$: 1326 (useSecondaryPassword: 1)
ログ内の 1326 は、ERROR_LOGON_FAILURE / The user name or password is incorrect. となりますので、このエラーが発生している場合にはコンピューターアカウントのパスワードの不整合が発生している可能性があると考えることができるのではないでしょうか。
AD 側で確認できる項目としては次のような情報があります。
- badPasswordTime
- badPwdCount
- pwdLastSet
- whenChanged
上記のようなエラーメッセージが出力されている時間帯で pwdLastSet の日付が更新されていれば、最終的にパスワード変更は問題なく実行されたと判断でき、過去の時間帯に設定されているのであれば、パスワード変更は最終的には実行できていないというような判断につなげることができるのではないでしょうか。
クラスターリソースの VCO についはコアクラスターリソースのコンピューターオブジェクト (クラスター名オブジェクト: CNO) がフルコントロールの権限を持ち、操作ができるようになっているはずですがパスワード矛盾が発生した場合などは、パスワードを変更することができない状態を作り出すことができます。
このような場合は、FailoverClustering のイベント ID 1206 が記録される現象 に記載されている「修復」の操作を行う必要が出てきます。
通常使用している状態では、コンピューターアカウントの矛盾は発生しないはずですが、何らかの問題により矛盾が発生した状態を作成したい場合などには、本投稿のような手法により、問題が発生している状態を意図的に作り出すことができるのではないでしょうか。