Linux から WinRM(HTTPS/5986)で Windows Server を管理する際、Basic 認証は通るのにクライアント証明書認証(証明書マッピング)だけが Windows Server 2012/2016 で「Access is denied/InvalidCredentials」になることがあります。本記事では原因のポイントと、レジストリ 1 つで解消できる代表的な対処を具体手順つきでまとめます。
症状:WinRM(HTTPS/5986)の証明書認証だけが 2012/2016 で拒否される
今回の現象を、よくある実務パターンに落とすと次のようになります。
- Linux から WinRM(5986/HTTPS)で Windows Server を操作したい
- Basic 認証なら接続できる(疎通は取れている)
- 要件により クライアント証明書認証(証明書マッピング)へ切り替えたい
- 自己署名のクライアント証明書(EKU: clientAuth)を用意し、サーバー側の証明書ストアへ投入、ローカル管理者へマッピング済み
- 開発環境では成功するのに、テスト環境だと Windows Server 2008 は成功、2012/2016 が一部だけ失敗
エラーの見え方は環境により多少異なりますが、代表例は以下です。
| クライアント | 操作 | 代表的なエラー | 示唆 |
|---|---|---|---|
| Windows | Enter-PSSession / New-PSSession(-UseSSL -CertificateThumbprint) | Access is denied / The WinRM client cannot process the request | WinRM 以前(TLS)か、WinRM の証明書認証・マッピングのどこかで拒否 |
| Linux | pywinrm / Ansible(WinRM over HTTPS) | InvalidCredentials / 401 / 403 相当の拒否 | 同じく TLS〜WinRM 認証層の問題。Basic が通るなら通信や WinRM 自体は概ね OK |
ポイント:証明書マッピングは「最後の一手前」まで通って初めて効く
WinRM のクライアント証明書認証は、ざっくり言うと次の二段階で成立します。
- TLS ハンドシェイクでクライアント証明書が提示され、サーバー側(SCHANNEL)が「信頼できる証明書チェーン」として受理する
- WinRM(WSMan)が certmapping(証明書マッピング)に基づいて証明書→ユーザーを紐付け、権限チェックを行う
重要なのは、certmapping が正しく入っていても、1 の時点で“信頼できない”判定になると 2 に進まないことです。現象としては「証明書は入っている」「マッピングも入っている」のに Access is denied/InvalidCredentials になり、切り分けが難しく感じます。
| 観点 | Basic 認証 | クライアント証明書認証(証明書マッピング) | 今回の肝 |
|---|---|---|---|
| 失敗しやすい層 | ユーザー権限やポリシー | TLS(SCHANNEL のチェーン判定)+マッピング | 2012/2016 の一部だけ失敗する“環境差”は TLS 側が原因になりやすい |
| ありがちな誤解 | — | 「Trusted People に入れたから信頼されるはず」 | ストアに“存在する”ことと、SCHANNEL が“信頼チェーンとして受理する”ことは別 |
原因:SCHANNEL のクライアント証明書 Trust Mode が“信頼の判定”を変える
結論として、Windows の TLS(SCHANNEL)には「クライアント証明書をどういうモードで信頼判定するか」を切り替える要素があり、その挙動差で 同じ証明書でも環境によって“信頼できない”扱いになることがあります。
ここで効いてくるのが、SCHANNEL のレジストリ値 ClientAuthTrustMode です。Microsoft Learn の Q&A でも、WinRM の証明書認証が一部の Windows Server 2012 系で失敗するケースの対処として、この値の設定が紹介されています。
解決策:ClientAuthTrustMode を 2(Exclusive CA Trust)に設定する
問題が出ている Windows Server 2012/2016 側で、次のレジストリ値を追加します。
| 項目 | 設定 |
|---|---|
| パス | HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL |
| 値名 | ClientAuthTrustMode(REG_DWORD) |
| 値 | 2 |
| 補足 | Stack Overflow では 2 が SCHANNEL の Trust Mode を Exclusive CA Trust にする設定として説明されています |
PowerShell(管理者)での設定例
New-ItemProperty `
-Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL' `
-Name 'ClientAuthTrustMode' -PropertyType DWord -Value 2 -Force
反映と再テストのコツ
この値は SCHANNEL に関わるため、反映に再起動が必要になる場合があります。切り分けとしては次の順が安全です。
- 設定後、まず WinRM サービスを再起動して再テスト(環境によってはこれで反映する)
- 変化がなければ、計画停止のうえでサーバー再起動して再テスト(確実)
設定確認(現在値の確認)
Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL' `
-Name 'ClientAuthTrustMode' -ErrorAction SilentlyContinue
WinRM 側の確認:certmapping と認証設定を「目で見て」揃える
ClientAuthTrustMode で改善するケースでも、WinRM 側の設定に不足があると当然失敗します。次の 3 点は、まずコマンドで確認しておくと迷いません。
証明書マッピングが正しく入っているか
winrm enum winrm/config/service/certmapping
Enabled=true、そして Issuer/Subject(または URI/Thumbprint)条件が意図どおりであることを確認します。自己署名証明書は Issuer と Subject が同じに見えるため、複数枚運用している場合は条件が衝突しやすい点に注意してください。
WinRM で Certificate 認証が有効になっているか
winrm get winrm/config/service/auth
出力の中で Certificate = true になっているかを確認します。Basic を無効化する前に、証明書認証が有効化できているか(GPO で上書きされていないか)も見ておきます。
HTTPS リスナーが存在し、意図したサーバー証明書を使っているか
winrm enumerate winrm/config/listener
Transport=HTTPS のリスナーが存在し、Thumbprint が意図したサーバー証明書のものかを確認します。
Windows クライアントからの簡易テスト:Enter-PSSession の -CertificateThumbprint
Linux 側のツール(pywinrm/Ansible)で切り分けが難しいときは、Windows から同じ WinRM に対して証明書認証を試すと、問題がサーバー側かクライアント側かを素早く切り分けできます。
# クライアント証明書(CurrentUser\My)から Thumbprint を指定して接続する例
Enter-PSSession -ComputerName 'server.example.local' -UseSSL -CertificateThumbprint 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
ここでも同様に Access is denied になるなら、Linux 側の実装差というより、サーバー側(SCHANNEL/WinRM 設定/マッピング)に原因が寄っている可能性が高くなります。
補足:同時に確認するとよい点(失敗原因の“取りこぼし”を防ぐ)
ClientAuthTrustMode が本命でも、周辺条件が揃っていないと別の理由で失敗し続けます。現場で効く順にまとめます。
| 確認項目 | なぜ重要か | 確認方法の例 | NG だと起きやすい症状 |
|---|---|---|---|
| クライアント証明書の EKU(clientAuth) | 用途不一致だと TLS で受理されにくい | 証明書の詳細で EKU を確認 | 証明書を提示しても認証として成立しない |
| 秘密鍵の存在とアクセス権 | 秘密鍵が読めないと署名できず失敗 | Linux のファイル権限、Windows の秘密鍵 ACL | クライアント側で握手失敗/証明書未送信 |
| 証明書ストアの“場所”(LocalMachine / CurrentUser) | WinRM サービスが参照できるストアが違う | certlm.msc / certmgr.msc で確認 | 入れたつもりでもサーバー側で信頼されない |
| 接続先名とサーバー証明書の CN/SAN | 不一致は別エラーになりやすい | FQDN で接続、SAN を確認 | 証明書認証以前に TLS で失敗 |
| WinRM 実行権限(グループ/セッション構成) | マッピング成功後の最終関門 | Remote Management Users、セッション構成 ACL | 常に Access is denied(OS 差は出にくい) |
ログで裏取りする:WinRM と Schannel を見る
「証明書は入っているのに拒否される」状況では、ログが判断材料になります。
- WinRM の Operational ログ:Applications and Services Logs > Microsoft > Windows > WinRM > Operational
- Schannel:システム ログに TLS 関連の警告/エラーが出ることがある
WinRM 側に“証明書認証を試した”形跡が薄い場合は、TLS の段階で弾かれている可能性が高くなります。このときに ClientAuthTrustMode を変えて改善する、という流れが典型です。
影響範囲とロールバック:SCHANNEL なので段階適用が安全
ClientAuthTrustMode は OS 全体の TLS(SCHANNEL)に関わるため、WinRM 以外のサービスにも影響し得ます。同一サーバーで IIS のクライアント証明書認証などを使っている場合は、必ず影響評価を行い、まずは問題が出ている 1 台から段階的に適用してください。
ロールバック(元に戻す)
切り戻しが必要になった場合は、値を削除(または 0 に戻す)します。
Remove-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL' `
-Name 'ClientAuthTrustMode' -ErrorAction SilentlyContinue
現場向け:最短で解決するためのチェック順
「WinRM HTTPS+クライアント証明書認証で 2012/2016 だけ Access is denied」という状況で、最短で片付けるための流れを 1 枚にまとめます。
| ステップ | やること | 狙い | コマンド例 |
|---|---|---|---|
| A | HTTPS リスナーと Certificate 認証の有効化を確認 | WinRM 設定不足を除外 | winrm enumerate winrm/config/listener winrm get winrm/config/service/auth |
| B | certmapping を確認 | マッピング条件の不一致を除外 | winrm enum winrm/config/service/certmapping |
| C | 証明書が LocalMachine の適切なストアにあるか確認 | “入れたつもり”事故を除外 | certlm.msc / certutil -store |
| D | ClientAuthTrustMode=2 を適用 | SCHANNEL の信頼判定の環境差を潰す | New-ItemProperty … ClientAuthTrustMode=2 |
| E | 必要なら再起動して再テスト | 反映タイミングを確実にする | Restart-Service WinRM(切り分け) Restart-Computer(確実) |

コメント