新しく作成したユーザーがデータベースに接続した後にテーブルを作成できるのはなぜですか。データベースが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のアクセスが拒否されました。何が悪いのですか?
新しいデータベースを作成すると、どのロールでも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...
_はCONNECT
とCREATE
とTEMP
を付与しますが、このコンテキストのCREATE
は永続テーブルではなくスキーマに関連しています。
このエラーについて:_ERROR: no schema has been selected to create in
_、_search_path
_のスキーマでオブジェクトを作成する権限がないにもかかわらず、スキーマ修飾なしでオブジェクトを作成しようとすると(create table foo(...)
のように)発生します。
ここで理解しておくべき重要なことは、特権は継承されないであり、包含オブジェクトから継承されないであることです。 ALL
はこのオブジェクトのすべての特権ではないこのオブジェクトおよび含まれているすべてのオブジェクトのすべての特権を意味します。
データベースにALL
を付与すると、CREATE, CONNECT, TEMP
が付与されます。これらは、データベースオブジェクト自体に対するアクションです。
CONNECT
:DBに接続しますCREATE
:スキーマ(notテーブルを作成)TEMP
:一時テーブルを含むがそれに限定されない一時オブジェクトを作成します現在、各PostgreSQLデータベースには、デフォルトで、データベースの作成時に作成されるpublic
スキーマがあります。このスキーマには、ロールpublic
に付与されたすべての権限があり、その全員が暗黙的にメンバーです。スキーマの場合、ALL
はCREATE, 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
は成功になります。
データベースとスキーマについても同様です。
新しいユーザーがテーブルを作成できないようにする場合は、次のコマンドを実行する必要があります。
REVOKE CREATE ON SCHEMA public FROM public;
もし、あんたが REVOKE ALL
(他の回答が示すように)、ユーザーがUSAGE
権限を持つことも禁止します。 USAGE
は、ユーザーが自分に割り当てられた権限を使用できることを意味します。そのため、これを削除すると、ユーザーは、自分がアクセスできるテーブルを一覧表示したり、アクセスしたりできなくなります。
または、REVOKE CREATE
特定のユーザーの場合:
REVOKE CREATE ON schema public FROM myuser;