データベースロール管理
======================

CloudNativePGは、当初から、PostgreSQLインスタンスで必要な特定のロールの作成を管理してきました。

-  ``postgres`` スーパーユーザー、\ ``streaming_replica``
   、\ ``cnpg_pooler_pgbouncer`` などの一部の予約済みユーザーPgBouncer
   ``Pooler`` を使用する場合

-  アプリケーションデータベースの低特権の所有者として設定されたアプリケーションユーザー

このプロセスは、 :ref:`Bootstrap <Bootstrap>` セクションで説明しています。

クラスター仕様の\ ``managed``
スタンザにより、CloudNativePGは\ ``.spec.managed.roles``
で指定されたロールの完全なライフサイクル管理を提供するようになりました。

この機能により、既存のロールの宣言的管理と、データベースにまだ存在しない場合は新しいロールの作成が可能になります。ロールの作成は、データベースのブートストラップが完了した後*に発生します。

宣言的なロール管理を使用するクラスターのマニフェストの例は、次のファイルにあります。

::

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   metadata:
     name: cluster-example-with-roles
   spec:
     instances: 3
     storage:
       size: 1Gi

     managed:
       roles:
       - name: app
         createdb: true
         login: true
       - name: dante
         ensure: present
         comment: my database-side comment
         login: true
         superuser: false
         createdb: true
         createrole: false
         inherit: false
         replication: false
         bypassrls: false
         connectionLimit: 4
         validUntil: "2053-04-12T15:04:05Z"
         inRoles:
           - pg_monitor
           - pg_signal_backend
         passwordSecret:
           name: cluster-example-dante
   - --
   apiVersion: v1
   data:
     username: ZGFudGU=
     password: ZGFudGU=
   kind: Secret
   metadata:
     name: cluster-example-dante
   type: kubernetes.io/basic-auth

。

次に、そのファイルからの抜粋を示します。

.. code:: yaml

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   spec:
     managed:
       roles:
       - name: dante
         ensure: present
         comment: Dante Alighieri
         login: true
         superuser: false
         inRoles:
           - pg_monitor
           - pg_signal_backend

``spec.managed.roles`` のロール仕様は `PostgreSQL structure and naming conventions <https://www.postgresql.org/docs/current/sql-createrole.html>`_ 
に従います。ロールごとに定義できる属性の完全なリストについては、
 :ref:`APIリファレンス <APIリファレンス>` を参照してください。

いくつかの点に注意してください。

1. ``ensure`` 属性はPostgreSQLの **ではありません**
   。これにより、宣言的なロール管理でロールを作成および削除できます。
   2つの値は、\ ``present`` デフォルトと\ ``absent`` です。

2. ``inherit`` 属性は、PostgreSQLの規則に従って、デフォルトでtrueです。

3. ``connectionLimit``
   属性は、PostgreSQLの規約に従って、デフォルトの-1に設定されます。

4. ``inRoles``
   のロールメンバーシップは、デフォルトでメンバーシップなしです。

宣言的ロール管理により、PostgreSQLインスタンスが仕様に準拠していることが保証されます。ユーザーがデータベースでロール属性を直接変更した場合、CloudNativePGオペレーターは、次の調整サイクル中にこれらの変更を元に戻します。

パスワード管理
--------------

宣言的ロール管理機能には、ロールパスワードの調整が含まれます。パスワードはKubernetesの世界とPostgreSQLでは根本的に異なる方法で管理されており、その結果、いくつかの注意事項があります。

管理対象ロール構成は、オプションでユーザー名とパスワードが保存される
**シークレット**
の名前を指定できます。Kubernetesで通常のようにBase64でエンコードされます。例

.. code:: yaml

     managed:
       roles:
       - name: dante
         ensure: present
         [… snipped …]
         passwordSecret:
           name: cluster-example-dante

これは、ユーザー名とパスワードを含む\ ``cluster-example-dante``
と呼ばれるシークレットの存在を前提としています。ユーザー名は、パスワードを設定しているロールと一致する必要があります。例

.. code:: yaml

   apiVersion: v1
   data:
     username: ZGFudGU=
     password: ZGFudGU=
   kind: Secret
   metadata:
     name: cluster-example-dante
     labels:
       cnpg.io/reload: "true"
   type: kubernetes.io/basic-auth

ロールに\ ``passwordSecret``
が指定されていない場合、インスタンスマネージャーはパスワードを使用してロールを作成/変更しようとしません。これは、
``WITH PASSWORD``
で指示されない限り、ALTERがパスワードを更新しないPostgreSQL規約に従います。

ロールが最初にパスワードを使用して作成され、PostgreSQLでパスワードをNULLに設定したい場合、これはCloudNativePGのユーザー側で明示的にする必要があります。
「仕様で提供されているパスワードなし」と「パスワードをNULLに設定する」を区別するには、フィールド
``DisablePassword`` を使用する必要があります。

データベースの\ ``dante``
ロールにパスワードを設定しないことにしたとします。このような場合、次を指定します。

.. code:: yaml

     managed:
       roles:
       - name: dante
         ensure: present
         [… snipped …]
         disablePassword: true

注特定のロールで\ ``passwordSecret`` と\ ``disablePassword``
の両方を設定することはエラーとみなされます。この構成は、検証Webhookによって拒否されます。

パスワードの有効期限 ``VALID UNTIL``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

PostgreSQLの\ ``VALID UNTIL``
ロール属性は、パスワードの有効期限を制御します。 ``VALID UNTIL``
を指定せずに作成されたロールは、PostgreSQLでデフォルトでNULLを取得します。これは、パスワードの有効期限が無期限であることを意味します。

PostgreSQLは、 ``VALID UNTIL``
のタイムスタンプタイプを使用します。これには、パスワードの有効期限が無期限であることを示す値\ ``'infinity'``
のサポートが含まれます。 `PostgreSQL documentation <https://www.postgresql.org/docs/current/datatype-datetime.html>`_ を参照してください。

参考までに。

宣言的ロール管理では、管理対象ロールの\ ``validUntil``
属性がパスワードの有効期限を制御します。 ``validUntil``
は以下のみを取ることができます。

-  Kubernetesタイムスタンプ、または

-  省略しますデフォルト\ ``null``

最初のケースでは、指定された\ ``validUntil``
タイムスタンプは、ロールの\ ``VALID UNTIL``
属性としてデータベースに設定されます。

2番目のケース\ ``validUntil`` 省略
オペレーターは、パスワードの有効期限が決してないことを保証し、PostgreSQLの動作をミラーリングします。具体的には

-  新しいロールの場合、ロール作成ステートメントの\ ``VALID UNTIL``
   句を省略します

-  既存のロールの場合、データベースで\ ``VALID UNTIL`` が\ ``NULL``
   に設定されていない場合、\ ``VALID UNTIL`` を\ ``infinity``
   に設定します。これは、PostgreSQLが\ ``ALTER ROLE``
   SQLステートメントで\ ``VALID UNTIL NULL`` を許可していないためです。

..  Warning::
   宣言的ロール管理機能は、初期バージョン1.20.0から動作が変更されました。 1.20.0では、`passwordSecret` のないロールは、PostgreSQLでパスワードをNULLに設定することになります。実際には、1.20.0とほとんど違いはありません。 `passwordSecret` を使用せずに作成された新しいロールのパスワードは`NULL` になります。関連する変更は、管理対象ロールを使用して、以前に作成したロールを管理する場合です。 1.20.0では、これを行うと、既存のパスワードを誤って`NULL` に設定してしまう場合があります。

実現不可能なロール構成
----------------------

PostgreSQLでは、場合によっては、コマンドはデータベースが受け入れられず、拒否されます。
 `PostgreSQL documentation on error codes <https://www.postgresql.org/docs/current/errcodes-appendix.html>`_ を参照してください。

詳細については。

ロール操作では、このような基本的なエラーが発生する可能性があります。
2つの例

-  PostgreSQLに、ロールグループ\ ``poets``
   のメンバーとしてロール\ ``petrarca`` を作成するように依頼しますが、
   ``poets`` は存在しません。

-  PostgreSQLにロール\ ``dante``
   を削除するように求めますが、ロール\ ``dante``
   はデータベース\ ``inferno`` の所有者です。

これらの基本的なエラーは、人間の管理者の説明がない限り、データベースまたはCloudNativePGオペレーターによって修正できません。上記の2つの例は、それぞれロール\ ``poets``
を作成するか、データベース\ ``inferno``
を削除することにより修正できますが、それらは人的エラーが原因で発生した可能性があり、そのような場合、提案された「修正」は間違ったものである可能性があります。

CloudNativePGは、このような基本的なエラーが発生すると記録し、クラスターステータスに表示します。どちらが続くか…

管理対象ロールのステータス
--------------------------

CRDステータスには、以下に示すように、管理対象ロールのステータスのセクションが含まれます。

.. code:: yaml

   status:
     […snipped…]
     managedRolesStatus:
       byStatus:
         not-managed:
         - app
         pending-reconciliation:
         - dante
         - petrarca
         reconciled:
         - ariosto
         reserved:
         - postgres
         - streaming_replica
       cannotReconcile:
         dante:
         - could not perform DELETE on role dante: owner of database inferno
         petrarca:
         - could not perform UPDATE_MEMBERSHIPS on role petrarca: role "poets" does not exist

データベースおよびCloudNativePGが受け入れられない操作、および人間の介入を必要とする操作用の特別なサブセクション\ ``cannotReconcile``
に注意してください。

このセクションでは、オペレーター使用のために予約されているロールと、宣言的管理の下ではない**ロールをカバーし、データベースインスタンスのロールの包括的なビューを提供します。

..  Important::
   下位互換性の観点から、宣言的ロール管理は、データベースには存在するが仕様に含まれていないロールを無視するように設計されています。これらのロールのライフサイクルは、引き続きPostgreSQL内で管理されるため、CloudNativePGユーザーは自分の都合に合わせてこの機能を採用できます。
