sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLの権限とユーザー管理-知っておくべきこと

    PostgreSQL内のユーザー管理には注意が必要です。通常、新しいユーザーは、環境内のいくつかの重要な領域内で協調して管理されます。多くの場合、特権は一方の面では完璧ですが、もう一方の面では正しく構成されていません。このブログ投稿では、PostgreSQL内でセットアップすることでわかるように、ユーザーまたはロールに実用的な「ヒントとコツ」を提供します。

    私たちが焦点を当てる主題分野は次のとおりです。

    • PostgreSQLの役割の引き受け

    役割、役割の属性、役割に名前を付けるためのベストプラクティス、および一般的な役割の設定について学習します。

    • pg_hba.confファイル

    このセクションでは、クライアント側の接続とサーバーとの通信のために、主要なファイルの1つとその設定について説明します。

    • データベース、テーブル、および列レベルの権限と制限。

    最適なパフォーマンスと使用法のために役割を構成したいとお考えですか?テーブルには機密データが含まれており、特権ロールにのみアクセスできますか?しかし、さまざまな役割が限られた作業を実行できるようにする必要がありますか?これらの質問などは、このセクションで公開されます。

    PostgreSQLの役割の引き受け-「役割」とは何ですか、またその作成方法は?

    PostgreSQL内のデータベースアクセスのアクセス許可は、ユーザーに似たロールの概念で処理されます。役割は、PostgreSQLエコシステムのユーザーのグループを表すこともできます。

    PostgreSQLは、ロールが所有するデータベースオブジェクトに特権を割り当てる能力を確立し、それらのオブジェクトへのアクセスとアクションを可能にします。ロールには、別のロールにメンバーシップを付与する機能があります。属性は、許可されたクライアント認証のためのカスタマイズオプションを提供します。

    CREATE ROLEコマンドによるロールの属性は、PostgreSQLの公式ドキュメントで入手できます。

    以下は、新しい役割を設定するときに一般的に割り当てる属性です。これらのほとんどは自明です。ただし、使用例とともに混乱を解消するために簡単な説明が提供されています。

    SUPERUSER-データベースSUPERUSERは注意が必要です。結論として、この属性を持つロールは別のSUPERUSERを作成できます。実際のところ、この属性は別のSUPERUSERロールを作成するために必要です。この属性を持つロールはすべての権限チェックをバイパスするため、この権限を慎重に付与してください。

    CREATEDB-ロールがデータベースを作成できるようにします。

    CREATEROLE-この属性を使用すると、ロールはCREATEROLEコマンドを発行できます。したがって、他の役割を作成します。

    LOGIN-ログイン機能を有効にします。この属性を持つロール名は、クライアント接続コマンドで使用できます。今後の例でこの属性の詳細を確認してください。

    特定の属性には、明示的に反対の名前のコマンドがあり、通常、指定しない場合のデフォルトです。

    例:
    スーパーユーザー| NOSUPERUSER
    CREATEROLE | NOCREATEROLE
    LOGIN | NOLOGIN

    設定できるさまざまな構成で、これらの属性の実際の動作を見てみましょう。

    役割の作成と削除

    ロールの作成は比較的簡単です。簡単な例を次に示します。

    postgres=# CREATE ROLE $money_man;
    ERROR: syntax error at or near "$"
    LINE 1: CREATE ROLE $money_man;

    そこで何が悪かったのですか?結局のところ、役割名は文字以外で始めることはできません。

    「名前を二重引用符で囲むのはどうですか?」見てみましょう:

    postgres=# CREATE ROLE "$money_man";
    CREATE ROLE

    それはうまくいきましたが、おそらく良い考えではありません。名前の真ん中にある特殊文字はどうですか?

    postgres=# CREATE ROLE money$_man;
    CREATE ROLE

    問題ありません。二重引用符がなくても、エラーは返されませんでした。

    私はユーザーの$money_manの名前構造が好きではありません。 $ money_manを削除して、新たに開始します。 DROP ROLEコマンドは、役割の削除を処理します。ここで使用中です。

    postgres=# DROP ROLE $money_man;
    ERROR: syntax error at or near "$"
    LINE 1: DROP ROLE $money_man;

    そして、$money_manロールに関する別のエラー。繰り返しになりますが、二重引用符を使用します。

    postgres=# DROP ROLE "$money_man";
    DROP ROLE

    ログイン特権

    2人の異なるユーザーを見てみましょう。1人はLOGIN特権を持っており、もう1人は持っていません。パスワードも割り当てます。

    postgres=# CREATE ROLE nolog_user WITH PASSWORD 'pass1';
    CREATE ROLE
    postgres=# CREATE ROLE log_user WITH LOGIN PASSWORD 'pass2';
    CREATE ROLE

    注:上記の架空の役割に提供されているパスワードは、デモンストレーションのみを目的としています。役割を実装するときは、常に一意で強化されたパスワードを提供するように努める必要があります。パスワードはパスワードなしよりも優れていますが、強化されたパスワードは些細なパスワードよりも優れています。

    ALTERROLEコマンドを使用してlog_userにCREATEDB属性とCREATEROLE属性を割り当てましょう。

    postgres=# ALTER ROLE log_user CREATEROLE CREATEDB;
    ALTER ROLE

    pg_roleカタログを確認することにより、これらの設定された属性を確認できます。対象となる2つの列は、rolcreateroleとrolcreatedbです。どちらもブールデータ型であるため、これらの属性のtrueを設定するにはtに設定する必要があります。

    同様のSELECTクエリで確認します。

    postgres=# SELECT rolcreaterole, rolcreatedb FROM pg_roles WHERE rolname = 'log_user';
    rolcreaterole | rolcreatedb 
    ---------------+-------------
    t | t
    (1 row)
    今日のホワイトペーパーをダウンロードするClusterControlを使用したPostgreSQLの管理と自動化PostgreSQLの導入、監視、管理、スケーリングを行うために知っておくべきことについて学ぶホワイトペーパーをダウンロードする

    データベースに存在する既存の役割をどのように判断できますか?

    使用可能な2つの方法は、psql\duコマンドまたはpg_rolesカタログからの選択です。

    ここでは両方とも使用されています。

    postgres=> \du
    List of roles
    Role name | Attributes | Member of 
    ------------+------------------------------------------------------------+-----------
    log_user | Create role, Create DB | {}
    nolog_user | Cannot login | {}
    
    postgres=> SELECT rolname FROM pg_roles;
    rolname 
    ----------------------
    nolog_user
    log_user
    (2 rows)

    ログイン

    両方の役割に、サーバーにログインする機会を与えましょう。

    psql -U nolog_user -W postgres
    Password for user nolog_user: 
    psql: FATAL: no pg_hba.conf entry for host "[local]", user "nolog_user", database "postgres", SSL off
    psql -U log_user -W postgres
    Password for user log_user: 
    psql: FATAL: no pg_hba.conf entry for host "[local]", user "log_user", database "postgres", SSL off

    この問題を解決するには、そのpg_hba.confファイルを掘り下げる必要があります。この投稿でその特定のセクションに進むにつれて、解決策について説明します。

    実用的なポイント

    • CREATEROLEとそれに対応するDROPROLEは、役割を実装および削除するための頼りになるコマンドです。
    • ALTER ROLEは、ロールの属性の変更を処理します。
    • データベースクラスターレベルで定義されているため、ロールはすべてのデータベース内で有効です。
    • 特殊文字で始まるロール名を作成するには、二重引用符で「アドレス指定」する必要があることに注意してください。
    • ロールとその特権は、属性を使用して確立されます。
    • デフォルトでLOGIN属性を必要とする役割を確立するために、CREATEUSERはオプションのコマンドです。 CREATE ROLE role_name LOGINの代わりに使用され、基本的に同じです。

    pg_hba.confファイル-サーバーとクライアント間の共通基盤の確立

    1つのブログ投稿でpg_hba.confファイルのすべての側面と設定をカバーすることは、せいぜい気が遠くなるでしょう。代わりに、このセクションでは、遭遇する可能性のある一般的な落とし穴と、それらを修正するための解決策を紹介します。

    接続を成功させるには、全体として両方の部分からの共同作業が必要です。サーバーに接続するロールは、pg_hba.confファイルの設定を渡した後も、データベースレベルで設定されたアクセス制限を満たす必要があります。

    このセクションが進むにつれて、この関係の関連する例が含まれます。

    pg_hba.confファイルを見つけるには、pg_settingsVIEWで同様のSELECTクエリを発行します。このビューを照会するには、SUPERUSERとしてログインする必要があります。

    postgres=# SELECT name, setting
    FROM pg_settings WHERE name LIKE '%hba%';
    name | setting 
    ----------+-------------------------------------
    hba_file | /etc/postgresql/10/main/pg_hba.conf
    (1 row)

    pg_hba.confファイルには、特定の接続要求で使用可能な7つの形式の1つを指定するレコードが含まれています。ここで完全なスペクトルを参照してください。

    このブログ投稿では、ローカル環境で使用できる設定について説明します。

    おそらく、このサーバーはあなたの継続的な学習と研究のためのものです(私のように)。

    これらの設定は、複数のユーザーを含む強化されたシステムに最適な設定ではないことに特に注意する必要があります。

    このタイプの接続のフィールドは次のとおりです。

    local database user auth-method [auth-options]

    意味:

    ローカル-接続はUnixドメインソケットで試行されます。

    database-このレコードの一致に名前が付けられたデータベースを指定します。

    user-このレコードに一致するデータベースユーザー名。このフィールドには、複数のユーザーまたはすべてのユーザーのコンマ区切りリストも使用できます。

    auth-method-接続がこの一意のレコードと一致する場合に使用されます。このフィールドで可能な選択肢は次のとおりです。

    • 信頼
    • 拒否
    • scram-sha-256
    • md5
    • パスワード
    • gss
    • sspi
    • アイデンティティ
    • ピア
    • ldap
    • 半径
    • 証明書
    • pam
    • bsd

    ロールnolog_userおよびlog_userのpg_hba.confファイルに設定された行は、次のようになります。

    local all nolog_user password
    local all log_user password

    注:パスワードはクリアテキストで送信されるため、信頼できないネットワークのある信頼できない環境では使用しないでください。

    以下のクエリを使用して、pg_hba_file_rulesVIEWの3つの興味深い列を見てみましょう。この場合も、このVIEWを照会するには、ロールにSUPERUSER属性が必要です。

    postgres=# SELECT database, user_name, auth_method
    postgres-# FROM pg_hba_file_rules
    postgres-# WHERE CAST(user_name AS TEXT) LIKE '%log_user%';
    database | user_name | auth_method 
    ----------+--------------+-------------
    {all} | {nolog_user} | password
    {all} | {log_user} | password
    (2 rows)

    付随するクエリからわかるように、pg_hba.confファイルにある上記の行から同じ情報を見ることができます。一見すると、両方の役割がログインできるように見えます。

    テストして確認します。

    psql -U nolog_user -W postgres
    Password for user nolog_user: 
    psql: FATAL: role "nolog_user" is not permitted to log in
    psql -U log_user -W postgres
    Password for user log_user: 
    psql (10.1)
    Type "help" for help.
    postgres=>

    ここで重要なのは、nolog_userとlog_userはどちらもpg_hba.confファイルに従ってログインできますが、実際にログインできるのはlog_userだけです。

    log_userがデータベースレベルのアクセス制限を通過した場合(LOGIN属性を持つことにより)、nolog_userは通過しませんでした。

    pg_hba.confファイルのlog_userの行を編集して、このロールがアクセスを許可されているデータベース名を変更してみましょう。これが変更であり、log_userがトライアルデータベースにのみログインできるようになったことを示しています。

    local trial log_user password

    まず、allフラグのためにlog_userが以前にアクセスしていたpostgresデータベースにログインしてみましょう。

    $ psql -U log_user -W postgres
    Password for user log_user: 
    psql: FATAL: no pg_hba.conf entry for host "[local]", user "log_user", database "postgres", SSL off

    トライアルデータベースを使用すると、log_userには次の権限があります

    $ psql -U log_user -W trial
    Password for user log_user: 
    psql (10.1)
    Type "help" for help.
    trial=>

    エラーはなく、trial=>プロンプトに現在接続されているデータベースが表示されます。

    これらの設定は、接続が確立されると、サーバー環境内にも適用されます。

    そのpostgresデータベースへの接続をもう一度試してみましょう:

    trial=> \c postgres;
    Password for user log_user: 
    FATAL: no pg_hba.conf entry for host "[local]", user "log_user", database "postgres", SSL off
    Previous connection kept

    ここに示す例では、クラスター内の役割のカスタマイズオプションに注意する必要があります。

    注:変更を有効にするには、多くの場合、pg_hba.confファイルを再読み込みする必要があります。

    pg_ctlユーティリティを使用してサーバーをリロードします。

    構文は次のようになります:

    pg_ctl reload [-D datadir] [-s]

    以下のようなSELECTクエリを使用してSUPERUSERとしてログインしている場合は、datadirがどこにあるかを知るために、pg_settingsシステムのVIEWにクエリを実行できます。

    postgres=# SELECT setting FROM pg_settings WHERE name = 'data_directory';
               setting           
    -----------------------------
     /var/lib/postgresql/10/main
    (1 row)

    次に、次のコマンドを使用してシェルをpostgresユーザー(または他のSUPERUSER)に渡します。

    $ sudo -u postgres bash

    pg_ctlユーティリティを$PATHに追加していない限り、使用するために完全に修飾してから、実行するコマンドとdatadirの場所を渡す必要があります。

    次に例を示します:

    $ /usr/lib/postgresql/10/bin/pg_ctl reload -D /var/lib/postgresql/10/main
    server signaled

    次のコマンドでサーバーのステータスを確認しましょう:

    $ /usr/lib/postgresql/10/bin/pg_ctl status -D /var/lib/postgresql/10/main
    pg_ctl: server is running (PID: 1415)
    /usr/lib/postgresql/10/bin/postgres "-D" "/var/lib/postgresql/10/main" "-c" "config_file=/etc/postgresql/10/main/postgresql.conf"

    実用的なポイント

    • ロールは、pg_hba.confファイルとデータベースレベルのアクセス権限の両方から要件を渡す必要があります。
    • pg_hba.confファイルは、接続要求ごとに上から下にチェックされます。ファイル内の順序は重要です。

    データベース、テーブル、および列の特権と制限-タスクと責任に合わせた役割を調整する

    ロールがデータベースオブジェクト(テーブル、ビュー、列、関数など)を使用するには、それらへのアクセス権が付与されている必要があります。

    GRANTコマンドは、これらの重要な特権を定義します。

    その使用法の本質を理解するために、いくつかの例を見ていきます。

    データベースの作成

    log_userにはCREATEDB属性とCREATEROLE属性が付与されているため、この役割を使用して、trialという名前のテストデータベースを作成できます。

    postgres=> CREATE DATABASE trial:
    CREATE DATABASE

    新しいROLEの作成に加えて:

    postgres=> CREATE ROLE db_user WITH LOGIN PASSWORD 'scooby';
    CREATE ROLE

    最後に、log_userは新しいトライアルデータベースに接続します:

    postgres=> \c trial;
    Password for user log_user: 
    You are now connected to database "trial" as user "log_user".
    trial=>

    プロンプトが「trial」という名前に変更され、そのデータベースに接続していることを示していることに注意してください。

    log_userを利用してモックテーブルを作成しましょう。

    trial=> CREATE TABLE another_workload(
    trial(> id INTEGER,
    trial(> first_name VARCHAR(20),
    trial(> last_name VARCHAR(20),
    trial(> sensitive_info TEXT);
    CREATE TABLE

    ロールlog_userは最近、ヘルパーロールdb_userを作成しました。 db_userには、テーブルanother_workloadに対する制限付きの権限が必要です。

    間違いなく、このロールはsensitive_info列にアクセスしないでください。現時点では、db_userが特定の期待値を満たすまで、INSERT、UPDATE、およびDELETEコマンドを付与しないでください。

    ただし、SELECTクエリを発行するにはdb_userが必要です。 another_workloadテーブル内でこの役割の能力をどのように制限できますか?

    まず、PostgreSQLGRANTコマンドのドキュメントにある正確な構文をテーブルレベルで調べてみましょう。

    GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )
    [, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) }
    ON [ TABLE ] table_name [, ...]
    TO role_specification [, ...] [ WITH GRANT OPTION ]

    次に、特定の構文を適用して、ロールdb_userに規定されている要件を実装します。

    trial=> GRANT SELECT (id, first_name, last_name) ON TABLE another_workload TO db_user;
    GRANT

    SELECTキーワードの直後に、db_userがアクセスできる列をリストしていることに注意してください。変更されるまで、db_userがsensitive_info列でSELECTクエリを試行した場合、またはその他のコマンドを実行した場合、それらのクエリは実行されません。

    db_userがログインしたら、これを実行して、テーブルからすべての列とレコードを返すSELECTクエリを試行します。

    trial=> SELECT * FROM another_workload;
    ERROR: permission denied for relation another_workload

    このクエリには、sensitive_info列が含まれています。したがって、db_userにレコードは返されません。

    ただし、db_userは許可される列を選択できます

    trial=> SELECT id, first_name, last_name
    trial-> FROM another_workload;
    id | first_name | last_name 
    -----+------------+-----------
    10 | John | Morris
    191 | Jannis | Harper
    2 | Remmy | Rosebuilt
    (3 rows)

    それは問題なく機能します。

    INSERT、UPDATE、およびDELETEコマンドもテストします。

    trial=> INSERT INTO another_workload(id,first_name,last_name,sensitive_info)
    VALUES(17,'Jeremy','Stillman','key code:400Z');
    ERROR: permission denied for relation another_workload
    trial=> UPDATE another_workload
    trial-> SET id = 101
    trial-> WHERE id = 10;
    ERROR: permission denied for relation another_workload
    trial=> DELETE FROM another_workload
    trial-> WHERE id = 2;;
    ERROR: permission denied for relation another_workload

    INSERT、UPDATE、またはDELETEコマンドをdb_userに割り当てないことにより、ロールはそれらを使用するためのアクセスを拒否されます。

    利用可能なオプションが豊富にあるため、役割の構成は事実上無制限です。それらを完全に機能させたり、任意のコマンドを実行したり、要件に応じて制約したりすることができます。

    実用的なポイント

    • ロールには、GRANTコマンドを介してデータベースオブジェクトへのアクセス権限が付与されます。
    • データベースオブジェクトとそれらのオブジェクトに対するコマンドは、PostgreSQL環境内で高度に構成可能です。

    締めくくり

    このブログ投稿で提供されている例を通じて、次のことをよりよく理解する必要があります。

    1. 特定の属性を持つ役割を作成します。
    2. クライアントとサーバーの間に実行可能な接続を設定し、ロールがデータベースにログインアクセスできるようにします。
    3. 必要な属性を実装することにより、データベース、テーブル、および列レベルのアクセスに関する個々の要件を満たすように役割を高度にカスタマイズします。

    1. MariaDB JSON_ARRAY_APPEND()の説明

    2. シェルスクリプトからMySQLコマンドを実行する方法は?

    3. Mysql:別のテーブルにない行をテーブルから選択します

    4. Oracleは、select句で定義されたデータチャンクのチェックサム値を取得します