ADFSアクセス制御でのOR条件

Office365のアクセス制御を行なうクレームルールですが、サンプルで記載されているルールを参考に実装をしていくと、少し記載が難しいルールがあることに気がつきます。

それは、ルールの中に「OR条件」を入れられないことです。

例えば、許可する条件が

  • ADFS Proxy経由ではない
  • Active Syncプロトコルによるアクセス
  • Exchange Onlineに接続するグローバルIPが①

を記載する場合、サンプルでは

  • 全てのユーザーを許可
  • 「Proxy経由のアクセス」かつ「プロトコルがActiveSync以外」かつ「Exchange Onlineへの接続元が①以外」のアクセスを拒否

という記述方法を取っています。

ここで、企業内で拠点ごとにインターネットを利用している場合など、IPアドレスの接続元が複数あることはよくあることです。

また、POP/IMAPのプロトコルをアクセス制御する場合、特定条件のユーザにおいて、IPアドレスの送信元がユーザのIP帯ではなくExchange OnlineのIP帯になってくるので、そちらも許可しないといけないという仕様もございます(当該ユーザのCAS/MBX収容のDCロケーションが分かれてしまった場合に発生するらしいです)。

この場合、上記例でいう許可したいIPが追加されて、「①」から「①または②」に変更しようとして

  • 全てのユーザーを許可
  • 「Proxy経由のアクセス」かつ「プロトコルがActiveSync以外」かつ「Exchange Onlineへの接続元が①または②以外を拒否」

という正規表現内でOR条件を記載した場合、エラーが出てしまい記述できません。

また、例えば許可ルールが

  • 社内からは許可
  • ActiveSyncの外部アクセスはActiveSync_External_Accessグループのメンバのみ許可
  • Outlookの外部アクセスはMAPI_External_Accessグループのメンバのみ許可

を記載しようとした場合、

  • 全てのユーザーを許可
  • 「ActiveSync」かつ「ActiveSync_External_Accessグループ以外のアクセス」または「プロトコルがMAPI」かつ「MAPI_External_Accessグループ以外のアクセス」は拒否

などを記載できれば良いのですが、「&&」は記載できますが「||」という条件のOR記述はできません。

ということで、こういった場合は最初の全許可のルールを削除して、複数個の許可ルールを記載することにより対応できます。今回は、例として以下のサンプルをADFSに登録してみたいと思います。

  1. イントラネットからのADFS Proxyを利用しないアクセスは許可
  2. ActiveSyncは許可
  3. xxx.xxx.xxx.xxxまたはyyy.yyy.yyy.yyyのIPからのアクセスは許可
  4. MAPI_External_Accessグループの外部からのOutlookアクセスは許可
  5. それ以外のアクセスは拒否

承認する為の条件はpermitのクレームが発行され、かつdenyのクレームが発行されていないということになります。また、permitのクレームが複数発行されても動作上は問題ありませんので、デフォルトのルール(全てのユーザーを許可)を削除し、新しく個別に特定条件下にのみpermitのクレームを発行するルールを作成してみることにします。

まず、4)の準備として既存のクレームルールをバックアップしておきます。また、セキュリティグループの制御用に渡されてくる情報はグループ名ではなくSIDなので、そちらも事前に調べておきます。

【ADFSサーバ:PowerShellから実行】

Add-PSSnapin Microsoft.Adfs.PowerShell
(Get-ADFSRelyingPartyTrust -Name "Microsoft Office 365 Identity Platform").IssuanceAuthorizationRules > c:\adfs_claim.bak

【ドメインコントローラ:Windows PowerShell用のActive Directoryモジュールから実行】

(Get-ADGroup "MAPI_External_Access").SID.Value

-> S1-2-34-1234567890-1234567890-1234567890-123 であったと仮定します。

そして、ADFSサーバで、PowerShellで以下のコマンドを実行して

$NewRule = @"
@RuleName = "1) accept Internal access to Office365"
NOT exists([Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy"])
 => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");

@RuleName = "2) accept Exchange ActiveSync access to Office365"
exists([Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application", Value == "Microsoft.Exchange.ActiveSync"])
 => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");

@RuleName = "3) accept customer specified IP address to Office365 #1"
exists([Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip", Value =~ "xxx\.xxx\.xxx\.xxx"])
 => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");

@RuleName = "3) accept customer specified IP address to Office365 #2"
exists([Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip", Value =~ "yyy\.yyy\.yyy\.yyy"])
 => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");

@RuleName = "4) accept customer specified member to Office365 by MAPI#1"
exists([Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value =~ "S-1-2-34-1234567890-1234567890-1234567890-1234"])
&& exists([Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application", Value == "Microsoft.Exchange.Autodiscover"])
 => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");

@RuleName = "4) accept customer specified member to Office365 by MAPI#2"
exists([Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value =~ "S-1-2-34-1234567890-1234567890-1234567890-1234"])
&& exists([Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application", Value == "Microsoft.Exchange.OfflineAddressBook"])
 => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");

@RuleName = "4) accept customer specified member to Office365 by MAPI#3"
exists([Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value =~ "S-1-2-34-1234567890-1234567890-1234567890-1234"])
&& exists([Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application", Value == "Microsoft.Exchange.RPC"])
 => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");

@RuleName = "4) accept customer specified member to Office365 by MAPI#4"
exists([Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value =~ "S-1-2-34-1234567890-1234567890-1234567890-1234"])
&& exists([Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application", Value == "Microsoft.Exchange.WebServices"])
 => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");
"@

Set-ADFSRelyingPartyTrust -TargetName "Microsoft Office 365 Identity Platform" -IssuanceAuthorizationRules $NewRule

※Rule3 IPアドレスのマッチングは==ではなく、=~で記載します。(同じIPアドレスが複数個渡されてくる場合がある。)
※Rule4 OutlookはMAPI(=RPC)だけではなく、4種類のプロトコルで動作するため、全て記載する必要があります。

また、前提条件の解釈によりますが、本ルールで許容されない通信があります。それは、ホワイトリストのIP帯からのWebによるアクセスになります。これは、例えば「物理的にyyy.yyy.yyy.yyyが別AD組織である場合」「クライアントPCのDNSが外部DNSを参照している場合」などで、ADFS Proxyに対してPassiveフェデレーションを行なう場合に発生します。

この際、ADFS ProxyからADFSサーバにx-ms-proxyの属性は付与されますが、x-ms-forwarded-client-ipの値は渡されてきません。(同値は、あくまでExchange Onlineから折り返してアクセスする際の元のIPアドレスなので) このため、もしこのアクセス制御を実装しようとすると、クレームルールだけでは実装できず、IISのIP制限を組み合わせて実装する必要があります。

  1. ADFS ProxyサーバのIISで、指定IP以外は拒否するIP制限を実装。この際、Exchange OnlineのIP帯を許可リストに加えることを忘れないこと。
  2. ADFSサーバでADFS Proxy経由のWebアクセスを許容するクレームルール作成
@RuleName = "accept Web access to Office365"
exists([Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-endpoint-absolute-path"])
=> issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");

色々あって面倒かもしれませんが、アクセス必要なパターン数はそれほど多くないと思いますので、検証しながら進めていこうかなと思ってます。

「ADFSでこんなアクセス制御はできる?」とかリクエストがあったらコメント頂ければ頑張ってみます。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中