こんにちは、富士榮です。
前回も書きましたが今年の11月でAzure Access Control Service(ACS)のサービス提供が終了します。
Azure ACSを自前サービス用に使っているようなB2B/B2C向けサービスを提供している企業の方はある程度切り替えは終わっているとは思いますが、意外と見落としがちなのがオンプレミスでSharePointを構築して使っている企業の方々です。
現状、SharePointサーバは最新バージョンであるSharePoint Server 2016でさえClaimベース認証を構成しようとするとプロトコルとしてws-federation、トークンはSAML
1.1しかサポートしていません。
この制限により、SAML2.0トークンしかサポートしていないAzure ADとSharePoint Serverの間で直接のフェデレーションを構成することが出来ませんでした。
このことを解決するために、これまではAD FSやAzure ACSなど割と柔軟にws-federationの構成が出来る製品やサービスを間に噛ませてシングルサインオンを実現していました
こんな構成です。
が、いよいよAzure ACSのサービス提供が終了、ということでそろそろ対策を行わないと手遅れになってしまいます。
となると、引き続きAD FSを使う、というのも一つの手段ではありますが、今更オンプレミスにサーバを配置して管理するのも面倒なので、出来ることならSharePointとAzure ADを直接接続しておきたいところです。
と、言うことで今回はAzure ADにSAML1.1のトークンを発行させることでSharePoint Serverと直接接続するための方法を解説します。
尚、この手法は特に裏技というわけではなく、オフィシャルに(ひっそりと)公開されている手順です。
Using Azure AD for SharePoint Server Authentication
https://docs.microsoft.com/en-us/Office365/Enterprise/using-azure-ad-for-sharepoint-server-authentication
簡単に言うと、Azure ADのトークン発行ポリシーをカスタマイズしてSAML1.1のトークンを発行させることによって、SharePoint Serverが解釈できるようにしてやろう、という作戦です。
以下の順に構成を行います。
- Azure ADのエンタープライズ・アプリケーションにSharePoint Server接続用のアプリケーションを登録する
- SharePointのEntityID、Reply URLを登録する
- トークン署名用の証明書を生成し、公開鍵をダウンロードする
- ユーザの割り当てを行う
- 作成したAzure AD上のアプリケーション(ServicePrincipal)にリンクされたトークン発行ポリシーを変更する
- SAML1.1トークンを発行するカスタム・ポリシーを作成する
- 元々ServicePrincipalにリンクされているSAML2.0トークン発行のポリシーとのリンクを解除する
- 新規作成したカスタム・ポリシーをServicePrincipalにリンクする
- SharePoint Serverの信頼済みアイデンティティ・トークン発行者としてAzure ADを構成する
- Azure ADからダウンロードした公開鍵を登録する
- クレームマッピング、識別用属性を指定し、アイデンティティ・トークン発行者登録を行う
- SharePoint Serverのユーザ・ポリシーを構成する
- サイトへのAzure AD上のユーザへのアクセス権限を設定する
◆まずはありのままを
はじめる前に、まずは何もしない素の状態のAzure ADのws-federationでSharePoint Serverと接続するとどうなるのか?について確認しておきたいと思います。
要はSAML2.0のトークンをSharePoint Serverが受け取ったらどういう挙動をするか?の確認です。
(上記の手順のトークン発行ポリシーの変更をしないとどうなるか?という話しです)
結果、ID4014エラーが出てSAML2.0はサポートされていない、と言って怒られます。
※エラー内容がわかりやすくなるように、web.configのcustomErrors modeをoffに設定しています。
では早速。
◆Azure ADのエンタープライズ・アプリケーションにSharePoint Serverを登録する
当然ギャラリーには無いアプリケーションなので、「ギャラリー以外のアプリケーション」を選択してアプリケーションを登録していきます。
つまり、この段階ではプロトコルもトークンもSAML2.0のアプリケーションとして登録します。
アプリケーションの作成が終わったら、シングルサインオン設定を行います。
必要な設定はSharePoint ServerのEntityIDとサインオンURLです。
- EntityID
- 任意の文字列(後でSharePoint Server側に登録するRealmの文字列と同一の文字列) ※通常は「urn:sharepoint:{サーバ名}」とか「http://{サーバ名}」を使うことが多いです。
- サインインURL
- https://{SharePointサーバ名}/_trust/default.aspx ※httpsが必要なので、先にSharePointのSSL化は済ませておくこと
こんな感じです。
次に、トークン署名用の証明書をダウンロードしておきます。
また、他にも後でAzure ADのサインインURLと作成したアプリケーションのオブジェクトIDが必要になるのでメモしておきましょう。
SSO URLはシングルサインオンの構成のページに表示されているものを使います。(実際はSAMLではなくws-federationを使うので、URLのパスはwsfedに変更する必要があります)
オブジェクトIDはプロパティのページにあります。
アプリケーションIDと間違えやすいの注意です。オブジェクトIDの方を使います。
また、同じページにユーザの割り当ての設定もあるので、Azure AD上のユーザでSharePointを利用するユーザの限定が必要なければ「割り当てが必要ですか?」は「いいえ」を設定しておきます。
◆SAML1.1トークン発行用のカスタム・ポリシーの作成とリンクを行う
この作業が一番のキモです。
PowerShellを使って構成することも可能ですが、結局はInvoke-RestMethodでGraph APIを叩いているだけなので、Azure AD Graph Explorer(
https://graphexplorer.azurewebsites.net/)で直接実行した方が手っ取り早いと思います。(トラブルを避けるために、先のエンタープライズ・アプリケーションの登録に使ったグローバル管理者権限を持った組織アカウントでログインしてください。マイクロソフトアカウントは不可です)
実行するのは、以下のAPIです。
- メソッド:GET
- リソース:https://graph.windows.net/myorganization/servicePrincipals/{先ほどメモしたエンタープライズ・アプリケーションのオブジェクトID}/policies
これで、現在アプリケーションにリンクされているトークン発行ポリシー(SAML2.0のトークンを発行するポリシー)のIDが取得できます。同時に複数のトークン発行ポリシーを一つのServicePrincipalにリンクすることは出来ないので、このポリシーとのリンクは削除してしまいます。(ポリシーそのものは他のアプリケーションで使っているので削除しない様に気を付けてください)
- ポリシーとのリンクを削除する
- メソッド:DELETE
- リソース:https://graph.windows.net/myorganization/servicePrincipals/{先ほどメモしたエンタープライズ・アプリケーションのオブジェクトID}/$links/policies/{直前の手順で取得したリンクしているポリシーのオブジェクトID}
ちなみに、Graph Explorerを使うとDELETEなどHTTP 204 no contentsが返ってくるようなクエリはいつまでたっても結果が表示されずにプログレスバーがじりじりと動くだけですが、ちゃんと処理は実行されているので、遠慮なく止めてしまってOKです。
再度、リンクされているポリシーを確認するとnullが返ってくるのでトークン発行ポリシーとのリンクが解除されたことがわかります。
次は、いよいよカスタムポリシーを作成します。
- SAML1.1トークン発行ポリシーを作成する
- メソッド:POST
- リソース:https://graph.windows.net/myorganization/policies/
- ボディ:{"displayName":"SPSAML11","type":"TokenIssuancePolicy","definition":["{\"TokenIssuancePolicy\":{\"TokenResponseSigningPolicy\":\"TokenOnly\",\"SamlTokenVersion\":\"1.1\",\"SigningAlgorithm\":\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\",\"Version\":1}}"]}
作成が完了したら、作成したポリシーのオブジェクトIDを確認しておきます。
- 作成したポリシーを確認する
- メソッド:GET
- リソース:https://graph.windows.net/myorganization/policies
ここで先ほど作ったカスタム・ポリシーのオブジェクトIDを取得しておき、エンタープライズ・アプリケーションとリンクします。
- ポリシーのリンクを作成する
- メソッド:POST
- リソース:https://graph.windows.net/myorganization/servicePrincipals/{先ほど作成したエンタープライズ・アプリケーションのオブジェクトID}/$links/policies
- ボディ:{"url":"https://graph.windows.net/myorganization/policies/{作成したカスタム・ポリシーのオブジェクトID}?api-version=1.6"}
このクエリも返事がない(no contents)のでポリシーのリンク状態を確認しておきます。
- ポリシーのリンク状態を確認する
- メソッド:GET
- リソース:https://graph.windows.net/myorganization/servicePrincipals/{先ほど作成したエンタープライズ・アプリケーションのオブジェクトID}/policies
これでAzure AD側の準備は完了です。
◆SharePoint Serverに信頼済みアイデンティティ・トークン発行者を登録する
先ほどAzure AD上に登録したSharePoint ServerのEntityID、Azure ADのサインオンURL、ダウンロードした証明書を用意しておき、SharePoint管理シェル(PowerShell)を管理者権限で起動、以下のコマンドを実行します。
- $realm : SharePoint ServerのEntityIDとしてAzure AD上に設定した文字列
- $wsfedurl : Azure ADのサインオンURL。最後のsaml2をwsfedに変更する
- $filepath : ダウンロードした証明書ファイルのパス
$realm = "urn:sharepoint:xxxx"
$wsfedurl="https://login.microsoftonline.com/{tenantid}/wsfed"
$filepath="C:\users\Administrator\desktop\sharepoint.cer"
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($filepath)
New-SPTrustedRootAuthority -Name "AzureAD" -Certificate $cert
$map = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" -IncomingClaimTypeDisplayName "name" -LocalClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"
$map2 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" -IncomingClaimTypeDisplayName "GivenName" -SameAsIncoming
$map3 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" -IncomingClaimTypeDisplayName "SurName" -SameAsIncoming
$ap = New-SPTrustedIdentityTokenIssuer -Name "AzureAD" -Description "SharePoint secured by Azure AD" -realm $realm -ImportTrustCertificate $cert -ClaimsMappings $map,$map2,$map3 -SignInUrl $wsfedurl -IdentifierClaim "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
これで信頼済みのアイデンティティ・トークン発行者の登録が完了しますので、SharePoint Serverの管理ページのWebアプリケーションの管理で認証プロバイダとして設定を行います。
対象のWebアプリケーションを選択して認証プロバイダの設定を開き、信頼済みアイデンティティ・トークン発行者の設定で先ほど作成したAzure ADを選択します。
これで、SharePoint ServerのSSO設定も完了です。
いよいよ最後です。
◆ユーザーポリシー(ユーザへの権限付与)を構成する
最後に信頼済みアイデンティティ・トークン発行者からわたってくるユーザがサイトへアクセスできるように権限を付与します。
この手順が抜けると認証は出来ても認可がされないのでログインすることが出来ません。
対象のWebアプリケーションを選択してユーザ・ポリシーを開きます。
ユーザの追加より、ピープル・ピッカーを開き、Azure ADのname(今回は識別子をname属性にしているので)を選択した状態で画面上部の検索窓にAzure AD上のユーザ名を入れて検索ボタンをクリックし、出てくるユーザを追加します。
これで全ての設定が完了です。
早速サイトへアクセスするとAzure ADへリダイレクトされ、認証が終わるとコンテンツが表示されるはずです。
SAML Tracerでトレースをしてみると、ちゃんとトークンのバージョンがSAML1.1になっていることがわかります。
<t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:Lifetime>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2018-08-12T13:00:58.881Z</wsu:Created>
<wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2018-08-12T14:00:58.881Z</wsu:Expires>
</t:Lifetime>
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address>urn:sharepoint:xxxxx</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<t:RequestedSecurityToken>
<saml:Assertion MajorVersion="1"
MinorVersion="1"
AssertionID="_d9aa279a-50f5-4f42-a553-ea45faa33ce4"
Issuer="https://sts.windows.net/{tenant id}/"
IssueInstant="2018-08-12T13:05:58.881Z"
xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"
>
いかがでしょうか?まだACSを使っている人は早めにAzure ADと直接フェデレーションする様に構成を変更しておきましょう。