Azure Active Directoryの動的メンバーシップを実装してみる

#はじめに
ADグループ割り当てを自動で実施する機能です。ユーザの属性情報を設定したルールで評価し、動的にグループに含まれるor含まれないかを決定します。
(2020/1月時点の情報です)

参考リンク
[動的グループの作成と状態チェックを行う](https://docs.microsoft.com/ja-jp/azure/active-directory/users-groups-roles/groups-create-rule)
[Azure Active Directory の動的グループ メンバーシップ ルール](https://docs.microsoft.com/ja-jp/azure/active-directory/users-groups-roles/groups-dynamic-membership)


#前提条件
P1以上のライセンスが必要です。
今回はP2試用版環境でやってみます。

> この機能を使うには、少なくとも 1 つの動的グループのメンバーである一意のユーザーごとに Azure AD Premium P1 ライセンスが必要です。 ユーザーを動的グループのメンバーにするために、そのユーザーにライセンスを割り当てる必要はありませんが、少なくともそのすべてのユーザーを対象にできるだけのライセンス数は必要です。 たとえば、テナントのすべての動的グループに、合計 1,000 人の一意のユーザーがいる場合、ライセンス要件を満たすには、Azure AD Premium P1 に対するライセンスが 1,000 個以上必要です。 動的なデバイス グループのメンバーであるデバイスには、ライセンスは必要ありません。

#手順
 - 準備
    - ユーザ作成
    - グループ作成
 - ルールの設定
 - ユーザの属性変更
 - 動作確認

##準備
###ユーザ作成
適当に作りました。
手順は以下。
[Azure Active Directory を使用してユーザーを追加または削除する](https://docs.microsoft.com/ja-jp/azure/active-directory/fundamentals/add-users-azure-active-directory?context=azure/active-directory/users-groups-roles/context/ugr-context)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/db530649-4b35-e1a5-c2eb-80ce7e774583.png)

###グループ作成
作成時に動的ルールを設定できるようですが、割り当て済みを選択して後から変更してみるようにしてみます。
手順は以下。
[Azure Active Directory を使用して基本グループを作成してメンバーを追加する](https://docs.microsoft.com/ja-jp/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal?context=azure/active-directory/users-groups-roles/context/ugr-context)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/37a01aa1-d0f9-bda6-0dce-fd8e23e3e6a8.png)

メンバーはいない状態です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/aee55147-5091-f457-14a1-b86247f77cd7.png)


##ルールの設定
グループのプロパティへ。
ドキュメントだと違う場所から入るようになっていたので注意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/ee068c78-e913-bf32-1ca8-f6b6d4535824.png)

メンバーシップの変更をすると、「動的クエリの追加」が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/e7a7882a-8d9d-d6a9-6bc0-b87bfa235e1b.png)

ルールビルダー画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2d45d603-dd7e-c4e0-5f8e-e3ef9178f51a.png)

プロパティのCityが東京を含む場合にグループメンバーとなるように設定、保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/f338fc43-0eae-665a-b7f9-3e846229be52.png)

最後にグループも保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2b4257c3-0612-6b07-59c5-4b8d3f4cda21.png)

##ユーザの属性変更
では、対象ユーザのCity=市区町村の値を東京都品川区としましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/c0a6bd82-9047-2942-d180-e13587535ddf.png)

##動作確認
数十秒後にグループに追加されていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/4425ff11-ef87-ba82-9f09-627238928c78.png)

評価タイミングは下記記載のように属性が変更されるたびに評価が発生するようです。
>ユーザーまたはデバイスの属性が変更されると、組織内のすべての動的グループ ルールが、メンバーシップの変更のために処理されます。 


#補足
式に利用できるプロパティは下記の通りですが、Azureが日本語環境だと、Cityは市区町村など変換されているため、項目名が一致しません。

今回のユーザはできるだけ日本語項目で設定してみましたが、わかりやすい項目以外はあまり一致しませんでした。
有識者の方コメントいただけると嬉しいです。


| properties                   | 使用できる値                                                 | 使用法                                                       |
| :--------------------------- | :----------------------------------------------------------- | :----------------------------------------------------------- |
| city                         | 任意の文字列値または *null*                                  | (user.city -eq "value")                                      |
| country                      | 任意の文字列値または *null*                                  | (user.country -eq "value")                                   |
| companyName                  | 任意の文字列値または *null*                                  | (user.companyName -eq "value")                               |
| department                   | 任意の文字列値または *null*                                  | (user.department -eq "value")                                |
| displayName                  | 任意の文字列値                                               | (user.displayName -eq "value")                               |
| employeeId                   | 任意の文字列値                                               | (user.employeeId -eq "value") (user.employeeId -ne *null*)   |
| facsimileTelephoneNumber     | 任意の文字列値または *null*                                  | (user.facsimileTelephoneNumber -eq "value")                  |
| givenName                    | 任意の文字列値または *null*                                  | (user.givenName -eq "value")                                 |
| jobTitle                     | 任意の文字列値または *null*                                  | (user.jobTitle -eq "value")                                  |
| mail                         | 任意の文字列値または *null* (ユーザーの SMTP アドレス)       | (user.mail -eq "value")                                      |
| mailNickName                 | 任意の文字列値 (ユーザーのメール エイリアス)                 | (user.mailNickName -eq "value")                              |
| mobile                       | 任意の文字列値または *null*                                  | (user.mobile -eq "value")                                    |
| objectId                     | ユーザー オブジェクトの GUID                                 | (user.objectId -eq "11111111-1111-1111-1111-111111111111")   |
| onPremisesSecurityIdentifier | オンプレミスからクラウドに同期されたユーザーのオンプレミスのセキュリティ識別子 (SID)。 | (user.onPremisesSecurityIdentifier -eq "S-1-1-11-1111111111-1111111111-1111111111-1111111") |
| passwordPolicies             | なし DisableStrongPassword DisablePasswordExpiration DisablePasswordExpiration、DisableStrongPassword | (user.passwordPolicies -eq "DisableStrongPassword")          |
| physicalDeliveryOfficeName   | 任意の文字列値または *null*                                  | (user.physicalDeliveryOfficeName -eq "value")                |
| postalCode                   | 任意の文字列値または *null*                                  | (user.postalCode -eq "value")                                |
| preferredLanguage            | ISO 639-1 コード                                             | (user.preferredLanguage -eq "en-US")                         |
| sipProxyAddress              | 任意の文字列値または *null*                                  | (user.sipProxyAddress -eq "value")                           |
| state                        | 任意の文字列値または *null*                                  | (user.state -eq "value")                                     |
| streetAddress                | 任意の文字列値または *null*                                  | (user.streetAddress -eq "value")                             |
| surname                      | 任意の文字列値または *null*                                  | (user.surname -eq "value")                                   |
| telephoneNumber              | 任意の文字列値または *null*                                  | (user.telephoneNumber -eq "value")                           |
| usageLocation                | 2 文字の国コード                                             | (user.usageLocation -eq "US")                                |
| userPrincipalName            | 任意の文字列値                                               | (user.userPrincipalName -eq "alias@domain")                  |
| userType                     | member guest *null*                                          | (user.userType -eq "Member")                                 |