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


41

新しく作成したユーザーがデータベースに接続した後にテーブルを作成できるのはなぜだろうかと思っています。私は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からテーブルを実行する前に、ユーザーが何もできないことを期待していました。

私の間違いはどこですか?何が間違っていますか?私が望むものを達成するにはどうすればよいですか(新しいユーザーが適切な権利を明示的に付与する前に何もすることはできません)。

私は失われました、そしてあなたの助けは大歓迎です:)

編集 @ daniel-veriteのアドバイスに従って、データベースの作成後すぐにすべてを取り消します。ユーザーdietrichは、これ以上テーブルを作成できません。良い。しかし:今、また、データベースの所有者は、Project2のは、テーブルを作成することはできません。GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2and を発行した後でもGRANT ALL PRIVILEGES ON SCHEMA public TO project2、エラーERROR:no schema are selected to create to createCREATE TABLE public.WHATEVER ();を取得し、具体的にしようとすると、ERROR:permission denied for schema publicを取得します。私は何を間違えていますか?

回答:


38

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

REVOKE ALL ON schema public FROM public;

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

GRANT ALL ON schema public TO foo_user;

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

一方、GRANT ALL PRIVILEGES ON DATABASE...付与されますCONNECTCREATEしてTEMP、しかし、CREATEこの文脈ではスキーマではなく、永続テーブルに関するものです。

このエラーに関して:ERROR: no schema has been selected to create in、スキーマの修飾なしでオブジェクトを作成しようとすると(のようにcreate table foo(...))、のスキーマでオブジェクトを作成する権限がありませんsearch_path


動作します:)しかし、私はまだ理解していません:私はすでに試しましたREVOKE ALL ON DATABASE project2_core FROM PUBLIC;。なぜこれは効果がなかったのですか?
andreas-h

うん。現在、データベースの所有者はCREATE TABLEこれ以上許可されていません。上記の私の編集を参照してください。
アンドレアス・時間

@ andreas-h:より詳細に回答を編集した
ダニエル

エラーに関しては、質問からコマンドを発行し、REVOKEを順番に発行することで簡単に再現できます:)
dezso

@DanielVérité私はあなたを補うために新しい答えでこの背後にある概念について詳しく説明しました。健全性チェックが評価されます。
クレイグリンガー14

19

ここで理解する重要なことは、特権は階層的ではなく、オブジェクトを含むことから継承されないということですALL、このオブジェクトおよび含まれるすべてのオブジェクトに対するすべての特権ではなく、このオブジェクトに対するすべての特権を意味ます

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

  • CONNECT:DBへの接続
  • CREATEスキーマを作成します(テーブルではありません
  • TEMP:一時テーブルを含むがこれに限定されない一時オブジェクトを作成する

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

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

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

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

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


ファイルシステムの類推を見ると、これはより理にかなっているかもしれません。

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

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

内に/dir1は何も作成できません。書き込み権限がないためです。したがってtouch /dir1/somefile、許可が拒否されたというエラーが表示されます。

しかし、私内部を見て/dir1、含まれているファイルやディレクトリにアクセスする許可を持っています/dir1/dir2。に書き込み許可がありdir2ます。だからtouch /dir1/dir2/somefileます成功、私はへの書き込み権限を持っていないにもかかわらず、dir1

データベースとスキーマについても同じことが言えます。


7

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

REVOKE CREATE ON SCHEMA public FROM public;

あなたの場合はREVOKE ALL(他の回答が示唆するように)、あなたも持っていることからユーザーを防ぐことができますUSAGE許可を。USAGEは、ユーザーに割り当てられた権限を使用できることを意味します。したがって、ユーザーがそれを削除すると、ユーザーはアクセスできるテーブルを一覧表示またはアクセスできなくなります。

または、REVOKE CREATE特定のユーザーに対してもできます。

REVOKE CREATE ON schema public FROM myuser;

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.