Heroku Postgres の資格情報
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2022年10月13日(木)
Postgres では、ロールの概念を使用してデータベースアクセスを管理します。ロールには、データベースに接続したときにそのロールが実行できる操作を定義する特定の権限を付与する (また、付与した権限を取り消す) ことができます。
Heroku Postgres では、これらのロールを中心に、資格情報と呼ばれる管理レイヤーを提供しています。個々の資格情報は、異なる Postgres ロールと、各ロールに固有のデータベース権限のセットに対応しています。
資格情報は data.heroku.com または Heroku CLI から管理できます。 資格情報は、本番クラスのプラン (Standard、Premium、Private、および Shield) でのみ利用可能です。条件を満たさないプランにはデフォルト資格情報のみが含まれます。この資格情報では、他の資格情報の作成やアクセス許可の管理はできません。Postgres の資格情報パスワードは、動的に生成される 65 バイトの英数字文字列です。
デフォルト資格情報
新しくプロビジョニングされたすべての Heroku Postgres データベースには、デフォルト資格情報が含まれています。この資格は、スーパーユーザーより 1 段階下の許容的なロールに対応します。以下の操作を実行できます。
- 他の資格情報への権限の
GRANT
(付与) - データベース内のテーブルに対する
SELECT
の実行 - 新しいデータの
INSERT
(挿入) - データの
UPDATE
(更新) - テーブルからのデータの
DELETE
(削除) - Postgres 10 以上での、一部の使用統計および監視データの表示
新しい資格情報の作成
新しい資格情報は、Heroku CLI と data.heroku.com のどちらからでも作成できます。
data.heroku.com から資格情報を作成するには、Credentials
(資格情報) タブを選択して Create Credential
(資格情報の作成) ボタンをクリックします。
CLI コマンド pg:credentials:create
を使用して資格情報を作成することもできます。
$ heroku pg:credentials:create postgresql-sunny-1234 --name limited_user -a example-app
Creating credential limited_user... done
資格情報の目的を反映した名前を付けてください。上記の例では、データベースに接続するときの資格情報のユーザー名として limited_user
を使用しています。
どちらの場合も、資格情報パスワードは、動的に生成される 65 バイトの英数字文字列です。
CLI から作成された資格情報は、データベースへのログインには使用できますが、テーブルからの読み取りやテーブルへの書き込みは実行できません。
アクセス許可の管理
新規または既存の資格情報のアクセス許可は、Heroku CLI と data.heroku.com のどちらからでも設定できます。
data.heroku.com 経由で資格情報を設定するには、資格情報の作成時に下にある各種のアクセスレベルのいずれかを選択するか、または “Credentials” (資格情報) タブに移動し、設定する資格情報を見つけて、いずれかのアクセス許可レベルを選択します。レベルは以下のとおりです。
- No permissions (アクセス許可なし) — データベース内のどのテーブルに対するアクセス権限もありません
- Read-only permissions (読み取り専用アクセス許可) — データベース内のすべてのテーブルに対する読み取りアクセス
- Read-write permissions (読み取り/書き込みアクセス許可) — データベース内のすべてのテーブルに対する読み取りおよび書き込みアクセス (データの削除を含む)。これに加えて、シーケンスから値を生成することが可能
前述した “テーブル” には、ビュー、マテリアライズドビュー、外部テーブルも含まれることに注意してください。設定された権限は、(異なるアクセス許可のセットで資格情報が再設定されるまでの間は) 将来作成されるすべてのテーブルにも適用されます。
また、すべてのユーザーが、データベースの構造と基本的な統計を記述する information_schema
および pg_catalog
スキーマのシステムカタログを読み取ることができることに注意してください。これらのテーブルとビューには、上記のアクセス許可は適用されません。
組み込みのアクセス許可レベルのどれにも、新しいテーブルやその他のデータベースオブジェクトを作成するためのアクセス権はありません。
CLI から権限を設定するには、デフォルト資格情報を使用して psql
コンソールにログインし、Postgres の標準の GRANT、REVOKE、および ALTER DEFAULT PRIVILEGES コマンドを実行します。
たとえば、パブリックスキーマへの読み取り専用アクセスの権限の上から limited_user
資格情報を付与できます。これは標準 Postgres 規則に従います。
$ heroku pg:psql postgresql-sunny-1234 -a example-app
--> Connecting to postgresql-sunny-1234
psql (13.2, server 11.12 (Ubuntu 11.12-1.pgdg16.04+1))
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
example-app::CYAN=> GRANT USAGE ON SCHEMA PUBLIC TO limited_user;
GRANT
example-app::CYAN=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO limited_user;
GRANT
example-app::CYAN=> ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO limited_user;
ALTER PRIVILEGES
example-app::CYAN=> \q
この例では、limited_user
資格情報には、public
というスキーマ内の任意のテーブルに対して読み取り専用クエリを実行するために必要な権限が付与されています。この時点で、limited_user
を使用してデータベースにログインし、そのデータベース内の情報を操作できます。
これをステップごとに説明します。
GRANT USAGE ON SCHEMA PUBLIC TO limited_user;
この資格情報で、スキーマ内のテーブルやその他のデータベースオブジェクトをルックアップできるようにします。
GRANT SELECT ON ALL TABLES IN SCHEMA public TO limited_user;
この資格情報で、スキーマ “public” (デフォルトスキーマ) 内の任意のテーブル、ビュー、マテリアライズドビュー、または外部テーブルに対して SELECT を実行できるようにします。追加のスキーマを使用していて、それらのスキーマへのアクセスを付与する場合は、カンマで区切ってスキーマを追加できます。
GRANT SELECT ON ALL TABLES IN SCHEMA public, my_schema TO limited_user;
1 つ 1 つのスキーマを明示的にリストに含める必要があります。すべてのスキーマへのアクセスを一度に付与することはできません。ただし、特定のテーブルのみへのアクセスを付与できます。
GRANT SELECT ON TABLE public.users TO limited_user;
最後は次のとおりです。
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO limited_user;
この資格情報に、スキーマ “public” のデフォルトユーザーによって作成された新しいテーブル、ビュー、マテリアライズドビュー、または外部テーブルのすべてに対する SELECT 権限が自動的に付与されるようにします。ALTER DEFAULT PRIVILEGES
コマンドを使用すると、まだ作成していないテーブルやその他のデータベースオブジェクトに対する権限を事前に設定できます。前述した GRANT と異なり、すべてのスキーマのデフォルト権限を変更することもできます。
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES TO limited_user;
ロールの権限を制限したい場合は必ず、より制限された権限を付与する前に、既存のアクセスを取り消してください。たとえば、パブリックスキーマ内のテーブルに対する SELECT
および UPDATE
を以前に付与されていたユーザーの権限を変更するには、次のように実行します。
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM limited_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO limited_user;
資格情報の設定方法についての詳細は、ロールと権限、また GRANT、REVOKE、ALTER DEFAULT PRIVILEGES の各コマンドに関する Postgres コミュニティのドキュメントを参照してください。
アプリへの資格情報のアタッチ
addons:attach
Heroku Postgres 内で作成された資格情報は、addons:attach
コマンドを使用して環境設定としてアプリにアタッチできます。新しい資格情報が作成済みであるとします。
$ heroku pg:credentials:create postgresql-sunny-1234 --name analyst -a example-app
Creating credential analyst.... done
アナリストの資格情報が作成されたので、Heroku 内の任意の数のアプリケーションにこの資格情報をアタッチできます。これは請求アプリケーションの場合もあれば、アクセスを必要とするその他のアプリケーションの場合もあります。
$ heroku addons:attach postgresql-sunny-1234 --credential analyst -a example-app
Attaching analyst of postgresql-sunny-1234 to ⬢ example-app... done
Setting DATABASE config vars and restarting ⬢ example-app... done, v24
データベースのアタッチ先アプリケーションの一部として他の Heroku Postgres が存在しない場合、資格情報は DATABASE_URL
環境設定に割り当てられます。DATABASE_URL
がすでにアプリケーションに存在する場合、資格情報は HEROKU_POSTGRESQL_[COLOR]_URL
の形式を使用してアプリケーションにアタッチされます。
addons:detach
アプリケーションに対する資格情報が必要でない場合、資格情報をアプリケーションから分離する必要があります。analyst
という資格情報が作成されて example-app
アプリケーションにアタッチされている場合、その資格情報を削除するには、その資格情報を含む環境設定と組み合わせて addons:detach
コマンドを使用する必要があります。
$ heroku addons:detach DATABASE -a example-app
Detaching DATABASE from postgresql-sunny-1234 from ⬢ example-app... done
Unsetting DATABASE config vars and restarting ⬢ example-app... done, v23
資格情報の管理
Heroku CLI では、Postgres の資格情報を管理するための複数のコマンドを提供しています。この機能は data.heroku.com の Credentials
(資格情報) タブからも利用できます。
pg:credentials
特定のデータベースに対して作成されているすべての資格情報の名前と状態を一覧表示するには、pg:credentials
コマンドを使用します。
$ heroku pg:credentials DATABASE_URL -a example-app
Credential State
────────── ──────
default active
analyst active
上記の例のデータベースには、1 つのカスタム資格情報 (analyst
) とデフォルト資格情報があります。
資格情報がとりうる状態 (上記の例の active
など) については、「資格情報のローテーション状態の詳細」で説明しています。
pg:credentials:create
データベースの新しい資格情報を作成するには、pg:credentials:create
コマンドを使用します。
$ heroku pg:credentials:create DATABASE_URL --name analyst -a example-app
Creating credential analyst.... done
作成されたばかりの資格情報には CONNECT
権限しかありません。新しい資格情報のアクセスを設定する方法については、「アクセス許可の管理」を参照してください。
pg:credentials:destroy
pg:credentials:destroy
コマンドで Postgres から資格情報を削除します。
$ heroku pg:credentials:destroy DATABASE --name analyst -a example-app
▸ WARNING: Destructive action
▸ To proceed, type example-app or re-run this command with --confirm example-app
> example-app
Destroying credential analyst... done
The credential has been destroyed within postgresql-solid-58569 and detached from all apps.
Database objects owned by analyst will be assigned to the default credential
データベースから資格情報を削除するには、確認が必要です。資格情報がアプリケーションにアタッチされている場合、分離してからでないと資格情報を破棄できません。
セカンダリアプリケーションから資格情報を削除する方法について、詳しくは heroku addons:detach
のヘルプを参照してください。
pg:credentials:rotate
資格情報に関連付けられているパスワードを置き換えることが必要な場合があります。一般的に、資格情報の定期的なローテーションは優れたセキュリティ対策です。
pg:credentials:rotate
コマンドを使用すると、データベース内の資格情報パスワードの一部またはすべてを一度に変更できます。資格情報のローテーションが発生すると、影響を受けるすべてのアプリに Heroku Postgres から通知が出され、新しい資格情報を取得するためにアプリが再起動します。
1 つの資格情報のローテーションは次のようになります。
$ heroku pg:credentials:rotate DATABASE --name analyst -a example-app
▸ WARNING: Destructive action
▸ To proceed, type example-app or re-run this command with --confirm example-app
> example-app
Rotating analyst on postgresql-solid-58569... done
--name
引数に値を指定しない場合、デフォルト資格情報がローテーションされます。
$ heroku pg:credentials:rotate DATABASE -a example-app
▸ WARNING: Destructive action
▸ To proceed, type example-app or re-run this command with --confirm example-app
> example-app
Rotating default on postgresql-solid-58569... done
すべての資格情報をローテーションするには、--all
フラグをコマンドに渡します。
$ heroku pg:credentials:rotate DATABASE --all -a example-app
▸ WARNING: Destructive action
▸ To proceed, type example-app or re-run this command with --confirm example-app
> example-app
Rotating all credentials on postgresql-solid-58569... done
資格情報のローテーション状態の詳細
資格情報のローテーションが要求されたとき、アプリケーションでデータベースへの接続が開いている場合があります。進行中のトランザクションを完了するために、Heroku Postgres は約 30 分待ってから、既存の接続を強制終了し、新しいログイン詳細を使用するようクライアントに要求します。
資格情報のローテーション中、進行中のトランザクションが存在する場合、Heroku Postgres は、一時的な “rotating” というユーザー名を現在使用中のユーザー名に加えてプロビジョニングします。ローテーション中、pg:credentials
コマンドはこれらのユーザー名を表示し、一時的であることを示す -rotating
がすべての名前の末尾に付きます。
$ heroku pg:credentials:rotate DATABASE --name analyst -a example-app --confirm
Rotating analyst on postgresql-solid-58569... done
$ heroku pg:credentials -a example-app
Credential State
──────────────────────────────────────────── ──────────
default created
analyst rotating
Usernames currently active for this credential:
analyst-rotating active 0 connections
analyst waiting for no connections to be revoked 0 connections
これらの進行中のトランザクションが完了し、関連付けられた接続が閉じた後、“rotating” のユーザー名は元のユーザー名に変更されます。ローテーションの間に作成された接続はどれも、この名前変更が発生する前に停止することが認められています。
強制ローテーション
接続が閉じるまで 30 分間待つのは長すぎる場合があります。そのような場合、--force
フラグを使用できます。--force
を指定すると、資格情報へのすべての接続をすぐに強制終了してローテーションを実行します。
$ heroku pg:credentials:rotate DATABASE --name analyst --force -a example-app --confirm
Rotating analyst on postgresql-solid-58569... done
pg:credentials:url
pg:credentials:url
コマンドは、さまざまな視覚化ツールでアクセスできるよう、データベースの場所とログイン資格情報への便利なアクセスを提供します。
$ heroku pg:credentials:url DATABASE --name analyst -a example-app
Connection information for analyst credential
Connection info string:
"dbname=dee932clc3mg8h host=ec2-123-73-145-214.compute-1.amazonaws.com port=6212 user=analyst password=98kd8a9 sslmode=require"
Connection URL:
postgres://analyst:98kd8a9@ec2-123-73-145-214.compute-1.amazonaws.com:6212/dee932clc3mg8h
--name
引数に値を指定しない場合、デフォルト資格情報の接続詳細が stdout に出力されます。
pg:credentials:repair-default
デフォルトのアクセス許可またはデータベースオブジェクトの所有権が誤って変更された場合にデータベースのデフォルト資格情報を復元するには、pg:credentials:repair-default コマンドを使用します。これにより、デフォルト資格情報がデータベース内のすべてのオブジェクトの所有者になり、デフォルトのアクセス許可が復元され、データベース内のすべての追加資格情報にデフォルト資格情報の管理オプションが付与されます。
$ heroku pg:credentials:repair-default DATABASE -a example-app
Resetting permissions and object ownership for default role to factory settings... done
フォークとフォロワー
Heroku Postgres のフォロワーデータベースは、それに対応するプライマリデータベースの (ほぼ) 正確なコピーです。プライマリデータベースに変更が加えられると、それらの変更はリアルタイムでフォロワーにストリーミングされます。したがって、プライマリデータベースで作成された資格情報はすべて、フォロワーに自動的に伝播します。 フォロワーデータベースの資格情報はプライマリデータベースの資格情報と一致しますが、フォロワーは本質的に読み取り専用であり、(書き込みアクセス許可を持っている場合でも) どのロールによっても書き込むことができません。unfollow コマンドを実行すると、フォロワーはフォークになり、必要なアクセス許可を持っているすべての資格情報で書き込みができるようになります。
create、destroy、rotate などの資格情報コマンドをフォロワーに対して実行すると、データベースに対してコマンドを実行できないことを示すエラーメッセージが表示されます。
$ heroku pg:credentials:create postgresql-moonlight-5678 -a example-app
This operation is not supported for follower databases.
フォークは、別の既存の Heroku Postgres データベースからのデータのスナップショットを含むまったく新しいデータベースです。フォロワーデータベースと異なり、フォークはプライマリデータベースと同期されるわけではないため、書き込み可能です。 フォークが作成されると、フォークの時点でプライマリデータベースにあったすべての資格情報がフォークに取り込まれます。ただし、プライマリデータベースの資格情報に対する将来の変更は、フォークに反映されません。
ベストプラクティス
デフォルト資格情報の使用
データストアとして Heroku Postgres を使用するアプリケーションでは、データベースへの接続を作成するときにデフォルト資格情報を使用してください。スキーマを変更するときも同様です。デフォルト資格情報は、Heroku プラットフォーム全体とシームレスに連携するように設計されています。
読み取り専用ユーザー
Postgres 内の資格情報の一般的なパターンは、スキーマ内のすべての情報への読み取り専用アクセスをユーザーに与えるというものです。つまり、この資格情報によるデータの INSERT
、UPDATE
、DELETE
、またはスキーマの変更は実行できません。読み取り専用のユーザーは、Heroku Data Dashboard の “Credentials” (資格情報) タブを使用して、または CLI 経由で作成できます。
CLI から読み取り専用ユーザーを追加するには、まず前の手順のように資格情報を作成します。次に、デフォルト資格情報を使用して、データベースの Postgres コンソールにログインします。
$ heroku pg:psql postgresql-sunny-1234 -a example-app
--> Connecting to postgresql-sunny-1234
psql (13.2, server 11.12 (Ubuntu 11.12-1.pgdg16.04+1))
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
example-app::CYAN=> GRANT USAGE ON SCHEMA PUBLIC TO analyst;
GRANT
example-app::CYAN=> GRANT SELECT ON ALL TABLES IN SCHEMA PUBLIC
TO analyst; -- give access to the existing tables
GRANT
example-app::CYAN=> ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO analyst; -- give access to future tables
ALTER PRIVILEGES
ステートメントの詳細と付与されるアクセス許可については、前出の「アクセス許可の管理」を参照してください。
注意事項と考慮事項
- アクセス許可の設定は永続的ではありません。デフォルト資格情報、または WITH GRANT OPTION 権限を持つその他の資格情報によっていつでも更新できます。
- data.heroku.com のアクセス許可管理では、すべてのテーブルとその他のデータベースオブジェクトをデフォルト資格情報で作成することを想定しています。それ以外の資格情報を使用してオブジェクトを作成すると、ユーザーのアクセス許可設定で指定されているアクセス権がユーザーに自動的に付与されない場合があります。
- 資格情報は、CREATE ROLE と関連 DDL ステートメントを直接使用する代わりに CLI または data.heroku.com から作成および破棄する必要がありますが、それ以外の点に関しては標準の Postgres 資格情報と同様に動作します。
- 資格情報の名前は英数字に制限されており (
-
と_
もサポートされています)、50 文字を超えてはなりません。 - 資格情報は PGBackups によってバックアップされず、バックアップから復元しても使用可能になりません。
制限
Heroku Postgres では現在、60 個までの資格情報がサポートされています。