Azure FunctionsからAzure Web Apps 上のAPIを呼び出すときの認証認可について(Python)
人がwebアプリ使うとき、通常認証の為にIDとパスワードを入力します。
(ワンタイムパスワードや生体認証もありますが、一旦おいておきます)
では、人の手を介さずにイベント駆動するAzure Functionsがアプリを使う時の認証はどうすればよいでしょうか?
人と同じ用にIDやパスワードを入力させるという手段もありますが、そのためにはAzure Functionsにパスワードを保存しておく必要があり、セキュリティ的にイマイチです。
更にいうとAzureADは、パスワードを一定期間で強制的に変更させるという残念な仕様の為、
この方式だと定期的にパスワードの設定を変更する必要があり、とても面倒くさいです。
ということで、よりよい方法を考えます。
やりたいこと
- Azure Functions(Python)からAzure Web Apps上に構築したAPIを呼びたい
- Azure Web AppsはEasy Authで認証・認可を構築済とする
- Azure Functionsの中でAADのユーザーIDやパスワードを入力するのではなく、ロールベースでFunctions自体にAPIへの実行許可を出したい
参考ドキュメント
Azure Functionsで認証情報を取得して、APIを呼び出すコード
Azure Functionsで必要は処理は下記のようになります
-
DefaultAzureCredential()
を使って認証 - AccessTokenを取得
- AuthorizationヘッダーにAccessTokenを付けてAPI呼び出し
import requests
from azure.core.credentials import AccessToken
from azure.identity import DefaultAzureCredential
# tokenの取得
credential = DefaultAzureCredential()
scope = "https://(web appsの名前).azurewebsites.net/.default"
token: AccessToken = credential.get_token(scope)
# api呼び出し(Authorization以外のパラメータはいい感じに書き換えること)
headers["Authorization"] = "Bearer " + token.token
requests.get("https://(web appsの名前).azurewebsites.net/api/hello_world", headers=headers)
補足:DefaultAzureCredentialという便利クラスについて
上記のソースコードでは、DefaultAzureCredential
を使いました。
今回の目的はマネージドIDで認証することなので、ManagedIdentityCredential
を使えば良さそうに見えますし、実際にAzure上で問題なく動作します。しかし、ManagedIdentityCredential
はローカル環境では動かないので、動作確認の度にAzure上へのDeployが必要になります。
一方でDefaultAzureCredential
を使えば、Azure上で実行するとマネージドIDを用いて認証するし、ローカル環境で実行するとローカル環境の認証情報(az loginした情報)で認証してくれます。
つまり、このクラスを使って認証を書けば、ローカル環境でのテストで簡単に実現できます。
ローカル環境の設定方法については、この記事では記載しませんので、下記のドキュメントをご参照ください。
Discussion