PostgreSQL role inheritance not working? - postgresql

I ran into a very annoying role inheritance issue with PostgreSQL. It simply doesn't behave as it should according to the documentation.
I would like to have a master role, and grant its permissions to newly created users. These users should inherit the permissions without issuing SET ROLE manually.
CREATE ROLE testrole NOSUPERUSER INHERIT CREATEDB NOCREATEROLE;
CREATE ROLE testuser LOGIN NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE;
GRANT testrole TO testuser;
Now after I connect as testuser, I get the following:
postgres=> CREATE DATABASE foobar;
ERROR: permission denied to create database
postgres=> SET ROLE testrole;
SET
postgres=> CREATE DATABASE foobar;
CREATE DATABASE
According to the docs linked above (because of the INHERIT option), the SET ROLE shouldn't be required.
What am I missing here?

A bit further down the same page:
"The role attributes LOGIN, SUPERUSER, CREATEDB, and CREATEROLE can be thought of as special privileges, but they are never inherited as ordinary privileges on database objects are. You must actually SET ROLE to a specific role having one of these attributes in order to make use of the attribute."

Related

Superuser cannot create or alter roles

Created a user/role via following method is Aurora Postgres:
CREATE ROLE rds_user_test;
GRANT rds_superuser to rds_user_test;
GRANT rds_iam TO rds_user_test;
When I login using IAM DB Auth as rds_user_test it appears that I can do all operations as needed except creating or altering roles (maybe other functionality is missing but haven't tested all operations yet). When I check role memberships of this new role against other roles that are able to create/alter roles, both are members of superuser.
I also followed the instructions here:
https://aws.amazon.com/premiumsupport/knowledge-center/rds-aurora-postgresql-clone-master-user/
Still get the same permissions error:
[42501] ERROR: permission denied to create role
Any thoughts on why this new role cannot create/alter other roles even though it seems to have the same privileges of superuser as other roles?
rds_superuser on Amazon Aurora is typically not a superuser. Check with:
SELECT rolsuper FROM pg_roles WHERE rolname = 'rds_superuser';
But to create a role, you don't need superuser privileges. All you need is the CREATEROLE privilege. Check if your user has that:
SELECT rolcreaterole FROM pg_roles WHERE rolname = 'rds_user_test';
Else you need to grant it (as a role that's allowed to do so):
ALTER ROLE rds_user_test CREATEROLE;
Any role with the CREATEROLE privilege can do that (typically including rds_superuser).
The manual:
Roles having CREATEROLE privilege can change any of these settings except SUPERUSER, REPLICATION, and BYPASSRLS; but only for non-superuser and non-replication roles.
The instructions you followed, explicitly instruct to add CREATEROLE, you seem to have skipped that bit:
CREATE ROLE new_master WITH PASSWORD 'password' CREATEDB CREATEROLE LOGIN;

Granting rolegroup to role did not inherit the config from rolegroup in postgres

We have a scenario where some users would need super user permissions and other db users dont need it. So we have create the users and then created a role 'SuperRole' which has permissions to create role, db.
Let's say I have user 'User1' mapped to role 'User1' by default with INHERIT. After creating 'SuperRole' role I have ran
GRANT superrole to user1;
After this if I see \du output
postgres=# \du user1
List of roles
Role name | Attributes | Member of
--------------+------------------------+--------------
user1 | Create role, Create DB | {superrole}
As per the documentation https://www.postgresql.org/docs/11/role-membership.html the privileges of role 'member of' should also be inherited. But when i connect to psql with user1, I should be having the privileges of superrole also to create role and db. However when I try to create a db I am getting the below error.
postgres=> create database test;
ERROR: permission denied to create database
The similar error shows for creating role as well. What should be done to make the privileges set for superrole to be available for user1 as well.
The role attributes LOGIN, SUPERUSER, CREATEDB, and CREATEROLE can be thought of as special privileges, but they are never inherited as ordinary privileges on database objects are. You must actually SET ROLE to a specific role having one of these attributes in order to make use of the attribute.
refer: https://www.postgresql.org/docs/current/role-membership.html

PostgreSQL : Accessing tables owned by another user

As a Superuser, I have created two roles in Postgres on the same schema:
read_only_with_create_view
read_write
Then I created two users from each role:
read_only_with_create_view_user
read_write
Now any new views created by read_only_with_create_view_user cannot be accessed by read_write_user as the owner for views is different (read_only_with_create_view_user).
So what is the way to access all new views by read_write_user?
I want everything created by one user to be accessible to another user.
Steps I followed:
CREATE ROLE read_only_role WITH
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION VALID UNTIL 'infinity';
GRANT CONNECT ON DATABASE mydb to read_only_role;
GRANT USAGE,CREATE ON SCHEMA myschema TO read_only_role;
GRANT SELECT ON ALL TABLES IN SCHEMA myschema TO read_only_role;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA myschema TO read_only_role;
CREATE USER read_only_with_create_view_user
WITH PASSWORD '*****'
in ROLE read_only_role;
-- Now created new views using this role. That means read_only_with_create_view_user is owner of those views.
-- Creating new read-write role.
CREATE ROLE rw_role WITH
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION VALID UNTIL 'infinity' IN ROLE read_only_role;
GRANT CONNECT ON DATABASE mydb to rw_role;
GRANT USAGE ON SCHEMA myschema TO crn_rw_role_qa;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA myschema TO rw_role;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA myschema TO rw_role;
CREATE USER read_write_user
WITH PASSWORD '*****'
in role rw_role;
After login with read_write_user, when I try to access new views created by read_only_with_create_view_user, I get this error:
ERROR: permission denied for relation view_name
********** Error **********
ERROR: permission denied for relation view_name
SQL state: 42501
You can set a role as a member of another role:
GRANT read_only_with_create_view_user TO read_write_user;
More info here.
EDIT
It will never work as you expect. See your current user schema:
Role read_write_user will cannot access objects owned by read_only_with_create_view_user simply because both don't have any relationship. To make this works as you expect you can reassign objects ownership to an "upper" level role, in this case: read_only_role (because everybody is a member of this role). But be warned that it will no longer be a read-only role.
You can do one of the following:
--Connected as read_only_with_create_view_user
CREATE VIEW my_view AS SELECT 1;
--Assign ownership to top-level role
ALTER VIEW my_view OWNER TO read_only_role;
Or you may prefer this approach:
--Connected as read_only_with_create_view_user
--Change current user to read_only_role
SET role = read_only_role;
--Create a view...
CREATE VIEW my_view AS SELECT 1;
--Turn back to read_only_with_create_view_user
RESET role;
If you prefer to do all at once you can reassign ownership of objects owned by read_only_with_create_view_user to your top-level role in just one command:
REASSIGN OWNED BY read_only_with_create_view_user TO read_only_role;
Finally, if you don't want to break your read-only rule you can also, of course, give permission directly to the object.
-- As read_only_with_create_view_user, execute the following:
CREATE VIEW my_view_2 AS SELECT 1;
GRANT SELECT ON my_view_2 TO read_write_user

Postgres unable to create db after granting privs to role

I'm sure I'm missing something simple, but I've created the following:
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+-----------------------------------------+-----------
admin | No inheritance, Create DB, Cannot login | {}
postgres | Superuser, Create role, Create DB | {}
wade | | {admin}
(Note that Cannot login and No inheritance don't affect what's happening to wade, here. See the PostgreSQL documentation for role membership to understand why. —bignose)
However, when I try to create a db, I get:
bin wwilliam$ createdb -U wade test
Password:
createdb: database creation failed: ERROR: permission denied to create database
What am I missing?
An excerpt from the manual:
The INHERIT attribute governs inheritance of grantable privileges (that is, access privileges for database objects and role memberships). It does not apply to the special role attributes set by CREATE ROLE and ALTER ROLE. For example, being a member of a role with CREATEDB privilege does not immediately grant the ability to create databases, even if INHERIT is set; it would be necessary to become that role via SET ROLE before creating a database.
(Emphasis mine).
In documentation:
The role attributes LOGIN, SUPERUSER, CREATEDB, and CREATEROLE can be thought of as special privileges, but they are never inherited as ordinary privileges on database objects are. You must actually SET ROLE to a specific role having one of these attributes in order to make use of the attribute
So you must activate admin role using SET ROLE admin; before creating DB.

CREATEDB through a ROLE for a User in PostgreSQL

I have created a ROLE with name Admin and I have given it all accesses (including CREATEDB). I have created a User ekekakos who is member of Admin role and inherints from it. When I am trying to create a new DB with ekekakos I am getting the following message:
ERROR. PERMISSION DENIED TO CREATE DATABASE.
When I enable the option CAN CREATE DB to the user ekekakos, the database is created.
Why the user do not take the privilages of the role Admin?
Thanks
Excerpt from the docs:
The role attributes LOGIN, SUPERUSER, CREATEDB, and CREATEROLE can be thought of as special privileges, but they are never inherited as ordinary privileges on database objects are. You must actually SET ROLE to a specific role having one of these attributes in order to make use of the attribute.