【Azure】App Serviceの流儀に従って、NGINXで環境変数を使いこなす秘訣:Tech TIPS
Azure App Serviceでは環境変数を活用することでWebアプリの挙動を容易に変更できる。それと同じ仕組みを使ってNGINXの挙動もプログラム修正なしで変更できると便利だ。その方法と注意点を詳しく説明する。
対象:Azure App Service on Linux
Azure App Serviceでは「環境変数」を設定することで、Webアプリに各種設定値を簡単に渡すことが可能だ。プログラムコードを修正しなくても、環境変数の値を変えることでWebアプリの挙動を変えられる。
NGINXをカスタマイズしている場合、同様にApp Serviceの環境変数を活用してNGINXの挙動を変更できると、各種設定値を環境変数で一元管理できて便利そうだ。
そこで本Tech TIPSでは、App Service on Linuxを対象として、その環境変数の「アプリ設定」に設定した値を、NGINXで活用するための方法や注意点を紹介する。
ここでは、Tech TIPS「【Azure】App Service on LinuxでディレクトリごとにクライアントIP制限を実装する方法と注意点(NGINX編)」で説明しているクライアントIP(ソースIP)アドレスによるアクセス制限を例として挙げている。運用時には、手動で設定ファイルを修正しなくても、環境変数の設定値であるクライアントIPアドレスを変えるだけで、それが自動的にNGINXへ反映される、という仕組みである。
NGINXのカスタマイズ方法は、Tech TIPS「【Azure】App Service on LinuxのWebサーバ『NGINX』をカスタマイズする方法」を前提としているので、あらかじめご一読いただきたい。
NGINXで環境変数を活用する2種類の方法
NGINXの標準機能だけでは、環境変数を活用することが難しい。親プロセスから環境変数を引き継ぐことは可能なものの、それをNGINXの変数に代入したり加工したりするには機能が足りないからだ。
しかし標準機能にこだわらなければ解決策はある。1つは「ngx_http_perl_module」モジュールを使ってPerlで環境変数を処理することだ。App Serviceの場合、(少なくともPHPスタックでは)このモジュールは標準で組み込まれているので、追加のセットアップなしでPerlによる拡張が可能だ。しかし当然ながら、本格的に活用するにはPerlの知識が欠かせない。
もう1つは、NGINXの設定ファイル(拡張子が.confのファイル。以下、confファイル)を動的に生成するという手法だ。具体的には、App Serviceのスタートアップスクリプトから呼び出せるプログラミング言語で環境変数を読み出し、それを加工してNGINXのディレクティブなどに変換し、confファイルとして保存する。それをNGINXの「default」などのconfファイルにインクルードすればよい。
本Tech TIPSでは、より自由に言語を選べる後者の方法を説明する。環境変数の読み出しとconfファイルの生成には、Bashで実行するシェルスクリプトを用いる。
手順その1――App Serviceに環境変数(アプリ設定)を追加
まず、NGINXに値を渡す環境変数をApp Serviceに追加する。Azureポータルで追加する手順は以下の画面の通りだ。
■操作手順
- Azureポータルで対象のApp Serviceのページを開く
- 左側メニューで[設定]−[環境変数]を選ぶ
- 右ペインで[アプリ設定]タブを選ぶ
- [+ 追加]ボタンをクリックする
- 「アプリケーション設定の追加/編集」ダイアログが現れたら、[名前]に環境変数の名称を入力する
- [値]欄に環境変数の値を入力する
- [適用]ボタンをクリックする
- 元の画面で[適用]ボタンをクリックする
- アプリが再起動してもよいタイミングで、「変更の保存」ダイアログの[確認]ボタンをクリックする
ここでは、「ADMIN_ALLOWED_IP_ADDRS」という環境変数に、アクセスを許可すべきクライアントIPアドレスの範囲(CIDR形式)を「;」(セミコロン)で区切って列挙した文字列を代入している。
上記の設定後、自動的にApp Serviceが再起動される。以後、シェルスクリプトからは「ADMIN_ALLOWED_IP_ADDRS」「APPSETTING_ADMIN_ALLOWED_IP_ADDRS」という環境変数名でその設定値を参照できる。
手順その2――NGINXのconf(設定)ファイルのテンプレートを作成
次に、NGINXのconfファイルの基になる「テンプレートファイル」を用意する。これは、confファイル内で動的に変更したい部分を環境変数への参照で置き換えたものだ。
以下の例では、「allow <IPアドレス範囲>;」というアクセス許可の行を複数記述するべき部分を、「${TEMP_ALLOWED_IP_ADDRS}」という環境変数への参照に置き換えている。同様に、シェルスクリプト自身のフルパスを「${MY_OWN_SCRIPT_PATH}」に置き換えている。
# 管理ページ向けのIPアドレス制限
# 許可するIPアドレス枠
# 【注意】以下は ${MY_OWN_SCRIPT_PATH} で自動生成されています
${TEMP_ALLOWED_IP_ADDRS}
# 最後は全拒否
deny all;
ファイル: /home/custom/etc/nginx/inc/template/template-admin-allowed-ip-addrs.conf※NGINXのレファレンス: deny
App Serviceで設定した環境変数「ADMIN_ALLOWED_IP_ADDRS」ではなく「TEMP_ALLOWED_IP_ADDRS」を選んだのは、ADMIN_ALLOWED_IP_ADDRSの値そのものではなく、それを加工/変換したものをconfファイルに反映したいからだ。
手順その3――テンプレートからconfファイルを生成するためのシェルスクリプトを用意
上記のテンプレートファイルと環境変数からconfファイルを生成するためのシェルスクリプトを用意する。
#!/usr/bin/env bash
# このシェルスクリプトのパス
export MY_OWN_SCRIPT_PATH=$(readlink -f "${BASH_SOURCE[0]}")
# NGINXのconfファイルの基になるテンプレートファイル
TEMPLATE_CONF="/home/custom/etc/nginx/inc/template/template-admin-allowed-ip-addrs.conf"
# NGINXのconfファイルの出力先
TARGET_CONF="/home/custom/etc/nginx/inc/admin-allowed-ip-addrs.conf"
# 環境変数「ADMIN_ALLOWED_IP_ADDRS」の値の例:
# 192.0.2.10;198.51.100.0/24;2001:db8:7:6::/64
if [ -n "$ADMIN_ALLOWED_IP_ADDRS" ]; then # 環境変数が設定済みで、かつ
if [ -f "$TEMPLATE_CONF" ]; then # テンプレートファイルが存在する場合……
# ADMIN_ALLOWED_IP_ADDRSからIPアドレス一覧を取得 |
# セミコロンを改行に変換して1行ずつ展開 |
# 空行を削除 |
# NGINXのallowディレクティブに変換
# 環境変数「TEMP_ALLOWED_IP_ADDRS」に代入
export TEMP_ALLOWED_IP_ADDRS=$(echo "$ADMIN_ALLOWED_IP_ADDRS" | \
tr ';' '\n' | \
sed '/^$/d' | \
sed 's/^.*$/allow \0;/')
# テンプレートに記載の環境変数を置き換えつつ、対象のconfファイルを生成
envsubst < $TEMPLATE_CONF > $TARGET_CONF
fi
fi
ファイル: /home/make-admin-allowed-ip-addrs-conf.sh
環境変数「MY_OWN_SCRIPT_PATH」には、「BASH_SOURCE」というBashの機能と「readlink」コマンドを使って、自分自身のフルパスを代入している。
環境変数「TEMP_ALLOWED_IP_ADDRS」には、セミコロンで区切られている複数のIPアドレス範囲を、それぞれ「allow <IPアドレス範囲>;」に変換した複数行のテキストを代入している。
最後に「envsubst」コマンドを使って、テンプレート内の「${TEMP_ALLOWED_IP_ADDRS}」「${MY_OWN_SCRIPT_PATH}」をそれぞれの環境変数の値に置き換えつつ、confファイルを生成している。
ここで上記スクリプトが正しく実行できるかどうかを試してみよう。Tech TIPS「【Azure】App Service on LinuxにSSHで接続する方法と注意点(WebSSH編)」を参考にしてSSHでApp Serviceに接続し、上記のスクリプトを手動で実行し、以下のようなconfファイルが生成されることを確認する。
# 管理ページ向けのIPアドレス制限
# 許可するIPアドレス枠
# 【注意】以下は /home/make-admin-allowed-ip-addrs-conf.sh で自動生成されています
allow 192.0.2.10;
allow 198.51.100.0/24;
allow 2001:db8:7:6::/64;
# 最後は全拒否
deny all;
ファイル: /home/custom/etc/nginx/inc/admin-allowed-ip-addrs.conf
※NGINXのレファレンス: allow/deny
「${TEMP_ALLOWED_IP_ADDRS}」を記述した部分には、App Serviceで設定した環境変数「ADMIN_ALLOWED_IP_ADDRS」を基にしたAllowディレクティブの行が記載されているはずだ。
手順その4――生成したconfファイルをNGINXの設定ファイル「default」にインクルード
「手順その3」で作成したシェルスクリプトが正常に実行できたら、生成される予定のconfファイルをインクルードするようにNGINXの設定ファイル「default」を修正する。
server {
#proxy_cache cache;
#proxy_cache_valid 200 1s;
listen 8080;
listen [::]:8080;
root /home/site/wwwroot;
index index.php index.html index.htm;
server_name example.com www.example.com;
port_in_redirect off;
# ---------- 以下を挿入 ----------
# 正しいクライアントIPアドレスを取得するための設定
real_ip_header X-Forwarded-For;
set_real_ip_from 169.254.0.0/16;
# 管理専用の「/kanrishanoheya」ディレクトリ以下は、
# 特定のクライアントIPアドレスからのアクセスだけを許可
location ~ ^/kanrishanoheya/ {
# 生成したconfファイルを読み込む
include inc/admin-allowed-ip-addrs.conf;
# 必要なら他のディレクティブをここに記述
}
# ---------- 挿入終わり ----------
location / {
index index.php index.html index.htm hostingstart.html;
}
# <後略>
}
ファイル: /home/custom/etc/nginx/sites-available/default
※NGINXのレファレンス: real_ip_header/set_real_ip_from
上記で挿入している「real_ip_header」「set_real_ip_from」ディレクティブは、NGINXとクライアントの間にリバースプロキシまたはロードバランサーなどが存在している状況で、実際のクライアントのIPアドレスを導出するためのものだ。
手順その5――スタートアップスクリプトにconfファイルの生成と差し替えのためのコードを挿入
最後に、「手順その3」で作成したシェルスクリプトをApp Serviceのスタートアップスクリプトに組み込んで、App Serviceの起動時やデプロイ時に実行されるようにする。
#!/usr/bin/env bash
# <前略>
# ---------- 以下を挿入 ----------
# NGINXでクライアントIPアドレス制限を設定するためのconfファイルを生成
. /home/make-admin-allowed-ip-addrs-conf.sh
# 設定ファイルを差し替える
ln -nfs /home/custom/etc/nginx/conf.d/mapping.conf /etc/nginx/conf.d/mapping.conf
mkdir -p /etc/nginx/inc
ln -nfs /home/custom/etc/nginx/inc/admin-allowed-ip-addrs.conf /etc/nginx/inc/admin-allowed-ip-addrs.conf
ln -snf /home/custom/etc/nginx/sites-available/default.conf /etc/nginx/sites-available/default
# 差し替えた設定ファイルを検証して、成功したらNGINXを再ロード
nginx -t && nginx -s reload
# ---------- 挿入終わり ----------
# <後略>
ファイル名: /home/startup.sh
ここまでの手順を全て終えたら、App Serviceを再起動してみよう。正しく機能していれば、Azureポータルで設定した環境変数の値に応じて、アクセスが許可されるクライアントIPアドレスが変わるはずだ。
■関連リンク
- App Service アプリを構成する(Microsoft Learn)
- ENVディレクティブとNGINXにおける環境変数の取り扱いの説明(NGINX)
- ngx_http_perl_moduleモジュールの説明(NGINX)
Copyright© Digital Advantage Corp. All Rights Reserved.