I try add audit trigger for table in BD. I find example on GitHub. But I dont understand why author use this construction after create schema and table
CREATE SCHEMA audit;
REVOKE ALL ON SCHEMA audit FROM public;
And for table:
REVOKE ALL ON audit.logged_actions FROM public;
What the aim of using REVOKE ?
Revoke removes access permissions to an object.
it means only specific users that you will grant permission to them can access the audit scheme / logged_actions table.
"The key word PUBLIC refers to the implicitly defined group of all roles."
The REVOKE is pointless, because the default permissions on a new schema only allow the owner (the user that ran CREATE SCHEMA) to use it. See the documentation:
No privileges are granted to PUBLIC by default on tables, table columns, sequences, foreign data wrappers, foreign servers, large objects, schemas, tablespaces, or configuration parameters.
I can only assume that the REVOKE is a safety measure, in case the user who runs CREATE SCHEMA has changed the default privileges as follows:
ALTER DEFAULT PRIVILEGES GRANT ... ON SCHEMAS TO PUBLIC;
Related
I have a Postgres database and a read-only user that I want to grant permissions to. I have two schemas currently but expect to make many more in the future. How do I grant select permissions to my read-only user so that they can read data from the tables that are currently created as well as tables that will be created in a new schema in the future?
I don't want to have to explicitly grant permissions for each new schema when they are created.
Use ALTER DEFAULT PRIVILEGES without specifying any schema:
The privileges can be set globally (i.e., for all objects created in the current database) […]
If IN SCHEMA is omitted, the global default privileges are altered.
So this should do it:
ALTER DEFAULT PRIVILEGES FOR whoever_will_create_the_tables
GRANT SELECT ON TABLES TO the_readonly_user;
ALTER DEFAULT PRIVILEGES FOR whoever_will_create_the_schemas
GRANT USAGE ON SCHEMAS TO the_readonly_user;
Granting the privilege on the tables that already are created needs a separate statement:
GRANT SELECT ON ALL TABLES IN SCHEMA schema_1, schema_2 TO the_readonly_user;
I am experiencing a weird and (to me) inexplicable behaviour related to DEFAULT PRIVILEGES. It seems default privileges cannot be revoked just for a specific schema once they have been granted database-wide.
I am currently testing this with PostgreSQL 10.5 on CentOS.
Let's say there are 3 users:
admin Owner of the database. Used to manipulate the STRUCTURE of the database (CREATE, DROP, TRUNCATE...)
manager Used for DATA manipulation (INSERT, UPDATE, DELETE)
reader Used to read DATA (basically SELECT)
The idea is that:
admin will be the owner of the database and all the objects contained into it
manager will be used for data manipulation across all schemas but public (only user admin can modify data in public schema)
reader will be able to read everything.
To make things easier, this will rely on default privileges, so that newly created objects (schemas, tables, views, functions, etc.) will all have the correct permissions.
This is the first time I am trying something like that instead of a fine-grained permissions policy based on multiple users for all different schemas and apparently this setup should be very straightforward.
It turns out I am missing something.
Here is a simple test script. User admin is the owner of db database and all those commands are issued being connected to it as admin:
-- 1. User manager inherits from user "reader"
GRANT reader TO manager;
-- 2. Allow connections to the database to our users, but not PUBLIC
REVOKE ALL ON DATABASE db FROM PUBLIC;
GRANT CONNECT ON DATABASE db TO reader;
-- 3. Revoke default privileges from PUBLIC
ALTER DEFAULT PRIVILEGES REVOKE ALL ON SCHEMAS FROM PUBLIC;
ALTER DEFAULT PRIVILEGES REVOKE ALL ON TABLES FROM PUBLIC;
ALTER DEFAULT PRIVILEGES REVOKE ALL ON SEQUENCES FROM PUBLIC;
ALTER DEFAULT PRIVILEGES REVOKE ALL ON FUNCTIONS FROM PUBLIC;
-- 4. Grant default reading privileges to user "reader"
ALTER DEFAULT PRIVILEGES GRANT USAGE ON SCHEMAS TO reader;
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES TO reader;
ALTER DEFAULT PRIVILEGES GRANT SELECT ON SEQUENCES TO reader;
ALTER DEFAULT PRIVILEGES GRANT EXECUTE ON FUNCTIONS TO reader;
-- 5. Grant Defauly writing privileges to user "manager"
ALTER DEFAULT PRIVILEGES GRANT INSERT, UPDATE, DELETE ON TABLES TO manager;
ALTER DEFAULT PRIVILEGES GRANT USAGE ON SEQUENCES TO manager;
-- 6. Reinit "public" schema
DROP SCHEMA public;
CREATE SCHEMA public;
-- 7. HERE COMES THE WEIRD STUFF, the two following statements don't have any effect at all
ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE INSERT, UPDATE, DELETE ON TABLES FROM manager;
ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE USAGE ON SEQUENCES FROM manager;
This can be easily verified like that:
-- Execute as user "admin":
CREATE TABLE public.t (id serial PRIMARY KEY, dummy integer)
-- Execute as user "manager" (it should not be allowed, but it is!)
DELETE FROM public.t;
I know I could circumvent this using some trigger functions, but the point of the question is whether this is something normal and expected, some sort of bug or am I missing something?
I have been thinking about it and the most elegant solution I could come up with relies on an Event Trigger.
Of course it does not answer my question directly, meaning that I am still wondering why default privileges cannot be used like that, but at least this meets the initial requirement of set-and-forget that default privileges would have provided.
Create a function that revokes unwanted privileges and returns an event_trigger:
CREATE FUNCTION reset_privileges() RETURNS event_trigger AS $$
BEGIN
IF EXISTS (SELECT true FROM pg_event_trigger_ddl_commands() WHERE schema_name = 'public') THEN
REVOKE INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public FROM manager;
REVOKE USAGE ON ALL SEQUENCES IN SCHEMA public FROM manager;
END IF;
END;
$$ LANGUAGE plpgsql;
Create an actual EVENT TRIGGER (This requires superuser privileges!):
CREATE EVENT TRIGGER reset_public_schema_privileges
ON ddl_command_end WHEN TAG IN (
'CREATE TABLE',
'CREATE TABLE AS',
'CREATE VIEW',
'CREATE MATERIALIZED VIEW',
'CREATE FUNCTION'
) EXECUTE PROCEDURE reset_privileges();
The function checks whether the newly created object(s) are in the public schema and eventually revokes all the unwanted privileges from the user manager.
It does not even bother to filter those objects, but rather it revokes the privileges for ALL TABLEs, VIEWs and FUNCTIONs in the public schema. Of course it can be easily customised using the object_identity field provided by pg_event_trigger_ddl_commands and a more refined logic inside the function.
According to the manual for ALTER DEFAULT PRIVILEGES:
Default privileges that are specified per-schema are added to whatever the global default privileges are for the particular object type. This means you cannot revoke privileges per-schema if they are granted globally (either by default, or according to a previous ALTER DEFAULT PRIVILEGES command that did not specify a schema). Per-schema REVOKE is only useful to reverse the effects of a previous per-schema GRANT.
(This is even more explicit in the examples given on that manual page.)
So I think what is happening is that in step 5 of your script, you are setting the default privilege to grant DELETE on the tables of all schemas (as a global default):
ALTER DEFAULT PRIVILEGES GRANT INSERT, UPDATE, DELETE ON TABLES TO manager;
But in step 7 you are revoking from the public schema specifically. This revocation has no effect on the global grant, so the DELETE (and other) privileges will still be granted:
ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE INSERT, UPDATE, DELETE ON TABLES FROM manager;
I think I would either (a) bite the bullet and add default privileges for each schema (which isn't "fire-and-forget" but is more explicit) or (b) challenge why I need the public schema to exist, aiming to remove it to simplify this situation.
I am facing an issue while creating a readonly users in RDS PostgreSQL 9.6. I am executing the following SQL commands:
---- ###### CREATE ROLE ################
CREATE ROLE readonlyrole_dev;
-- Grant access to existing tables
GRANT USAGE ON SCHEMA public TO readonlyrole_dev;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonlyrole_dev;
-- set the privileges that will be applied to objects created in the future.
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonlyrole_dev;
CREATE USER readonly_dev WITH PASSWORD 'welcome1';
GRANT readonlyrole_dev TO readonly_dev;
When I login with the readonly_dev user, it has privilege to create the new tables by default but I don't want to do that. I want to keep readonly_dev only a read only user.
Note: To revoke the access from the user I am executing
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
which revokes create objects privilege to all old users as well. I only want to revoke create privilege from newly created user.
How can I do that?
You cannot do that, and it is not necessary either.
Just deny the user the CREATE permission on all schemas. You should use user groups for that - put all users who should have the privilege to create tables in a group that has the required privilege on the schema and revoke CREATE from PUBLIC.
If you insist that you must have this, try creating an event trigger that throws an exception whenever a certain user tries to create a table.
Is there a way to restrict the user to view all the schemas in a database?
Scenario:
I have a database with multiple schemas. I need to give access to a user for a particular schema and it's tabled.
Even though I try revoking all the access to that particular user and PUBLIC group, still he can view all the schemas and its tables. (Only the data he can't view.
I tried below commands:
REVOKE ALL ON SCHEMA devops_test FROM testuser;
REVOKE ALL ON SCHEMA devops_test FROM PUBLIC;
REVOKE ALL on all tables IN SCHEMA devops_test FROM testuser;
Once connected to database, users can read a list of all databases, schema's, tables, and even table columns in the cluster from the system tables, even if they are prevented from reading the data within those tables through the use of REVOKE ALL FROM. Try this:
REVOKE USAGE ON SCHEMA information_schema FROM PUBLIC;
REVOKE USAGE ON SCHEMA pg_catalog FROM PUBLIC;
REVOKE SELECT ON TABLE pg_catalog.pg_database FROM PUBLIC;
If I’ve made a bad assumption please comment and I’ll refocus my answer.
Using PostgreSQL 9.0, I have a group role called "staff" and would like to grant all (or certain) privileges to this role on tables in a particular schema. None of the following work
GRANT ALL ON SCHEMA foo TO staff;
GRANT ALL ON DATABASE mydb TO staff;
Members of "staff" are still unable to SELECT or UPDATE on the individual tables in the schema "foo" or (in the case of the second command) to any table in the database unless I grant all on that specific table.
What can I do make my and my users' lives easier?
Update: Figured it out with the help of a similar question on serverfault.com.
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA foo TO staff;
You found the shorthand to set privileges for all existing tables in the given schema. The manual clarifies:
(but note that ALL TABLES is considered to include views and foreign tables).
Bold emphasis mine. serial columns are implemented with nextval() on a sequence as column default and, quoting the manual:
For sequences, this privilege allows the use of the currval and nextval functions.
So if there are serial columns, you'll also want to grant USAGE (or ALL PRIVILEGES) on sequences
GRANT USAGE ON ALL SEQUENCES IN SCHEMA foo TO mygrp;
Note: IDENTITY columns in Postgres 10 or later use implicit sequences that don't require additional privileges. (Consider upgrading serial columns.)
What about new objects?
You'll also be interested in DEFAULT PRIVILEGES for users or schemas:
ALTER DEFAULT PRIVILEGES IN SCHEMA foo GRANT ALL PRIVILEGES ON TABLES TO staff;
ALTER DEFAULT PRIVILEGES IN SCHEMA foo GRANT USAGE ON SEQUENCES TO staff;
ALTER DEFAULT PRIVILEGES IN SCHEMA foo REVOKE ...;
This sets privileges for objects created in the future automatically - but not for pre-existing objects.
Default privileges are only applied to objects created by the targeted user (FOR ROLE my_creating_role). If that clause is omitted, it defaults to the current user executing ALTER DEFAULT PRIVILEGES. To be explicit:
ALTER DEFAULT PRIVILEGES FOR ROLE my_creating_role IN SCHEMA foo GRANT ...;
ALTER DEFAULT PRIVILEGES FOR ROLE my_creating_role IN SCHEMA foo REVOKE ...;
Note also that all versions of pgAdmin III have a subtle bug and display default privileges in the SQL pane, even if they do not apply to the current role. Be sure to adjust the FOR ROLE clause manually when copying the SQL script.
My answer is similar to this one on ServerFault.com.
To Be Conservative
If you want to be more conservative than granting "all privileges", you might want to try something more like these.
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO some_user_;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO some_user_;
The use of public there refers to the name of the default schema created for every new database/catalog. Replace with your own name if you created a schema.
Access to the Schema
To access a schema at all, for any action, the user must be granted "usage" rights. Before a user can select, insert, update, or delete, a user must first be granted "usage" to a schema.
You will not notice this requirement when first using Postgres. By default every database has a first schema named public. And every user by default has been automatically been granted "usage" rights to that particular schema. When adding additional schema, then you must explicitly grant usage rights.
GRANT USAGE ON SCHEMA some_schema_ TO some_user_ ;
Excerpt from the Postgres doc:
For schemas, allows access to objects contained in the specified schema (assuming that the objects' own privilege requirements are also met). Essentially this allows the grantee to "look up" objects within the schema. Without this permission, it is still possible to see the object names, e.g. by querying the system tables. Also, after revoking this permission, existing backends might have statements that have previously performed this lookup, so this is not a completely secure way to prevent object access.
For more discussion see the Question, What GRANT USAGE ON SCHEMA exactly do?. Pay special attention to the Answer by Postgres expert Craig Ringer.
Existing Objects Versus Future
These commands only affect existing objects. Tables and such you create in the future get default privileges until you re-execute those lines above. See the other answer by Erwin Brandstetter to change the defaults thereby affecting future objects.