web-dev-qa-db-ja.com

新しいユーザーがテーブルを作成できるのはなぜですか?

新しく作成したユーザーがデータベースに接続した後にテーブルを作成できるのはなぜですか。データベースが1つあります、_project2_core_:

_postgres=# \l
                                          List of databases
     Name      |    Owner     | Encoding  |   Collate   |    Ctype    |       Access privileges       
---------------+--------------+-----------+-------------+-------------+-------------------------------
 postgres      | postgres     | SQL_ASCII | C           | C           | 
 project2_core | atm_project2 | UTF8      | de_DE.UTF-8 | de_DE.UTF-8 | project2=CTc/project2
 template0     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
 template1     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
(5 rows)
_

ここまでは順調ですね。次に、ユーザーを作成します。

_postgres=# CREATE ROLE dietrich ENCRYPTED PASSWORD 'md5XXX' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER
_

はい。データベースに接続しようとすると、ユーザーは接続できません。

_$ psql -h localhost -p 5432 -U dietrich -W project2_core
Password for user dietrich: 
psql: FATAL:  permission denied for database "project2_core"
DETAIL:  User does not have CONNECT privilege.
_

これは私が期待したことです。今、奇妙なものが始まります。ユーザーにCONNECTを付与します。

_postgres=# GRANT CONNECT ON DATABASE project2_core TO dietrich;
GRANT
postgres=# \l
                                          List of databases
     Name      |    Owner     | Encoding  |   Collate   |    Ctype    |       Access privileges       
---------------+--------------+-----------+-------------+-------------+-------------------------------
 postgres      | postgres     | SQL_ASCII | C           | C           | 
 project2_core | atm_project2 | UTF8      | de_DE.UTF-8 | de_DE.UTF-8 | project2=CTc/project2+
               |              |           |             |             | dietrich=c/project2
 template0     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
 template1     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
(5 rows)
_

そして、それ以上の許可なしで、ユーザーはテーブルを作成することが許可されます:

_$ psql -h localhost -p 5432 -U dietrich -W project2_core
Password for user dietrich: 
psql (9.2.3)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

project2_core=> create table adsf ();
CREATE TABLE
project2_core=> \d
        List of relations
 Schema | Name | Type  |  Owner   
--------+------+-------+----------
 public | adsf | table | dietrich
(1 row)
_

スキーマで_GRANT USAGE_を明示的に実行してから、テーブルで_GRANT SELECT_を明示的に実行する前に、ユーザーが何も実行できないことを期待していました。

私の間違いはどこですか?何が悪いのですか?新しいユーザーに適切な権限を明示的に付与する前に何も実行できないようにするには、どうすればよいですか。

私は道に迷いました、そしてあなたの助けは大いに感謝されます:)

[〜#〜] edit [〜#〜] @ daniel-veriteのアドバイスに従って、データベースを作成した直後にすべてを取り消します。ユーザーdietrichはテーブルを作成できなくなりました。良い。 [〜#〜] but [〜#〜]:現在、データベースの所有者project2もテーブルを作成できます。 _GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2_および_GRANT ALL PRIVILEGES ON SCHEMA public TO project2_を発行した後でも、エラーが表示されますエラー:作成するスキーマが選択されていません、および具体的にはCREATE TABLE public.WHATEVER ();を試しますが、エラーが発生します:スキーマpublicのアクセスが拒否されました。何が悪いのですか?

44
andreas-h

新しいデータベースを作成すると、どのロールでもpublicスキーマにオブジェクトを作成できます。この可能性を取り除くために、データベースの作成直後に発行することができます:

_REVOKE ALL ON schema public FROM public;
_

編集:上記のコマンドの後、スーパーユーザーのみがpublicスキーマ内に新しいオブジェクトを作成できますが、これは実用的ではありません。スーパーユーザー以外の_foo_user_にこの特権を付与する必要があるとすると、これは次のようにして行う必要があります。

_GRANT ALL ON schema public TO foo_user;
_

スキーマに対するALLの意味を知るには、 ドキュメント内のGRANT を参照する必要があります(PG 9.2では、さまざまなことに適用されるGRANTステートメントの形式が14以上あります。 ..)。スキーマの場合、CREATEおよびUSAGEを意味するようです。

一方、_GRANT ALL PRIVILEGES ON DATABASE..._はCONNECTCREATETEMPを付与しますが、このコンテキストのCREATEは永続テーブルではなくスキーマに関連しています。

このエラーについて:_ERROR: no schema has been selected to create in_、_search_path_のスキーマでオブジェクトを作成する権限がないにもかかわらず、スキーマ修飾なしでオブジェクトを作成しようとすると(create table foo(...)のように)発生します。

41
Daniel Vérité

ここで理解しておくべき重要なことは、特権は継承されないであり、包含オブジェクトから継承されないであることです。 ALLこのオブジェクトのすべての特権ではないこのオブジェクトおよび含まれているすべてのオブジェクトのすべての特権を意味します。

データベースにALLを付与すると、CREATE, CONNECT, TEMPが付与されます。これらは、データベースオブジェクト自体に対するアクションです。

  • CONNECT:DBに接続します
  • CREATEスキーマnotテーブルを作成)
  • TEMP:一時テーブルを含むがそれに限定されない一時オブジェクトを作成します

現在、各PostgreSQLデータベースには、デフォルトで、データベースの作成時に作成されるpublicスキーマがあります。このスキーマには、ロールpublicに付与されたすべての権限があり、その全員が暗黙的にメンバーです。スキーマの場合、ALLCREATE, USAGEを意味します。

  • CREATE:このスキーマ内にオブジェクト(テーブルを含む)を作成します
  • USAGE:スキーマ内のオブジェクトをリストし、権限が許可する場合はそれらにアクセスします

テーブルのようなオブジェクトを作成するスキーマを指定しない場合、データベースエンジンはsearch_pathを使用します。デフォルトでは、publicスキーマはsearch_pathの最初にあるため、テーブルそこに作成されます。デフォルトでは、誰もがpublicに対する権限を持っているため、作成は許可されています。ユーザーはデータベースオブジェクト自体に対して何も実行しようとしておらず、データベース内のスキーマのみであるため、データベースに対するユーザーの権限はこの時点では関係ありません。

CONNECTスキーマでは、デフォルトですべてのユーザーがテーブルを作成できるため、データベースでpublicを付与する以外の権限をユーザーに付与していなくても問題ありません。ダニエルは、必要に応じてその権利を取り消す方法をすでに説明しています。

すべての権限を明示的に委任する場合は、すべてをpublicから取り消します。または単にpublicスキーマを削除します。必要に応じて、この変更を適用した新しいテンプレートデータベースを作成できます。代わりにtemplate1に適用することもできますが、publicが存在し、書き込み可能であると想定している多くのサードパーティコードが壊れる可能性があります。


これは、ファイルシステムのアナロジーを見ると、もっと理にかなっているかもしれません。

ディレクトリ構造がある場合(現在のユーザーに適用されるモードのみを表示するように簡略化されたモード):

/dir1           mode=r-x
/dir1/dir2      mode=rwx

書き込み権限がないため、/dir1内には何も作成できません。したがって、touch /dir1/somefileを実行すると、アクセス拒否のエラーが発生します。

ただし、私はdoにアクセスして、/dir1内を調べ、/dir1/dir2を含む、含まれているファイルやディレクトリにアクセスすることができます。 dir2に対する書き込み権限があります。したがって、touch /dir1/dir2/somefileへの書き込み権限がない場合でも、dir1成功になります。

データベースとスキーマについても同様です。

19
Craig Ringer

新しいユーザーがテーブルを作成できないようにする場合は、次のコマンドを実行する必要があります。

REVOKE CREATE ON SCHEMA public FROM public;

もし、あんたが REVOKE ALL(他の回答が示すように)、ユーザーがUSAGE権限を持つことも禁止します。 USAGEは、ユーザーが自分に割り当てられた権限を使用できることを意味します。そのため、これを削除すると、ユーザーは、自分がアクセスできるテーブルを一覧表示したり、アクセスしたりできなくなります。

または、REVOKE CREATE特定のユーザーの場合:

REVOKE CREATE ON schema public FROM myuser;

参照: PostgreSQLで読み取り専用ユーザーを作成する方法

7
Adrian Macneil