2010-12-12 2 views
6

私は2つのテーブルを持っています。 1つは、他のテーブルのシリアルフィールドを参照する外部キーがあります。所有者以外の役割にINSERT権限を与えましたが、参照されたフィールドを含むテーブルに対してテーブルUPDATE権限の所有者を許可しない限り、外部キーを含むテーブルには挿入できません。 このケースで行を挿入できるように、別の別のロール(INSERT特権付き)を使用するために、所有者がUPDATE権限を必要とする理由を理解できません。権限:この場合、テーブル所有者はなぜUPDATEを必要としますか?

これはちょっと混乱しているので、私は自分の問題の煮詰めた例を提供しました。

createuser -U postgres testowner -DIRS --pwprompt 
createdb -U postgres -O testowner testdb 
createuser -U postgres testupdater -DIRS --pwprompt 

psql -d testdb -U testowner 
CREATE TABLE a (id serial PRIMARY KEY); 
CREATE TABLE b (a_id integer REFERENCES a(id)); 
GRANT SELECT,INSERT ON ALL TABLES IN SCHEMA public TO testupdater; 
GRANT USAGE,UPDATE ON SEQUENCE a_id_seq TO testupdater; 
REVOKE INSERT, UPDATE ON ALL TABLES IN SCHEMA public FROM testowner; 
INSERT INTO a VALUES (DEFAULT); -- as expected: ERROR: permission denied for relation a 
\q 

psql -d testdb -U testupdater 
INSERT INTO a VALUES (DEFAULT); 
SELECT id FROM a LIMIT 1; -- selects the first id (1) 
INSERT INTO b VALUES (1); -- unexpected error: see below 
\q 

ERROR: permission denied for relation a

CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."a" x WHERE "id" OPERATOR(pg_catalog.=) $1 FOR SHARE OF x"

私はUPDATE権限(GRANT UPDATE ON a TO testowner;)をtestownerをお返し場合は、上記の挿入が動作します。この場合、テスト所有者はなぜUPDATEを必要としますか?

注:GRANT UPDATE ON a TO testupdater;は役に立ちません。私はtestownerの役割に更新を与える必要があるようです。

+0

testownerに読み取り権限を与えても問題はありませんか? testupdaterの挿入は、挿入が有効であることを確認するために、testownerの外部キーの値を読み取る必要があります。 –

+0

@Macy 'testowner'ロールのSELECT権限を取り消したことはありません。 'testupdater'にもSELECT権限が与えられているので、参照を確認するためにテーブル' a'を読み込むことができるようです。 –

+0

ここでうまく動作し、予期しないエラーは発生しません。 –

答えて

6

この問題は、そのselect文で "SHARE OF"とみなされます。その行ロックを作成するには、少なくともある種の書込みアクセスが必要です。

私はテーブルを作成し、のみ付与した場合、自分はそれへのアクセスを選択:

[email protected]=# create table t(t1_id serial primary key, value text); 
NOTICE: CREATE TABLE will create implicit sequence "t_t1_id_seq" for serial column "t.t1_id" 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "t_pkey" for table "t" 
CREATE TABLE 
[email protected]=# insert into t(value) values('foo'); 
INSERT 0 1 
[email protected]=# grant select on t to steve; 
GRANT 

今、私はテーブルから行を読み込むことができますが、私はそれらをロックすることはできません。

今の推測を作る
[email protected]@[local] => select * from t; 
t1_id | value 
-------+------- 
    1 | foo 
(1 row) 

[email protected]@[local] => select * from t for share; 
ERROR: permission denied for relation t 

。 ..おそらく、外部キーの実装は、外部テーブルに存在するターゲット行をチェックして動作し、ソーステーブルまたはターゲットテーブルのいずれかの所有者に基づいて認可コンテキストを設定します... TBH私は決してテーブルを取り消さなかった所有者の特権があるので、私はこれまでに遭遇していません。

私は、アカウントを作成したためにすべてのテーブルにアクセスできるアカウントは必要ないと考えています。私がお勧めします:

  • は「postgresの」または代わりにpg_hba.conf
  • に制限されたアクセス権を持っているいくつかの他のスーパーユーザーとしてスキーマの変更を実行し、持っていない一部のユーザー(たとえばデータベース所有者)として、スキーマの変更を実行します'postgres'または他のスーパーユーザーのset session authorizationを使用してください。
関連する問題