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に登録してみたいと思います。
- イントラネットからのADFS Proxyを利用しないアクセスは許可
- ActiveSyncは許可
- xxx.xxx.xxx.xxxまたはyyy.yyy.yyy.yyyのIPからのアクセスは許可
- MAPI_External_Accessグループの外部からのOutlookアクセスは許可
- それ以外のアクセスは拒否
|
承認する為の条件は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制限を組み合わせて実装する必要があります。
- ADFS ProxyサーバのIISで、指定IP以外は拒否するIP制限を実装。この際、Exchange OnlineのIP帯を許可リストに加えることを忘れないこと。
- 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でこんなアクセス制御はできる?」とかリクエストがあったらコメント頂ければ頑張ってみます。