In Postgres, how can I create a user that has CREATEROLE
-privileges, but only for a specific DB/set of DBs?
I tried doing:
CREATE ROLE user WITH LOGIN PASSWORD 'password' NOCREATEDB CREATEROLE;
Is this correct? + How can I grant CREATEROLE
to more than one db?
Roles are created by database cluster, as per the doc, not by database. If you give this powerful right to a user, he will be able to create role usable in every Database of the cluster.
Since you need to grant priviledges to the roles, you can make sure that content from a single DB get assigned to the role.
It seems that it is no a simple way to do it. But you can to create function with security definer
option to achieve the desired behavior:
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 $$;
Create this function as superuser.
Then you could to create the role with NOCREATEROLE
option but grant to it the EXECUTE
privilege to this function and use it to create another roles.
Note: you need to revoke connect
option from public
role for particular DBs to disallow roles connect to them by default, for example:
revoke connect on database db1, db2 from public;
Test it:
As superuser (nd
in my case who also owns the schema with same name)
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)
And in terminal:
$ 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. win@db1=> \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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With