こんにちは、富士榮です。
ゴールデンウィークも終わりですね。
と、いうことで今回は今年の私のゴールデンウィークの7割を奪ったAzure Active Directory(Azure AD)へのデバイス登録時のトラブルと、トラブルシューティングの中で見えてきたAzure AD DRS(Device Registration Service)の裏側の仕組みの話です。
◆何が起きていたのか?
4月の終わりから5月の頭にかけてAzure AD DRSの一部機能で障害が発生しており、
Windows 10デバイスをAzure ADへ参加させた後のサインイン時のPIN作成でエラー 0x801c03ed が出る
という状況になっていました。
こんなエラーが出ます。
どうやらみなさん困っていたようで、各所に情報が出始めていました。
(未解決) PIN setup on Azure AD joined machine fails.が、現在も発生
Error 0x801c03ed during PIN create/change
エラーコードだけを見ているとデバイス参加時に多要素認証が必要な設定になっているにも関わらず、
多要素認証を実施しなかった等が原因で対策としては
一旦Azure ADから切り離して再参加する、と書いてあるのですが、
多要素認証を要求する設定をしていないにもかかわらずこのエラーがでたり、
多要素認証を実施してもエラーがでたり、
そもそも再参加しても状況が改善しない、という状態でした。
エラー時のリファレンス
Microsoft Passport errors during PIN creation
◆トラブルシューティングとして何をする/したのか
先に書いたように今回はトラブルシューティングをしても一向に解決しなかったので、中の人に泣きついた結果障害が発覚して収束したんですが、トラブルシューティングの過程を残しておくことも今後の役に立つと思ったので少し残しておきます。
1.イベントログを確認する
ユーザがデバイスを登録する際、クライアント側のイベントログに様々な情報が記録されます。関連するのは、主にUser Device Registrationで、必要に応じてAADについても見ることになります。(両方とも、アプリケーションとサービスログ->Microsoft->Windowsの配下にあります)
エラーが発生しているときは、User Device RegistrationのAdminログにID:301のエラーが発生していました。
NGC KeyをAzure DRSへ登録する際にInsufficient privilegesが出ていますので、先の多要素認証が正常に実行されていない時と同じエラーだと判断されたようです。
この前後のログを見ると、Azure DRSへNGCを登録する際の動きを推測することが出来ます。
流れは、
1.Azure DRSのエンドポイントを検出する
2.対象ユーザが関連付けされているデバイスをAzure ADディレクトリから探し出す
3.クライアントで生成した鍵ペアより公開鍵を登録する
となっています。
(細かくは省きますが、OOBEでのセットアップ時(WinPE)かどうか判別したり、レジストリからNGC関連の情報を読み取ろうとしたり、と前処理では他にも色々とやっています)
順番に見ていきます。
1のAzure DRSのエンドポイントの検出です。ここは障害が発生している間もうまく動いていました。検出は以下の2つのXMLドキュメントを使ってクライアント・コンフィグレーションをAzureから取得するところからスタートします。
https://clientconfig.microsoftonline-p.net/FPURL.xml
https://clientconfig.microsoftonline-p.net/fplist.xml
ここで主にやっているのは、通常のテナント(MicrosoftOnline.com)なのか、中国用テナント(partnet.microsoftonline.com)なのかの判別をして、必要なIdPのURLを取得するところです。
この後、ユーザのドメイン名からDRSや関連するエンドポイントを検出し、その結果がイベントログに記録されます。
DRSのエンドポイントと、Azure AD上でのリソースURI、OAuth関連のエンドポイントが検出されています。
2のAzure ADに登録されたデバイスとの関連付けについてはイベントログには現れませんが、前段でAzure ADへの参加をした時にAzure AD上に登録されたデバイスからのNGC登録要求でないとAzure DRSは受付けません。デバイスの登録状態はAzure ADのPowerShellコマンドレッド(新しい奴)もしくはGraph APIで状態の確認ができます。
Get-MsolDevice -Allで一覧を取得した結果はこんな感じです。このDeviceTrustTypeに「Azure AD Joined」とあるのがAzure AD参加したデバイスです。※ちなみにオンプレADに参加したデバイスをAzure ADへ同期すると「Domain Joined」となります。また、Intuneで管理されている状態だとDeviceTrustLevelがCompliantに、単純にデバイスが登録されただけの状態だとAuthenticatedになります。
最後にクライアント側で生成した鍵をAzure ADへ登録するところで先ほどは「Insufficient privilege」と言われてエラーになっていましたが、正常に登録できると「Microsoft Passport key was successfully registered」というメッセージが出ます。
なお、今回トラブルシューティングをする上では、さらに細かい情報を取得する必要があったため、User Device Registrationのデバッグログを有効にしました。
有効にするには、イベントログのデバッグおよびトレースを有効化した上で、User Device RegistrationのDebugログを有効にします。
デバッグログを有効化することで膨大なログ(PIN登録部分だけで1000件近く)が出ますが、より細かい状態を把握できます。
今回のケースだとID:502で以下の3つのエラーが記録されていました。
・XMLのパースエラー(エンドポイントのディスカバリ時のエラー)
・NGCコンテナの作成エラー
・NGC登録時にサーバーエラー(400)
後半2つは最初のエラーに起因するものだと思われるので、一番の原因はディスカバリだった、ということですね。ちなみに事象が解消した現在でもfplist.xmlにDRS要素はないので、fplist.xmlのパース処理自体に問題があった、ということだと思います。
イベントログはこんな感じです。
2.Azure ADへのクライアント登録の状態からWindows 10とAzure ADの関連を知る
これは今回のトラブル解消には全く関係ありませんでしたが、イベントログを見て行く過程でAADのイベントログにこんな情報が出ていました。(User Device Registrationではなく、AAD側のログ)
この辺りを見ると、Azure ADの共通テナント(https://login.microsoftonline.com/common)上にAAD.BrokerPlugin用のクライアントがマルチテナント構成で登録されていることがわかります。
※この画面では、クライアントID「dd762716-544d-4aeb-a526-687b73838a22」が見えますが、他にも「a40d7d7d-59aa-447e-a655-679a4107e548」などが登録されています。
仕組みとしては、Windows 10のネイティブアプリケーションであるMicrosoft.AAD.BrokerPluginがAzure ADの情報にアクセスするために、共通のクライアントがAzure AD上に登録されており、そのクライアントを使ってAzure ADとやり取りをしているようです。Edgeを使ったデバイス->ブラウザのシングルサインオンにおけるPRT(Primary Refresh Token)からアクセストークンの取得でも活用されているので、知っておいて損はありません。
実際の動きはFiddlerでも見ることが出来ますが、無理やりブラウザを使ってリクエストを投げてみるとクライアントがどのような名前で登録されているか、くらいはわかります。
例えば、DRSへのアクセストークンを取得したい場合は、
https://login.microsoftonline.com/common/oauth2/authorize?
response_type=code%20token&
client_id=dd762716-544d-4aeb-a526-687b73838a22&
redirect_uri=ms-appx-web%3A%2F%2FMicrosoft.AAD.BrokerPlugin%2Fdd762716-544d-4aeb-a526-687b73838a22&
resource=urn:ms-drs:enterpriseregistration.windows.net
を投げるとクライアントのDisplayNameは空白で、多要素認証を要求していることがわかります。
(実際は多要素認証に回答してもそのまま固まりますが)
同様にアカウント設定画面での操作は、
https://login.microsoftonline.com/common/oauth2/authorize?
response_type=code%20token&
client_id=a40d7d7d-59aa-447e-a655-679a4107e548&
redirect_uri=ms-appx-web%3A%2F%2FMicrosoft.AAD.BrokerPlugin%2Fa40d7d7d-59aa-447e-a655-679a4107e548&
resource=https%3A%2F%2F<ドメイン名>
を投げるとクライアントが「Accounts Control UI」という名前で登録されていることがわかります。
(こちらはBad Requestになります)
このあたりはトラブルシューティングにはあんまり役に立ちませんが、内部の動きを知っておくのは良いことだと思います。
3.PIN生成時の通信をFilddlerでキャプチャする
この辺りも基本的なところなので、押さえておきたいところです。
Jairoの
blog(翻訳版は
こちら)を見ると、PIN登録時に「https://account.live.com/aadngc」へアクセスする、とありますが実際の動きはどうなっているのかを確認してみましょう。
Fiddlerのセットアップや基本的な操作方法については割愛しますが、ポイントは以下の2点です。
・ブラウザ以外のセッションもキャプチャする
・HTTPSの復号を有効にする
特にポイントになるのは、Windowsアプリケーションからの通信をキャプチャするという部分で、具体的にはFiddlerの左上のWinConfigをクリックして必要なアプリケーションを選択して保存を行います。
画面の中にアカウントや職場または学校アカウントなどが関連するのでチェックが入っているか確認しておきましょう。
この状態でPINのセットアップを行うと、以下のようなキャプチャが取得できます。
<リクエスト>
GET https://account.live.com/aadngc?uiflavor=win10&mkt=ja-JP&hasngc=0&platform=Windows10&scid=4&ctc=0&uiflavor=Win10 HTTP/1.1
Accept: text/html, application/xhtml+xml, image/jxr, */*
Accept-Language: ja
cxh-osVersionInfo: {"platformId":0,"majorVersion":10,"minorVersion":0,"buildNumber":14332}
hostApp: CloudExperienceHost
client-request-id: 872a9ff6-a81d-0000-0cad-2d871da8d101
cxh-protocol: ms-cxh
cxh-cxid: NGC
cxh-preferredLanguage: ja
cxh-correlationId: 872a9ff6-a81d-0000-0cad-2d871da8d101
cxh-source: ms-cxh://NTHAADNGCONLY/
cxh-osPlatform: CloudExperienceHost.Platform.DESKTOP
cxh-platform: CloudExperienceHost.Platform.DESKTOP
cxh-isRTL: false
cxh-colors: themeAccent=#0078d7;themeAccentLight1=#429ce3;themeAccentLight2=#76b9ed;themeAccentLight3=#a6d8ff;themeAccentDark1=#005a9e;themeAccentDark2=#004275;themeAccentDark3=#002642;themeTextApplication=#000000;themeTextSystem=#ffffff;
cxh-host: NTHAADNGCONLY
cxh-hostAppVersion: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; MSAppHost/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36 Edge/14.14332
Accept-Encoding: gzip, deflate
Host: account.live.com
Connection: Keep-Alive
Cookie: mkt=ja-JP; DID=5737
こうやって見ると、CXH(Cloud eXperience Host)が内部的には健在なことがわかりますね。レスポンスはHTMLが返ってきているので、CXH内での画面表示はHTMLであることがわかります。
その後、https://auth.gfx.msへのアクセスが続いた後、最終的にhttps://account.live.com/API/ReportClientEventへ以下のJSONがPOSTされます。
{
"pageApiId":"Account_AAD_NGC_Provisioning",
"clientDetails":[],
"userAction":"",
"source":"PageView",
"clientTelemetryData":{
"category":"PageLoad",
"pageName":"Account_AAD_NGC_Provisioning",
"eventInfo":{
"timestamp":1462676178361,
"perceivedPlt":2641,
"networkLatency":1874,
"networkType":null,
"precaching":null,
"bundleVersion":null,
"appVersion":null,
"deviceYear":null,
"isMaster":null,
"bundleHits":null,
"bundleMisses":null
}
},
"uiflvr":13,
"uaid":"872a9ff6a81d00000cad2d871da8d101",
"scid":100185,
"hpgid":"Account_AAD_NGC_Provisioning"
}
そして、最後に
https://enterpriseregistration.windows.net/EnrollmentServer/key/?api-version=1.0
に対して公開鍵をPOSTします。
{
"kngc":"UlNBMQAI...snip...tFNEC+U/BbJ+WU0pKD1tAOINB2w==",
"ak":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
}
こんな感じです。
尚、同様にFiddlerを使ってAzure ADへ参加する際の通信の流れやMicrosoft Passportの流れもキャプチャすることが出来ます。
例えば、Azure ADへ参加する時は、
- https://login.microsoftonline.com/WebApp/CloudDomainJoin/4へGET
- https://login.microsoftonline.com/common/.well-known/openid-configurationでOAuth関連のエンドポイント取得
- https://login.microsoftonline.com/common/oauth2/authorizeへclient_id:01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9で認可要求
という流れになります。
このあたりの細かい話は別途まとめてお話ししたいですね。
4.NGC(Next Generation Credential)のプロビジョニング状態を確認する
デバイスがAzure ADやオンプレミスのADへ参加しているかどうか、MDMでの管理状態はどうなっているのか、およびNGCがプロビジョニングされているかどうかを簡単にチェックするにはdsregcmd.exeを使います。
使い方としては、dsregcmd /statusとたたくだけです。
出力結果は2つのパートに分かれており、デバイスの状態およびユーザの状態を示します。(Windows 10 1511.10586.xxxの場合。14332だともっと項目が増えています)
セクション | 項目 | 説明 |
Device State | AzureAdJoined | Azure ADに参加しているかどうか |
AzureAdDeviceId | Azure ADに登録されているデバイスのID |
AzureAdThumprint | Azure ADに登録されているデバイス証明書の拇印 |
AzureAdIdP | Azure ADのIdP |
AzureAdTenantId | Azure ADのテナントID |
AzureAdTenantName | Azure ADのテナント名 |
AzureAdMdmUrl | IntuneのURL |
AzureAdSettingsUrl | IntuneのURL |
DomainJoined | オンプレADドメインに参加しているかどうか |
DomainName | オンプレADドメイン名 |
User State | NgcSet | NGCがプロビジョニングされているかどうか |
NgcKeyId | NGCのキーID |
WorkplaceJoined | ワークプレイスジョインしているかどうか |
WamDefaultSet | WebSSOに関する状態 |
WamDefaultAuthority | デフォルトで利用されるWebSSOのオーソリティ |
WamDefalutId | デフォルトで利用されるWebSSOのID |
WamDefalutGUID | デフォルトで利用されるWebSSOのGUID |
特徴的なのは、Workplace Joinはあくまでユーザ単位なので、User State側に分類されているところでしょうか。
例えば、オンプレミスADへドメイン参加した状態でデバイス情報をAzure ADへ同期するとAzureAdJoinedおよびDomainJoinedの両方がYesになります。
参考)Build 14332系でのdsregcmd /statusの結果
Device StateにEnterpriseJoinedという謎の項目が増えていたり、DRS関係の情報が出てきます。
User Stateこちらはあんまり変わりません。
5.TPMをクリアする
これは、TPMが搭載されているマシンを使っている場合に限りますが、キーペアがTPM上に保存される以上、Azure AD DRS上に登録された公開鍵とTPMコンテナ内の秘密鍵の紐づけがおかしくなってしまったらTPMをクリアするのも一つの手になるかも知れません。(根拠はありません。そういう事態に陥ったことはないので)
とりあえず手順だけを書いておくと、ファイル名を指定して実行(Windowsキー+R)で「tpm.msc」を実行してTPMのクリアを選択して実行するだけです。
再起動が要求されます。
ここで再起動すると起動画面でTPMのクリアが行われます。(手順はデバイスによって異なります)
ちなみにAcerのPCではボリュームUPボタンを押すとクリアされました。
注)ここでTPMをクリアすると当然のことながらマイクロソフトアカウントやローカルアカウントでのログイン時のPINがすべて使えなくなります。パスワードがわからないとPCへログインすらできなくなりますので、慎重に実施する必要があります。同じく、EFSやBitLockerなどに関しても要注意です。
まぁ、色々と書きましたが、トラブルシュートの基本は状態の把握だと思うので、イベントログや通信のキャプチャなどは覚えておいて損はないですね。
おまけ)
ちなみにPIN設定をキャンセルしようとすると以下の画面が出て、頑張って設定させようとしてきます。一旦キャプチャしたいのでスキップしたかったんですけどね。。こういう場合はあえてエラー状態を作っておくと先に進めます。(メッセージの焦った感じがウケます)