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でこんなアクセス制御はできる?」とかリクエストがあったらコメント頂ければ頑張ってみます。

5 thoughts on “ADFSアクセス制御でのOR条件

  1. ADFS,ADFS Proxyの構成でWindowsドメインクライアントにはDesktopSSOにてOffice365へ透過的にログイン、Windowsドメインクライアント以外はForm認証を行いたいのですが、どのようにすればいいのかがわかりません。
    ご教示いただけますでしょうか?

    • 通常の設定ですと、全員SSOを試みる(Windowsドメインクライアント以外はID/PASSを求められるポップアップが出る)もしくは全員Form入力になってしまいますね…。
      少しトリッキーですが、ドメインに所属するクライアントとそれ以外でADFSのサービス名(例:sts.contoso.com)が異なるIPに解決されるようにNWを設計されては如何でしょうか? WindowsドメインクライアントはADFSに、それ以外はADFS Proxyに解決されるようにすれば構成できるのではないかと思います。

  2. ためになるページでいつも助かっています。最近ADFSをいじっているのですが、クレームルールを書く上で認証がどうされているかを調べています。”4種類のプロトコルで動作するため”という部分を確認したいのですが、これらイベントログから確認することは可能でしょうか?実際には書かないでも動作しているように見えたので・・・。

  3. Android/iOS/WinPC/MacPCといった会社支給ではないBYOD端末で、SFDC/BOX/O365/WebexといったCloudサービスへのアクセスを許可されたデバイス(ユーザ)だけにアクセスさせるといった社内のオンプレサ―ビスではないアクセス制限をADFSでどこまで制御可能でしょうか。
     ・会社支給端末(PC・スマホ):社内外とわずCloudサービスにアクセス可
     ・BYOD端末(PC/スマホ):許可されたユーザのデバイスのみCloudサービスにアクセス可
    といったユーザ毎および所有端末種類ごとにアクセス制御はかけられますでしょうか。

  4. こんにちは。
    いつも貴重な情報の提供いただき、ありがとうございます。
    ADFSのクレームルールについて、お聞きしたい点がございます。

    ・要求元のIPアドレスの制限(会社で利用しているグローバルIPのレンジ以外拒否)
    ・iPhoneインストールされたyammer,skype,onedriveの社外からアクセス許可

    iPhoneだけは社外からのアクセスを許可して、それ以外(PC)は要求元のIPからの通信を行わせる、の両方を実現するようなクレームルールを書くことは可能なのでしょうか。

    ご教示いただけますと幸いです。
    どうぞ宜しくお願い致します。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です