LoginSignup
1
2

Azure App Service から Azure Database for PostgreSQL にパスワードレス認証

Last updated at Posted at 2023-11-03

一応できたものの、まだ全容を掴めていないのでかなりメモっぽい感じでまとめる。

やりたいこと

Azure App Service から Azure Database for PostgreSQL にパスワードレス認証したい。

現状は普通に PostgreSQL ユーザを作成してその認証情報を App Service に渡して接続しているが、これをやめたい。

ざっくり仕組み解説

  • アクセス元リソース (App Service) の「マネージド ID」を発行して「サービスプリンシパル」として扱えるようにしておく
  • データベース側でアクセスを許可する接続元として「サービスプリンシパル」を登録しておく
  • 接続時は「マネージド ID」をもとに一時アクセストークンを入手し、それをパスワードとして使用することでデータベース側で認証できる

image.png

※ 図は Azure の公式ドキュメント から引用
※ この図はユーザプリンシパルのケースを説明しているため Step1 で az login しているが、今回のケースではこれに相当する操作は不要

初期設定手順

Azure Portal の画面から操作した手順を記載する。

1. App Service 側でマネージド ID を有効化する

App Service > ID > システム割り当て済みオン に設定する。

これによって App Service の「オブジェクト ID (プリンシパル ID)」が発行される。

2. データベースの認証方式として Microsoft Entra 認証を有効化する

Azure Database for PostgreSQL > 認証 > アクセスの割り当て先PostgreSQL と Microsoft Entra 認証 に設定する。

この設定を変更するとデータベースサーバが再起動する。

3. App Service に紐づく (?) サービスプリンシパルを管理者として追加する

Azure Database for PostgreSQL > 認証 > Microsoft Entra 管理者 でサービスプリンシパルを追加する。 1. で発行されたオブジェクト ID を入力したらいけた。

4. データベース内の権限を付与

3. までで認証が通ってデータベースに接続できるようにはなるのだが、このままだとテーブルなどの操作権限がなくて何もできない。

普通の PostgreSQL のパスワード認証で管理者ユーザで接続して、下記 SQL を実行して権限を付与する。

GRANT ALL PRIVILEGES ON DATABASE <DB_NAME> TO "<SERVICE_PRINCIPAL_NAME>";
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "<SERVICE_PRINCIPAL_NAME>";
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO "<SERVICE_PRINCIPAL_NAME>";

※ この例では何でもできる権限をつけているが、必要に応じて制限した方がよさそう。

接続手順

今回の App Service では Python アプリが動いていたので、Python から接続するパターンを考える。

1. 一時アクセストークンを取得する

azure-identity ってモジュールを pip で入れておけば、以下のノリでデータベース接続用の一時アクセストークンが得られる。

from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
token = credential.get_token("https://ossrdbms-aad.database.windows.net/.default")

print(token.token)

実際は get_connection みたいな関数に包むなどしてもうちょっといい感じに書く。

2. データベースに接続する

以下の情報を使って PostgreSQL クライアントを使って接続する。

  • ユーザ名として、初期設定の際にデータベースの Microsoft Entra 管理者として追加したサービスプリンシパルの 名前 (オブジェクト ID ではない) を使用
  • パスワードとして、上記 1. で取得した一時アクセストークンを使用

注意点としては、アプリケーション起動時にトークンを取得するような作りにしてしまうと トークンの期限が切れたときに更新されず、再接続時に死ぬ ので、必ず「接続が作られるとき」にトークンを取得するようにやる。例えば SQLAlchemy であれば do_connect イベントとか creator, async_creator オプションとかを使うとよい。

わかっていないこと

  • この Managed Identity による方法はいわゆる「RBAC (Role Based Access Control)」とは異なる概念ってことでいいのだろうか? 今回特にロールは触ってないし...
  • 今回はデータベース内の操作権限を付与するために通常の PostgreSQL ユーザを作成したが、これを回避して Microsoft Entra 認証だけで初期設定することは出来ないか?
  • 今回の方法とは別に App Service の「サービスコネクタ」を作成する方法もあるようだが、何が違うのか?

参考資料

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2