I am unsure about what does a PostgreSQL table owner means. I notice that it changes an attribute of the table itself and not about the owner because it is specified through an
ALTER TABLE table_name OWNER TO role_name;
You can see who is owner in certain table:
select * from pg_tables where tablename = 'my_tbl';
or you can see all tables by certain owner:
select * from pg_tables where tableowner = 'username';
The owner is (if nothing else happened) the user (role) that created the table. So if user arthur runs CREATE TABLE foo (id INTEGER), arthur owns the table.
The owner of a table has all privileges on it - including the privilege to drop it. Or the privilege to grant other users (roles) access to the table.
The SQL script generated by pg_dump typically includes the ALTER TABLE ... OWNER TO ... statement as those scripts are intended to be run by the DBA and in that case all tables would be owned by the DBA - which means the "real" owner could not change or access the tables.
Some excerpts from the official docs:
When an object is created, it is assigned an owner. The owner is normally the role that executed the creation statement. For most kinds of objects, the initial state is that only the owner (or a superuser) can do anything with the object. To allow other roles to use it, privileges must be granted.
The right to modify or destroy an object is inherent in being the object's owner, and cannot be granted or revoked in itself. (However, like all privileges, that right can be inherited by members of the owning role; see Section 21.3.)
Ordinarily, only the object's owner (or a superuser) can grant or revoke privileges on an object.
An object's owner can choose to revoke their own ordinary privileges, for example to make a table read-only for themselves as well as others. But owners are always treated as holding all grant options, so they can always re-grant their own privileges.
Related
Is it possible to set role with access to one database, with all privileges except to drop tables?
Not really. If a user can issue CREATE TABLE, it can issue a DROP for that table as well. From the docs:
The right to drop an object, or to alter its definition in any way, is not treated as a grantable privilege; it is inherent in the owner, and cannot be granted or revoked.
And as noted by the CREATE TABLE docs:
The table will be owned by the user issuing the command.
There is no mechanism to allow a user to create tables that they do not own and therefore cannot drop.
I am maintaining a database 'db' in which there are around 100 tables.I have one super user 'A' and 'A' is the owner of all tables. How can I give Alter permission to new user 'B' specific to single table without inheriting all permissions from 'A'.
I tried by providing Grant A to B;. This Grant option given all permissions from 'A' to 'B'. I want above scenario to restrict to one particular table.
Is this possible?
The documentation recently acquired this explanation:
The right to modify or destroy an object is inherent in being the object's owner, and cannot be granted or revoked in itself. (However, like all privileges, that right can be inherited by members of the owning role; see Section 21.3.)
So the only people who can run ALTER TABLE are:
Superusers
the table owner
members of the table owner role
So GRANT a TO b is the only way to give somebody the privilege.
You might be able to use a SECURITY DEFINER function that belongs to a, but be careful with that.
I'm coming to postgreSQL with a SQL Server background and was naively applying the same concepts to postgreSQL in order to allow different users to share 'by default' some objects within a database.
This is what I did:
CREATE DATABASE testdb;
CREATE ROLE testdb_role_full INHERIT;
GRANT ALL PRIVILEGES ON DATABASE testdb TO testdb_role_full;
CREATE USER user1 INHERIT;
GRANT testdb_role_full TO user1;
CREATE USER user2 INHERIT;
GRANT testdb_role_full TO user2;
Once done, I created a table t1 using the user1.
Then, I tried, as user2, to read the t1 table and I received a "permission denied error"... :-(
By reading the documentation, it seems that I have to issue a SET ROLE testdb_role_full first so as to act as the testdb_role_full.
However, this is not really that I want. I do not want the user to be aware of this.
So my question:
Is there any way to make this work?
Thanks a lot,
José
You've granted some privileges on the database, but that doesn't mean any user with the role testdb_role_full would have all privileges on all objects inside that database. To quote from the documentation:
When an object is created, it is assigned an owner. The owner is normally the role that executed the creation statement. For most kinds of objects, the initial state is that only the owner (or a superuser) can do anything with the object. To allow other roles to use it, privileges must be granted.
So after the user1 created the table t1, he is the owner and only he has the privileges on it. He would need to run
GRANT ALL PRIVILEGES ON TABLE t1 TO testdb_role_full;
then user2 would be able to access it as well (without having to switch any roles - that's only necessary when it has the NOINHERIT attribute on the role).
If you don't want your users to have to execute GRANT each time they create a new object in the database, you can alter the default privileges that will be applied whenever an object is created by user2:
ALTER DEFAULT PRIVILEGES FOR user2
GRANT ALL PRIVILEGES ON TABLES TO testdb_role_full;
Notice these specify the initial value only, and user2 could revoke the privileges on his tables if he wanted to prevent others from seeing them.
I'm trying to allow a database user to be able to alter/drop (certain) tables, but not GRANT privileges on them. Is this possible?
It looks like they need to be the owner of the tables, but from https://www.postgresql.org/docs/current/sql-grant.html
The right to drop an object, or to alter its definition in any way, is not treated as a grantable privilege; it is inherent in the owner, and cannot be granted or revoked. (However, a similar effect can be obtained by granting or revoking membership in the role that owns the object; see below.) The owner implicitly has all grant options for the object, too.
This sounds like it's not possible. However, is this definitely the case? Is there some way with triggers for example to make certain GRANTs fail?
Yes, only the owner of a table or a superuser can ALTER or DROP it, and these users can always GRANT privileges on the table.
Your only option is to create an event trigger that fires on GRANT and throws an error for the tables where it should be forbidden.
I have a multi-schema, multi-user Postgres DB. There is one table that I would like ALL users, both current and future, to be able to SELECT from.
I can GRANT SELECT to all current users... but how can I create a table that allows any future user to select? Is there a way to set table permissions, rather than granting user privileges?
A filesystem analogy would be using chmod to make a file to be readable by the public.
grant select on the_table to public;
From the manual:
The key word PUBLIC indicates that the privileges are to be granted to all roles, including those that might be created later. PUBLIC can be thought of as an implicitly defined group that always includes all roles