対象:Azure App Service、Key Vault(キーコンテナー)、Azureポータル
「Azure App Service」上のアプリケーションから、認証の必要な別のサービスを利用するのはよくあることだろう。
そして、その認証に必要なID/パスワードといった秘密情報をApp Serviceの「アプリケーション設定」などに保存しておき、アプリケーションのコードから参照するのも、よくあることだ。
しかし、その秘密情報は安全だろうか? 例えばアプリケーション設定に保存した秘密情報は、そのApp Serviceの設定を閲覧できるスタッフならば容易に知ることができる。また、リソースをデプロイしているコードのアプリケーション設定部分には、秘密情報が暗号化されずに露出していることも多いのではないだろうか。
本Tech TIPSでは、秘密情報を管理するためのサービス「Azure Key Vault」(キーコンテナー)とApp Serviceを連携させることで、こうした秘密情報の漏えいをなるべく防ぐ方法の一つを紹介したい。
簡単に説明すると、Key Vaultの「シークレット」に秘密情報を保存し、それをApp Serviceから「参照」するように設定する。これによりApp Serviceを参照可能なユーザーでも、Key Vault上の秘密情報を知ることができない。また、デプロイのコードには秘密情報を埋め込まずに済む。
本Tech TIPSでは、Azureポータルでの設定手順を説明する。App ServiceとKey Vaultはあらかじめデプロイ済みとする。
【準備】App Serviceの「マネージドID」を有効化する
Key Vaultからシークレットを読み出すには、事前にKey VaultとApp Serviceの間で設定しなければならないことがある。その一つが、対象のApp Serviceで「マネージドID」を有効にすることだ。
マネージドIDとは、Azure標準のIDサービス「Microsoft Entra ID(Azure Active Directory)」からApp Serviceなどのリソースに対して発行されるIDの一種だ。マネージドIDをサポートしているAzure上のリソースに対し、容易に認証して接続できる。また、パスワードなどの資格情報を管理する必要はない。詳細は、Microsoft Learnの「Azure リソースのマネージド ID とは」を参照していただきたい。
マネージドIDには「システム割り当て」「ユーザー割り当て」の2種類のIDがある。本Tech TIPSでは、より簡単に利用できる前者で説明する。
App ServiceでマネージドIDを有効化するには、以下の画面のようにAzureポータルを操作する。この作業は1回行えばよい。
■操作手順
- Azureポータルで[App Service]−[<App Service名>]を開く
- 左側メニューの「設定」欄にある「ID」をクリック
- [システム割り当て済み]タブを選択
- [状態]スイッチを「オン」にする
- [保存]をクリックする。確認のダイアログが表示されたら、指示に従って[はい]ボタンをクリックする。正常に有効化できると、有効化されたマネージドIDのオブジェクトIDなどが表示されるはずだ。
これでマネージドIDの有効化は完了だ。
【準備】App ServiceにKey Vaultシークレットの取得(参照)を許可する
App ServiceのマネージドIDを有効化したら、そのIDを使って、App ServiceがKey Vaultのシークレットを取得できるようにアクセス許可を設定する。
このとき、Key Vaultでアクセス許可の仕組み(モデル)として、あらかじめ「コンテナーアクセスポリシー」「Azureロールベースのアクセス制御(Azure RBAC)」のどちらを選択しているかによって、設定手順は異なる。ここでは、シンプルな前者を選んでいるものとして説明する(Microsoftは後者を推奨している)。
コンテナーアクセスポリシーでApp Serviceにシークレット取得を許可するには、以下の画面のようにAzureポータルを操作する。この作業は1回行えばよい。
■操作手順
- Azureポータルで[キーコンテナー]−[<Key Vault名>]を開く
- 左側メニューの[アクセスポリシー]をクリック
- 上部メニューの[作成]をクリックして、アクセスポリシー作成ウィザードを開始
- ウィザードの「アクセス許可」画面で、「シークレットのアクセス許可」−「シークレットの管理操作」欄にある[取得]チェックボックスに「✔」を入れて「オン」にする
- 下端の[次へ]ボタンをクリック
- 「プリシパル」画面で、アクセス許可の対象の<App Service名>を検索窓に入力していく
- 検索窓の下に対象のApp Service(のマネージドID)が表示されたら、それを選択
- 下端の[次へ]ボタンをクリック
- 「アプリケーション」画面では、下端の[次へ]ボタンをクリック
- 「確認および作成」画面で設定内容を確認
- 下端の[作成]ボタンをクリック
これでアクセスポリシーの設定は完了だ。
Key Vaultのシークレットにパスワードなどの秘密情報を保存する
Key Vaultにシークレットを保存するには、以下の画面のようにAzureポータルを操作する。この作業はシークレットごとに1回ずつ行う必要がある。
▼
▼
■操作手順
- Azureポータルで[キーコンテナー]−[<Key Vault名>]を開く
- 左側メニューの「オブジェクト」欄にある[シークレット]をクリック
- 上部メニューの[作成/インポート]をクリック
- 「シークレットの作成」画面の[アップロードオプション]では[手動]を選択
- [名前]に、シークレットに付ける名前を入力する(以下、これを<シークレット名>とする)。半角の英数字およびハイフン、かつ127文字以内で指定する必要がある
- [シークレット値]に、App Serviceに渡したいパスワードなどの秘密情報を入力
- [コンテンツの種類][アクティブ化する日を設定する][有効期限を設定する][有効][タグ]については必要に応じて設定する。デフォルトのままでもよい
- 下端の[作成]ボタンをクリック
これでシークレットの保存は完了だ。
App ServiceからKey Vaultのシークレット値を参照(取得)する
Key Vaultにシークレットを保存したら、それをApp Serviceで取得するように設定しよう。
ここではApp Serviceのアプリケーション設定を対象として説明する。ただ接続文字列についても、ほぼ同じ手順でKey Vaultシークレットを参照できる。
アプリケーション設定の値(内容)には、平文で秘密情報を記入する代わりに、Key Vaultのシークレットを参照するための下記文字列を指定する。
@Microsoft.KeyVault(VaultName=<Key Vault名>;SecretName=<シークレット名>)
操作手順は以下の画面の通りだ。ただし、アプリケーション設定の内容を除けば、その手順は通常のアプリケーション設定と変わらず、アプリケーション設定ごとに1回ずつ行う必要がある。
▼
▼
■操作手順
- Azureポータルで[App Service]−[<App Service名>]を開く
- 左側メニューの「設定」欄にある「構成」をクリック
- [アプリケーション設定]タブを選択
- [+ 新しいアプリケーション設定]をクリック
- 「アプリケーション設定の追加/編集」画面が表示されたら、[名前]にアプリケーション設定の名前を記入(以下、これを<アプリケーション設定名>とする)。通常時と同じく、半角の英数字とピリオド、アンダースコアで指定する。アプリケーションのコードからは、この名前の環境変数で参照できる
- [値]には、前述したKey Vaultのシークレットを参照するための文字列を入力
- 下端の[OK]ボタンをクリック
- 元の画面に戻ったら、上部メニューの[保存]をクリック。App Serviceの再起動を確認するダイアログが表示されたら、指示に従って[はい]ボタンをクリックして再起動する
これでアプリケーション設定の追加は完了だ。
Key Vaultシークレットの値が正しく取得できているかどうか確認する
App Serviceの再起動が確認したら、Key Vaultのシークレットを正しく参照できているかどうか、必ず確認しよう。
それには、前述の手順で対象のアプリケーション設定の編集画面を再び開く。以下の画面のように「状態」が[✔ Resolved]と表示されていれば、Key Vaultのシークレットを正しく参照して、その値を取得できている。
一方、参照が失敗していると、以下の画面のように「状態」が「× <エラーを表すタイトル>」と表示される。「エラーの詳細」に表示されている内容を確認して対処しよう。特に、前述の参照文字列では名前のスペルミスやカッコの過不足、セミコロンの欠落などがないかどうか、よく確認したい。
正常に参照できたら、アプリケーション側でもKey Vaultシークレットに設定した値が正しく取得できているかどうか確認してみよう。それには「<アプリケーション設定名>」あるいは「APPSETTING_<アプリケーション設定名>」という環境変数の値を取得すればよい。
これはPHPのphpinfo()の例。PHPなら「$_SERVER["<アプリケーション設定名>"]」で直接参照できる。
上記の環境変数に、アプリケーション設定の値、すなわち「@」から始まる参照文字列そのものが格納されていたら、Key Vaultシークレットへの参照が失敗しているので、設定を再確認すること。
注意したいのは、Key Vaultシークレットへの参照を設定していても、アプリケーションのインスタンス内部を参照可能なユーザーには秘密情報が閲覧されてしまう、という点だ。実際、上記のphpinfo()の出力では、インスタンス上の環境変数の値が平文で表示されている。つまり、何らかの方法で環境変数を参照できるなら、そこから漏えいする恐れがあるということだ。
本Tech TIPSで紹介している方法では漏えいの危険性を下げることはできても、完全に防ぐことはできない。引き続きアクセス権の制限などに注意を払う必要があるだろう。
Key Vaultシークレットの値を「更新」する
例えばApp Serviceからアクセスしているリソースで認証用パスワードが変更された場合、当然ながらApp Service側でもアプリケーション設定に含まれるパスワードを更新する必要がある。それがKey Vaultシークレットへの参照なら、Key Vault側でシークレットの内容を更新する必要がある。
ここで注意が必要なのは、Key Vaultシークレットの値を変更すると、それまでの値は「以前のバージョン」に、最新の値が「現在のバージョン」にそれぞれ扱いが変わるという点だ。つまり、上書き更新ではなく、新たな値が追加されつつ、過去の値は削除されることなく残るということである。以下にその追加手順を示す。
▼
▼
▼
■操作手順
- Azureポータルで[キーコンテナー]−[<Key Vault名>]を開く
- 左側メニューの「オブジェクト」欄にある[シークレット]をクリック
- 右ペインに表示された対象のシークレットをクリック
- 上部メニューの[新しいバージョン]をクリック
- [シークレットの作成]画面が表示されたら、[シークレット値]に更新後の新しい秘密情報(パスワードなど)を記入
- 下端の[作成]ボタンをクリック
「以前のバージョン」「現在のバージョン」にはそれぞれ16進数からなる識別子が付けられていて、参照する側からバージョンを特定して取得できるようになっている。App Serviceの場合、以下のように「SecretVersion=」の指定を参照文字列に追加すればよい。
@Microsoft.KeyVault(VaultName=<Key Vault名>;SecretName=<シークレット名>;SecretVersion=<バージョン番号>)
<バージョン番号>の指定を省略した場合、「現在のバージョン」すなわち最後に追加した最新の値が参照される。そのため、常に最新の値を参照するなら、<バージョン番号>を指定する必要はない。
ここで注意しなければならないのは、Key Vaultシークレットに新しい値を追加した後、App Serviceのアプリケーション設定の内容が最新の値に変わるタイミングだ。
App Serviceを放置した場合は、24時間以内に自動で最新値が反映される。
すぐに反映したいなら、App Serviceで何らかの設定変更をしてKey Vaultシークレットからの再取得を促す必要がある。筆者が試した限りでは、(対象とは関係のない)アプリケーション設定や接続文字列、[構成]−[全般設定]、[ネットワーク]−[アクセス制限]の設定を追加/変更/削除すると、その数秒〜十数秒後には、最新値が反映された。
一方、何の設定変更も伴わない単なる再起動や停止→起動では、最新値は反映されず、1つ前の値のまま変わらなかった。また、Key Vaultシークレットを参照しているアプリケーション設定の編集画面を開き、変更せずに保存しても、やはり変わらなかった。
■関連リンク
からの記事と詳細 ( 【Azure Key Vault】App Serviceのアプリケーション設定から「シークレット」な情報が漏れないようにする(Azure ... - @IT )
https://ift.tt/QeHKdoC
No comments:
Post a Comment