概要
Azure App Service や Azure Container Apps で利用可能な Azure Easy Auth のユーザー認証情報を扱うことができる NJS (NGINX JavaScript) のモジュールを作ったので紹介します。
これを使うと、Azure Easy Auth が認証したユーザーのIDや所属グループのIDのクレームに基づくアクセス制御が簡単に実現できるようになります。
しくみ
Azure Easy Auth が有効な Web サービスでは、すべてのアクセスに対して次の HTTP ヘッダが追加されます。
-
X-MS-CLIENT-PRINCIPAL
: Base64 エンコードされたすべてのクレームを含む JSON オブジェクト -
X-MS-CLIENT-PRINCIPAL-ID
: 認証済みユーザーのID -
X-MS-CLIENT-PRINCIPAL-NAME
: 認証済みユーザーの名前 -
X-MS-CLIENT-PRINCIPAL-IDP
: 認証済みユーザーの IdPの名前 (aad
: Microsoft Entra ID)
これらのヘッダの値が持つ意味や実例については、次の勉強会資料の 28 ページ目からを参照してください。
今回紹介する azure_easy_auth.js
モジュールは、上記のヘッダ情報を取得・デコードする様々な JavaScript 関数を提供するものです。
- HTTPヘッダアクセス関数
-
getHeaderClientPrincipal()
:X-MS-CLIENT-PRINCIPAL
ヘッダの値を取得 -
getHeaderClientPrincipalId()
:X-MS-CLIENT-PRINCIPAL-ID
ヘッダの値を取得 -
getHeaderClientPrincipalName()
:X-MS-CLIENT-PRINCIPAL-NAME
ヘッダの値を取得 -
getHeaderClientPrincipalIdp()
:X-MS-CLIENT-PRINCIPAL-IDP
ヘッダの値を取得 -
decodeHeaderClientPrincipal()
:X-MS-CLIENT-PRINCIPAL
ヘッダの値を Base64 デコードした結果のオブジェクトを取得
-
- クレームアクセス関数
-
getClaimValue()
: 指定したクレームの値を取得 (複数ある場合は最初の値) -
getClaimValues()
: 指定したクレームのすべての値をリストで取得 -
getClaimEmail()
: Email のクレームを取得 -
getClaimName()
: Name のクレームを取得 -
getClaimObjectId()
: Object ID のクレームを取得 -
getClaimPreferredUsername()
: Preferred Username のクレームを取得 -
getClaimGroups()
: 所属グループのクレームをリストで取得
-
- アクセス判定関数
-
hasClaimGroup()
: 認証したユーザーの所属グループのクレームに特定のクレームが含まれているかどうかを判定 -
isAuthorizedPrincipals()
: 認証したユーザーのIDクレームおよび所属グループクレームのリストと、NGINX 変数$authorized_principals
で指定したクレームのリストに、共通の要素が含まれる場合は"1"
を返し、そうでない場合は"0"
を返す
-
上記の関数を NGINX 設定ファイルから呼び出してアクセス許可・不許可の判定に利用するには、 js_set
による関数参照設定や変数による引数渡しなど、NJS 特有の記法が要求されます。次のセクションの利用例を参考にしてください。
使用例
単純なアクセス保護
/secure/
以下のパスがリクエストされたとき、認証されたユーザーのIDおよび所属グループのIDに特定のIDが含まれている場合のみ、アクセスを許可します。
$authorized_principals
変数にアクセスを許可したい特定のIDをセットし、 $is_authorized
変数にisAuthorizedPrincipals()
関数の参照をセットすることで、この関数による判定が利用できます。
server {
listen 80;
server_name _;
root /nginx/sites/default;
js_import auth from azure_easy_auth.js;
js_set $is_authorized auth.isAuthorizedPrincipals;
location ~ ^/secure/ {
set $authorized_principals "98a7b6c5-d4e3-21f0-9g8h-765432109876";
if ($is_authorized = "0") {
return 403 "Forbidden";
}
}
}
パスを利用したアクセス保護
リクエストされたパス /secure/<$secure_principal>/
から $seure_principal
を取り出し、管理者ユーザーの ID である $user_principal
と連結して $authorized_principals
にセットします。
一般ユーザーは自分のために用意された場所 /secure/<ObjectID>
のみアクセスが許可され、スーパーユーザーはすべての場所のアクセスが許可されます。
server {
listen 80;
server_name _;
root /nginx/sites/default;
js_import auth from azure_easy_auth.js;
js_set $is_authorized auth.isAuthorizedPrincipals;
set $super_principal "123e4567-e89b-12d3-a456-426614174000";
location ~ ^/secure/(?<secured_principal>[^/]+) {
set $authorized_principals "$secured_principal,$super_principal";
if ($is_authorized = "0") {
return 403 "Forbidden";
}
}
}
まとめ
今回紹介した azure_easy_auth.js
モジュールを使えば、Microsoft Entra ID をユーザー認証に利用する企業内部向けの Web サーバーで、ユーザー ID と所属グループ ID を基準にしたきめこまかなアクセス制御の機能を NGINX に追加できます。
そのような企業内部の静的 Web サイトのホスティングサービス向けに、公式 NGINX Docker イメージに azure_easy_auth.js
モジュールを組み込んで調整したコンテナイメージを公開しています。
また上記イメージによるサービスを提供する Azure App Service および Azure Container Apps の GitOps リポジトリをそれぞれ公開しています。
これらを利用すると、様々なアクセスパターンを持つ多数の社内向け静的 Web サイトのホスティングサービスを、最適なクラウドサービスを使って低いランニングコストで運用できるようになります。その詳細については別の記事で紹介したいと思います。