🍙

Azure FunctionsからAzure Web Apps 上のAPIを呼び出すときの認証認可について(Python)

2021/10/26に公開

人が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への実行許可を出したい

参考ドキュメント

https://docs.microsoft.com/ja-jp/azure/developer/python/azure-sdk-authenticate

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した情報)で認証してくれます。
つまり、このクラスを使って認証を書けば、ローカル環境でのテストで簡単に実現できます。
ローカル環境の設定方法については、この記事では記載しませんので、下記のドキュメントをご参照ください。
https://docs.microsoft.com/ja-jp/azure/developer/python/configure-local-development-environment?tabs=cmd

Discussion