postgresql DROP DATABASE not working with user having role of owner - postgresql

I have a requirement where I need to have two users as database owner. I have created a role of db owner and assigned the role to two users. Now either of the users are able to drop the database. What is missing here?
mydb=> SELECT d.datname as "Name",
mydb-> pg_catalog.pg_get_userbyid(d.datdba) as "Owner"
mydb-> FROM pg_catalog.pg_database d;
Name | Owner
-----------+-----------
mydb | mydb_role
(1 row)
mydb=> \du
List of roles
Role name | Attributes | Member of
----------------------+------------------------------------------------------------+-------------------------------------------------------------
mydb_role | Create DB, Cannot login | {}
mydb_user | | { mydb_role}
mydb_user_clone | | { mydb_role}
ubuntu#ip-10-69-163-164:~$ psql -U mydb_user_clone -d postgres
psql (13.4 (Ubuntu 13.4-4.pgdg20.04+1), server 13.3)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
postgres=> DROP DATABASE mydb WITH (FORCE);
ERROR: must be a member of the role whose process is being terminated or member of pg_signal_backend
postgres=>
Below commands are used to create user and role
CREATE ROLE mydb_role nologin;
ALTER DATABASE mydb OWNER TO mydb_role;
GRANT mydb_role TO mydb_user;
GRANT mydb_role TO mydb_user_clone;

Because you have not enough permission to terminate a backend process.
Your db user must be a member of the pg_signal_backend role to terminate another database user's process, OR you have to use another user with the superuser privilege.

Related

Create true read only user in PostgreSQL

I've spanned a PostgreSQL database in Digital Ocean. I now need to come with a set of users and databases for which I've thought on creating several databases (production, staging, etc) and having 2 associated roles for each database with read-only and read-write permissions (production_ro, production_rw, staging_ro, staging_rw, etc). My idea is that, by having those roles, I can now create individual users and assign them one of the roles so that I can quickly change/remove them in case of a breach.
I've been researching on this and all pages I can find have a set of instructions similar to the ones in here:
-- Revoke privileges from 'public' role
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON DATABASE mydatabase FROM PUBLIC;
-- Read-only role
CREATE ROLE readonly;
GRANT CONNECT ON DATABASE mydatabase TO readonly;
GRANT USAGE ON SCHEMA myschema TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA myschema TO readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT SELECT ON TABLES TO readonly;
-- Read/write role
CREATE ROLE readwrite;
GRANT CONNECT ON DATABASE mydatabase TO readwrite;
GRANT USAGE, CREATE ON SCHEMA myschema TO readwrite;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA myschema TO readwrite;
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO readwrite;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA myschema TO readwrite;
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT USAGE ON SEQUENCES TO readwrite;
-- Users creation
CREATE USER reporting_user1 WITH PASSWORD 'some_secret_passwd';
CREATE USER reporting_user2 WITH PASSWORD 'some_secret_passwd';
CREATE USER app_user1 WITH PASSWORD 'some_secret_passwd';
CREATE USER app_user2 WITH PASSWORD 'some_secret_passwd';
-- Grant privileges to users
GRANT readonly TO reporting_user1;
GRANT readonly TO reporting_user2;
GRANT readwrite TO app_user1;
GRANT readwrite TO app_user2;
I've carefully followed those instructions and monitored that none of them failed but, after successfully running them all, I'm left with supposedly read-only users that can, in fact, create tables, not see the tables created by other users, and switch databases.
What am I doing wrong?
--- Edit ---
This is the result of the \dn+ command:
List of schemas
Name | Owner | Access privileges | Description
--------+----------+----------------------+------------------------
public | postgres | postgres=UC/postgres+| standard public schema
| | =UC/postgres |
--- Edit 2 ---
Here is what I do (for security reasons, I'll redact the users as <USER_A>, <USER_B>, etc. those redacted users will match 1 to 1 to the real ones):
$ psql "postgresql://USER_A:<PASSWORD>#<DOMAIN>:<PORT>/<DEFAULT_DB>?sslmode=require"
psql (15.1, server 14.6)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.
<DEFAULT_DB>=> \connect production
psql (15.1, server 14.6)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
You are now connected to database "production" as user "USER_A"
production=> \du
List of roles
Role name | Attributes | Member of
-----------------+------------------------------------------------------------+---------------------------------------------------------------------------
USER_B | Superuser, Replication | {}
USER_A | Create role, Create DB, Replication, Bypass RLS | {pg_read_all_stats,pg_stat_scan_tables,pg_signal_backend,r_production_ro}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
production_ro | Cannot login | {}
production=> REVOKE CREATE ON SCHEMA public FROM PUBLIC;
WARNING: no privileges could be revoked for "public"
REVOKE
production=>
--- Edit 3 ---
Got in contact with DigitalOcean. This is their response:
Just to let you know that we are investigating this issue, so far I
was able to reproduce the behavior. It seems that in order to remove
the create table from the public schema from a user we would need to
"REVOKE CREATE ON SCHEMA public FROM PUBLIC;" which is not allowed as
the doadmin use is not a superuser and revoking this privilege would
impact other roles.
If the user can create tables it has CREATE permissions on the schema in question. Look at those permissions with \dn+ public in psql. Identify the permissions in question and REVOKE them.
Alternatively, if you use PostgreSQL v15 or above, it micht be that your database user is directly or indirectly a member of the predefiled role pg_write_all_data. Revoke that membership.
In your specific case, the correct thing to do is to revoke the default CREATE privilege on schema public from PUBLIC, that is, everyone:
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
You say you already did that, and it caused a warning and had no effect. That is not what PostgreSQL would do. You'll have to ask the people who modified PostgreSQL, in your case DigitalOcean.

Trying to access psql after dropping a user but still got asked for entering password for the dropped user

initially I have
Role name | Attributes | Member of
------------+------------------------------------------------------------+-----------
hezhenghao | Create DB | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
and I typed
postgres=# REASSIGN OWNED BY hezhenghao to postgres
postgres-# ;
REASSIGN OWNED
postgres=# REASSIGN OWNED BY hezhenghao to postgres; REASSIGN OWNED
postgres=# DROP OWNED BY hezhenghao;
DROP OWNED
postgres=# DROP USER hezhenghao;
DROP ROLE
Now there is only one user
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
However when I type psql in terminal, I still got asked to Password for user hezhenghao:
and then I would end up with psql: FATAL: password authentication failed for user "hezhenghao"
I am new to postgres so I don't really understand what's going on here. Can someone help me with this?
If you don't specify a user with -U then psql will default to the username of the user currently logged in. In this case, it sounds like that user is hezhenghao. Use -U postgres to log in as the postgres user.

Postgres : Create a role and login with psql -U role

Code:
postgres=# create role hello;
CREATE ROLE
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------+-----------
hello | Cannot login | {}
postgres | Superuser, Create role, Create DB, Replication | {}
postgres=# ALTER ROLE hello WITH LOGIN;
ALTER ROLE
postgres=# ALTER ROLE hello WITH CREATEDB;
ALTER ROLE
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------+-----------
hello | Create DB | {}
postgres | Superuser, Create role, Create DB, Replication | {}
postgres=# ALTER ROLE hello WITH PASSWORD '123';
ALTER ROLE
postgres=# \q
-bash-4.2$ logout
[root#host test_user]# psql -U hello
Password for user hello:
psql: FATAL: database "hello" does not exist
I am trying to create a role named hello in Postgres with CREATE ROLE and changed it's permission for logging in and created database. However, when I try to login with -U it shows me the above. Is my understanding wrong here for -U?
By default, another assumption that the Postgres authentication system
makes is that there will be an database with the same name as the role
being used to login, which the role has access to.
See here:link for more info.
After creating the database, you can then do:
sudo -u hello psql
to log in to the shell automatically.
so i ran into a similar issue, Basically what postgres is expecting is a database that you want to choose,
And when you run the command
psql -U hello
It is assuming that you are trying to access hello database,
But by default only postgres db is created .
Try this command instead
psql -U hello postgres

Postgres user permission is not working

I have created a Postgres user user1, and granted all permission to my_db, when I try to select a table from the database, I'm getting a permission denied error.
Create user1
>>zya$ psql -d postgres
psql (9.6.3)
Type "help" for help.
postgres=# CREATE USER user1 WITH PASSWORD 'password1';
CREATE ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE my_db to user1;
GRANT
postgres=# \q
Login as user1
>>zya$ psql -d my_db --username=user1
psql (9.6.3)
Type "help" for help.
my_db=> SELECT DISTINCT name FROM user_tbl order by id;
ERROR: permission denied for relation user_tbl
ALTER DATABASE name OWNER TO new_owner;
you have to change database my_db owner to your username user1
I know this might be late but what you might want to do is to assign
This is from my trials and I was able to fix similar issue. It seems you have to set similar privileges to tables function and sequences like shown below
GRANT ALL PRIVILEGES ON DATABASE yourdb TO yourusr;
GRANT ALL ON ALL TABLES IN SCHEMA your_schema TO yourusr;
GRANT ALL ON ALL SEQUENCES IN SCHEMA your_schema TO yourusr;
GRANT ALL ON ALL FUNCTIONS IN SCHEMA your_schema TO yourusr;

How do you change a user in PostgreSQL?

postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication | {}
shorturl | Superuser | {}
postgres=# create database shorturl;
CREATE DATABASE
postgres=# \c shorturl;
You are now connected to database "shorturl" as user "postgres".
shorturl=#
My preference was to use database shorturl being the user shorturl and not postgres. How do I change the same?
Thanks in advance.
When you display the psql online help by entering \? you can see:
Connection
\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}
connect to new database (currently "postgres")
So you need to use:
\c shorturl shorturl
Another option, if you're already connected to database shorturl, is the command:
SET ROLE shorturl;
The benefits of that command are that it's not tied to psql, and that you can change user "midstream" of your work.