How to create user(read-write & readonly) and admin roles for an existing postgres database? - postgresql

We have an existing postgres database in production with a superuser adm that is being used to do everything. Our web application connects to the database using the same user and also the administrators(for patching/updating etc.) use the same credentials.
We have to fix this to have roles so that we can have read-write, readonly and admin roles.
We don't want our web application and admin to connect to the database as superuser.
With that being said, I have created the following sql script to make the appropriate roles.
I am not a database expert(not yet) so wanted to know the issues or better ways to solve this.
ALTER ROLE adm NOLOGIN;
CREATE role user_role NOINHERIT;
CREATE role readonlyuser_role NOINHERIT;
CREATE role admin_role CREATEDB CREATEROLE NOINHERIT;
CREATE ROLE u_service LOGIN PASSWORD '<some password>' INHERIT;
CREATE ROLE u_admin LOGIN PASSWORD '<some password>' INHERIT;
CREATE ROLE u_reader LOGIN PASSWORD '<some password>' INHERIT;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonlyuser_role;
GRANT ALL PRIVILEGES ON SCHEMA public TO admin_role;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO user_role, admin_role;
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO user_role, admin_role;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO user_role, admin_role;
GRANT ALL PRIVILEGES ON ALL PROCEDURES IN SCHEMA public TO user_role, admin_role;
GRANT ALL PRIVILEGES ON ALL ROUTINES IN SCHEMA public TO user_role, admin_role;
GRANT ALL PRIVILEGES ON SCHEMA audit TO admin_role;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA audit TO admin_role;
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA audit TO admin_role;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA audit TO admin_role;
GRANT ALL PRIVILEGES ON ALL PROCEDURES IN SCHEMA audit TO admin_role;
GRANT ALL PRIVILEGES ON ALL ROUTINES IN SCHEMA audit TO admin_role;
GRANT admin_role TO u_admin;
GRANT user_role TO u_service;
GRANT readonlyuser_role TO u_reader;

A few things to consider.
Spell out what user_role and readonlyuser_role can do
Start by revoking all privileges from both these roles, then add them back only as needed. This makes it both clearer in your intentions about what the roles should do, and safer in practice because higher privileges than intended won't accidentally sneak in.
REVOKE ALL ON SCHEMA public FROM public; --only authorized roles can do anything here.
REVOKE ALL ON SCHEMA public FROM user_role;
REVOKE ALL ON SCHEMA public FROM readonlyuser_role;
GRANT ...
The Database Owner is a local Superuser
We usually make the db owner an additional role; one who only logs in to create or alter the schema, then gracefully exits. If your admin_role does more than this, consider adding an owner_role.
Does a public role need to connect?
Consider adding
REVOKE CONNECT ON DATABASE yourdb FROM public;
This blocks the loophole where any role created on the same DB server could log into this database.
Do all this in a transaction block
Stopping privilege assignment half-way through the job can lead to all sorts of trouble, much akin to locking your keys in your car. Make the privilege assignments a single transaction where possible, so a missed semicolon doesn't lock you out.

Related

Can't revoke default schema privilege

pgadmin shows the default privilege for a schema was granted to an individual user and I need to revoke privilege granted from individual users.
ALTER DEFAULT PRIVILEGES IN SCHEMA a_schema
GRANT ALL ON TABLES TO a_user;
I try the following command but can't revoke the privilege.
ALTER DEFAULT PRIVILEGES IN SCHEMA a_schema
REVOKE ALL ON TABLES FROM a_user;
Can someone show me how to revoke the default privilege schema from user?

Postgres - how can I restrict the privilege to create/drop a table?

I would like to create "read-only privileges" in a PostgreSQL database (including the restriction of creating or dropping tables).
My strategy is to create a group with these privileges and then add roles that have had all their privileges revoked. In that way, the only inherit privileges when part of the read-only group.
I used the following commands to create privileges but it seems roles can add, delete tables when they join the group:
role_test_db=# REVOKE ALL ON DATABASE role_test_db FROM select_access_group;
REVOKE
role_test_db=# GRANT CONNECT ON DATABASE role_test_db TO select_access_group;
GRANT
role_test_db=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO select_access_group;
GRANT
I was reading the documentation and it seems like creating tables would be under CREATE privilege but I have not granted this. Can some explain why users part of this group can still make tables?
There are several mistakes:
Revoking privileges on the database does not restrict user's rights to create objects. For that, you have to revoke privileges on the schemas.
You can only REVOKE privileges that were GRANTed (by default or explicitly). I doubt that select_access_group has ever been granted any privileges on the database.
You likely forgot to revoke the dangerous default CREATE privilege on schema public. Connect as superuser and run
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
A user can only revoke privileges that were granted directly by that user
https://www.postgresql.org/docs/13/sql-revoke.html
See privileges
\du
select * from pg_roles;
Change (base) prilileges under admin role (postgres)

dropping a postgres role

I am struggling with dropping a ready only user I created on one of the database in the cluster. I created a read only user using following script:
CREATE USER is_user_readonly WITH ENCRYPTED PASSWORD 'test1';
GRANT CONNECT ON DATABASE db1 to is_user_readonly;
GRANT USAGE ON SCHEMA public to is_user_readonly;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO is_user_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO is_user_readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO is_user_readonly;
I logged in database db1 and created this user is_user_readonly. I logged in as admin. This user is created on all databases in the cluster.
Now, for dropping this user, I logged in db1 as admin and ran below scripts:
REVOKE ALL PRIVILEGES ON DATABASE db1 FROM is_user_readonly;
REVOKE ALL PRIVILEGES ON SCHEMA public FROM is_user_readonly;
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM is_user_readonly;
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM is_user_readonly;
REVOKE USAGE ON SCHEMA public FROM is_user_readonly;
REVOKE CONNECT ON DATABASE db1 FROM is_user_readonly;
At this point I am really pulling out my hair that there is still some dependency.
SQL Error [2BP01]: ERROR: role "is_user_readonly" cannot be dropped because some objects depend on it
Detail: privileges for default privileges on new relations belonging to role isadmin in schema public
ERROR: role "is_user_readonly" cannot be dropped because some objects depend on it
Detail: privileges for default privileges on new relations belonging to role isadmin in schema public
ERROR: role "is_user_readonly" cannot be dropped because some objects depend on it
Detail: privileges for default privileges on new relations belonging to role isadmin in schema public.
Do I need to run the revoke script on all database in this cluster?
Any help is highly appreciated.
Revoke the default privileges:
ALTER DEFAULT PRIVILEGES FOR ROLE whatever IN SCHEMA public
REVOKE SELECT ON TABLES FROM is_user_readonly;
The role whatever here is the user you were logged in as when you ran the ALTER DEFAULT PRIVILEGES statement.

Create roles and users only in a certain database and not in the default postgres database

I'm trying to setup a database with a readwrite user jirauser and a readonly user controlling_ro. This is my script to set it up based on this Blog article. testuser is the master user.
PGPASSWORD=XXX psql \
--dbname=postgres \
--host=XXX.XXX.eu-central-1.rds.amazonaws.com \
--port=5432 \
--username=testuser \
<<EOF
-- Clean DB
DROP DATABASE jiradb;
DROP USER jirauser;
DROP USER controlling_ro;
DROP SCHEMA jiraschema;
DROP ROLE readonly;
DROP ROLE readwrite;
-- Create DB
CREATE DATABASE jiradb;
\connect jiradb;
CREATE SCHEMA jiraschema;
-- Revoke privileges from 'public' role
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON DATABASE jiradb FROM PUBLIC;
-- Read-only role
CREATE ROLE readonly;
GRANT CONNECT ON DATABASE jiradb TO readonly;
GRANT USAGE ON SCHEMA jiraschema TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA jiraschema TO readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA jiraschema GRANT SELECT ON TABLES TO readonly;
-- Read/write role
CREATE ROLE readwrite;
GRANT CONNECT ON DATABASE jiradb TO readwrite;
GRANT USAGE, CREATE ON SCHEMA jiraschema TO readwrite;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA jiraschema TO readwrite;
ALTER DEFAULT PRIVILEGES IN SCHEMA jiraschema GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO readwrite;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA jiraschema TO readwrite;
ALTER DEFAULT PRIVILEGES IN SCHEMA jiraschema GRANT USAGE ON SEQUENCES TO readwrite;
-- Users creation
CREATE USER controlling_ro WITH PASSWORD 'XXX';
CREATE USER jirauser WITH PASSWORD 'XXX';
-- Grant privileges to users
GRANT readonly TO controlling_ro;
GRANT readwrite TO jirauser;
EOF
After running this script I expect the roles and the users only to be in the jiradb database. However looking into the default database postgres with dbeaver they are also there. Does this mean they also have access to the postgres database?
That's just an artifact of your client tool.
In reality, PostgreSQL users don't belong to any database; they are shared by all databases. So no matter to which database you are connected when you create a user, it will equally exist for all databases.
You can use the CONNECT permission on the database object or (more typically) configure pg_hba.conf to determine which user can access which database.
According to https://www.postgresql.org/docs/current/sql-createrole.html:
CREATE ROLE adds a new role to a PostgreSQL database cluster. A role is an entity that can own database objects and have database privileges; a role can be considered a “user”, a “group”, or both depending on how it is used. Refer to Chapter 21 and Chapter 20 for information about managing users and authentication. You must have CREATEROLE privilege or be a database superuser to use this command.
Note that roles are defined at the database cluster level, and so are valid in all databases in the cluster.
So it's just your GUI misleading you.

Creating admin user in PostgreSQL

I am trying to create an admin role/user in PostgreSQL which should fulfil the following requirements:
Should be able to do backup for the particular database (and not
others)
Should be able to create usernames which can access the
particular database (and not others).
Should be able to create/delete tables in the specific database and not other database
Should not be able to create other data bases.
This is what I have so far:
create role dba with nosuperuser createdb createrole nologin replication bypassrls;
grant usage on schema public to dba;
alter default privileges in schema public grant all on tables to dba;
alter default privileges in schema public grant all on sequences to dba;
grant connect on database myDatabase to dba;
grant usage on schema public to dba;
grant select on all tables in schema public to dba;
grant select on all sequences in schema public to dba;
grant all privileges on all tables in schema public to dba;
create user dba_user login inherit encrypted password 'password' in role dba;
Please advise how to modify the above code to fulfill the requirements.
To achieve that, perform the following modifications:
Transfer ownership of the database and all schemas and objects in it to the new user.
Give the user CREATEROLE.
Make sure to REVOKE CONNECT ON all databases FROM PUBLIC. Grant the new user the CONNECT privilege on the database in question.
Don't give the new user any permissions on other databases or objects therein.