ADFSトレーニングテキスト全文公開チャレンジ(14) – クレームルール言語の原則

皆さんこんにちは。国井です。
ADFSトレーニングテキスト全文公開チャレンジの14回目はクレームルール言語のルールについて解説します。

■ ■ ■

スライド96

クレームルール言語は、クレームを発行するための条件を記す条件部分と、発行するクレームに関する情報 (発行内容や発行方法など) を記す発行部分から構成されています。2 つの構成要素は => の記号で結ばれており、=> の手前に条件部分、=> の後ろに発行部分をそれぞれ記述します。
条件部分または発行部分には次の基本構文を利用することができます。

■条件部分の基本構文:Exists([A])
条件部分で、「A が存在する場合」という条件指定をするときは、Exists([A]) と指定します。Exists は省略可能な構文で、省略するときは [A] と記述します。

■条件部分の基本構文:Not Exists([A])
条件部分で、「A が存在しない場合」という条件指定をするときは、Not Exists([A]) と指定します。

■条件部分の基本構文:c:[A]
条件部分で A で扱った内容を変数にセットし、発行部分で活用したい場合には、c:[A] と指定します。たとえば、パススルーするときには c:[A] => issue(claim.c); のように記述することで、A の内容がそのままクレームとして発行されます。(発行部分の記述方法については後述します)

■条件部分の基本構文:Count[A]>=B
条件部分で扱うクレーム (A) に含まれる値の個数 (B) を数えて条件とする場合には、Count[A]>=B と指定します。たとえば、メールアドレスが複数ある場合を指定するときには、Count[“http://xxxx/mail”]>=2 のように指定します。また、等号、不等号は自由に組み合わせて利用することができるのでメールアドレスが 1 つしかない場合を指定するときには Count[“http://xxxx/mail”]<2 と指定することも可能です。

■条件部分の基本構文:&&
条件部分で複数の条件を指定するときは && を使います。A と B の条件を満たす場合という指定をするときは Exists([A]) && Exists([B]) と記述することができます。複数の条件を組み合わせる構文には AND 条件を示す && だけが利用可能で、OR 条件を指定することはできません。そのため、OR 条件を指定するときはルールセット内のルール自体を複数にして対応します。

■発行部分の基本構文:Issue(A) / Add(A)
発行部分で特定の情報をクレームにセットするときは Issue(A) または Add(A) を指定します。Issue(A) は Output Claim Set への発行、Add(A) Input Claim Set への発行を意味します。(詳細は後のページで解説します)


スライド97

クレームルール言語を使ってカスタムルールを直接記述する場合、前のページで解説した基本構文を使用し、構文内で具体的な条件または発行する情報を記述します。ここでは、具体的な例を基に構文内の記述方法を確認します。

■条件部分
Exists([ ]) の基本構文を使用しているので、クレームへの有無をチェックしています。チェックするクレームは Type と Value を使って指定します。Type はクレームの種類 (要求の種類) を表しており、ADFS 管理ツールの [要求記述] で指定されている要求の種類 (URL 形式で指定されている情報) を指定します。一方、Value は値を表します。ここでの例では、title クレーム (要求の種類名 http://schemas.example.com/claims/title) の値が部長の場合、という条件指定になります。
また、条件部分でイコールを記述するときは == のようにイコールを 2 つ重ねて記述します。

■発行部分
=> の後は Issue で始まっているので Output Claim Set へのクレーム発行を表します。発行するクレームの種類 (要求の種類) と値には、条件部分と同じく Type と Value を使います。そのため、今回の例では role クレーム (要求の種類名
http://schemas.microsoft.com/ws/2008/06/identity/claims/role) に値として manager をセットするというクレーム発行になります。
また、発行部分でイコールを記述するときはイコールを 1 つだけ記述します。


スライド98

ここまで確認してきた基本構文と構文内の記述方法をもとに、具体的なクレームルールの記述例をいくつか確認します。

■条件を指定しないで役割クレームに manager の値を発行
条件を指定しない場合には、=> の後だけを記述します。=> の前に何も記述しなければ、無条件にissue( ) 部分で指定したクレームが発行されます。

■役職が設定されていない場合、役職クレームに一般社員の値を発行
基本構文でも確認したように、トークン内に条件部分で指定したクレームが存在しない場合、Not Exists([ ]) を使用します。ここでの例では Not Exists 内に Value を指定していないので、役職クレームに何も入っていない場合 (つまり役職クレームがない場合) になりますが、Value を指定した場合には特定の値が存在しない場合という条件指定になります。

■役職が部長の場合、役職クレームを発行
条件部分で、c:[ ] を指定した場合、[ ] 内に入る情報がそのまま変数 c にセットされます。発行部分で変数 c を利用するときは claim=c と指定することで条件部分の [ ] 内の内容がクレームとして発行されます。

■役職が部長の場合、役割クレームにも役職クレームと同じ値を発行
条件部分でセットした変数 c のうち、値の部分だけを発行に活用したい場合、発行部分で値を指定するときに c.Value とします。これにより role クレームに部長の値がセットされます。


スライド99

■役職と名前を組み合わせた値を指定名クレームとして発行
条件部分で使用する変数 c は複数使用することができます。それぞれの条件を c1[ ]、c2[ ] とすることで、変数 c1 と c2 にクレームの情報がセットされるため、発行部分では 2 つの変数からクレーム発行の手続きを行うことができます。また、変数の値は発行部分で組み合わせて利用することも可能です。

■Input Claim Set に含まれるクレームをそのまま発行
条件部分で何も指定しなければ無条件にクレームが発行されることを前のページで解説しましたが、発行部分では発行するクレームの情報を手動で指定しなければなりません。そのため、Input Claim Set に含まれる情報をすべて Output Claim Set にパススルーする場合には c:[ ] => Issue(claim=c) と指定します。


スライド100

発行承認規則で使われるルールの場合、他の規則とは異なり、許可または拒否の判定を行います。許可または拒否の判定は、許可/拒否のクレームを発行することで判断します。発行承認規則の後続の規則である、発行変換規則では許可のクレームが発行されていることを確認し、発行変換規則の処理を開始します。また、拒否のクレームが発行されている場合、明示的に発行変換規則の処理を拒否するように構成できます。
許可または拒否のクレームを発行する場合、上記のルールを記述します。
また、発行承認規則で複数のルールが設定されている場合、いずれかの許可ルールに該当すれば、アクセスを許可することになりますが、いずれかの拒否ルールに該当する場合は優先順位や許可ルールに関わりなく拒否される点に注意してください。


スライド101

発行部分では Issue または Add が利用できることを前のページで解説しました。Issue と Add はいずれもクレームに値を発行することができますが、Issue はOutput Claim Set に対して、Add はInput Claim Set に対して、それぞれ発行する違いがあります。
Output Claim Set は規則 (ルールセット) による処理が完了した結果、記録されるクレームの集合であるため、一度クレームに値をセットすると、後から値を変更したり、取り消したりすることができません。
一方、Input Claim Set はこれからルールセットで処理する内容が記録されるクレームの集合です。そのため、Add ルールでクレームを発行することで、最終的な結果としてクレームを発行するのではなく、後続のルールが使用するための値としてクレームを仮置きしておくことができます。
たとえば、上記の例では最初に Add ルールで role クレームに manager という値をセットしています。しかし、Input Claim Set への発行なので、この時点では Output Claim Set にはまだ何も記録されていません。続く Issue ルールでは title クレームに 部長という値をセットしています。これにより、Output Claim Set に初めてクレームが発行されたことになります。


スライド102

正規表現とは、いくつかの文字列をひとつの文字列で表現する表現方法で、クレームルールの中では特定の条件に合致する文字列を発見するために使用します。
たとえば、条件部分で example.com ドメインを持つメールアドレスを指定する場合、ドメイン内のすべてのユーザーのメールアドレスを条件として指定することは事実上不可能です。そこで、正規表現を使って Value=~”@example\.com$” と指定すれば、たったひとつのルールで条件を簡単に指定できるメリットがあります。
正規表現には様々な表現方法といくつかのルールがあります。

■正規表現を含む文字列を扱うときはイコールとして =~ と表現する
条件部分の値に正規表現が含まれる場合、Value=~”@example\.com$” のように本来 == とするイコールを=~ と表現します。

■正規表現で使われる文字列で先頭には^、最後には$を使う
正規表現では*を利用して任意の文字列を指定することができます。逆に先頭もしくは最後に文字列がこれ以上含まれないことを示すときには^または$を使います。

■正規表現では大文字、小文字を区別する
正規表現では入力した文字について大文字/小文字を区別します。区別をしないで表現する場合は文字列の先頭に(?i)を記入します。なお、2 バイト文字の場合、大文字 / 小文字のように区別する要素はありません。

■特殊文字の前には \ (バックスラッシュ) を入れる
正規表現で特殊文字 (主にドット) を扱う場合、特殊文字の前に \ マークを入れてください。

■ 条件を使用するときは | (パイプ) を入れる
正規表現でどちらかの文字を含む、という条件を設定するときは | を使って表現します。

■特定範囲の文字または数字の指定には [ ] を使う
特定範囲の文字・数字が含まれることを指定する場合、[ ] を使います。0 から 9 までの数字を指定する場合なら [0-9]、アルファベットの a または b が含まれることを指定する場合なら [ab] のように指定します。また文字数や桁数を指定する場合は { } を使います。2 桁の数字なら [0-9]{2} のように指定します。

■特定範囲の文字または数字が含まれないことを指定する場合は [^] を使う
特定範囲の文字・数字が含まれないことを指定する場合、[^] を使います。たとえば、6 から 8 までの数字が含まれないように指定する場合なら [^6-8] と指定します。

■任意の数字を指定する場合は \d を使う
すべての数字 (10 進数) を指定する方法として、[0-9] を紹介しましたが、代わりに \d と指定することもできます。その他、英数字を表す \w、英数字以外を表す \W、空白文字を表す \s、空白文字以外を表す \S などがあります。

■IP アドレスを指定する場合は \b を使う
IP アドレスを指定する場合は、.を\.と記述します。

例:IP アドレス 192.168.1.1
192\.168\.1\.1

例:IP アドレス 192.168.1.1 または 192.168.1.2
192\.168\.1\.1\b|\b192\.168\.1\.2

例:192.168.1.0/24 サブネット内の任意の IP アドレスを指定
192\.168\.1\.([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-5][0-9])

その他、利用可能な正規表現の一覧はマイクロソフトWebサイトより確認できます。


スライド103

Office 365 へのアクセスを行う場合、トークンにはあらかじめ決められたものをクレームとして実装するため、私たちがカスタマイズを行うことはありません。一方、Office 365 へのアクセス許可を制御する発行承認規則は自由にカスタマイズできるため、発行承認規則を利用して、様々なアクセス制御を行うことができます。その際、次のポイントを抑えた上で、発行承認規則を活用してください。

■5 つの追加要求規則
Office 365 の SSO 設定の一環としてNew-MsolFederatedDomain または
Convert-MsolDomainToFederated コマンドレットを実行すると、次の要求記述が登録され、ADFS のクレーム ルールで利用できるようになります。

① X-MS-Forwarded-Client-IP : Office 365 に接続された末端の端末の IP アドレス

② X-MS-Client-Application : Office 365 に接続したプロトコル (アプリケーション)

③ X-MS-Client-User-Agent : Office 365 に接続したクライアントの User-Agent

④ X-MS-Proxy : Proxyサーバー経由でのアクセスであるか (プロキシサーバーのホスト名)

⑤ X-MS-Endpoint-Absolute-Path : パッシブプロファイルまたはアクティブ プロファイル

5 つの追加された要求規則は受け付け変換規則に、これらの要求規則がトークンに含まれるよう、ルールが設定されています。そのため、発行承認規則の前提条件である受け付け変換規則の設定は行う必要はありません。

■シナリオ : 外部アクセスをすべてブロックする
社外からのアクセスをブロックし、社内からのアクセスのみを許可する場合、Web アプリケーション プロキシを経由しないアクセスのみを許可することになります。その場合には、X-MS-Proxy に値が入っていることを確認することで、社外からのアクセスであるとみなします。

exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy”])

=> issue(Type = “http://schemas.microsoft.com/authorization/claims/deny”, Value = “true”);

■シナリオ : Exchange ActiveSync 以外の外部アクセスをすべてブロックする
Exchange ActiveSync による接続を行う場合には、X-MS-Client-Application の値に Exchange ActiveSync を利用していることを示す値 (正確には、Microsoft.Exchange.ActiveSync) が入ります。X-MS-Client-Application の値を、前のシナリオで登場した社外からのアクセスをブロックするルールと共に確認することで、シナリオの条件を設定できます。(ただし、先進認証で接続する場合は X-MS-Client-Application の値が設定されないケースがあることにご注意ください)

exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy”]) &&

NOT 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/deny”, Value = “true”);

■シナリオ : Firefox によるアクセスを許可する
特定のブラウザーによるアクセスのみを許可したい場合、X-MS-Client-User-Agent を利用します。User-Agent 内では Firefox の文字列以外にも様々な文字列が含まれるため、「Firefox という文字列が含まれる場合」となるような条件になるよう、正規表現を活用します。(参考までに Microsoft Intune で使用する Managed Browser の場合、UserAgent には「ManagedBrowser」という文字列が入ります。)

exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent”, Value =~ “(?i)Firefox”])

=> issue(Type = “http://schemas.microsoft.com/authorization/claims/permit”, Value = “true”);

これまでに解説した issue 部で deny としているルールを作成する場合、deny の条件に当てはまるもの以外は、すべて許可するルールを別途作成してください。最後にすべて許可するルールを作らないと、すべて拒否されてしまう点に注意してください。

■シナリオ : 社内からのブラウザー アクセスのみ許可する
ブラウザー アクセスの場合、利用するブラウザーがまちまちなので、X-MS-Client-User-Agent を利用することができません。そのため、ブラウザー アクセスを行うときのエンドポイント URL に着目し、URL に /adfs/ls/wia が含まれる場合にはブラウザー アクセスであると判定します。

exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-endpoint-absolute-path”, Value == “/adfs/ls/wia”])

=> issue(Type = “http://schemas.microsoft.com/authorization/claims/permit”, Value = “true”);

■シナリオ : Windows 10 のみアクセスを許可する
特定の OS によるアクセスのみを許可したい場合、X-MS-Client-User-Agent を利用します。User-Agent 内では Windows 10 の場合には Windows NT 10.0 という文字列が含まれるため、「Windows 10 という文字列が含まれる場合」となるような条件になるよう、正規表現を活用します。

exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent”, Value =~ “(?i)Windows NT 10.0”])

=> issue(Type = “http://schemas.microsoft.com/authorization/claims/permit”, Value = “true”);

そのほかの OS では次のような文字列を利用します (iOS/Android の場合、後続の文字列にバージョン番号が入ります)。

OS 種類 User-Agent 文字列
Windows 7, Windows Server 2008 R2 Windows NT 6.1
Windows 8.1, Windows Server 2012 R2 Windows NT 6.3
Windows 10 Windows NT 10.0
Android Android
iPad (iOS) iPad
iPhone (iOS) iPhone
iPod (iOS) iPod; CPU iPhone OS

■シナリオ : ブラウザー アクセスおよび先進認証のみ許可する
先進認証を利用していないアプリケーションからのアクセスをブロックする場合、その反対となるブラウザーアクセスまたは先進認証による通信を許可するようにルールを設定し、その他の通信に対する許可を与えないように設定します。そこで、X-ms-endpoint-absolute-path を利用して、URL に /adfs/ls または /adfs/oauth2 が含まれる場合にはブラウザー アクセスまたは先進認証のアクセスであると判定します。

c:[Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-endpoint-absolute-path”, Value =~ “(/adfs/ls)|(/adfs/oauth2)”]

=> issue(Type = “http://schemas.microsoft.com/authorization/claims/permit”, Value = “true”);

SharePoint Online への先進認証だけを許可
Office アプリによる SharePoint Online へのアクセスの場合、上記のクレームルールでは先進認証であるか識別できません。SharePoint Online へのアクセスを先進認証のみに限定する場合、SharePoint 管理センターより先進認証のみを許可する設定を有効にすることで対応してください。

クレームルールにおける IP アドレスの指定
X-MS-Forwarded-Client-IP 要求規則を利用してクレームルールを作成する場合、値として IP アドレスを指定します。指定する IP アドレスが複数になるときは、該当する複数のIP アドレスをすべて指定しなければならないため、正規表現を利用して IP アドレスの範囲を定義するのが一般的です。また、IP アドレスの範囲を指定するときには、マイクロソフトの Web サイトからダウンロード可能な Client Access Policy Builder を利用することも有効です。Client Access Policy Builder は PowerShell スクリプトで、指定した IP アドレス帯に対応するクレームルールを自動的に作成してくれます。なお、Client Access Policy Builder を実行するときは、Windows PowerShell ISE から起動すること、そして「Set-ExecutionPolicy Unrestricted」コマンドレットを実行してから実行する必要がある点にも注意してください。

■Client Access Policy Builder
https://gallery.technet.microsoft.com/office/Client-Access-Policy-30be8ae2

日本国外からのアクセスを拒否するルール
X-MS-Forwarded-Client-IP クレームに含まれる IP アドレスが日本で使われている IPアドレスであることを調べれば、日本国内/国外のアクセスを識別できます。しかし、日本で使用されている IP アドレス帯は非常に多く、クレームルールで制御することは現実的ではありません。例えば、AWS Route53 の Geolocation Routing を利用してフェデレーションサービス名の名前解決に日本国内と国外で異なるレコードを割り当て、国外からのアクセスを事実上拒否するような方法が現実的です。

編集後記

クレームルール言語の話でした。Windows Server 2016以降ではクレームルール言語は知らなくてもGUIベースでルールを書けるようになったので便利なのですが、発行承認規則以外の規則のカスタマイズをする場合は相変わらずクレームルール言語を直接書かなければなりません。ということで、利用することもまだまだあるだろうと思い、今回は掲載してみました。参考になれば幸いです。