(ほとんど)読み取り専用のワークロードになるPostgresサーバーをセットアップしています。
私は自分でテーブルをドロップしたり、テーブルを変更したりせずに、自分や同僚が適切にインデックスを作成/ドロップできるようにしたいと思います。
付与/取り消しのドキュメントとロールのドキュメントのページを読むのに時間を費やしましたが、テーブル所有者のロールには両方の権限があるようです。
私が見つけたものの1つは、おそらくcreate create tablespace でインデックスを作成できることですが、機能しませんでした(他のテーブルスペースは作成していません)。
具体的には、私は試しました:
mydb=# grant create on tablespace pg_default to bob;
GRANT
...次にbobに切り替えました:
mydb=> create index on foo(a);
ERROR: must be owner of relation foo
私もボブを所有者にしようとしましたが、ボブはテーブルを削除する権利を取得しました。その特権を取り消す方法はないようです。だから私は両方またはどちらにもこだわっています。
何か案は?
SQLレベルではできません。これらのタスクはすべてテーブルの所有権によって管理されているためです。
テーブルスペースのCREATE
は必須ですが、テーブルにインデックスを作成してそのテーブルスペースにインデックスを格納するには十分ではありません。インデックスを配置するテーブルスペースにCREATE
権限がない場合、そのインデックスを_CREATE INDEX
_することはできません。ただし、その権利を持つだけでは十分ではありません。それ以外の場合、任意のテーブルスペースに何かを作成する権限があれば、誰でも任意のテーブルにインデックスを作成できますが、それは望ましくありません。インデックスはパフォーマンスコストがかかり、作成中に重いロックを取得します。おそらく最も重要なことに、式インデックスは悪意のある関数または演算子を介してテーブルに関するデータをリークする可能性があります。したがって、インデックスを作成するテーブルをまたはで所有している必要があります。
テーブルに対する個別のINDEX
権限のサポートをPostgreSQLに追加できますが、追加されておらず、送信された場合に受け入れられない可能性があります。今のところ、あなたはテーブルを所有しなければならないことにこだわっています。
実行中の操作と現在のユーザーIDをチェックする_ProcessUtility_hook
_をインストールし、必要に応じてそれらを拒否または許可するC拡張を作成できます。 _ProcessUtility_hook
_の使用例は_contrib/sepgsql
_で、外部ではBDRプロジェクトのソースコードの_bdr_commandfilter.c
_ファイルで確認できます。拡張機能をコンパイルしてファイルシステムにインストールし、それを_shared_preload_libraries
_に追加してインストールする必要があるため、サーバーへの完全なファイルシステムレベルのアクセス権、通常はルートアクセス権が必要です。
より実用的なアプローチは、_SECURITY DEFINER
_関数をラッパーとして使用することです。テーブルの所有者として実行し、インデックス化するテーブル、インデックス化する列などを引数として受け入れるPL/PgSQL関数を記述します。format(...)
を使用して_CREATE INDEX
_式を作成します。 EXECUTE
に渡します。実行notを使用すると、ユーザーは任意のSQL式を引数として渡すことができます。または、基本的に、SQLインジェクションを介してフルアクセスを許可します。複数の列が必要ですか? _colname text[]
_を引数として受け入れ、_quote_ident
_をそれぞれ受け入れる必要があります。等々。この方法の詳細については、「動的SQL plpgsql」を検索してください。
Plpgsql event triggers は現在のバージョンではかなり制限されていますが、DROP TABLE
のみを許可しないという特定の結果を得ることができます。
このことを考慮:
CREATE OR REPLACE FUNCTION no_drop() RETURNS event_trigger AS $$
BEGIN
IF (tg_tag = 'DROP TABLE') THEN
RAISE exception 'DROP TABLE is not allowed';
END IF;
END;
$$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER nodrop_trigger ON sql_drop
EXECUTE PROCEDURE no_drop();
ユーザーpostgres(スーパーユーザー)として:
test =#create table foo(bar int); CREATE TABLE
test =#drop table foo; エラー:DROP TABLEは許可されていません
一方、CREATE INDEX
は機能します。
test =#foo(bar);にインデックスidxを作成; インデックスを作成