これは簡単な方法ではないようです。しかし、あなたは、目的の動作を達成するためにsecurity definer
オプションを指定して関数を作成することができます。
create or replace function fn_create_role(p_name text, p_password text, p_databases text[]) returns void
language plpgsql
security definer
as $$
begin
execute format('create role %I with login password %L;', p_name, p_password);
execute format('grant connect on database %s to %I', array_to_string(p_databases, ','), p_name);
return;
end $$;
は、スーパーユーザーとして、この関数を作成します。
NOCREATEROLE
オプションを使用してロールを作成することはできますが、この機能にはEXECUTE
特権を付与し、それを使用して別のロールを作成することができます。
注:役割は、例えば、デフォルトでそれらに接続できないように、特定のDB用public
役割からconnect
オプションを取り消す必要があります。
revoke connect on database db1, db2 from public;
テストそれ:スーパーユーザーとして
(私の場合はnd
同じ名前のスキーマも所有しています)
postgres=# create database db1; create database db2;
CREATE DATABASE
CREATE DATABASE
postgres=# revoke connect on database db1, db2 from public;
REVOKE
postgres=# create role foo with login password 'bar' nocreatedb nocreaterole;
CREATE ROLE
postgres=# set role foo;
SET
postgres=> create role win with login password 'amp' nocreatedb nocreaterole;
ERROR: permission denied to create role
postgres=> set role nd;
SET
postgres=# grant usage on schema nd to foo;
GRANT
postgres=# grant execute on function nd.fn_create_role(text, text, text[]) to foo;
GRANT
postgres=# set role foo;
SET
postgres=> select nd.fn_create_role('win', 'amp', '{db1}');
┌────────────────┐
│ fn_create_role │
╞════════════════╡
│ │
└────────────────┘
(1 row)
端末内:
$ psql -h localhost -d db1 -U win
Password for user win:
psql (9.6.3)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
[email protected]=> \q
$ psql -h localhost -d db2 -U win
Password for user win:
psql: FATAL: permission denied for database "db2"
DETAIL: User does not have CONNECT privilege.
"CREATEROLE特権には注意してください。 CREATEROLEロールの権限に対する継承の概念はありません。これは、ロールに特定の権限がなくても他のロールを作成できる場合でも、スーパーユーザー権限でロールを作成する場合を除いて、別のロールを簡単に作成できることを意味します。たとえば、ロール "user"にCREATEROLE特権がありますが、CREATEDB特権はない場合でも、CREATEDB特権で新しい役割を作成できます。したがって、CREATEROLE権限を持つロールをほぼスーパーユーザーロールと見なしてください._ " – Abelisto