Heroku Postgres の資格情報
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2024年04月24日(水)
Postgres では、ロールの概念を使用してデータベースアクセスを管理します。ロールに対して、データベースに接続したときにそのロールが実行できる操作を定義する特定の権限を付与したり、付与した権限を取り消したりすることができます。
Heroku Postgres では、これらのロールを中心に、資格情報と呼ばれる管理レイヤーを提供しています。個々の資格情報は、異なる Postgres ロールと、各ロールに固有のデータベース権限のセットに対応しています。
資格情報は data.heroku.com または Heroku CLI から管理できます。資格情報は、本番クラスのプラン (Standard、Premium、Private、および Shield) でのみ利用可能です。Essential プランでは default
の資格情報のみ与えられており、他の資格情報を作成したりアクセス許可を管理したりすることはできません。Postgres の資格情報パスワードは、動的に生成される 65 バイトの英数字文字列です。
デフォルト資格情報
新しくプロビジョニングされたすべての Heroku Postgres データベースには、default
の資格情報が含まれています。この資格は、スーパーユーザーより 1 段階下の許容的なロールに対応します。この資格情報はデータベースの所有者です。これは次のことを実行できます。
- 新しいスキーマと、データベース内のオブジェクトを作成し、所有するあらゆるスキーマおよびオブジェクトを管理または変更する。
- 他の資格情報への権限の
GRANT
(付与)。 - 統計および監視データを読み取る。
default
の資格情報はpg_monitor
、pg_read_all_settings
、pg_read_all_stats
のメンバーです。 - 他のスーパーユーザー以外のバックエンドプロセスをキャンセルまたは終了する。
default
の資格情報はpg_signal_backend
のメンバーです。 - サポートされる拡張機能をインストールする。
CVE-2018-1058 から保護するために、デフォルトではどのユーザーも public
のスキーマにアクセスできません。デフォルトでは、新しい資格情報に public
スキーマへのアクセス権がありません。
新しい資格情報の作成
CVE-2018-1058 から保護するため、デフォルトでは、新しい資格情報はどのユーザーにも public
のスキーマへのアクセス権がありません。スキーマへのアクセスを必要とするすべてのユーザーに、public
のスキーマへのアクセス権限を再度付与する必要があります。
資格情報は、Heroku CLI および data.heroku.com から作成できます。
data.heroku.com から資格情報を作成するには:
- Heroku Postgres データベースを開きます。
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
name
パラメーターには資格情報の目的を反映した名前を付ける必要があります。この例では limited_user
が、データベースに接続するときの資格情報のユーザー名です。
どちらの場合も、資格情報パスワードは、動的に生成される 65 バイトの英数字文字列です。
CLI から作成された資格情報は、データベースへのログインには使用できますが、テーブルからの読み取りやテーブルへの書き込みは実行できません。
アクセス許可の管理
新規または既存の資格情報のアクセス許可は、Heroku CLI および data.heroku.com から設定できます。
data.heroku.com から資格情報を設定するには、資格情報を作成する際に、以下のさまざまなアクセスレベルのいずれかを選択します。または Credentials
タブに移動して、設定する資格情報を検索し、アクセスレベルの 1 つを選択することもできます。レベルは以下のとおりです。
- No permissions (アクセス許可なし): データベース内のどのテーブルに対するアクセス許可もありません
- Read-only permissions (読み取り専用アクセス許可): データベース内のすべてのテーブルに対する読み取りアクセス
- Read-write permissions (読み取り/書き込みアクセス許可): データベース内のすべてのテーブルに対する読み取りおよび書き込みアクセス (データの削除を含む)。さらに、シーケンスから値を生成することが可能
このテーブルには、ビュー、マテリアライズドビュー、外部テーブルも含まれます。設定された権限は、(異なるアクセス許可のセットで資格情報が再設定されるまでの間は) 将来作成するすべてのテブルにも適用されます。
すべてのユーザーは、データベースの構造と基本的な統計を記述する information_schema
および pg_catalog
スキーマのシステムカタログを読み取ることができます。これらのテーブルとビューには、このアクセスレベルは適用されません。
組み込みのアクセス許可レベルのいずれにも、テーブルやその他のデータベースオブジェクトを作成するためのアクセス許可はありません。
CLI から権限を設定するには、default
の資格情報を使用して 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;
このコマンドを使用すると、この資格情報で、public
のスキーマ内のテーブルやその他のデータベースオブジェクトをルックアップできます。
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;
各スキーマは明示的にリストする必要があります。一度にすべてのスキーマへのアクセス権を付与することはできません。ただし、特定のテーブルのみへのアクセスを付与できます。
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
analyst
の資格情報が作成されたため、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
アプリケーションに対する資格情報が必要でない場合、資格情報をアプリケーションから分離する必要があります。たとえば、example-app
アプリに添付されている analyst
という資格情報を削除するには、次の資格情報を含む環境設定で 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 の Postgres データベースの Credentials
タブからも利用できます。
pg:credentials
特定のデータベースに対して作成されているすべての資格情報の名前と状態を一覧表示するには、pg:credentials
コマンドを使用します。
$ heroku pg:credentials DATABASE_URL -a example-app
Credential State
────────── ──────
default active
analyst active
この例のデータベースには、1 つのカスタム資格情報 (analyst
) と default
の資格情報があります。資格情報がとりうる状態 (この例の active
など) については、「資格情報のローテーション状態の詳細」で説明しています。
pg:credentials:create
データベースの資格情報を作成するには、pg:credentials:create
コマンドを使用します。
$ heroku pg:credentials:create DATABASE_URL --name analyst -a example-app
Creating credential analyst.... done
--name
パラメーターは、データベース内の資格情報の名前です。
作成されたばかりの資格情報には 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
引数にログイン情報名を指定しない場合、default
の資格情報がローテーションされます。
$ 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
引数にログイン情報名を指定しない場合、default
の資格情報の接続詳細が stdout に出力されます。
pg:credentials:repair-default
デフォルトのアクセス許可またはデータベースオブジェクトの所有権が誤って変更された場合にデータベースの default
の資格情報を復元するには、pg:credentials:repair-default
コマンドを使用します。このコマンドを使用すると、default
の資格情報がデータベース内のすべてのオブジェクトの所有者になり、デフォルトのアクセス許可が復元され、データベース内のすべての追加資格情報に 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 を使用するアプリケーションでは、データベースへの接続を作成するときに default
の資格情報を使用する必要があります。スキーマを変更するときも同様です。default
の資格情報は、Heroku プラットフォーム全体とシームレスに連携するように設計されています。
読み取り専用ユーザー
Postgres 内の資格情報の一般的なパターンは、スキーマ内のすべての情報への読み取り専用アクセスをユーザーに与えるというものです。つまり、この資格情報によるデータの INSERT
、UPDATE
、DELETE
、またはスキーマの変更は実行できません。読み取り専用のユーザーは、Heroku Data Dashboard の “Credentials” (資格情報) タブを使用して、または CLI 経由で作成できます。
CLI から読み取り専用ユーザーを追加するには、まず資格情報を作成します。次に、default
の資格情報を使用して、データベースの 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
ステートメントの詳細と付与されるアクセス許可については、前出の「アクセス許可の管理」を参照してください。
注意事項と考慮事項
- アクセス許可の設定は永続的ではありません。
default
の資格情報またはWITH GRANT OPTION
の権限を持つその他の資格情報を使用して、いつでも更新できます。 - data.heroku.com の権限管理では、
default
の資格情報ですべてのテーブルとその他のデータベースオブジェクトを作成します。他の資格情報を使用してオブジェクトを作成すると、ユーザーにアクセス許可の設定で指定されたアクセスが自動的に付与されない可能性があります。 - 資格情報は、
CREATE ROLE
および関連 DDL ステートメントを直接使用する代わりに CLI または data.heroku.com から作成および破棄する必要がありますが、それ以外の点に関しては標準の Postgres 資格情報と同様に動作します。 - 資格情報の名前は英数字に制限されており (
-
と_
もサポートされています)、50 文字を超えてはなりません。 - 資格情報は PGBackups によってバックアップされず、バックアップから復元しても使用可能になりません。
制限
Heroku Postgres では 120 個までの資格情報がサポートされています。
セキュリティと運用上の理由から、使用する資格情報はできるだけ少なくすることを強くお勧めします。資格情報を使用している場所を必ず追跡してください。