2015年2月7日土曜日

[Office365/ADFS/AAD]クラウドIDのアクセス制御にAD FSを利用する

タイトルだけを見ると一体何をしようとしているのか良くわからないと思いますが、Office365フォーラムに質問が上がっていたので、こんなケースもあるかも知れないなぁ、ということで動きを検証してみました。


◆実現したい環境の概要
・Office365をクラウドID(Azure Active Directory上のユーザ)で使いたい
 ※ローカルのActive Directoryユーザを使いたくない
・Azure Active DirectoryだとクライアントIPやブラウザ種別などでアクセス制御が出来ないのでActive Directory Federation Services(AD FS)のクレームルールでの制御を行いたい

いざ実現しようとすると色々と課題があります。



そこで、Office365(AzureAD)⇒AD FS(アクセス制御用)⇒AzureAD(認証用)というフェデレーションの連鎖をさせて実現できるか確認してみます。

こんな環境です。


かなりややこしい構成です。



◆結果は、、、、曲がりなりにも動いた!
まずは結論から。
「一応」動きました。。。。が、ユーザビリティに少々難ありかと。(ある程度工夫で何とかなりますが)

フローを追って確認してみます。
①Office365にアクセスする
 まずはOffice365にアクセスします。https://portal.office.comへブラウザでアクセスし、ログイン画面を表示させます。



②AD FSのドメイン名のユーザ(ダミー)をログインIDに入れる
 Office365(AzureAD)のレルム・ディスカバリ機能でAD FSへリダイレクトされます。



③AD FSのレルム選択画面でAzureADを選択する
 あらかじめAD FSに外部IdPを設定してあるとローカルのAD DSで認証するか、外部IdP(今回はAzureAD)で認証するかを選択できます。ここでAzureADを選択すると再度AzureADのログイン画面へ遷移します。


 ※ちなみにAzureADからAD FSへの遷移はajaxで制御されています。通常フローだとAzureADのログイン画面に入れたユーザ名がそのままAD FSに引き継がれるので便利なのですが、AD FSのログイン画面で別のユーザ名(AzureADのonmicrosoft.comユーザ)を入れる必要があるので、アドレスバーに表示されるURLのGETパラメータのusername=xxxという部分を手動で消してあげる必要があります。この部分の省力化方法は後で紹介します。


④AzureADユーザ(onmicrosoft.comユーザ)で認証する
 今度はAD FSにリダイレクトするためのダミーユーザではなく、AzureAD上の実ユーザでログインするため、ユーザ名にonmicrosoft.comドメインのユーザ名を入力します。するとAzureAD上の自分のテナントの認証画面へ遷移します。



⑤ログインする
 自分のテナントのログイン画面に遷移したらクラウドIDでログインします。



⑥AzureAD⇒AD FS⇒Office365(のIdPであるAzureAD)へ戻る
 認証が終わるとAzureADでAssertionが発行され、AD FSへ戻されます。次にAD FSはAzureADから受け取ったAssertionをOffice365(のIdPであるAzureAD)向けのAssertionに変換・発行し直してAzureADへ戻し、AzureADでの認証プロセスが完了します。
 この時、Office365のIdPとしてのAzureADはAD FSのユーザで認証されますが、前段階ですでにクラウドID(onmicrosoft.comユーザ)でログオンしていますので、すでに認証済みとして扱われ、改めてログインし直すか聞かれます。ここでログインし直す選択をするとログアウトからやり直すので、永遠に2重ログイン状態を繰り返してしまいますので、AD FSユーザでのログインはあくまでアクセス制御のためと割り切って、クラウドIDでのログイン継続を選択します。



⑦Office365へのログイン
 ライセンスを付与していないので画面ショットは単なるプロファイル表示画面になっていますが、無事にOffice365へアクセスできます。




これで一連の流れは完了です。
ここまで出来れば、AD FSの部分でアクセス制御ルールを設定してあげればOKです。上記フローの⑥の部分でアクセス制御が挟まるので、アクセス拒否されるとこんな画面が出てきます。




◆どうやって実現するか?
まずは環境設定です。
AzureAD、AD FSそれぞれに下記の設定を行います。

対象設定箇所設定内容設定方法
AzureADアプリケーション設定Office365を登録Office365の設定を行えば自動的に設定される
AD FSを登録ws-federationで連携するWebアプリケーションとして登録する
ドメイン設定AD FSとID連携するドメインを設定Office365のPowerShellで設定する
ユーザ設定ダミーユーザ(AD FS連携用ユーザ)PowerShellなどで登録する
実ユーザ(ログインするユーザ)PowerShellなどで登録する
AD FSRP設定Office365(AzureAD)を登録Office365のPowerShellで設定する
IdP設定AzureADを登録AzureADのFederationMetadataを使って登録する



順番に設定内容を見ていきます。
・AzureAD/アプリケーション設定
 Office365は自動的に登録されるので、AD FSを登録します。
 AzureADのアプリケーション設定で「組織で開発中のアプリケーションを追加」します。


 アプリケーションの種類は「WEBアプリケーションやWEB API」を選択します。


 以下の通りサインオンURLとアプリケーションID/URIを設定します。
 ・サインオンURL:AD FSのPassiveログインURL
 ・アプリケーションID/URI:AD FSのサービスID



・AzureAD/ドメイン設定
 こちらは通常のOffice365でAD FSとID連携用ドメインを設定する手順で設定を行います。

・AzureAD/ユーザ設定
 ・ダミーユーザ(AD FS連携用ユーザ)
  このユーザは実際にOffice365を利用するためのユーザではないので適当に作成すればOKです。
  作成した後、Get-MsolUserコマンドレットなどでImmutableIdおよびUserPrincipalNameの値を確認、メモしておきます。実際にログインに使うAzureAD上のユーザのSAML Assertionの中にこのダミーユーザのImmutableIdとUserPrincipalNameの値が必要となるためです。

 ・実ユーザ(ログインするユーザ。onmicrosoft.comユーザ)
  このユーザで実際にOffice365を使います。先にも書いたように、AzureADでこのユーザを認証した後、AD FSにSAML Assertionを渡すのですが、AD FSでこのユーザの属性(クレーム)と先に作成したダミーユーザのImmutableIdとUserPrincipalNameを一致させることで紐づけ(Federation)をさせます。
  そのため、このユーザの属性にダミーユーザのImmutableIdとUserPrincipalNameを設定します。
  今回は名にImmutableId、姓にUserPrincipalNameを設定しました。(この属性がOffice365のプロファイルに表示されてしまうので、本来はスキーマを拡張して利用者に見えない属性を使った方が良いと思います)



  また、このユーザでAzureAD上に登録してあるアプリケーションとしてのAD FSへアクセスするために、先に登録したAD FS(アプリケーション)へのアクセス権を割り当てます。



・AD FS/RP設定
 Office365とのID連携設定をすると自動的にRPとして「Microsoft Office 365 Identity Platform」が登録されるので、こちらのクレームルールを変更します。
 もともとあるのはActive Directoryから属性をとってきてNameID、ImmutableId、UserPrincipalNameを発行するルールなので、潔くすべて削除します。
 そして、以下の3つのルールを設定します。


 ・NameID発行(AzureADのユーザの名に入っているImmutableIdの値を発行)

c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"]
 => issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Issuer = c.Issuer, Value = c.Value, ValueType = c.ValueType, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");

 ・UserPrincipalName発行(AzureADのユーザの姓に入っているUserPrincipalNameの値を発行)

c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"]
 => issue(Type = "http://schemas.xmlsoap.org/claims/UPN", Issuer = c.Issuer, Value = c.Value, ValueType = c.ValueType);

 ・ImmutableId発行(AzureADのユーザの名に入っているImmutableIdの値を発行)

c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"]
 => issue(Type = "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID", Issuer = c.Issuer, Value = c.Value, ValueType = c.ValueType);

 アクセス制御をする場合はここで設定をしておきます。


・AD FS/IdP設定
 次にAD FSのIdPとしてAzureADを登録します。
 AzureADがFederationMetadataを公開しているので、URIを設定するだけで簡単に設定できます。
 設定するURIは「https://login.windows.net/[テナントID]/federationmetadata/2007-06/federationmetadata.xml」です。AzureADのアプリケーション設定のページでエンドポイントは確認できます。


 次に、AzureADから取得した属性(クレーム)を受け取る設定です。特に何も考えずにすべての属性をパススルーします。


 こんなルールです。

c:[]
 => issue(claim = c);



これですべての設定が完了しました。
先のフロー通りに動きます。


◆ちょっとした工夫
画面遷移を紹介しましたが、何度もレルムを選択したりするのは、かなり不便です。
そこで、最初のOffice365⇒AD FSへのレルム選択を自動化するために以下のURLをユーザにBookmarkしてもらうといきなりAD FSのログイン画面にたどり着きますので、かなり画面遷移がすっきりします。先の画面遷移の③からいきなり始まりますので、username=xxxをアドレスバーから手動で消す必要もなくなります。

 ブックマークするURL
  https://login.microsoftonline.com/login.srf?wa=wsignin1.0&wreply=https:%2F%2Fportal.office.com%2F&whr=example.net

◆Assertionの中身
細かい話ですが、ログインまでの間で以下のようなAssertionが飛んでおり、各ポイントで必要に応じて処理をします。
・AzureAD(実ユーザでログイン)⇒AD FS
<Subject>
   <NameID+Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">ixxxxxxxxxxxxxxxxx0ZM</NameID>
   <SubjectConfirmation+Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"+/>
</Subject>

<AttributeStatement>
   <Attribute+Name="http://schemas.microsoft.com/identity/claims/tenantid">
      <AttributeValue>2cxxxxxxxxxxxxxxxxxxxxxbfff</AttributeValue>
   </Attribute>
   <Attribute+Name="http://schemas.microsoft.com/identity/claims/objectidentifier">
      <AttributeValue>baxxxxxxxxxxxxxxxxxxxba2ac2</AttributeValue>
   </Attribute>
   <Attribute+Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">
      <AttributeValue>nobunagao@xxxx.onmicrosoft.com</AttributeValue>
   </Attribute>
   <Attribute+Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname">
      <AttributeValue>nobunagao@example.net</AttributeValue>
   </Attribute>
   <Attribute+Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
      <AttributeValue>QDibxxxxxxxxxfIENg==</AttributeValue>
   </Attribute>
   <Attribute+Name="http://schemas.microsoft.com/identity/claims/displayname">
      <AttributeValue>ADFS/AADテスト</AttributeValue>
   </Attribute>
   <Attribute+Name="http://schemas.microsoft.com/identity/claims/identityprovider">
      <AttributeValue>https://sts.windows.net/2c6xxxxxxxxx1bfff/</AttributeValue>
   </Attribute>
</AttributeStatement>



・AD FS⇒AzureAD(ダミーユーザ情報)
 クレーム変換ルールでImmutableId、UPNに必要な値が代入されています。
<saml:AttributeStatement>
   <saml:Subject>
      <saml:NameIdentifier+Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">QDxxxxxxNg==</saml:NameIdentifier>
      <saml:SubjectConfirmation>
         <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod>
      </saml:SubjectConfirmation>
   </saml:Subject>
   <saml:Attribute+AttributeName="UPN"+AttributeNamespace="http://schemas.xmlsoap.org/claims">
      <saml:AttributeValue>nobunagao@example.net</saml:AttributeValue>
   </saml:Attribute>
   <saml:Attribute+AttributeName="ImmutableID"+AttributeNamespace="http://schemas.microsoft.com/LiveID/Federation/2008/05">
      <saml:AttributeValue>QDxxxxxxNg==</saml:AttributeValue>
   </saml:Attribute>
</saml:AttributeStatement>





いかがでしょうか?
色々とトリッキーなことをしているので、実用性は?ですがクラウドIDを使う場合にアクセス制御をしたい、という要件はあると思います。
今後はAzureAD側でのアクセス制御が実装されてくる日が来るかも知れませんね。

0 件のコメント: