

# Amazon Aurora PostgreSQL でのセキュリティ
<a name="AuroraPostgreSQL.Security"></a>

Aurora のセキュリティの概要については、「[ Amazon Aurora でのセキュリティ](UsingWithRDS.md)」を参照してください。Amazon Aurora PostgreSQL のセキュリティは、いくつかの異なるレベルで管理できます。
+ Aurora PostgreSQL DB クラスターと DB インスタンスに対し Amazon RDS 管理アクションを実行できるユーザーを管理するには、AWS Identity and Access Management (IAM) を使用します。IAM は、ユーザーがサービスにアクセスする前に、ユーザー ID の認証を処理します。また、承認、つまりユーザーが行おうとしていることが許可されているかどうかについても処理します。IAM データベース認証は、Aurora PostgreSQL DB クラスターを作成するときに選択できる追加の認証方法です。詳細については、「[Amazon Aurora での Identity and Access Management](UsingWithRDS.IAM.md)」を参照してください。

  IAM を Aurora PostgreSQL DB クラスターで使用する場合は、Amazon RDS コンソールを [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/) で開く前に、まず、IAM 認証情報を使用して AWS マネジメントコンソール にサインインしてください。
+ Aurora DB クラスターを Amazon VPC サービスに基づいて仮想プライベートクラウド (VPC) で作成してください。VPC 内の Aurora DB クラスター用の DB インスタンスのエンドポイントとポートに対して接続を開くことができるデバイスと Amazon EC2 インスタンスを制御するには、VPC セキュリティグループを使用します。これらのエンドポイントとポート接続は、Secure Sockets Layer (SSL) を使用して作成できます。さらに、会社のファイアウォールルールでも、社内のいずれのデバイスが DB インスタンスへの接続を開くことができるかを制御できます。VPC の詳細については、「[Amazon VPC と Amazon Aurora](USER_VPC.md)」を参照してください。

  サポートされている VPC テナンシーは、Aurora PostgreSQL DB クラスターで使用しているインスタンスクラスによって異なります。`default` VPC テナンシーでは、DB クラスターは共有ハードウェアで実行されます。`dedicated` VPC テナンシーでは、DB クラスターは専用ハードウェアインスタンスで実行されます。バーストパフォーマンス DB インスタンスクラスでは、デフォルト VPC テナンシーのみがサポートされています。バーストパフォーマンス DB インスタンスクラスには、db.t3 および db.t4g DB インスタンスクラスが含まれます。その他すべての Aurora PostgreSQL DB インスタンスクラスでは、デフォルトと専用 VPC テナンシーの両方がサポートされています。

  インスタンスクラスの詳細については、「[Amazon Aurora DB インスタンスクラス](Concepts.DBInstanceClass.md)」を参照してください。`default` および `dedicated` VPC テナントの詳細については、*Amazon Elastic Compute Cloud ユーザーガイド*の「[ハードウェア専有インスタンス](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html)」を参照してください。
+ Amazon Aurora DB クラスターで実行されている PostgreSQL データベースにアクセス権限を付与するには、PostgreSQL のスタンドアロンインスタンスと同じ一般的なアプローチを使用します。`CREATE ROLE`、`ALTER ROLE`、`GRANT`、`REVOKE` などのコマンドは、オンプレミスデータベースでの方法と同様に、データベース、スキーマ、およびテーブルを直接変更します。

  PostgreSQL は、*ロール*を使用して権限を管理します。`rds_superuser` ロールは、Aurora PostgreSQL DB クラスターで最も権限があるロールです。このロールは自動的に作成され、DB クラスターを作成するユーザー (マスターユーザーアカウント、デフォルトでは `postgres`) に付与されます。詳細については[PostgreSQL のロールとアクセス権限について](Appendix.PostgreSQL.CommonDBATasks.Roles.md)を参照してください。

バージョン 10、11、12、13、14 以降のリリースを含む Aurora PostgreSQL バージョンでは、メッセージダイジェスト (MD5) の代替として、Salted Challenge Response Authentication Mechanism (SCRAM) がサポートされています。SCRAM は MD5 よりも安全であるため、使用が推奨されています。データベースユーザーパスワードを MD5 から SCRAM に移行する方法など、詳細については、「[PostgreSQL のパスワード暗号化に SCRAM を使用する](PostgreSQL_Password_Encryption_configuration.md)」を参照してください。

# PostgreSQL のロールとアクセス権限について
<a name="Appendix.PostgreSQL.CommonDBATasks.Roles"></a>

AWS マネジメントコンソール を使用してAurora PostgreSQL DB クラスター を作成すると、管理者アカウントが同時に作成されます。次のスクリーンショットに示すように、デフォルトでは `postgres` という名前になります。

![\[「データベースを作成」ページの認証情報のデフォルトのログイン ID は postgres です。\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/images/default-login-identity-apg-rpg.png)


デフォルト設定 (`postgres`) を受け入れるのではなく、別の名前を選択することもできます。この場合、選択する名前はアルファベットで始まり、1 文字以上 16 文字以下の英数字である必要があります。このガイドでは、わかりやすくするために、このメインユーザーアカウントをデフォルトの値 (`postgres`) で表記しています。

AWS マネジメントコンソール ではなく`create-db-cluster` AWS CLI を使用する場合は、`master-username` パラメータと一緒に渡すことでユーザー名を作成します。詳細については、 を参照してください。[ステップ 2: Aurora PostgreSQL DB クラスターを作成する](CHAP_GettingStartedAurora.AuroraPostgreSQL.FullConfig.md#CHAP_GettingStarted.AuroraPostgreSQL.CreateDBCluster)

AWS マネジメントコンソール、AWS CLI、または Amazon RDS API のいずれを使用する場合でも、またデフォルトの `postgres` 名を使用するか、別の名前を選択するかにかかわらず、この最初のデータベースユーザーアカウントは `rds_superuser` グループのメンバーであり、`rds_superuser` 権限を持つことになります。

**Topics**
+ [rds\$1superuser ロールを理解する](Appendix.PostgreSQL.CommonDBATasks.Roles.rds_superuser.md)
+ [PostgreSQL データベースへのユーザーアクセスのコントロール](Appendix.PostgreSQL.CommonDBATasks.Access.md)
+ [ユーザーパスワード管理の委任と制御](Appendix.PostgreSQL.CommonDBATasks.RestrictPasswordMgmt.md)
+ [PostgreSQL のパスワード暗号化に SCRAM を使用する](PostgreSQL_Password_Encryption_configuration.md)

# rds\$1superuser ロールを理解する
<a name="Appendix.PostgreSQL.CommonDBATasks.Roles.rds_superuser"></a>

PostgreSQL では、*ロール*はデータベース内のさまざまなオブジェクトに対して、ユーザー、グループ、またはグループやユーザーに与えられた特定のアクセス権限を定義することができます。`CREATE USER` と `CREATE GROUP` に対する PostgreSQL コマンドは、データベースユーザーを区別するために、より一般的な、特定のプロパティを持つ `CREATE ROLE` に置き換えられました。データベースユーザーは、LOGIN 権限を持つロールと考えることができます。

**注記**  
`CREATE USER` および `CREATE GROUP` コマンドは引き続き使用できます。詳細については、PostgreSQL のドキュメントの「[データベースロール](https://www.postgresql.org/docs/current/user-manag.html)」セクションを参照してください。

`postgres` ユーザーは、Aurora PostgreSQL DB クラスター で最も権限があるデータベースユーザーです。ユーザーには、次の `CREATE ROLE` ステートメントで定義される特性があります。

```
CREATE ROLE postgres WITH LOGIN NOSUPERUSER INHERIT CREATEDB CREATEROLE NOREPLICATION VALID UNTIL 'infinity'
```

特に指定がない限り、プロパティ `NOSUPERUSER`、`NOREPLICATION`、`INHERIT`、および `VALID UNTIL 'infinity'` が CREATE ROLE のデフォルトオプションです。

デフォルトでは、`postgres` には `rds_superuser` ロールに付与された権限と、ロールとデータベースを作成するアクセス許可があります。`rds_superuser` ロールでは、`postgres` ユーザーによる次の操作を許可します。
+  Aurora PostgreSQL」を参照してください。詳細については、 を参照してください。[エクステンションと外部データラッパーの使用](Appendix.PostgreSQL.CommonDBATasks.md)
+ ユーザーのロールを作成し、ユーザーに権限を付与します。詳細については、PostgreSQL のドキュメントの「[CREATE ROLE](https://www.postgresql.org/docs/current/sql-createrole.html)」および「[GRANT](https://www.postgresql.org/docs/14/sql-grant.html)」セクションを参照してください。
+ データベースの作成 詳細については、PostgreSQL のドキュメントの「[CREATE DATABASE](https://www.postgresql.org/docs/14/sql-createdatabase.html)」を参照してください。
+ これらの権限を持たないユーザーロールに対する `rds_superuser` 権限を付与し、必要に応じてそれらの権限を取り消します。このロールは、スーパーユーザータスクを実行するユーザーにのみ付与することをお勧めします。つまり、データベース管理者 (DBA) またはシステム管理者にこのロールを付与できます。
+ `rds_superuser` ロールを持たないデータベースユーザーに `rds_replication` ロールを付与 (または取り消し) します。
+ `rds_superuser` ロールを持たないデータベースユーザーに `rds_password` ロールを付与 (または取り消し) します。
+ `pg_stat_activity` ビューを使用して、すべてのデータベース接続に関するステータス情報を取得します。必要に応じて、`rds_superuser` で `pg_terminate_backend` または `pg_cancel_backend` を使用して接続を停止できます。

`CREATE ROLE postgres...` ステートメントで、`postgres` ユーザーロールは PostgreSQL の `superuser` アクセス許可を特に禁止することがわかります。Aurora PostgreSQL はマネージドサービスのため、ホスト OS へのアクセスや、PostgreSQL `superuser` アカウントを使用した接続はできません。スタンドアロンの PostgreSQL で `superuser` のアクセスが必要な作業の多くは、Aurora で自動的に管理されます。

権限の付与に関する詳細については、PostgreSQL のドキュメントの「[GRANT](http://www.postgresql.org/docs/current/sql-grant.html)」を参照してください。

`rds_superuser` ロールは、Aurora PostgreSQL DB クラスターにおけるいくつかの*事前定義済み*ロールの 1 つです。

**注記**  
PostgreSQL 13 以前のリリースでは、*定義済み*ロールは*デフォルト*ロールと呼ばれていました。

次のリストに、新しい Aurora PostgreSQL DB クラスターのために自動的に作成される他の定義済みロールの一部を示します。定義済みロールとその権限は変更できません。これらの定義済みロールに対して削除、名前の変更、変更を行うことはできません。それらの操作を試みると、エラーが発生します。
+ **rds\$1password** - データベースユーザーのパスワードを変更し、パスワード制約を設定できるロールです。`rds_superuser` ロールにはデフォルトでこのロールが付与され、データベースユーザーにロールを付与できます。詳細については、「[PostgreSQL データベースへのユーザーアクセスのコントロールPostgreSQL へのユーザーアクセスのコントロール](Appendix.PostgreSQL.CommonDBATasks.Access.md)」を参照してください。
  + 14 より前のバージョンの RDS for PostgreSQL の場合、`rds_password` ロールはパスワードを変更し、データベースユーザーと `rds_superuser` ロールを持つユーザーのパスワード制約を設定できます。RDS for PostgreSQL 14 以降のバージョンでは、`rds_password` ロールがユーザーのパスワードを変更し、パスワード制約を設定できるのは、データベースユーザーに対してのみです。`rds_superuser` ロールを持つユーザーのみが、`rds_superuser` ロールを持つ他のユーザーに対して上記のアクションを実行できます。
+ **rdsadmin** - `superuser` 権限を持つ管理者がスタンドアロンの PostgreSQL データベースで行う管理タスクの多くを処理するために作成されるロールです。このロールは、Aurora PostgreSQL によって多くの管理タスクのために内部的に使用されます。

# ロールとその権限の表示
<a name="Appendix.PostgreSQL.CommonDBATasks.Roles.View"></a>

PostgreSQL バージョン別に異なるコマンドを使用して、RDS for PostgreSQL DB インスタンスで事前定義されたロールとその権限を表示できます。事前定義されたロールをすべて表示するには、RDS for PostgreSQL DB インスタンスに接続し、`psql` を使用して以下のコマンドを実行します。

**`psql` バージョン 15 以前の場合**

RDS for PostgreSQL DB インスタンスに接続し、psql で `\du` コマンドを使用します。

```
postgres=> \du
                                                               List of roles
    Role name    |                         Attributes                         |                          Member of
-----------------+------------------------------------------------------------+------------------------------------------------------
 postgres        | Create role, Create DB                                    +| {rds_superuser}
                 | Password valid until infinity                              |
 rds_ad          | Cannot login                                               | {}
 rds_iam         | Cannot login                                               | {}
 rds_password    | Cannot login                                               | {}
 rds_replication | Cannot login                                               | {}
 rds_superuser   | Cannot login                                               | {pg_monitor,pg_signal_backend,rds_password,rds_replication}
 rdsadmin        | Superuser, Create role, Create DB, Replication, Bypass RLS+| {}
                 | Password valid until infinity                              |
```

**`psql` バージョン 16 以降の場合**

```
postgres=> \drg+
                             List of role grants
   Role name   |          Member of          |       Options       | Grantor
---------------+-----------------------------+---------------------+----------
 postgres      | rds_superuser               | INHERIT, SET        | rdsadmin
 rds_superuser | pg_checkpoint               | ADMIN, INHERIT, SET | rdsadmin
 rds_superuser | pg_monitor                  | ADMIN, INHERIT, SET | rdsadmin
 rds_superuser | pg_signal_backend           | ADMIN, INHERIT, SET | rdsadmin
 rds_superuser | pg_use_reserved_connections | ADMIN, INHERIT, SET | rdsadmin
 rds_superuser | rds_password                | ADMIN, INHERIT, SET | rdsadmin
 rds_superuser | rds_replication             | ADMIN, INHERIT, SET | rdsadmin
```

バージョンに関係なくロールのメンバーシップを確認するには、次の SQL クエリを使用できます。

```
SELECT m.rolname AS "Role name", r.rolname AS "Member of"
FROM pg_catalog.pg_roles m
JOIN pg_catalog.pg_auth_members pam ON (pam.member = m.oid)
LEFT JOIN pg_catalog.pg_roles r ON (pam.roleid = r.oid)
LEFT JOIN pg_catalog.pg_roles g ON (pam.grantor = g.oid)
WHERE m.rolname !~ '^pg_'
ORDER BY 1, 2;
```

出力では、`rds_superuser` がデータベースユーザーロールではない (ログインできない) が、他の多くのロールの特権を持っていることがわかります。また、そのデータベースユーザー `postgres` は `rds_superuser` ロールのメンバーであることも確認できます。前述のように、`postgres` が Amazon RDS コンソールの **[Create database]** (データベースを作成) ページのデフォルト値です。別の名前を選択した場合、代わりにその名前がロールのリストに表示されます。

**注記**  
 Aurora PostgreSQL バージョン 15.2 と 14.7 では、`rds_superuser` ロールの限定的動作が導入されました。Aurora PostgreSQL ユーザーには、ユーザーに `rds_superuser` ロールが付与されている場合でも、対応する接続対象のデータベースで `CONNECT` 権限を付与する必要があります。Aurora PostgreSQL バージョン 14.7 と 15.2 より前のバージョンでは、ユーザーに`rds_superuser` 権限が付与されていれば、どのデータベースとシステムテーブルにも接続できました。この制限的動作は、AWS そして、セキュリティの継続的な改善に取り組むという Amazon Aurora コミットメントに整合しています。  
上記の機能強化が影響する場合は、アプリケーションのそれぞれのロジックを更新してください。

# PostgreSQL データベースへのユーザーアクセスのコントロール
<a name="Appendix.PostgreSQL.CommonDBATasks.Access"></a>

PostgreSQL の新しいデータベースは、常にデータベースの `public` スキーマに、すべてのデータベースユーザーとロールがオブジェクトを作成できるようなデフォルトの権限セットで作成されます。これらの権限により、例えば、データベースユーザーがデータベースに接続し、接続しながら一時テーブルを作成することができます。

Aurora PostgreSQL DB クラスターのプライマリノード に作成するデータベースインスタンスへのユーザーアクセスをよりよく制御するために、これらのデフォルトの `public` 権限を取り消すことを推奨します。その後、次の手順で示すように、データベースのユーザーに特定の権限をより詳細に付与します。

**新しいデータベースインスタンスのロールと権限を設定するには**

全員がデータベースへの読み取り/書き込みアクセスを必要とする複数の研究者が使用するために、新しく作成された Aurora PostgreSQL DB クラスター 上にデータベースをセットアップしているとします。

1. `psql` (または pgAdmin) を使用して、Aurora PostgreSQL DB クラスター上のプライマリ DB インスタンス に接続します。

   ```
   psql --host=your-cluster-instance-1.666666666666.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
   ```

   プロンプトが表示されたら、パスワードを入力します。`psql` クライアントが接続し、プロンプトとしてデフォルトの管理用接続データベースである `postgres=>` を表示します。

1. データベースユーザーが `public` スキーマでオブジェクトを作成できないようにするには、次の操作を行います。

   ```
   postgres=> REVOKE CREATE ON SCHEMA public FROM PUBLIC;
   REVOKE
   ```

1. 次に、新しいデータベースインスタンスを作成します。

   ```
   postgres=> CREATE DATABASE lab_db;
   CREATE DATABASE
   ```

1. この新しいデータベースの `PUBLIC` スキーマからすべての権限を取り消します。

   ```
   postgres=> REVOKE ALL ON DATABASE lab_db FROM public;
   REVOKE
   ```

1. データベースユーザーのロールを作成します。

   ```
   postgres=> CREATE ROLE lab_tech;
   CREATE ROLE
   ```

1. このロールを持つデータベースユーザーに、データベースに接続する機能を付与します。

   ```
   postgres=> GRANT CONNECT ON DATABASE lab_db TO lab_tech;
   GRANT
   ```

1. `lab_tech` ロールを持つすべてのユーザーに、このデータベースのすべての権限を付与します。

   ```
   postgres=> GRANT ALL PRIVILEGES ON DATABASE lab_db TO lab_tech;
   GRANT
   ```

1. 次のように、データベースユーザーを作成します。

   ```
   postgres=> CREATE ROLE lab_user1 LOGIN PASSWORD 'change_me';
   CREATE ROLE
   postgres=> CREATE ROLE lab_user2 LOGIN PASSWORD 'change_me';
   CREATE ROLE
   ```

1. これら 2 人のユーザーに lab\$1tech ロールに関連付けられた権限を付与します。

   ```
   postgres=> GRANT lab_tech TO lab_user1;
   GRANT ROLE
   postgres=> GRANT lab_tech TO lab_user2;
   GRANT ROLE
   ```

この時点で、`lab_user1` と `lab_user2` は `lab_db` データベースに接続できます。この例は、複数のデータベースインスタンスの作成、異なるスキーマの作成、制限されたアクセス許可の付与などを含む、エンタープライズで使用するためのベストプラクティスに従ったものではありません。詳細な情報と追加のシナリオについては、「[PostgreSQL ユーザーとロールの管理](https://aws.amazon.com/blogs//database/managing-postgresql-users-and-roles/)」を参照してください。

PostgreSQL データベースでの権限の詳細については、PostgreSQL のドキュメントの [GRANT](https://www.postgresql.org/docs/current/static/sql-grant.html) コマンドを参照してください。

# ユーザーパスワード管理の委任と制御
<a name="Appendix.PostgreSQL.CommonDBATasks.RestrictPasswordMgmt"></a>

DBA は、ユーザーパスワードの管理を委任する場合があります。または、データベースユーザーがパスワードを変更したり、パスワードの有効期間などのパスワード制約を再設定したりしないようにする場合もあります。選択したデータベースユーザーのみがパスワード設定を変更できるようにするには、制限されたパスワード管理の機能をオンにします。この機能をアクティブにすると、`rds_password` ロールを付与されたデータベースユーザーのみがパスワードを管理できます。

**注記**  
制限されたパスワード管理を使用するには、 Aurora PostgreSQL DB クラスターで Amazon Aurora PostgreSQL 10.6 以上を実行している必要があります。

次に示すように、デフォルトではこの機能は `off` になっています。

```
postgres=> SHOW rds.restrict_password_commands;
  rds.restrict_password_commands
--------------------------------
 off
(1 row)
```

この機能をオンにするには、カスタムパラメータグループを使用して、`rds.restrict_password_commands` の設定を 1 に変更します。設定を有効にするには、Aurora PostgreSQL のプライマリ DB インスタンス を必ず再起動してください。

この機能をアクティブにすると、次の SQL コマンドには `rds_password` 権限が必要になります。

```
CREATE ROLE myrole WITH PASSWORD 'mypassword';
CREATE ROLE myrole WITH PASSWORD 'mypassword' VALID UNTIL '2023-01-01';
ALTER ROLE myrole WITH PASSWORD 'mypassword' VALID UNTIL '2023-01-01';
ALTER ROLE myrole WITH PASSWORD 'mypassword';
ALTER ROLE myrole VALID UNTIL '2023-01-01';
ALTER ROLE myrole RENAME TO myrole2;
```

ロールの名前の変更 (`ALTER ROLE myrole RENAME TO newname`) は、パスワードが MD5 ハッシュアルゴリズムを使用する場合にも制限されます。

この機能が有効な場合、`rds_password` ロールのアクセス許可なしでこれらの SQL コマンドの実行を試みると、次のエラーが発生します。

```
ERROR: must be a member of rds_password to alter passwords
```

`rds_password` は、パスワード管理専用の少数のロールにのみ付与することをお勧めします。`rds_superuser` 権限を持たないデータベースユーザーに `rds_password` 権限を付与する場合は、`CREATEROLE` 属性も付与する必要があります。

パスワード要件 (クライアント側の有効期限や必要な複雑さなど) を確認してください。パスワード関連の変更に独自のクライアント側ユーティリティを使用する場合、そのユーティリティは `rds_password` のメンバーであり、`CREATE ROLE` 権限を持つ必要があります。

# PostgreSQL のパスワード暗号化に SCRAM を使用する
<a name="PostgreSQL_Password_Encryption_configuration"></a>

*SCRAM (Salted Challenge Response Authentication Mechanism)* は、パスワードを暗号化するための PostgreSQL のデフォルトのメッセージダイジェスト (MD5) アルゴリズムの代替手段です。SCRAM 認証メカニズムは MD5 よりも安全であると見なされます。これら 2 つの異なるパスワードを保護する方法の詳細については、PostgreSQL のドキュメントの「[パスワード認証](https://www.postgresql.org/docs/14/auth-password.html)」を参照してください。

Aurora PostgreSQL DB クラスターに対しては、パスワード暗号化方式として MD5 ではなく SCRAM を使用することをお勧めします。SCRAM は、Aurora PostgreSQL バージョン 10 および以降のすべてのメジャーバージョンとマイナーバージョンでサポートされています。これは、パスワード認証と暗号化のために scram-sha-256 アルゴリズムを使用する暗号化チャレンジレスポンスのメカニズムです。

SCRAM をサポートするために、クライアントアプリケーションのライブラリを更新する必要があります。例えば、42.2.0 より前の JDBC バージョンで SCRAM はサポートされていません。詳細については、PostgreSQL JDBC ドライバーのドキュメントの「[PostgreSQL JDBC ドライバー](https://jdbc.postgresql.org/changelogs/2018-01-17-42.2.0-release/)」を参照してください。その他の PostgreSQL ドライバーおよび SCRAM サポートの一覧については、PostgreSQL のドキュメントの「[ドライバーの一覧](https://wiki.postgresql.org/wiki/List_of_drivers)」を参照してください。

Aurora PostgreSQL バージョン 14 以上では、新しい DB クラスターに対してデフォルトでパスワード暗号化に scram-sha-256 をサポートしています。これらのバージョンでは、デフォルトの DB クラスターパラメータグループ (`default.aurora-postgresql14`) が持っている `password_encryption` 値を scram-sha-256 に設定します。SCRAM は Aurora Serverless v1 ではサポートされていません。

## SCRAM を要求するために Aurora PostgreSQL DB クラスター を設定する
<a name="PostgreSQL_Password_Encryption_configuration.preliminary"></a>

Aurora PostgreSQL 14.3 以降のバージョンでは、scram-sha-256 アルゴリズムを使用するパスワードのみを受け入れるために、Aurora PostgreSQL DB クラスターに を要求できます。

**重要**  
PostgreSQL データベースを使用する既存の RDS プロキシでは、`SCRAM` のみを使用するようにデータベース認証を変更すると、プロキシは最大 60 秒間使用できなくなります。この問題を回避するには、以下のいずれかの方法で対応します。  
データベースが `SCRAM` と `MD5` 認証の両方を許可していることを確認します。
`SCRAM` 認証のみを使用するには、新しいプロキシを作成し、アプリケーショントラフィックを新しいプロキシに移行してから、以前にデータベースに関連付けられていたプロキシを削除します。

システムに変更を加える前に、次の完全なプロセスを理解していることを確認してください。
+ すべてのデータベースユーザーのすべてのロールとパスワードの暗号化に関する情報を取得します。
+ パスワードの暗号化を制御するパラメータを指定するために、Aurora PostgreSQL DB クラスター のパラメータ設定を再確認してください。
+ Aurora PostgreSQL DB クラスター でデフォルトのパラメータグループを使用する場合は、カスタムの DB クラスターのパラメータグループ を作成して、それを Aurora PostgreSQL DB クラスター に適用し、必要なときにパラメータを変更できるようにする必要があります。Aurora PostgreSQL DB クラスター がカスタムパラメータグループを使用している場合、必要に応じて、プロセスの後で必要なパラメータを変更できます。
+ `password_encryption` パラメータを `scram-sha-256` に変更します。
+ パスワードを更新する必要があることをすべてのデータベースユーザーに通知します。`postgres` アカウントに同じ操作を行います。新しいパスワードは暗号化され、scram-sha-256 アルゴリズムを使用して保存されます。
+ 暗号化の種類を使用して、すべてのパスワードが暗号化されていることを確認します。
+ すべてのパスワードで scram-sha-256 が使用されている場合、`rds.accepted_password_auth_method` パラメータを `md5+scram` から `scram-sha-256` に変更できます。

**警告**  
`rds.accepted_password_auth_method` を scram-sha-256 のみに変更した後、`md5` で暗号化されたパスワードを持つすべてのユーザー (ロール) は接続できなくなります。

### Aurora PostgreSQL DB クラスター に SCRAM を要求する準備
<a name="PostgreSQL_Password_Encryption_configuration.getting-ready"></a>

お使いの Aurora PostgreSQL DB クラスター、に変更を加える前に、既存のデータベースユーザーアカウントをすべて確認します。また、パスワードに使用されている暗号化の種類を確認してください。確認するためには、`rds_tools` 拡張機能を使用します。`rds_tools` をサポートする PostgreSQL バージョンを確認するには、「[Extension versions for Amazon RDS for PostgreSQL](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)」を参照してください。

**データベースユーザー (ロール) とパスワードの暗号化方法のリストを取得するには**

1. 次のように、`psql` を使用して Aurora PostgreSQL DB クラスターのプライマリ インスタンスを に接続します。

   ```
   psql --host=cluster-name-instance-1.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
   ```

1. `rds_tools` 拡張機能をインストールします。

   ```
   postgres=> CREATE EXTENSION rds_tools;
   CREATE EXTENSION
   ```

1. ロールと暗号化のリストを取得します。

   ```
   postgres=> SELECT * FROM 
         rds_tools.role_password_encryption_type();
   ```

   以下のような出力結果が表示されます。

   ```
          rolname        | encryption_type
   ----------------------+-----------------
    pg_monitor           |
    pg_read_all_settings |
    pg_read_all_stats    |
    pg_stat_scan_tables  |
    pg_signal_backend    |
    lab_tester           | md5
    user_465             | md5
    postgres             | md5
   (8 rows)
   ```

### カスタム DB クラスターのパラメータグループ の作成
<a name="PostgreSQL_Password_Encryption_configuration.custom-parameter-group"></a>

**注記**  
Aurora PostgreSQL DB クラスター で既にカスタムパラメータグループを使用している場合、新しいパラメータグループを作成する必要はありません。

Aurora のパラメータグループの概要については、「[Amazon Aurora での DB クラスターパラメータグループの作成](USER_WorkingWithParamGroups.CreatingCluster.md)」を参照してください。

パスワードに使用されるパスワード暗号化タイプは、1 つのパラメータ `password_encryption` で設定します。Aurora PostgreSQL DB クラスター で許可される暗号化は、別のパラメータ `rds.accepted_password_auth_method` で設定されます。これらのいずれかをデフォルト値から変更するには、カスタム DB クラスターのパラメータグループ を作成して、クラスター に適用する必要があります。

また、AWS マネジメントコンソール または RDS API を使用して、カスタムの DB クラスターのパラメータグループ を作成することもできます。詳細については、「[Amazon Aurora での DB クラスターパラメータグループの作成](USER_WorkingWithParamGroups.CreatingCluster.md)」を参照してください。

これで、カスタムパラメータグループを DB インスタンスに関連付けることができます。

**カスタム DB クラスターのパラメータグループ を作成するには**

1. `[create-db-cluster-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/create-db-cluster-parameter-group.html)` CLI コマンドを使用して、クラスターのカスタムパラメータグループを作成します。次の例では `aurora-postgresql13` をこのカスタムパラメータグループのソースとして使用します。

   Linux、macOS、Unix の場合:

   ```
   aws rds create-db-cluster-parameter-group --db-cluster-parameter-group-name 'docs-lab-scram-passwords' \
     --db-parameter-group-family aurora-postgresql13  --description 'Custom DB cluster parameter group for SCRAM'
   ```

   Windows の場合:

   ```
   aws rds create-db-cluster-parameter-group --db-cluster-parameter-group-name "docs-lab-scram-passwords" ^
     --db-parameter-group-family aurora-postgresql13  --description "Custom DB cluster parameter group for SCRAM"
   ```

   これで、カスタムパラメータグループをクラスターに関連付けることができます。

1. `[modify-db-cluster](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-cluster.html)` CLI コマンドを使用して、このカスタムパラメータグループを Aurora PostgreSQL DB クラスターに適用します。

   Linux、macOS、Unix の場合:

   ```
   aws rds modify-db-cluster --db-cluster-identifier 'your-instance-name' \
           --db-cluster-parameter-group-name "docs-lab-scram-passwords
   ```

   Windows の場合:

   ```
   aws rds modify-db-cluster --db-cluster-identifier "your-instance-name" ^
           --db-cluster-parameter-group-name "docs-lab-scram-passwords
   ```

   Aurora PostgreSQL DB クラスターとカスタム DB クラスターパラメータグループ、を再同期するには、プライマリインスタンスおよびクラスターの他のすべてのインスタンスを再起動します。

### SCRAM を使用するためのパスワード暗号化の設定
<a name="PostgreSQL_Password_Encryption_configuration.configure-password-encryption"></a>

Aurora PostgreSQL DB クラスター で使用されるパスワード暗号化メカニズムは、`password_encryption` パラメータの DB クラスターのパラメータグループ に設定されています。指定できる値は、未設定、`md5` または `scram-sha-256` です。デフォルト値は、次のように Aurora PostgreSQL のバージョンによって異なります。
+ Aurora PostgreSQL 14 — デフォルトは `scram-sha-256`
+ Aurora PostgreSQL 13 — デフォルトは `md5`

Aurora PostgreSQL DB クラスター にアタッチされているカスタム DB クラスターパラメータグループ では、パスワード暗号化パラメータの値を変更できます。

![\[次では、RDS コンソールには、Aurora PostgreSQL の password_encryption パラメータのデフォルト値が表示されます。\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/images/apg-pwd-encryption-md5-scram-1.png)


**パスワード暗号化の設定を scram-sha-256 に変更するには**
+ 次のように、パスワード暗号化の値を scram-sha-256 に設定します。パラメータが動的であるため、変更をすぐに適用できます。そのため、変更を有効にするために再起動は不要です。

  Linux、macOS、Unix の場合:

  ```
  aws rds modify-db-cluster-parameter-group --db-cluster-parameter-group-name \
    'docs-lab-scram-passwords' --parameters 'ParameterName=password_encryption,ParameterValue=scram-sha-256,ApplyMethod=immediate'
  ```

  Windows の場合:

  ```
  aws rds modify-db-parameter-group --db-parameter-group-name ^
    "docs-lab-scram-passwords" --parameters "ParameterName=password_encryption,ParameterValue=scram-sha-256,ApplyMethod=immediate"
  ```

### ユーザーロールのパスワードを SCRAM に移行する
<a name="PostgreSQL_Password_Encryption_configuration.migrating-users"></a>

以下に説明するように、ユーザーロールのパスワードを SCRAM に移行できます。

**データベースユーザー (ロール) のパスワードを MD5 から SCRAM に移行するには**

1. 次のように、管理者ユーザーとしてログインします (デフォルトのユーザー名、`postgres`)。

   ```
   psql --host=cluster-name-instance-1.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
   ```

1. 次のコマンドを使って、RDS for PostgreSQL DB インスタンスの `password_encryption` パラメータの設定を確認します。

   ```
   postgres=> SHOW password_encryption;
    password_encryption
   ---------------------
    md5
    (1 row)
   ```

1. このパラメータの値を scram-sha-256 に変更します。詳細については、「[SCRAM を使用するためのパスワード暗号化の設定](#PostgreSQL_Password_Encryption_configuration.configure-password-encryption)」を参照してください。

1.  値をもう一度チェックして、次のように `scram-sha-256` に設定されていることを確認します。

   ```
   postgres=> SHOW password_encryption;
    password_encryption
   ---------------------
    scram-sha-256
    (1 row)
   ```

1. パスワードの変更をすべてのデータベースユーザーに通知します。アカウント `postgres` (`rds_superuser` 権限を持つデータベースユーザー) のパスワードも必ず変更してください。

   ```
   labdb=> ALTER ROLE postgres WITH LOGIN PASSWORD 'change_me';
   ALTER ROLE
   ```

1. Aurora PostgreSQL DB クラスターのすべてのデータベースに対してこの処理を繰り返します。

### SCRAM を要求するようにパラメータを変更する
<a name="PostgreSQL_Password_Encryption_configuration.require-scram"></a>

これがプロセスの最後のステップです。次の手順で変更した後、パスワードに引き続き `md5` 暗号化を使用するユーザーアカウント (ロール) は Aurora PostgreSQL DB クラスターにログインできません。

`rds.accepted_password_auth_method` は、ログインプロセス中に Aurora PostgreSQL DB クラスターがユーザーパスワードに対して受け入れる暗号化方式を指定します。デフォルト値は `md5+scram` です。つまり、どちらの方法も受け入れられます。次の画像では、このパラメータのデフォルト設定が表示されています。

![\[rds.accepted_password_auth_method パラメータに対してデフォルト値と許可された値が表示されている RDS コンソール。\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/images/pwd-encryption-md5-scram-2.png)


このパラメータに指定できる値は、`md5+scram` または `scram` のみです。このパラメータの値を `scram` に変更すると、これが要件となります。

**パスワードの SCRAM 認証を要求するようにパラメータ値を変更するには**

1. Aurora PostgreSQL DB クラスター の上のすべてのデータベースに対するすべてのデータベースユーザーパスワードが、パスワード暗号化に `scram-sha-256` を使用していることを確認します。そのためには、`rds_tools` にロール (ユーザー) と暗号化タイプについて、次のようにクエリします。

   ```
   postgres=> SELECT * FROM rds_tools.role_password_encryption_type();
     rolname        | encryption_type
     ----------------------+-----------------
     pg_monitor           |
     pg_read_all_settings |
     pg_read_all_stats    |
     pg_stat_scan_tables  |
     pg_signal_backend    |
     lab_tester           | scram-sha-256
     user_465             | scram-sha-256
     postgres             | scram-sha-256
     ( rows)
   ```

1. Aurora PostgreSQL DB クラスターのすべての DB インスタンスでクエリを繰り返します。

   すべてのパスワードで scram-sha-256 が使用されている場合は続行できます。

1. 次のように、受け入れたパスワード認証の値を scram-sha-256 に設定します。

   Linux、macOS、Unix の場合:

   ```
   aws rds modify-db-cluster-parameter-group --db-cluster-parameter-group-name 'docs-lab-scram-passwords' \
     --parameters 'ParameterName=rds.accepted_password_auth_method,ParameterValue=scram,ApplyMethod=immediate'
   ```

   Windows の場合:

   ```
   aws rds modify-db-cluster-parameter-group --db-cluster-parameter-group-name "docs-lab-scram-passwords" ^
     --parameters "ParameterName=rds.accepted_password_auth_method,ParameterValue=scram,ApplyMethod=immediate"
   ```

## SSL/TLS での Aurora PostgreSQL データの保護
<a name="AuroraPostgreSQL.Security.SSL"></a>

Amazon RDS では、Aurora PostgreSQL DB クラスターの Secure Socket Layer (SSL) 暗号化と Transport Layer Security (TLS) 暗号化をサポートしています。SSL/TLS を使用して、アプリケーションと Aurora PostgreSQL DB クラスターとの接続を暗号化できます。また、Aurora PostgreSQL DB クラスターへのすべての接続に SSL/TLS の使用を強制することができます。Amazon Aurora PostgreSQL は、Transport Layer Security (TLS) バージョン 1.1 および 1.2 をサポートしています。暗号化された接続には TLS 1.2 を使用することをお勧めします。次の Aurora PostgreSQL のバージョンから TLSv1.3 のサポートが追加されました。
+ 15.3 以降のすべてのバージョン
+ 14.8 以降の 14 バージョン
+ 13.11 以降の 13 バージョン
+ 12.15 以降の 12 バージョン
+ 11.20 以降の 11 バージョン

SSL/TLS サポートおよび PostgreSQL データベースの一般情報については、PostgreSQL ドキュメントの「[SSL Support](https://www.postgresql.org/docs/current/libpq-ssl.html)」を参照してください。JDBC を介した SSL/TLS 接続の使用については、PostgreSQL ドキュメントの「[Configuring the Client](https://jdbc.postgresql.org/documentation/head/ssl-client.html)」を参照してください。

**Topics**
+ [Aurora PostgreSQL DB クラスターへの SSL/TLS 接続を必須にする](#AuroraPostgreSQL.Security.SSL.Requiring)
+ [SSL/TLS 接続ステータスを確認する](#AuroraPostgreSQL.Security.SSL.Status)
+ [Aurora PostgreSQL DB クラスターへの接続用暗号スイートを設定する](#AuroraPostgreSQL.Security.SSL.ConfiguringCipherSuites)

Aurora PostgreSQL の SSL/TLS サポートは、すべての AWS リージョンで利用可能です。DB クラスターが作成される際、Amazon RDS により、Aurora PostgreSQL DB クラスター用の SSL/TLS 証明書が作成されます。SSL/TLS 証明書認証を有効にした場合、SSL/TLS 証明書には、なりすまし攻撃から保護するために、SSL/TLS 証明書の共通名 (CN) として DB クラスターのエンドポイントが含まれます。

**SSL/TLS を使用して Aurora PostgreSQL DB クラスターに接続する方法**

1. 証明書をダウンロードします。

   証明書のダウンロードについては、[SSL/TLS を使用した DB クラスターへの接続の暗号化](UsingWithRDS.SSL.md) を参照してください。

1. オペレーティングシステムに証明書をインポートします。

1. SSL/TLS を使用して Aurora PostgreSQL DB クラスターに接続します。

   SSL/TLS を使用して接続するとき、クライアントでは証明書チェーンを検証するかどうかを選択できます。接続パラメータで `sslmode=verify-ca` または `sslmode=verify-full` を指定すると、RDS CA 証明書が信頼ストアに存在するか、または接続 URL で参照されることをクライアントは要求します。この要求は、データベース証明書に署名する証明書チェーンを検証するためのものです。

   psql や JDBC など、クライアントに SSL/TLS サポートが設定されている場合、クライアントは初期にデフォルトで SSL/TLS を使用してデータベースへの接続を試みます。クライアントが SSL/TLS を使用して接続できない場合、SSL/TLS を使用しない接続に戻ります。デフォルトでは、JDBC および libpq ベースのクライアントの `sslmode` オプションは `prefer` に設定されています。

   `sslrootcert` パラメータを使用して証明書を参照します (`sslrootcert=rds-ssl-ca-cert.pem` など)。

psql を使用して Aurora PostgreSQL DB クラスターに接続する例は次のとおりです。

```
$ psql -h testpg.cdhmuqifdpib.us-east-1.rds.amazonaws.com -p 5432 \
    "dbname=testpg user=testuser sslrootcert=rds-ca-2015-root.pem sslmode=verify-full"
```

### Aurora PostgreSQL DB クラスターへの SSL/TLS 接続を必須にする
<a name="AuroraPostgreSQL.Security.SSL.Requiring"></a>

Aurora PostgreSQL DB クラスターへの SSL/TLS 接続を必須にするには、`rds.force_ssl` パラメータを使用します。
+ SSL/TLS 接続を必須にするには、`rds.force_ssl` パラメータ値を 1 (オン) に設定します。
+ 必須の SSL/TLS 接続をオフにするには、`rds.force_ssl` パラメータ値を 0 (オフ) に設定します。

このパラメータのデフォルト値は、Aurora PostgreSQL のバージョンによって異なります。
+ Aurora PostgreSQL バージョン 17 以降では、デフォルト値は 1 (オン) です。
+ Aurora PostgreSQL バージョン 16 以前では、デフォルト値は 0 (オフ) です。

**注記**  
Aurora PostgreSQL バージョン 16 またはそれ以前のバージョンからバージョン 17 以降にメジャーバージョンアップグレードを実行すると、パラメータのデフォルト値は 0 (オフ) から 1 (オン) に変わります。この変更により、SSL 用に設定されていないアプリケーションで接続障害が発生する可能性があります。このパラメータを 0 (オフ) に設定することで、以前のデフォルトの動作に戻すことができます。

パラメータの処理に関する詳細については、「[Amazon Aurora のパラメータグループ](USER_WorkingWithParamGroups.md)」を参照してください。

`rds.force_ssl` パラメータを更新することでも PostgreSQL `ssl` パラメータは 1 (オン) に設定され、新しい SSL/TLS 設定をサポートするように DB クラスターの `pg_hba.conf` ファイルが変更されます。

DB クラスターで `rds.force_ssl` パラメータが 1 に設定されている場合、次のような出力が接続時に表示され、SSL/TLS が必須であることが示されます。

```
$ psql postgres -h SOMEHOST.amazonaws.com -p 8192 -U someuser
psql (9.3.12, server 9.4.4)
WARNING: psql major version 9.3, server major version 9.4.
Some psql features might not work.
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

postgres=>
```

### SSL/TLS 接続ステータスを確認する
<a name="AuroraPostgreSQL.Security.SSL.Status"></a>

接続の暗号化ステータスは、DB クラスターに接続するときにログオンバナーに表示されます。

```
Password for user master: 
psql (9.3.12) 
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256) 
Type "help" for help.   

postgres=>
```

また、`sslinfo` 拡張機能をロードしてから、`ssl_is_used()` 関数を呼び出して、SSL/TLS が使用されているかどうかを確認することもできます。この関数は、この接続が SSL/TLS を使用している場合に `t` を返し、それ以外の場合に `f` を返します。

```
postgres=> create extension sslinfo;
CREATE EXTENSION

postgres=> select ssl_is_used();
 ssl_is_used
---------
t
(1 row)
```

`select ssl_cipher()` コマンドを使用して、SSL/TLS 暗号を確認することができます。

```
postgres=> select ssl_cipher();
ssl_cipher
--------------------
DHE-RSA-AES256-SHA
(1 row)
```

 `set rds.force_ssl` を有効にして DB クラスターを再起動すると、次のメッセージが表示され SSL 以外の接続は拒否されます。

```
$ export PGSSLMODE=disable
$ psql postgres -h SOMEHOST.amazonaws.com -p 8192 -U someuser
psql: FATAL: no pg_hba.conf entry for host "host.ip", user "someuser", database "postgres", SSL off
$
```

`sslmode` オプションの詳細については、PostgreSQL ドキュメントの「[データベース接続制御関数](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-SSLMODE)」を参照してください。

### Aurora PostgreSQL DB クラスターへの接続用暗号スイートを設定する
<a name="AuroraPostgreSQL.Security.SSL.ConfiguringCipherSuites"></a>

設定可能な暗号スイートを使用すると、データベース接続のセキュリティをより詳細に制御できます。データベースへのクライアント SSL/TLS 接続を保護するために許可する暗号スイートのリストを指定できます。設定可能な暗号スイートを使用すると、データベースサーバーが受け入れる接続暗号化を制御できます。これにより、安全でない暗号や非推奨の暗号の使用を防ぐことができます。

設定可能な暗号スイートは、Aurora PostgreSQL バージョン 11.8 以降でサポートされています。

接続を暗号化するために許容できる暗号のリストを指定するには、`ssl_ciphers` クラスターパラメータを変更します。AWS マネジメントコンソール、AWS CLI、または RDS API を使用して、`ssl_ciphers` パラメータをクラスターパラメータグループのカンマ区切りの暗号文字列に設定します。クラスターパラメータを設定するには、「[Amazon Aurora での DB クラスターパラメータグループのパラメータの変更](USER_WorkingWithParamGroups.ModifyingCluster.md)」を参照してください。

次の表は、有効な Aurora PostgreSQL エンジンバージョンでサポートされる暗号を示しています。


| Aurora PostgreSQL のエンジンバージョン | サポートされる暗号 | TLS 1.1 | TLS 1.2 | TLS 1.3 | 
| --- | --- | --- | --- | --- | 
| 9.6、10.20 以前、11.15 以前、12.10 以前、13.6 以前 | DHE-RSA-AES128-SHA DHE-RSA-AES128-SHA256 DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES256-SHA DHE-RSA-AES256-SHA256 DHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES256-SHA ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-SHA384 ECDHE-RSA-AES128-SHA ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-SHA ECDHE-RSA-AES256-GCM-SHA384 | はい なし なし なし なし なし あり なし なし あり なし なし あり なし | なし はい はい はい はい はい はい はい はい はい はい はい はい あり |  なし なし なし なし なし なし なし なし なし なし なし なし なし いいえ  | 
| 10.21、11.16、12.11、13.7、14.3、14.4 |  ECDHE-RSA-AES128-SHATLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 TLS\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 TLS\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA TLS\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1CHACHA20\$1POLY1305\$1SHA256 | はい なし あり なし あり なし あり なし なし あり なし あり なし | はい はい はい はい はい はい はい はい はい はい はい はい あり | なし なし なし なし なし なし なし なし なし なし なし なし いいえ | 
| 10.22、11.17、12.12、13.8、14.5、および 15.2 |  TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 TLS\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 TLS\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA TLS\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1CHACHA20\$1POLY1305\$1SHA256 |  はい なし なし あり なし あり なし なし あり なし なし あり なし はい あり なし  | はい はい はい はい はい はい はい はい はい はい はい はい はい はい はい あり | なし なし なし なし なし なし なし なし なし なし なし なし なし なし なし いいえ | 
| 11.20、12.15、13.11、14.8、15.3、16.1 以降 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 TLS\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 TLS\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA TLS\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA TLS\$1ECDHE\$1RSA\$1WITH\$1CHACHA20\$1POLY1305\$1SHA256 TLS\$1AES\$1128\$1GCM\$1SHA256 TLS\$1AES\$1256\$1GCM\$1SHA384  | はい なし なし あり なし あり なし なし あり なし なし あり なし はい あり なし なし なし | はい はい はい はい はい はい はい はい はい はい はい はい はい はい はい あり なし なし |  なし なし なし なし なし なし なし なし なし なし なし なし なし なし なし なし はい はい  | 

また、CLI コマンドの [describe-engine-default-cluster-parameters](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-engine-default-cluster-parameters.html) を使用して、特定のパラメータグループファミリーで現在サポートされている暗号スイートを特定することもできます。次の例では、Aurora PostgreSQL 11 の `ssl_cipher` クラスターパラメータで許可される値を取得する方法を示しています。

```
aws rds describe-engine-default-cluster-parameters --db-parameter-group-family aurora-postgresql11
                
    ...some output truncated...
	{
		"ParameterName": "ssl_ciphers",
		"Description": "Sets the list of allowed TLS ciphers to be used on secure connections.",
		"Source": "engine-default",
		"ApplyType": "dynamic",
		"DataType": "list",
		"AllowedValues": "DHE-RSA-AES128-SHA,DHE-RSA-AES128-SHA256,DHE-RSA-AES128-GCM-SHA256,DHE-RSA-AES256-SHA,DHE-RSA-AES256-SHA256,DHE-RSA-AES256-GCM-SHA384,
		ECDHE-RSA-AES128-SHA,ECDHE-RSA-AES128-SHA256,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-RSA-AES256-SHA,ECDHE-RSA-AES256-SHA384,ECDHE-RSA-AES256-GCM-SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,
		TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
		TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
		"IsModifiable": true,
		"MinimumEngineVersion": "11.8",
		"SupportedEngineModes": [
			"provisioned"
		]
	},
    ...some output truncated...
```

`ssl_ciphers` パラメータのデフォルトは、許可されているすべての暗号スイートです。暗号の詳細については、PostgreSQL ドキュメントに記載されている変数 [ssl\$1ciphers](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-SSL-CIPHERS) を参照してください。

# Aurora PostgreSQL での動的マスキングの使用
<a name="AuroraPostgreSQL.Security.DynamicMasking"></a>

動的データマスキングは、クエリ時にデータがどのようにユーザーに表示されるかを制御することで、Aurora PostgreSQL データベース内の機密データを保護するセキュリティ機能です。Aurora は、`pg_columnmask` 拡張機能を通じて実装します。`pg_columnmask` は、PostgreSQL のネイティブな行レベルセキュリティときめ細かなアクセスコントロールメカニズムを補完する列レベルのデータ保護を提供します。

`pg_columnmask` では、ユーザーロールに基づいてデータの可視性を決定するマスキングポリシーを作成します。ユーザーがマスキングポリシーを使用してテーブルをクエリする場合、Aurora PostgreSQL はユーザーのロールとポリシーの重みに基づいて、クエリ時に適切なマスキング関数を適用します。基盤となるデータはストレージ内で変更されずに残ります。

`pg_columnmask` は、次の機能をサポートしています。
+ **組み込みおよびカスタムマスキング関数** – E メールやテキストのマスキングなどの一般的なパターンに構築済みの関数を使用するか、独自のカスタム関数を作成して SQL ベースのマスキングポリシーを通じて機密データ (PII) を保護します。
+ **複数のマスキング戦略** – 情報を完全に非表示にしたり、部分的な値をワイルドカードに置き換えたり、カスタムマスキングアプローチを定義したりできます。
+ **ポリシーの優先順位付け** – 1 つの列に複数のポリシーを定義します。重みを使用して、列に複数のポリシーが適用されるときに使用するマスキングポリシーを決定します。Aurora PostgreSQL は、重みとユーザーロールメンバーシップに基づいてポリシーを適用します。

`pg_columnmask` は、Aurora PostgreSQL バージョン 16.10 以降、およびバージョン 17.6 以降で使用できます。追加料金なしで利用できます。

# 動的マスキングの開始方法
<a name="AuroraPostgreSQL.Security.DynamicMasking.GetStarted"></a>

データを動的にマスクするには、データベースに `pg_columnmask` 拡張機能をインストールし、テーブルのマスキングポリシーを作成します。セットアッププロセスには、前提条件の検証、拡張機能のインストール、ロール設定、ポリシーの作成、検証テストが含まれます。

## 拡張機能のインストールと設定
<a name="AuroraPostgreSQL.Security.DynamicMasking.GetStarted.Installation"></a>

RDS コンソールクエリエディタまたは psql などの PostgreSQL クライアントと rds\$1superuser (マスターユーザー) 認証情報を使用して、Aurora PostgreSQL クラスターに接続します。

拡張機能作成コマンドを実行して `pg_columnmask` 機能を有効にします。

```
CREATE EXTENSION pg_columnmask;
```

このコマンドは、`pg_columnmask` 拡張機能をインストールし、必要なカタログテーブルを作成し、組み込みのマスキング関数を登録します。拡張機能のインストールはデータベース固有です。つまり、機能が必要なデータベースごとに個別にインストールする必要があります。

**注記**  
この拡張機能をインストールする前に行われた接続には、マスクされていないデータが表示されます。閉じて再接続し、これを修正します。

使用可能なマスキング関数を確認して、拡張機能のインストールを確認します。

```
SELECT proname FROM pg_proc
    WHERE pronamespace = 'pgcolumnmask'::regnamespace AND proname LIKE 'mask_%';
    proname     
--------Output --------
 mask_email
 mask_text
 mask_timestamp
(3 rows)
```

# データマスキングポリシーを管理する手順
<a name="AuroraPostgreSQL.Security.DynamicMasking.Procedures"></a>

`pg_columnmask` 拡張機能が提供する手順を使用して、マスキングポリシーを管理できます。マスキングポリシーを作成、変更、または削除するには、次のいずれかの権限が必要です。
+ `pg_columnmask` ポリシーを作成するテーブルの所有者。
+ `rds_superuser` のメンバー。
+ `pgcolumnmask.policy_admin_rolname` パラメータによって設定された `pg_columnmask` ポリシーマネージャーロールのメンバー。

次のコマンドは、以降のセクションで使用するテーブルを作成します。

```
CREATE TABLE public.customers (
    id SERIAL PRIMARY KEY,
    name TEXT,
    phone TEXT,
    address TEXT,
    email TEXT
);
```

## CREATE\$1MASKING\$1POLICY
<a name="AuroraPostgreSQL.Security.DynamicMasking.Procedures.CreateMaskingPolicy"></a>

次の手順では、ユーザーテーブルの新しいマスキングポリシーを作成します。

**構文**

```
create_masking_policy(
    policy_name,
    table_name,
    masking_expressions,
    roles,
    weight)
```

**引数**


| パラメータ | Datatype | 説明 | 
| --- | --- | --- | 
| policy\$1name | NAME |  マスキングポリシーの名前。テーブルごとに一意である必要があります。  | 
| table\$1name | REGCLASS |  マスキングポリシーを適用するテーブルの修飾名または非修飾名または oid。  | 
| masking\$1expressions | JSONB |  列名とマスキング関数のペアを含む JSON オブジェクト。各キーは列名で、その値はその列に適用されるマスキング式です。  | 
| roles | NAME[] |  このマスキングポリシーが適用されるロール。デフォルトは PUBLIC です。  | 
| weight | INT |  マスキングポリシーの重み。特定のユーザーのクエリに複数のポリシーが適用される場合、重みが最も大きいポリシー (整数数が高い) がマスクされた各列に適用されます。 デフォルトは 0 です。テーブル上の 2 つのマスキングポリシーが同じ重みを持つことはできません。  | 

**戻り値の型**:

なし

**Example `test_user` ロールの E メール列をマスクするマスキングポリシーの作成:**  

```
CALL pgcolumnmask.create_masking_policy(
    'customer_mask',
    'public.customers',
    JSON_OBJECT('{
        "email", "pgcolumnmask.mask_email(email)"
    }')::JSONB,
    ARRAY['test_user'],
    100
);
```

## ALTER\$1MASKING\$1POLICY
<a name="AuroraPostgreSQL.Security.DynamicMasking.Procedures.AlterMaskingPolicy"></a>

この手順では、既存のマスキングポリシーを変更します。`ALTER_MASKING_POLICY` は、ポリシーのマスキング式、ポリシーが適用されるロールのセット、およびマスキングポリシーの重みを変更できます。これらのパラメータのいずれかを省略すると、ポリシーの対応する部分は変更されません。

**構文**

```
alter_masking_policy(
    policy_name,
    table_name,
    masking_expressions,
    roles,
    weight)
```

**引数**


| パラメータ | Datatype | 説明 | 
| --- | --- | --- | 
| policy\$1name | NAME |  既存のマスキングポリシーの名前。  | 
| table\$1name | REGCLASS |  マスキングポリシーを含むテーブルの修飾/非修飾名 oid。  | 
| masking\$1expressions | JSONB |  列名とマスキング関数ペアまたは NULL を含む新しい JSON オブジェクト。  | 
| roles | NAME[] |  このマスキングポリシーが適用される新しいロールのリスト。それ以外の場合は NULL。  | 
| weight | INT |  マスキングポリシーまたは NULL の新しい重み。  | 

**戻り値の型**:

なし

**Example 他のポリシー属性を変更せずに、アナリストロールを既存のマスキングポリシーに追加する。**  

```
CALL pgcolumnmask.alter_masking_policy(
    'customer_mask',
    'public.customers',
    NULL,
    ARRAY['test_user', 'analyst'],
    NULL 
);

-- Alter the weight of the policy without altering other details
CALL pgcolumnmask.alter_masking_policy(
    'customer_mask',
    'customers',
    NULL,
    NULL,
    4
);
```

## DROP\$1MASKING\$1POLICY
<a name="AuroraPostgreSQL.Security.DynamicMasking.Procedures.DropMaskingPolicy"></a>

この手順では、既存のマスキングポリシーを削除します。

**構文**

```
drop_masking_policy(
        policy_name,
        table_name)
```

**引数**


| パラメータ | Datatype | 説明 | 
| --- | --- | --- | 
| policy\$1name | NAME |  既存のマスキングポリシーの名前。  | 
| table\$1name | REGCLASS |  マスキングポリシーを含むテーブルの修飾/非修飾名 oid。  | 

**戻り値の型**:

なし

**Example マスキングポリシー customer\$1mask の削除**  

```
-- Drop a masking policy
    CALL pgcolumnmask.drop_masking_policy(
        'customer_mask',
        'public.customers',
    );
```

# マスキングポリシー DDL プロシージャでの識別子のエスケープ
<a name="AuroraPostgreSQL.Security.DynamicMasking.EscapeIdentifiers"></a>

引用符で囲まれた識別子を使用してデータマスキングポリシーを作成する場合、正しいオブジェクト参照とポリシーアプリケーションを確保するために、適切なエスケープが必要です。`pg_columnmask` マスキングポリシー管理手順内で引用符で囲まれた識別子を使用するには:
+ **ポリシー名** – 二重引用符で囲む必要があります。
+ **テーブル名** – スキーマ名とテーブル名は、必要に応じて二重引用符で個別に囲む必要があります。
+ **マスキング式** – マスキング式の列名と関数名は二重引用符で囲む必要があり、引用符自体はバックスラッシュを使用してエスケープする必要があります。
+ **ロール** – ロール名の配列は自動的に引用符で囲まれます。ロール名は、大文字と小文字の区別を含めて、「`pg_roles`」に示されている名前と完全に一致する必要があります。

**Example エスケープ構文と引用構文**  
この例では、Aurora PostgreSQL で大文字と小文字が混在する名前を使用する、または引用符で囲まれた識別子を必要とするテーブル、列、関数、ロールのマスキングポリシーを作成する際における、適切なエスケープ構文と引用構文を示します。  

```
-- Create a table and columns with mixed case name 
CREATE TABLE public."Employees" (
    "Name" TEXT,
    "Email" TEXT,
    ssn VARCHAR(20)
);

-- Create a role with mixed case name
CREATE ROLE "Masked_user";

-- Create a function with mixed case name
CREATE OR REPLACE FUNCTION public."MaskEmail"(text)
    RETURNS character varying
    LANGUAGE plpgsql
    IMMUTABLE PARALLEL SAFE
    AS $$ BEGIN
        RETURN 'XXXXXXXX'::text;
    END $$;

-- Now use these objects with mixed case names in
-- masking policy management procedures
CALL pgcolumnmask.create_masking_policy(
    '"Policy1"',  -- policy name should be surrounded with double quotes for quoting
    'public."Employees"', -- table and schema name should be individually 
                          -- surrounded with double quotes for quoting
    JSON_OBJECT('{
        "\"Email\"", "\"MaskEmail\"(\"Email\")"
    }')::JSONB, -- masking expression should have double quotes around function names
                -- and columns names etc when needed. Also the double quotes itself
                -- should be escaped using \ (backslash) since this is a JSON string
    ARRAY['Masked_user'], -- Rolename do not need quoting
                          -- (this behaviour may change in future release)
    100
);

SELECT * FROM pgcolumnmask.pg_columnmask_policies
    WHERE tablename = 'Employees';
-[ RECORD 1 ]-----+-------------------------------------
schemaname        | public
tablename         | Employees
policyname        | Policy1
roles             | {Masked_user}
masked_columns    | {Email}
masking_functions | {"(\"MaskEmail\"(\"Email\"))::text"}
weight            | 100
```

## 管理ビュー
<a name="AuroraPostgreSQL.Security.DynamicMasking.AdminViews"></a>

パブリックにアクセス可能な `pgcolumnmask.pg_columnmask_policies` 管理ビューを使用して、すべての `pg_columnmask` ポリシーを確認できます。このビューでは、次の情報を使用できます。ビューは、現在のユーザーが所有するマスキングポリシーのみを返します。


| 列名 | データ型 | 説明 | 
| --- | --- | --- | 
|  schemaname  | NAME |  ポリシーがアタッチされているリレーションのスキーマ  | 
|  tablename  | NAME |  ポリシーがアタッチされているリレーションの名前  | 
|  policyname  | NAME |  マスキングポリシーの名前。すべてのマスキングポリシーには一意の名前があります。  | 
|  ロール  | TEXT[] |  ポリシーが適用されるロール。  | 
|  masked\$1columns  | TEXT[] |  マスクされた列  | 
|  masking\$1functions  | TEXT[] |  マスキング関数  | 
| weight | INT |  アタッチされたポリシーの重み  | 

# 事前定義されたデータマスキング関数
<a name="AuroraPostgreSQL.Security.DynamicMasking.PredefinedMaskingFunctions"></a>

`pg_columnmask` 拡張機能は、`pg_columnmask` ポリシーのマスキング式として使用できる C 言語 (高速実行用) で記述された組み込みユーティリティ関数を提供します。

**mask\$1text**

設定可能な可視性オプションを使用してテキストデータをマスクする関数。

**引数**:


| パラメータ | Datatype | 説明 | 
| --- | --- | --- | 
| input | TEXT |  マスクする元のテキスト文字列  | 
| mask\$1char | CHAR(1) |  マスキングに使用される文字 (デフォルト: 'X')  | 
| visible\$1prefix | INT |  入力テキストの先頭でマスクされていないままになる文字数 (デフォルト: 0)  | 
| visible\$1suffix | INT |  マスクされていないままになる入力テキストの末尾の文字数 (デフォルト: 0)  | 
| use\$1hash\$1mask | BOOLEAN |  TRUE の場合、mask\$1char の代わりにハッシュベースのマスキングを使用します (デフォルト: FALSE)  | 

**Example さまざまなマスキングオプションの使用**  
入力文字列全体をデフォルトの「X」文字でマスクする  

```
postgres=> SELECT pgcolumnmask.mask_text('Hello World');
  mask_text  
-------------
 XXXXXXXXXXX
```
`mask_char` 引数を使用して、別の文字を使用してテキスト入力をマスクする  

```
postgres=> SELECT pgcolumnmask.mask_text('Hello World', '*');
  mask_text  
-------------
 ***********
```
`visible_prefix` および `visible_suffix` パラメータを使用して、テキストの先頭と末尾でマスクされない文字数を制御します。  

```
postgres=> SELECT pgcolumnmask.mask_text('Hello World', '*', 5, 1);
  mask_text  
-------------
 Hello*****d
```
`use_hash_mask` が true の場合、入力文字列はランダムな文字を使用してマスクされます。`mask_char` 引数は無視されますが、`visible_prefix` と `visible_suffix` は引き続き有効です。  

```
postgres=> SELECT pgcolumnmask.mask_text('Hello World', '*', 2, 2, true);
  mask_text  
-------------
 Hex36dOHild
```

**mask\$1timestamp**


| パラメータ | Datatype | 説明 | 
| --- | --- | --- | 
| ts\$1to\$1mask | TIMESTAMP |  マスクする元のタイムスタンプ  | 
| mask\$1part | TEXT |  タイムスタンプのどの部分をマスクするかを指定します (デフォルト: 'all') 有効な値: 'year'、'month'、'day'、'hour'、'minute'、'second'、'all'  | 
| mask\$1value | TIMESTAMP |  マスキングに使用するタイムスタンプ値 (デフォルト: '1900-01-01 00:00:00')  | 

**Example `mask_timestamps` の使用**  
これらの例は、デフォルト値への完全なタイムスタンプのマスキング、特定のタイムスタンプコンポーネント (年のみ) の部分的なマスキング、カスタム置換値によるマスキングを示しています。  
入力値をデフォルトのタイムスタンプに完全にマスクする  

```
postgres=> SELECT pgcolumnmask.mask_timestamp('2023-06-15 14:30:00');
   mask_timestamp    
---------------------
 1900-01-01 00:00:00
```
年のみの例からタイムスタンプの一部のみをマスクするには  

```
postgres=> SELECT pgcolumnmask.mask_timestamp('2023-06-15 14:30:00', 'year');
   mask_timestamp    
---------------------
 1900-06-15 14:30:00
```
タイムスタンプのマスクされた値を変更するには、`mask_value` 引数を使用します。  

```
postgres=> SELECT pgcolumnmask.mask_timestamp('2023-06-15 14:30:00', 'all', '2012-12-12 12:12:12');
   mask_timestamp    
---------------------
 2012-12-12 12:12:12
```

**mask\$1timestamp**

E メール構造を保持しながら E メールアドレスをマスクする関数。


| パラメータ | Datatype | 説明 | 
| --- | --- | --- | 
| input | TEXT |  マスクする元の E メールアドレス  | 
| mask\$1char | CHAR(1) |  マスキングに使用される文字 (デフォルト: 'X')  | 
| mask\$1local | BOOLEAN |  TRUE の場合、E メールのローカル部分をマスクします (@ より前) (デフォルト: TRUE)  | 
| mask\$1domain | BOOLEAN |  TRUE の場合、E メールのドメイン部分をマスクします (@ の後) (デフォルト: TRUE)  | 

**Example `mask_email` の使用**  
これらの例は、E メールアドレスのローカル部分またはドメイン部分の完全な E メールマスキング、カスタムマスク文字、選択的マスキングを示しています。  
完全なマスキング  

```
postgres=> SELECT pgcolumnmask.mask_email('user@example.com');
    mask_email    
------------------
 XXXX@XXXXXXX.com
```
マスキングに使用する文字を変更するには、`mask_char` を使用します。  

```
postgres=> SELECT pgcolumnmask.mask_email('user@example.com', '*');
    mask_email    
------------------
 ****@*******.com
```
`mask_local` と `mask_domain` を使用してローカルとドメインのマスキングを制御する  

```
postgres=> SELECT pgcolumnmask.mask_email('user@example.com', '*', true, false);
    mask_email    
------------------
 ****@example.com

postgres=> SELECT pgcolumnmask.mask_email('user@example.com', '*', false, true);
    mask_email    
------------------
 user@*******.com
```

# エンドツーエンドのワークフローでの pg\$1columnmask の実装
<a name="AuroraPostgreSQL.Security.DynamicMasking.WorkflowExample"></a>

このセクションでは、機密データを含むサンプル従業員テーブル `pg_columnmask` を使用するための完全な実装を示します。カスタムマスキング関数を作成し、さまざまなロール (内部、サポート、アナリスト) の異なる重みレベルを持つ複数のマスキングポリシーを定義し、単一または複数のロールメンバーシップを持つユーザーがさまざまなレベルのマスクされたデータを表示する方法を確認します。この例では、RETURNING 句を使用した DML ステートメントのマスキング動作、テーブルとビューのトリガー、名前の変更、重みの変更、クリーンアップなどのポリシー管理オペレーションについても説明します。

1. 機密データを含むサンプルテーブルを作成します。

   ```
   CREATE SCHEMA hr;
   
   CREATE TABLE hr.employees (
       id INT PRIMARY KEY,
       name TEXT NOT NULL,
       email TEXT,
       ssn TEXT,
       salary NUMERIC(10,2)
    );
   
   INSERT INTO hr.employees VALUES
       (1, 'John Doe', 'john.doe@example.com', '123-45-6789', 50000.00),
       (2, 'Jane Smith', 'jane.smith@example.com', '987-65-4321', 60000.00);
   ```

1. カスタムマスキング関数を作成します。

   ```
   CREATE OR REPLACE FUNCTION public.mask_ssn(ssn TEXT)
       RETURNS TEXT AS $$
       BEGIN
           RETURN 'XXX-XX-' || RIGHT(ssn, 4);
       END;
       $$ LANGUAGE plpgsql;
   
   CREATE OR REPLACE FUNCTION public.mask_salary(salary NUMERIC, multiplier NUMERIC DEFAULT 0.0)
       RETURNS NUMERIC AS $$
       BEGIN
           RETURN salary * multiplier;
       END;
       $$ LANGUAGE plpgsql;
   ```

1. ユーザーロールに基づいて異なるマスキングレベルで複数のポリシーを作成します。

   ```
   -- Create different roles
   CREATE ROLE analyst_role;
   CREATE ROLE support_role;
   CREATE ROLE intern_role;
   
   GRANT USAGE ON SCHEMA hr TO analyst_role, support_role, intern_role;
   GRANT SELECT ON hr.employees TO analyst_role, support_role, intern_role;
   ----------------------------------------------------------------------
   
   -- Low-Weight Policy (Intern)
   CALL pgcolumnmask.create_masking_policy(
       'employee_mask_strict',
       'hr.employees',
       JSON_BUILD_OBJECT('name', 'pgcolumnmask.mask_text(name, ''*'')',
                         'email', 'pgcolumnmask.mask_email(email)',
                         'ssn', 'pgcolumnmask.mask_text(ssn, ''*'')',
                         'salary', 'public.mask_salary(salary)')::JSONB,
       ARRAY['intern_role'],
       10  -- Lowest weight
   );
   
   ----------------------------------------------------------------------
   -- Medium-Weight Policy (Support)
   CALL pgcolumnmask.create_masking_policy(
       'employee_mask_moderate',
       'hr.employees',
       JSON_BUILD_OBJECT('email', 'pgcolumnmask.mask_email(email, ''#'')',
                         'ssn', 'public.mask_ssn(ssn)',
                         'salary', 'public.mask_salary(salary)')::JSONB,
       ARRAY['support_role'],
       50   -- Medium weight
   );
   
   ----------------------------------------------------------------------
   -- High-Weight Policy (Analyst)
   CALL pgcolumnmask.create_masking_policy(
       'employee_mask_light',
       'hr.employees',
       JSON_BUILD_OBJECT('ssn', 'public.mask_ssn(ssn)',
                         'salary', 'public.mask_salary(salary, 0.9)')::JSONB,
       ARRAY['analyst_role'],
       100   -- Highest weight
   );
   ```

1. 次の例は、ロールメンバーシップとポリシーの重みに基づいてさまざまなユーザーがデータを表示する方法を示しています。

   ```
   -- Create users
   CREATE USER sarah_intern;
   GRANT intern_role TO sarah_intern;
   
   CREATE USER lisa_support;
   GRANT support_role TO lisa_support;
   
   CREATE USER mike_analyst;
   GRANT analyst_role TO mike_analyst;
   
   CREATE USER ethan_support_intern;
   GRANT support_role, intern_role TO ethan_support_intern;
   
   CREATE USER john_analyst_intern;
   GRANT analyst_role, intern_role TO john_analyst_intern;
   ```

   インターンとして (最も厳格なマスキング):

   ```
   SET ROLE sarah_intern;
   
   SELECT * FROM hr.employees;
    id |    name    |         email          |     ssn     | salary 
   ----+------------+------------------------+-------------+--------
     1 | ********   | XXXXXXXX@XXXXXXX.com   | *********** |   0.00
     2 | ********** | XXXXXXXXXX@XXXXXXX.com | *********** |   0.00
   ```

   サポートユーザーとして (中程度のマスキング):

   ```
   SET ROLE lisa_support;
   
   SELECT * FROM hr.employees;
    id |    name    |         email          |     ssn     | salary 
   ----+------------+------------------------+-------------+--------
     1 | John Doe   | ########@#######.com   | XXX-XX-6789 |   0.00
     2 | Jane Smith | ##########@#######.com | XXX-XX-4321 |   0.00
   ```

   アナリストとして (最小のマスキング):

   ```
   SET ROLE mike_analyst;
   
   SELECT * FROM hr.employees;
    id |    name    |         email          |     ssn     |  salary  
   ----+------------+------------------------+-------------+----------
     1 | John Doe   | john.doe@example.com   | XXX-XX-6789 | 45000.00
     2 | Jane Smith | jane.smith@example.com | XXX-XX-4321 | 54000.00
   ```

   インターンユーザーとサポートユーザーの両方である ethan\$1support\$1intern ユーザーとして:

   ```
   SET ROLE ethan_support_intern;
   
   -- masking policies appliable to this user: employee_mask_strict and employee_mask_moderate
   -- id : unmasked because no masking policy appliable on ethan_support_intern
   --            masks these columns
   -- name : masked because of employee_mask_strict policy
   -- email, ssn, salary : both employee_mask_strict and employee_mask_moderate mask these columns
   --                      but employee_mask_moderate will be use because of higher weight 
   
   SELECT * FROM hr.employees;
    id |    name    |         email          |     ssn     | salary 
   ----+------------+------------------------+-------------+--------
     1 | ********   | ########@#######.com   | XXX-XX-6789 |   0.00
     2 | ********** | ##########@#######.com | XXX-XX-4321 |   0.00
   ```

   インターンとアナリストの両方である john\$1analyst\$1intern として:

   ```
   SET ROLE john_analyst_intern;
   
   -- masking policies appliable to this user: employee_mask_strict and employee_mask_light
   -- id : unmasked because no masking policy appliable on john_analyst_intern
   --            masks these columns
   -- name, email : masked because of employee_mask_strict
   -- ssn, salary : both employee_mask_strict and employee_mask_light mask these columns
   --               but employee_mask_light will be use because of higher weight 
   
   SELECT * FROM hr.employees;
    id |    name    |         email          |     ssn     |  salary  
   ----+------------+------------------------+-------------+----------
     1 | ********   | XXXXXXXX@XXXXXXX.com   | XXX-XX-6789 | 45000.00
     2 | ********** | XXXXXXXXXX@XXXXXXX.com | XXX-XX-4321 | 54000.00
   ```

# DML オペレーションのマスキング動作について
<a name="AuroraPostgreSQL.Security.DynamicMasking.DMLMasking"></a>

`pg_columnmask` は、INSERT、UPDATE、DELETE、MERGE ステートメントを含むすべての DML オペレーションに一貫して適用されます。これらのオペレーションを実行すると、Aurora PostgreSQL はコア原則に従ってデータをマスクします。ストレージから読み取られたデータは、現在のユーザーの適用可能なポリシーに従ってマスクされます。

マスキングは、次のようなクエリコンポーネントの一部に影響します。
+ WHERE 句
+ JOIN 条件
+ サブクエリ
+ RETURNING 句

これらのコンポーネントはすべて、元のデータではなくマスクされた値で動作します。データはマスクされていない状態でストレージに書き込まれますが、ユーザーが読み返すときにはマスクされたビューのみが表示されます。

Aurora PostgreSQL は、マスクされた値ではなく、実際の保存値に対してすべてのデータベース制約 (NOT NULL、UNIQUE、CHECK、FOREIGN KEY) を適用します。これにより、マスキング関数が慎重に設計されていない場合に、明らかな不整合が生じることがあります。

マスキングは列レベルのアクセス許可とともに機能します。
+ SELECT 権限のないユーザーは列を読み取ることができません
+ SELECT 権限を持つユーザーは、該当するポリシーに従ってマスクされた値を表示します。

# トリガー関数のマスキング動作について
<a name="AuroraPostgreSQL.Security.DynamicMasking.TriggerFunctionMasking"></a>

`pg_columnmask` ポリシーをテーブルに適用するときは、マスキングがトリガー関数とどのように相互作用するかを理解することが重要です。トリガーは、INSERT、UPDATE、DELETE オペレーションなど、テーブル上の特定のイベントに応答して自動的に実行されるデータベース関数です。

デフォルトでは、DDM はトリガーのタイプに応じて異なるマスキングルールを適用します。

テーブルトリガー  
**移行テーブルのマスク解除** — テーブルのトリガー関数は、古い行バージョンと新しい行バージョンの両方で、移行テーブルのマスク解除されたデータにアクセスできます。  
テーブル所有者はトリガーを作成し、データを所有するため、テーブルを効果的に管理するためのフルアクセスを持ちます

ビュートリガー (トリガーの代わりに)  
**移行テーブルがマスクされている** – ビューのトリガー関数は、現在のユーザーのアクセス許可に従ってマスクされたデータを参照します  
ビュー所有者はベーステーブル所有者とは異なる場合があり、基盤となるテーブルのマスキングポリシーを尊重する必要があります

2 つのサーバーレベルの設定パラメータは、マスクされたテーブルでトリガーの動作を制御します。これらは `rds_superuser` によってのみ設定できます。
+ **マスクされたテーブルのトリガーを制限する** – マスクされたユーザーが、該当するマスキングポリシーを持つテーブルで DML オペレーションを実行するときにトリガーの実行を防止します。
+ **マスクされたテーブルを持つビューのトリガーを制限する:** – ビュー定義に現在のユーザーに適用されるマスキングポリシーを持つテーブルが含まれている場合、ビューでのトリガー実行を防止します。

**Example 関数アプリケーションとテーブルおよびビューの違い**  
次の例では、古い行の値と新しい行の値を出力するトリガー関数を作成し、同じ関数をテーブルにアタッチした場合とビューにアタッチした場合の動作がどのように異なるかを示します。  

```
-- Create trigger function
CREATE OR REPLACE FUNCTION print_changes()
    RETURNS TRIGGER AS
    $$
        BEGIN
        RAISE NOTICE 'Old row: name=%, email=%, ssn=%, salary=%',
            OLD.name, OLD.email, OLD.ssn, OLD.salary;
        
        RAISE NOTICE 'New row: name=%, email=%, ssn=%, salary=%',
            NEW.name, NEW.email, NEW.ssn, NEW.salary;
        
        RETURN NEW;
        END;
    $$ LANGUAGE plpgsql;

-- Create trigger
CREATE TRIGGER print_changes_trigger
    BEFORE UPDATE ON hr.employees
    FOR EACH ROW
    EXECUTE FUNCTION print_changes();

-- Grant update to analyst role
GRANT UPDATE ON hr.employees TO analyst_role;

-- Unmasked data must be seen inside trigger even for masked user for the OLD and NEW
-- row passed to trigger function
BEGIN;
SET ROLE mike_analyst;
UPDATE hr.employees SET id = id + 10 RETURNING *;
NOTICE:  Old row: name=John Doe, email=john.doe@example.com, ssn=123-45-6789, salary=50000.00
NOTICE:  New row: name=John Doe, email=john.doe@example.com, ssn=123-45-6789, salary=50000.00
NOTICE:  Old row: name=Jane Smith, email=jane.smith@example.com, ssn=987-65-4321, salary=60000.00
NOTICE:  New row: name=Jane Smith, email=jane.smith@example.com, ssn=987-65-4321, salary=60000.00
 id |    name    |         email          |     ssn     |  salary  
----+------------+------------------------+-------------+----------
 11 | John Doe   | john.doe@example.com   | XXX-XX-6789 | 45000.00
 12 | Jane Smith | jane.smith@example.com | XXX-XX-4321 | 54000.00
(2 rows)

ROLLBACK;


-- Triggers on views (which are supposed to see masked data for new/old row)
CREATE VIEW hr.view_over_employees AS SELECT * FROM hr.employees;
GRANT UPDATE, SELECT ON hr.view_over_employees TO analyst_role;

-- Create trigger for this view
CREATE TRIGGER print_changes_trigger
    INSTEAD OF UPDATE ON hr.view_over_employees
    FOR EACH ROW
    EXECUTE FUNCTION print_changes();

-- Masked new and old rows should be passed to trigger if trigger is on view
BEGIN;
SET ROLE mike_analyst;
UPDATE hr.view_over_employees SET id = id + 10 RETURNING *;
NOTICE:  Old row: name=John Doe, email=john.doe@example.com, ssn=XXX-XX-6789, salary=45000.00
NOTICE:  New row: name=John Doe, email=john.doe@example.com, ssn=XXX-XX-6789, salary=45000.00
NOTICE:  Old row: name=Jane Smith, email=jane.smith@example.com, ssn=XXX-XX-4321, salary=54000.00
NOTICE:  New row: name=Jane Smith, email=jane.smith@example.com, ssn=XXX-XX-4321, salary=54000.00
 id |    name    |         email          |     ssn     |  salary  
----+------------+------------------------+-------------+----------
 11 | John Doe   | john.doe@example.com   | XXX-XX-6789 | 45000.00
 12 | Jane Smith | jane.smith@example.com | XXX-XX-4321 | 54000.00
(2 rows)
ROLLBACK;
```
マスクされたテーブルにトリガーを実装する前に、トリガーの動作を確認することをお勧めします。テーブルトリガーは移行テーブルのマスクされていないデータにアクセスできますが、ビュートリガーにはマスクされたデータが表示されます。

**Example マスキングポリシーの名前変更**  
次の例は、`rename_masking_policy` プロシージャを使用して既存のポリシーの名前を変更する方法を示しています。  

```
-- Rename the strict policy
CALL pgcolumnmask.rename_masking_policy(
    'employee_mask_strict',
    'hr.employees',
    'intern_protection_policy'
);

-- Verify the rename
SELECT policyname, roles, weight
    FROM pgcolumnmask.pg_columnmask_policies
    WHERE tablename = 'employees'
    ORDER BY weight DESC;

        policyname        |     roles      | weight 
--------------------------+----------------+--------
 employee_mask_light      | {analyst_role} |    100
 employee_mask_moderate   | {support_role} |     50
 intern_protection_policy | {intern_role}  |     10
```

**Example ポリシーの重みの変更**  
次の例は、ポリシーの重みを変更して重みを変える方法を示しています。  

```
-- Change weight of moderate policy
CALL pgcolumnmask.alter_masking_policy(
    'employee_mask_moderate'::NAME,
    'hr.employees'::REGCLASS,
    NULL,    -- Keep existing masking expressions
    NULL,    -- Keep existing roles
    75       -- New weight
);

-- Verify the changes
SELECT policyname, roles, weight
    FROM pgcolumnmask.pg_columnmask_policies
    WHERE tablename = 'employees'
    ORDER BY weight DESC;
        policyname        |     roles      | weight 
--------------------------+----------------+--------
 employee_mask_light      | {analyst_role} |    100
 employee_mask_moderate   | {support_role} |     75
 intern_protection_policy | {intern_role}  |     10
```

**Example クリーンアップ**  
次の例は、すべてのポリシー、テーブル、ユーザーを削除する方法を示しています。  

```
-- Drop policies
CALL pgcolumnmask.drop_masking_policy(
    'intern_protection_policy',
    'hr.employees'
);

CALL pgcolumnmask.drop_masking_policy(
    'employee_mask_moderate',
    'hr.employees'
);

CALL pgcolumnmask.drop_masking_policy(
    'employee_mask_light',
    'hr.employees'
);

-- Drop table and functions
DROP VIEW IF EXISTS hr.view_over_employees;
DROP TABLE IF EXISTS hr.employees;
DROP SCHEMA IF EXISTS hr;
DROP FUNCTION IF EXISTS public.mask_ssn(text);
DROP FUNCTION IF EXISTS public.mask_salary(numeric, numeric);

-- Drop users
DROP USER sarah_intern, lisa_support, mike_analyst,
    ethan_support_intern, john_analyst_intern;
DROP ROLE intern_role, support_role, analyst_role;
```

# マスキングポリシー管理ロールの設定
<a name="AuroraPostgreSQL.Security.DynamicMasking.PolicyManagementRole"></a>

PostgreSQL 列マスキング拡張機能 を使用すると、`pg_columnmask` または `rds_superuser` テーブル所有者の権限を必要とせずに、マスキングポリシーの管理を特定のロールに委任できます。これにより、マスキングポリシーを作成、変更、削除できるユーザーをより詳細に制御できます。

マスキングポリシー管理権限を持つロールを設定するには、次の手順に従います。

1. ポリシー管理者ロールの作成 – `rds_superuser` として、マスキングポリシーの管理を担当する新しいロールを作成します。

   ```
   CREATE ROLE mask_admin NOLOGIN;
   ```

1. PostgreSQL パラメータの設定 – カスタム DB クラスターパラメータグループで、`pgcolumnmask.policy_admin_rolname` エンジン設定パラメータを作成したロールの名前に設定します。

   ```
   pgcolumnmask.policy_admin_rolname = mask_admin
   ```

   このエンジン設定パラメータは DB クラスターパラメータグループで設定でき、インスタンスの再起動は必要ありません。パラメータの更新の詳細については、「[Amazon Aurora での DB クラスターパラメータグループのパラメータの変更](USER_WorkingWithParamGroups.ModifyingCluster.md)」を参照してください。

1. ユーザーにロールを付与する `rds_superuser` として、マスキングポリシーを管理できるユーザーに `mask_admin` ロールを付与します。

   ```
   CREATE USER alice LOGIN;
   CREATE USER bob LOGIN;
   GRANT mask_admin TO alice, bob;
   ```

   さらに、マスキングポリシーを管理するスキーマに対する USAGE 権限がユーザーに付与されていることを確認します。

   ```
   GRANT USAGE ON SCHEMA hr TO alice, bob;
   ```

これで、ユーザー `alice` と `bob` がデータベースに接続すると、標準の `pg_columnmask` 拡張機能を使用して、スキーマに対する `USAGE` 権限を持つすべてのスキーマ内のすべてのテーブルでマスキングポリシーを作成、変更、削除できるようになります。

# 安全な pg\$1columnmask 実装のベストプラクティス
<a name="AuroraPostgreSQL.Security.DynamicMasking.BestPractices"></a>

次のセクションでは、Aurora PostgreSQL 環境で `pg_columnmask` を実装するためのセキュリティのベストプラクティスについて説明します。次の推奨事項に従ってください。
+ 安全なロールベースのアクセスコントロールアーキテクチャを確立する
+ セキュリティの脆弱性を防ぐマスキング関数を開発する
+ マスクされたデータを使用してトリガーの動作を理解して制御する

## ロールベースのセキュリティアーキテクチャ
<a name="AuroraPostgreSQL.Security.DynamicMasking.BestPractices.architecture"></a>

データベースにアクセス制御を実装するロール階層を定義します。Aurora PostgreSQL `pg_columnmask` は、これらのロール内できめ細かなデータマスキング用のレイヤーを追加することで、これらのコントロールを強化します。

個々のユーザーにアクセス許可を付与するのではなく、組織の機能に沿った専用ロールを作成します。このアプローチにより、監査性が向上し、組織構造が進化するにつれてアクセス許可の管理が簡素化されます。

**Example 組織ロール階層の作成**  
次の例では、さまざまな機能専用のロールを持つ組織ロール階層を作成し、個々のユーザーを適切なロールに割り当てます。この例では、組織ロール (analyst\$1role、support\$1role) が最初に作成され、個々のユーザーにこれらのロールのメンバーシップが付与されます。この構造により、個々のユーザーではなくロールレベルでアクセス許可を管理できます。  

```
-- Create organizational role hierarchy
CREATE ROLE data_admin_role;
CREATE ROLE security_admin_role;
CREATE ROLE analyst_role;
CREATE ROLE support_role;
CREATE ROLE developer_role;

-- Specify security_admin_role as masking policy manager in the DB cluster parameter
-- group pgcolumnmask.policy_admin_rolname = 'security_admin_role'

-- Create specific users and assign to appropriate roles
CREATE USER security_manager;
CREATE USER data_analyst1, data_analyst2;
CREATE USER support_agent1, support_agent2;

GRANT security_admin_role TO security_manager;
GRANT analyst_role TO data_analyst1, data_analyst2;
GRANT support_role TO support_agent1, support_agent2;
```
各ロールに必要な最小限のアクセス許可のみを付与することで、最小特権の原則を実装します。認証情報が侵害された場合に悪用される可能性のある広範なアクセス許可を付与することは避けてください。  

```
-- Grant specific table permissions rather than schema-wide access
GRANT SELECT ON sensitive_data.customers TO analyst_role;
GRANT SELECT ON sensitive_data.transactions TO analyst_role;
-- Do not grant: GRANT ALL ON SCHEMA sensitive_data TO analyst_role;
```
ポリシー管理者には、マスキングポリシーを管理するスキーマに対する `USAGE` 権限が必要です。最小特権の原則に従って、これらの権限を選択的に付与します。スキーマアクセス許可を定期的に見直して、承認された担当者のみがポリシー管理機能を維持できるようにします。  
ポリシー管理者ロールのパラメータ設定は、データベース管理者のみに制限されます。このパラメータをデータベースレベルまたはセッションレベルで変更することはできません。これにより、権限のないユーザーがポリシー管理者割り当てを上書きできなくなります。この制限により、マスキングポリシーの制御が一元化され、安全に維持されます。  
ポリシー管理者ロールをグループではなく特定の個人に割り当てます。このターゲットを絞ったアプローチにより、ポリシー管理者はデータベース内のすべてのテーブルをマスクできるため、マスキングポリシー管理への選択的なアクセスが保証されます。

## 安全なマスキング関数の開発
<a name="AuroraPostgreSQL.Security.DynamicMasking.BestPractices.MaskingDevelopment"></a>

早期バインディングセマンティクスを使用してマスキング関数を開発し、適切な依存関係の追跡を確保し、ランタイム中の検索パスの変更などの遅延バインディングの脆弱性を防止します。SQL 関数の `BEGIN ATOMIC` 構文を使用して、コンパイル時の検証 (早期バインディング) と依存関係管理を有効にすることをお勧めします。

```
-- Example - Secure masking function with early binding
CREATE OR REPLACE FUNCTION secure_mask_ssn(input_ssn TEXT)
    RETURNS TEXT
    LANGUAGE SQL
    IMMUTABLE PARALLEL SAFE STRICT
    BEGIN ATOMIC
        SELECT CASE
            WHEN input_ssn IS NULL THEN NULL
            WHEN length(input_ssn) < 4 THEN repeat('X', length(input_ssn))
            ELSE repeat('X', length(input_ssn) - 4) || right(input_ssn, 4)
        END;
    END;
```

または、すべてのオブジェクト参照を明示的にスキーマで修飾することで、検索パスの変更を許容しない関数を作成し、異なるユーザーセッション間で一貫した動作を確保します。

```
-- Function immune to search path changes
CREATE OR REPLACE FUNCTION data_masking.secure_phone_mask(phone_number TEXT)
    RETURNS TEXT
    LANGUAGE SQL
    IMMUTABLE PARALLEL SAFE STRICT
    AS $$
    SELECT CASE
        WHEN phone_number IS NULL THEN NULL
        WHEN public.length(public.regexp_replace(phone_number, '[^0-9]', '', 'g')) < 10 THEN 'XXX-XXX-XXXX'
        ELSE public.regexp_replace(
            phone_number,
            '([0-9]{3})[0-9]{3}([0-9]{4})',
            public.concat('\1-XXX-\2')
        )
    END;
    $$;
```

マスキング関数内に入力検証を実装してエッジケースを処理し、予期しない動作を防止します。常に NULL 処理を含め、入力形式を検証して、一貫したマスキング動作を確保します。

```
-- Robust masking function with comprehensive input validation
CREATE OR REPLACE FUNCTION secure_mask_phone(phone_number TEXT)
    RETURNS TEXT
    LANGUAGE SQL
    IMMUTABLE PARALLEL SAFE STRICT
    BEGIN ATOMIC
        SELECT CASE
            WHEN phone_number IS NULL THEN NULL
            WHEN length(trim(phone_number)) = 0 THEN phone_number
            WHEN length(regexp_replace(phone_number, '[^0-9]', '', 'g')) < 10 THEN 'XXX-XXX-XXXX'
            ELSE regexp_replace(phone_number, '([0-9]{3})[0-9]{3}([0-9]{4})', '\1-XXX-\2')
        END;
    END;
```

## pg\$1columnmask を使用した DML トリガーの動作
<a name="AuroraPostgreSQL.Security.DynamicMasking.BestPractices.DMLTriggerBehavior"></a>

テーブルトリガーの場合、移行テーブルは完全にマスク解除されます。ビュートリガー (IOT) の場合、移行テーブルは現在のユーザーのビューアクセス許可に従ってマスクされます。

pg\$1columnmask を使用したテーブルトリガー  
トリガーには、DML クエリの実行によって変更された行の古いバージョンと新しいバージョンを含む移行テーブルが渡されます。トリガーがいつ起動されるかに応じて、Aurora PostgreSQL は古い行と新しい行を入力します。例えば、参照する古いバージョンがないため、`BEFORE INSERT` トリガーには新しいバージョンの行と空の古いバージョンのみが含まれます。  
`pg_columnmask` は、テーブルのトリガー内の移行テーブルをマスクしません。トリガーは、マスクされた列を本文内で使用でき、マスクされていないデータが表示されます。トリガー作成者は、トリガーがユーザーに対してどのように実行されるかを確認する必要があります。この場合、次の例は正しく動作します。  

```
-- Example for table trigger uses masked column in its definition
-- Create a table and insert some rows
CREATE TABLE public.credit_card_table (
    name TEXT,
    credit_card_no VARCHAR(16),
    is_fraud BOOL
);

INSERT INTO public.credit_card_table (name, credit_card_no, is_fraud)
    VALUES
    ('John Doe', '4532015112830366', false),
    ('Jane Smith', '5410000000000000', true),
    ('Brad Smith', '1234567891234567', true);

-- Create a role which will see masked data and grant it privileges
CREATE ROLE intern_user;
GRANT SELECT, DELETE ON public.credit_card_table TO intern_user;

-- Trigger which will silenty skip delete of non fraudelent credit cards
CREATE OR REPLACE FUNCTION prevent_non_fraud_delete()
    RETURNS TRIGGER AS
    $$
    BEGIN
        IF OLD.is_fraud = false THEN
            RETURN NULL;
        END IF;
        RETURN OLD;
    END;
    $$ LANGUAGE plpgsql;

CREATE TRIGGER prevent_non_fraud_delete
    BEFORE DELETE ON credit_card_table
    FOR EACH ROW
    EXECUTE FUNCTION prevent_non_fraud_delete();

CREATE OR REPLACE FUNCTION public.return_false()
    RETURNS BOOLEAN
    LANGUAGE SQL
    IMMUTABLE PARALLEL SAFE STRICT
    BEGIN ATOMIC
      SELECT false;
    END;

-- A masking policy that masks both credit card number and is_fraud column.
-- If we apply masking inside trigger then prevent_non_fraud_delete trigger will
-- allow deleting more rows to masked user (even non fraud ones).
CALL pgcolumnmask.create_masking_policy(
    'mask_credit_card_no_&_is_fraud'::NAME,
    'public.credit_card_table'::REGCLASS,
    JSON_BUILD_OBJECT('credit_card_no', 'pgcolumnmask.mask_text(credit_card_no)',
                      'is_fraud', 'public.return_false()')::JSONB,
    ARRAY['intern_user']::NAME[],
    10::INT
);

-- Test trigger behaviour using intern_user
BEGIN;
SET ROLE intern_user;
-- credit card number & is_fraud is completely masked from intern_user
SELECT * FROM public.credit_card_table;
    name    |  credit_card_no  | is_fraud 
------------+------------------+----------
 John Doe   | XXXXXXXXXXXXXXXX | f
 Jane Smith | XXXXXXXXXXXXXXXX | f
 Brad Smith | XXXXXXXXXXXXXXXX | f
(3 rows)

-- The delete trigger lets the intern user delete rows for Jane and Brad even though
-- intern_user sees their is_fraud = false, but the table trigger works with original
-- unmasked value
DELETE FROM public.credit_card_table RETURNING *;
    name    |  credit_card_no  | is_fraud 
------------+------------------+----------
 Jane Smith | XXXXXXXXXXXXXXXX | f
 Brad Smith | XXXXXXXXXXXXXXXX | f
(2 rows)

COMMIT;
```
トリガー作成者は、ユーザーがトリガー本文で使用するステートメントに気を付けないと、マスクされていないデータをユーザーに漏洩してしまいます。例えば、`RAISE NOTICE ‘%’, masked_column;` を使用すると、現在のユーザーに列が出力されます。  

```
-- Example showing table trigger leaking column value to current user
CREATE OR REPLACE FUNCTION leaky_trigger_func()
    RETURNS TRIGGER AS
    $$
    BEGIN
        RAISE NOTICE 'Old credit card number was: %', OLD.credit_card_no;
        RAISE NOTICE 'New credit card number is %', NEW.credit_card_no;
        RETURN NEW;
    END;
    $$ LANGUAGE plpgsql;

CREATE TRIGGER leaky_trigger
    AFTER UPDATE ON public.credit_card_table
    FOR EACH ROW
    EXECUTE FUNCTION leaky_trigger_func();

-- Grant update on column is_fraud to auditor role
-- auditor will NOT HAVE PERMISSION TO READ DATA
CREATE ROLE auditor;
GRANT UPDATE (is_fraud) ON public.credit_card_table TO auditor;

-- Also add auditor role to existing masking policy on credit card table
CALL pgcolumnmask.alter_masking_policy(
    'mask_credit_card_no_&_is_fraud'::NAME,
    'public.credit_card_table'::REGCLASS,
    NULL::JSONB,
    ARRAY['intern_user', 'auditor']::NAME[],
    NULL::INT
);

-- Log in as auditor
-- [auditor]
-- Update will fail if trying to read data from the table
UPDATE public.credit_card_table
    SET is_fraud = true
    WHERE credit_card_no = '4532015112830366';
ERROR:  permission denied for table cc_table

-- [auditor]
-- But leaky update trigger will still print the entire row even though
-- current user does not have permission to select from public.credit_card_table
UPDATE public.credit_card_table SET is_fraud = true;
NOTICE:  Old credit_card_no was: 4532015112830366
NOTICE:  New credit_card_no is 4532015112830366
```

(トリガーの代わりに) pg\$1columnmask を使用したビューでのトリガー  
トリガーは PostgreSQL のビューでのみ作成できます。更新できないビューで DML ステートメントを実行するために使用されます。ビュークエリ内で使用されるビューとベーステーブルの所有者が異なる可能性があるため、トランジットテーブルは常にトリガー (IOT) ではなく内部でマスクされます。この場合、ベーステーブルにはビュー所有者に適用されるマスキングポリシーがあり、ビュー所有者は常にトリガー内のベーステーブルからのマスクされたデータを表示する必要があります。これは、テーブルのトリガーとは異なります。この場合、トリガー作成者とテーブル内のデータは、ここでは存在しない同じユーザーによって所有されるためです。  

```
-- Create a view over credit card table
CREATE OR REPLACE VIEW public.credit_card_view
    AS
    SELECT * FROM public.credit_card_table;

-- Truncate credit card table and insert fresh data
TRUNCATE TABLE public.credit_card_table;
INSERT INTO public.credit_card_table (name, credit_card_no, is_fraud)
    VALUES
    ('John Doe', '4532015112830366', false),
    ('Jane Smith', '5410000000000000', true),
    ('Brad Smith', '1234567891234567', true);

CREATE OR REPLACE FUNCTION public.print_changes()
    RETURNS TRIGGER AS
    $$
    BEGIN
        RAISE NOTICE 'Old row: name=%, credit card number=%, is fraud=%',
            OLD.name, OLD.credit_card_no, OLD.is_fraud;
    
        RAISE NOTICE 'New row: name=%, credit card number=%, is fraud=%',
            NEW.name, NEW.credit_card_no, NEW.is_fraud;
    
    RETURN NEW;
   END;
   $$ LANGUAGE plpgsql;

CREATE TRIGGER print_changes_trigger
    INSTEAD OF UPDATE ON public.credit_card_view
    FOR EACH ROW
    EXECUTE FUNCTION public.print_changes();

GRANT SELECT, UPDATE ON public.credit_card_view TO auditor;

-- [auditor]
-- Login as auditor role
BEGIN;

-- Any data coming out from the table will be masked in instead of triggers
-- according to masking policies applicable to current user
UPDATE public.credit_card_view
    SET name = CONCAT(name, '_new_name')
    RETURNING *;
NOTICE:  Old row: name=John Doe, credit card number=XXXXXXXXXXXXXXXX, is fraud=f
NOTICE:  New row: name=John Doe_new_name, credit card number=XXXXXXXXXXXXXXXX, is fraud=f
NOTICE:  Old row: name=Jane Smith, credit card number=XXXXXXXXXXXXXXXX, is fraud=f
NOTICE:  New row: name=Jane Smith_new_name, credit card number=XXXXXXXXXXXXXXXX, is fraud=f
NOTICE:  Old row: name=Brad Smith, credit card number=XXXXXXXXXXXXXXXX, is fraud=f
NOTICE:  New row: name=Brad Smith_new_name, credit card number=XXXXXXXXXXXXXXXX, is fraud=f
        name         |  credit_card_no  | is_fraud 
---------------------+------------------+----------
 John Doe_new_name   | XXXXXXXXXXXXXXXX | f
 Jane Smith_new_name | XXXXXXXXXXXXXXXX | f
 Brad Smith_new_name | XXXXXXXXXXXXXXXX | f
 
 -- Any new data going into the table using INSERT or UPDATE command will be unmasked
 UPDATE public.credit_card_view
    SET credit_card_no = '9876987698769876'
    RETURNING *;
NOTICE:  Old row: name=John Doe, credit card number=XXXXXXXXXXXXXXXX, is fraud=f
NOTICE:  New row: name=John Doe, credit card number=9876987698769876, is fraud=f
NOTICE:  Old row: name=Jane Smith, credit card number=XXXXXXXXXXXXXXXX, is fraud=f
NOTICE:  New row: name=Jane Smith, credit card number=9876987698769876, is fraud=f
NOTICE:  Old row: name=Brad Smith, credit card number=XXXXXXXXXXXXXXXX, is fraud=f
NOTICE:  New row: name=Brad Smith, credit card number=9876987698769876, is fraud=f
    name    |  credit_card_no  | is_fraud 
------------+------------------+----------
 John Doe   | 9876987698769876 | f
 Jane Smith | 9876987698769876 | f
 Brad Smith | 9876987698769876 | f
 
 COMMIT;
```

トリガーの動作を制御するデータベース/ユーザーレベルの GuC  
2 つの設定パラメータは、該当するマスキングポリシーを持つユーザーのトリガー実行動作を制御します。これらのパラメータを使用して、追加のセキュリティ制限が必要な場合に、マスクされたテーブルまたはビューでトリガーが実行されないようにします。両方のパラメータはデフォルトで無効になっているため、トリガーが正常に実行されます。  
**最初の GUC: マスクされたテーブルの発射制限をトリガーする**  
仕様:  
+ 名前: `pgcolumnmask.restrict_dml_triggers_for_masked_users`
+ 型: `boolean`
+ デフォルト: `false` (トリガーの実行が許可されます)
TRUE に設定すると、マスクされたユーザーのマスクされたテーブルでトリガーが実行されるのを防ぎます。`pg_columnmask` はエラーを実行します。  
**2 番目の GUC: マスクされたテーブルを持つビューで射撃制限をトリガーする**  
仕様:  
+ 名前: `pgcolumnmask.restrict_iot_triggers_for_masked_users`
+ 型: `boolean`
+ デフォルト: `false` (トリガーの実行が許可されます)
TRUE に設定すると、マスクされたユーザーの定義にマスクされたテーブルを含むビューでトリガーの実行が禁止されます。

これらのパラメータは独立して動作し、標準のデータベース設定パラメータのように設定できます。

# Aurora PostgreSQL pg\$1columnmask データ移動シナリオ
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement"></a>

`pg_columnmask` の動作は、オペレーションがストレージ、論理、またはアプリケーションレイヤーのいずれで行われるかに応じて、データ移動オペレーションごとに異なります。ストレージレベルのオペレーション (クローン作成など) の動作は、論理オペレーション (`pg_dump` など) やアプリケーションレベルのオペレーション (FDW クエリなど) とは異なります。このセクションでは、レプリケーション、バックアップ、エクスポート、移行などの一般的なシナリオのマスキング動作と、それぞれのセキュリティへの影響について説明します。

**Topics**
+ [Aurora Global Database とリードレプリカ](#AuroraPostgreSQL.Security.DynamicMasking.DataMovement.RR)
+ [データベースクローンとスナップショットの復元](#AuroraPostgreSQL.Security.DynamicMasking.DataMovement.Clones)
+ [論理レプリケーション](#AuroraPostgreSQL.Security.DynamicMasking.DataMovement.LogRep)
+ [Blue/Green デプロイ](#AuroraPostgreSQL.Security.DynamicMasking.DataMovement.BlueGreen)
+ [ゼロ ETL ストリームと CDC ストリーム](#AuroraPostgreSQL.Security.DynamicMasking.DataMovement.ZETL)
+ [AWS Database Migration Service](#AuroraPostgreSQL.Security.DynamicMasking.DataMovement.DMS)
+ [データエクスポート](#AuroraPostgreSQL.Security.DynamicMasking.DataMovement.DataExport)
+ [ビューとマテリアライズドビュー](#AuroraPostgreSQL.Security.DynamicMasking.DataMovement.Views)
+ [データダンプと復元](#AuroraPostgreSQL.Security.DynamicMasking.DataMovement.DDR)
+ [外部データラッパー](#AuroraPostgreSQL.Security.DynamicMasking.DataMovement.FDQ)

## Aurora Global Database とリードレプリカ
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement.RR"></a>

Aurora `pg_columnmask` ポリシーは、クラスターボリューム内のデータベースシステムテーブルに保存されます。すべてのレプリカが同じポリシーにアクセスし、一貫してマスクされた結果を返します。Aurora Global Database デプロイの場合、`pg_columnmask` ポリシーは他のデータベースシステムテーブルとともにセカンダリ AWS リージョンにレプリケートされるため、リージョン間で一貫したデータ保護が保証されます。フェイルオーバーシナリオ中、すべての `pg_columnmask` ポリシーはそのまま機能します。

## データベースクローンとスナップショットの復元
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement.Clones"></a>

Aurora Fast Clone およびスナップショット復元オペレーションでは、すべての `pg_columnmask` ポリシー、ロール、および設定がデータベースシステムテーブルの一部として保持されます。クローンまたは復元されたデータベースは、ソースクラスターから既存のすべてのポリシーを継承します。クローン作成または復元後、各データベースクラスターは独立した `pg_columnmask` ポリシーを維持します。

## 論理レプリケーション
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement.LogRep"></a>

初期同期中、論理レプリケーションは標準の SQL COPY オペレーションを使用し、`pg_columnmask` ポリシーはレプリケーションユーザーのアクセス許可に基づいて適用されます。進行中の CDC (変更データキャプチャ) 中、マスキングポリシーは適用されず、マスクされていないデータは WAL レコードを介してレプリケートされます。`pg_create_subscription` 権限を持つユーザーは、管理するシステムへのレプリケーションを設定することで、マスクされていないデータを流出する可能性があります。

## Blue/Green デプロイ
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement.BlueGreen"></a>

スナップショットの復元中、`pg_columnmask` ポリシーは自動的に含まれます。グリーン環境は、ブルー環境のすべてのポリシーの同じコピーから始まります。ブルーからグリーンへのレプリケーション中、データはマスクされません。ブルークラスターでのその後のマスキングポリシーの変更 (DDL コマンド) は、グリーンクラスターにレプリケートされず、RDS ブルー/グリーンデプロイが無効になります。

## ゼロ ETL ストリームと CDC ストリーム
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement.ZETL"></a>

データレプリケーションは `pg_columnmask` ポリシーの影響を受けません。ゼロ ETL は DDL レプリケーションをサポートしますが、`pg_columnmask` または RLS ポリシーはレプリケートしません。ゼロ ETL のレプリケートされたデータにはマスキングポリシーは適用されません。

## AWS Database Migration Service
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement.DMS"></a>

初期データ同期は、DMS タスク用に選択されたユーザーに基づいてマスクまたはマスク解除されます。CDC データは常にマスク解除されます。`pg_columnmask` 関連の内部 RLS ポリシーは移行できますが、pg\$1columnmask 対応以外のターゲットでは機能しません。

## データエクスポート
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement.DataExport"></a>

`pg_columnmask` はエクスポートを他のクエリオペレーションと同様に扱います。マスキングは実行中のユーザーのアクセス許可に基づいて適用されます。これは、COPY、SELECT INTO、CREATE TABLE AS、Aurora PostgreSQL の S3 エクスポート機能などの SQL コマンドに適用されます。

**注記**  
マスクされたユーザーがデータをエクスポートする場合、結果のファイルには、復元時にデータベースの制約に違反する可能性のあるマスクされた値が含まれます。

## ビューとマテリアライズドビュー
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement.Views"></a>

ビューと連携させるときは、次の考慮事項に注意してください。
+ **通常のビュー** – 常に `INVOKER` セマンティクスを使用します。現在のユーザーのマスキングポリシーは、ビューを作成したユーザーに関係なく、ビューのクエリ時に適用されます。
+ **マテリアライズドビュー** – 更新すると、更新を実行するユーザーのポリシーではなく、マテリアライズドビュー所有者のマスキングポリシーが適用されます。所有者にマスキングポリシーがある場合、マテリアライズドビューには常にマスクされたデータが含まれます。

## データダンプと復元
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement.DDR"></a>

`pg_dump` は通常のデータベースユーザーとして動作し、接続するユーザーのアクセス許可に基づいてマスキングポリシーを適用します。マスクされたユーザーがダンプを実行する場合、バックアップファイルにはマスクされたデータが含まれます。`pg_columnmask` ポリシーはデータベーススキーマの一部としてダンプに含まれます。復元を成功させるには、参照されるすべてのロールがターゲットデータベースに存在し、ターゲットに `pg_columnmask` 拡張機能がインストールされている必要があります。

**注記**  
PostgreSQL 18 以降、`pg_dump` は、行レベルセキュリティ (RLS) ポリシーと `pg_columnmask` マスキングポリシーの両方をデータベースダンプから除外する `—no-policies` オプションをサポートしています。詳細については、「[pg\$1dump](https://www.postgresql.org/docs/current/app-pgdump.html)」を参照してください。

## 外部データラッパー
<a name="AuroraPostgreSQL.Security.DynamicMasking.DataMovement.FDQ"></a>

外部データラッパーを使用する場合、リモートテーブルのマスキングポリシーは、ローカルクエリユーザーのアクセス許可ではなく、マッピングされたユーザーのソースサーバーに対するアクセス許可に基づいて適用され、FDW を介してマスクされたリモートデータにアクセスできますが、ローカルデータベースの外部テーブルで DDM または RLS ポリシーを直接作成することはできません。