How to grant all privileges on views to arbitrary user - sql

How do you grant read/select access on all functions and views to an arbitrary user?
I use psql --user=postgres -d mydb -f myview.sql to create several functions and views, and then I run:
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;
Having been granted all privileges, I would expect myuser to now have access to the functions and views created by the postgres user. However, when I try and access them with myuser, I get a "permission denied for relation..." error. Why is this?

The reason is that you need additional privileges to access a view or table. Privileges on the database do not cover access to all objects in it.
It is different with functions: EXECUTE privilege is granted to public by default. But the function is executed with the privileges of the current user. You may be interested in the SECURITY DEFINER modifier for CREATE FUNCTION. But normally it is enough to grant SELECT on involved tables.
Per documentation about default privileges:
Depending on the type of object, the initial default privileges might
include granting some privileges to PUBLIC. The default is no public
access for tables, columns, schemas, and tablespaces; CONNECT
privilege and TEMP table creation privilege for databases; EXECUTE
privilege for functions; and USAGE privilege for languages.
You may be interested in this DDL command (requires Postgres 9.0 or later):
GRANT SELECT ON ALL TABLES IN SCHEMA public TO myuser;
While connected to the database in question, of course (see #marcel's comment below), and as a user with sufficient privileges. You may also be interested in the setting DEFAULT PRIVILEGES:
Grant all on a specific schema in the db to a group role in PostgreSQL
More detailed answer how to manage privileges:
How to manage DEFAULT PRIVILEGES for USERs on a DATABASE vs SCHEMA?
pgAdmin has a feature for more sophisticated bulk operations:
Or you can query the system catalogs to create DDL statements for bulk granting / revoking ...

Related

Add a new firebird-db user with acces to specific tables?

I need to create a new firebird-db user which has only access to 4 specific tables. Is there a way to do that?
http://www.destructor.de/firebird/gsec.htm isn't really helpful in that regard.
The - third-party - gsec documentation you link does not provide information about granting rights on tables, because gsec is only for managing users in the security database. In Firebird, rights of users are managed in the individual databases using the GRANT (and REVOKE) statements (it is even possible to grant rights to users that do not exist (yet)). Be aware, Firebird 3 deprecated gsec, and since Firebird 2.5, it is recommended to use the SQL user management statements instead of gsec.
You need to create the user, and then give the user privileges to the tables you want. See the Security chapter in the Firebird 2.5 Language Reference.
A regular, authenticated user has no privileges on any database object
until they are explicitly granted, either to that individual user or
to all users bundled as the user PUBLIC.
Specifically:
Create a user:
create user <username> password '<password>';
See also CREATE USER; to create a user, you need to be either SYSDBA, or you need to have and the admin role in the security database, and the RDB$ADMIN role in the current database, and be logged in specifying the RDB$ADMIN role on connect.
Grant the necessary privileges to the user. For example to give SELECT privileges:
grant select on table <tablename> to user <username>;
To allow select, insert, update and delete:
grant select, insert, update, delete on table <tablename> to user <username>;
See also GRANT; to grant permission to an object, you must be either SYSDBA, the owner of the object, be RDB$ADMIN in the current database, or have been granted the privilege(s) with the WITH GRANT OPTION.
When you need to grant the same set of rights to multiple users, it is better to grant rights to a role, and then grant that role to the users. However in Firebird 3 and earlier, to get the rights granted to a role, the user needs to explicitly specify that role on connect (Firebird 4 will introduce roles that are automatically applied).

How SELECT ANY TABLE privilege work in Oracle?

I would like to know how the privilege SELECT ANY TABLE works internally in Oracle.
Is it treated as a single privilege? Or is it equivalent to make a GRANT SELECT ON MyTable TO MyUser for each table?
As example, I would like to know if this work :
GRANT SELECT ANY TABLE TO PUBLIC;
REVOKE ALL ON MY_TABLE FROM PUBLIC;
Would I still have access to MY_TABLE from any user after those queries?
Yes, all users would still be able to query MY_TABLE.
You are looking at different privilege types:
The main types of user privileges are as follows:
System privileges—A system privilege gives a user the ability to perform a particular action, or to perform an action on any schema objects of a particular type. For example, the system privilege CREATE TABLE permits a user to create tables in the schema associated with that user, and the system privilege CREATE USER permits a user to create database users.
Object privileges—An objectprivilege gives a user the ability to perform a particular action on a specific schema object. Different object privileges are available for different types of schema objects. The privilege to select rows from the EMPLOYEES table or to delete rows from the DEPARTMENTS table are examples of object privileges.
SELECT ANY TABLE is a system privilege that allows the grantee to:
Query tables, views, or materialized views in any schema except SYS. Obtain row locks using a SELECT ... FOR UPDATE.
When you grant that it is a standalone single privilege, visible in dba_sys_privs. When Oracle decides if the user is allowed to access a table it can look first at system privleges, and only goes on to look for specific object privileges (visible in dba_tab_privs) if there isn't a system privilege that allows the action being performed.
System privileges are not translated into individual privileges on each object in the database - maintaining that would be horrible, as creating a new object would have to automatically figure out who should be granted privileges on it based on the system privilege; and it would mean that you couldn't tell the difference between that and individually granted privileges. So, for instance, if you explicitly granted select privs on a specific table, then the user was granted SELECT ANY TABLE, and then they had SELECT ANY TABLE revoked - what happens to the previous explicit grant?
Your scenario is basically the same, except you've specifed all privileges on the object to be revoked. If those are the only two commands involved then PUBLIC has no explicit privileges on MY_TABLE so revoking doesn't really do anything; but if any explicit privileges on that table had been granted then they would be revoked. That has no impact on the higher-level SELECT ANY TABLE system privileg though.
Privileges are cummulative; revoking a privilege on a specific object doesn't block access to that object, it just removes one possible access route.
Incidentally, hopefully you've used a contrived example, as such powerful system privileges should be granted sparingly and only when really needed. Letting any user query any table in your database potentially blows a big hole in the security model. Again from the docs:
Oracle recommends that you only grant the ANY privileges to trusted users
and
Oracle recommends against granting system privileges to PUBLIC.
and read more in the database security guide.

Grant privileges for a particular database in PostgreSQL

I'm moving from MySQL to PostgreSQL and have hit a wall with user privileges. I am used to assigning a user all privileges to all tables of a database with the following command:
# MySQL
grant all privileges on mydatabase.* to 'myuser'#'localhost' identified by 'mypassword';
It appears to me that the PostgreSQL 9.x solution involves assigning privileges to a "schema", but the effort required of me to figure out exactly what SQL to issue is proving excessive. I know that a few more hours of research will yield an answer, but I think everyone moving from MySQL to PostgreSQL could benefit from having at least one page on the web that provides a simple and complete recipe. This is the only command I have ever needed to issue for users. I'd rather not have to issue a command for every new table.
I don't know what scenarios have to be handled differently in PostgreSQL, so I'll list some of the scenarios that I have typically had to handle in the past. Assume that we only mean to modify privileges to a single database that has already been created.
(1a) Not all of the tables have been created yet, or (1b) the tables have already been created.
(2a) The user has not yet been created, or (2b) the user has already been created.
(3a) Privileges have not yet been assigned to the user, or (3b) privileges were previously assigned to the user.
(4a) The user only needs to insert, update, select, and delete rows, or (4b) the user also needs to be able to create and delete tables.
I have seen answers that grant all privileges to all databases, but that's not what I want here. Please, I am looking for a simple recipe, although I wouldn't mind an explanation as well.
I don't want to grant rights to all users and all databases, as seems to be the conventional shortcut, because that approach compromises all databases when any one user is compromised. I host multiple database clients and assign each client a different login.
It looks like I also need the USAGE privilege to get the increasing values of a serial column, but I have to grant it on some sort of sequence. My problem got more complex.
Basic concept in Postgres
Roles are global objects that can access all databases in a db cluster - given the required privileges.
A cluster holds many databases, which hold many schemas. Schemas (even with the same name) in different DBs are unrelated. Granting privileges for a schema only applies to this particular schema in the current DB (the current DB at the time of granting).
Every database starts with a schema public by default. That's a convention, and many settings start with it. Other than that, the schema public is just a schema like any other.
Coming from MySQL, you may want to start with a single schema public, effectively ignoring the schema layer completely. I am using dozens of schema per database regularly.
Schemas are a bit (but not completely) like directories in the file system.
Once you make use of multiple schemas, be sure to understand search_path setting:
How does the search_path influence identifier resolution and the "current schema"
Default privileges
Per documentation on GRANT:
PostgreSQL grants default privileges on some types of objects to
PUBLIC. No privileges are granted to PUBLIC by default on tables,
columns, schemas or tablespaces. For other types, the default
privileges granted to PUBLIC are as follows: CONNECT and CREATE TEMP TABLE
for databases; EXECUTE privilege for functions; and USAGE privilege for languages.
All of these defaults can be changed with ALTER DEFAULT PRIVILEGES:
Grant all on a specific schema in the db to a group role in PostgreSQL
Group role
Like #Craig commented, it's best to GRANT privileges to a group role and then make a specific user member of that role (GRANT the group role to the user role). This way it is simpler to deal out and revoke bundles of privileges needed for certain tasks.
A group role is just another role without login. Add a login to transform it into a user role. More:
Why did PostgreSQL merge users and groups into roles?
Predefined roles
Update: Postgres 14 or later adds the new predefined roles (formally "default roles") pg_read_all_data and pg_write_all_data to simplify some of the below. See:
Grant access to all tables of a database
Recipe
Say, we have a new database mydb, a group mygrp, and a user myusr ...
While connected to the database in question as superuser (postgres for instance):
REVOKE ALL ON DATABASE mydb FROM public; -- shut out the general public
GRANT CONNECT ON DATABASE mydb TO mygrp; -- since we revoked from public
GRANT USAGE ON SCHEMA public TO mygrp;
To assign "a user all privileges to all tables" like you wrote (I might be more restrictive):
GRANT ALL ON ALL TABLES IN SCHEMA public TO mygrp;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO mygrp; -- don't forget those
To set default privileges for future objects, run for every role that creates objects in this schema:
ALTER DEFAULT PRIVILEGES FOR ROLE myusr IN SCHEMA public
GRANT ALL ON TABLES TO mygrp;
ALTER DEFAULT PRIVILEGES FOR ROLE myusr IN SCHEMA public
GRANT ALL ON SEQUENCES TO mygrp;
-- more roles?
Now, grant the group to the user:
GRANT mygrp TO myusr;
Related answer:
PostgreSQL - DB user should only be allowed to call functions
Alternative (non-standard) setting
Coming from MySQL, and since you want to keep privileges on databases separated, you might like this non-standard setting db_user_namespace. Per documentation:
This parameter enables per-database user names. It is off by default.
Read the manual carefully. I don't use this setting. It does not void the above.
Maybe you could give me an example that grants a specific user
select/insert/update/delete on all tables -- those existing and not
yet created -- of a specific database?
What you call a database in MySQL more closely resembles a PostgreSQL schema than a PostgreSQL database.
Connect to database "test" as a superuser. Here that's
$ psql -U postgres test
Change the default privileges for the existing user "tester".
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT INSERT, SELECT, UPDATE, DELETE ON TABLES
TO tester;
Changing default privileges has no effect on existing tables. That's by design. For existing tables, use standard GRANT and REVOKE syntax.
You can't assign privileges for a user that doesn't exist.
You can forget about the schema if you only use PUBLIC.
Then you do something like this: (see doc here)
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[, ...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
I don't want to grant rights to all users and all databases, as seems to be the conventional shortcut, because that approach compromises all databases when any one user is compromised. I host multiple database clients and assign each client a different login.
OK. When you assign tables to the correct role, the privileges granted will be role-specific and not to all users! Then you can decide who to give roles to.
Create a role for each database. A role can hold many users.
Then assign a client-username to the correct role.
Also assign your-username to each role if needed.
(1a) Not all of the tables have been created yet, or (1b) the tables have already been created.
OK. You can create tables later.
When you are ready, assign tables to the correct client role.
CREATE TABLE tablename();
CREATE ROLE rolename;
ALTER TABLE tablename OWNER TO rolename;
(2a) The user has not yet been created, or (2b) the user has already been created.
OK. Create usernames when you are ready. If your client needs more than one username simply create a second client-username.
CREATE USER username1;
CREATE USER username2;
(3a) Privileges have not yet been assigned to the user, or (3b) privileges were previously assigned to the user.
OK. When you are ready to give privileges, create the user and assign the correct role to her.
Use GRANT-TO command to assign roles to users.
GRANT rolename TO username1;
GRANT rolename TO username2;
(4a) The user only needs to insert, update, select, and delete rows, or (4b) the user also needs to be able to create and delete tables.
OK. You run these commands to add permissions to your users.
GRANT SELECT, UPDATE, INSERT, DELETE ON dbname TO role-or-user-name;
ALTER USER username1 CREATEDB;

PostgreSQL: Give all permissions to a user on a PostgreSQL database

I would like to give a user all the permissions on a database without making it an admin.
The reason why I want to do that is that at the moment DEV and PROD are different DBs on the same cluster so I don't want a user to be able to change production objects but it must be able to change objects on DEV.
I tried:
grant ALL on database MY_DB to group MY_GROUP;
but it doesn't seem to give any permission.
Then I tried:
grant all privileges on schema MY_SCHEMA to group MY_GROUP;
and it seems to give me permission to create objects but not to query\delete objects on that schema that belong to other users
I could go on by giving USAGE permission to the user on MY_SCHEMA but then it would complain about not having permissions on the table ...
So I guess my question is: is there any easy way of giving all the permissions to a user on a DB?
I'm working on PostgreSQL 8.1.23.
All commands must be executed while connected to the right database cluster. Make sure of it.
Roles are objects of the database cluster. All databases of the same cluster share the set of defined roles. Privileges are granted / revoked per database / schema / table etc.
A role needs access to the database, obviously. That's granted to PUBLIC by default. Else:
GRANT CONNECT ON DATABASE my_db TO my_user;
Basic privileges for Postgres 14 or later
Postgres 14 adds the predefined, non-login roles pg_read_all_data / pg_write_all_data.
They have SELECT / INSERT, UPDATE, DELETE privileges for all tables, views, and sequences. Plus USAGE on schemas. We can GRANT membership in these roles:
GRANT pg_read_all_data TO my_user;
GRANT pg_write_all_data TO my_user;
This covers all basic DML commands (but not DDL, and not some special commands like TRUNCATE or the EXECUTE privilege for functions!). The manual:
pg_read_all_data
Read all data (tables, views, sequences), as if having SELECT rights
on those objects, and USAGE rights on all schemas, even without
having it explicitly. This role does not have the role attribute
BYPASSRLS set. If RLS is being used, an administrator may wish to
set BYPASSRLS on roles which this role is GRANTed to.
pg_write_all_data
Write all data (tables, views, sequences), as if having INSERT,
UPDATE, and DELETE rights on those objects, and USAGE rights on
all schemas, even without having it explicitly. This role does not
have the role attribute BYPASSRLS set. If RLS is being used, an
administrator may wish to set BYPASSRLS on roles which this role is
GRANTed to.
All privileges without using predefined roles (any Postgres version)
Commands must be executed while connected to the right database. Make sure of it.
The role needs (at least) the USAGE privilege on the schema. Again, if that's granted to PUBLIC, you are covered. Else:
GRANT USAGE ON SCHEMA public TO my_user;
Or grant USAGE on all custom schemas:
DO
$$
BEGIN
-- RAISE NOTICE '%', ( -- use instead of EXECUTE to see generated commands
EXECUTE (
SELECT string_agg(format('GRANT USAGE ON SCHEMA %I TO my_user', nspname), '; ')
FROM pg_namespace
WHERE nspname <> 'information_schema' -- exclude information schema and ...
AND nspname NOT LIKE 'pg\_%' -- ... system schemas
);
END
$$;
Then, all permissions for all tables (requires Postgres 9.0 or later).
And don't forget sequences (if any):
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO my_user;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO my_user;
Alternatively, you could use the "Grant Wizard" of pgAdmin 4 to work with a GUI.
This covers privileges for existing objects. To also cover future objects, set DEFAULT PRIVILEGES. See:
Grant privileges for a particular database in PostgreSQL
How to manage DEFAULT PRIVILEGES for USERs on a DATABASE vs SCHEMA?
There are some other objects, the manual for GRANT has the complete list. As of Postgres 14:
privileges on a database object (table, column, view, foreign table, sequence, database, foreign-data wrapper, foreign server, function, procedure, procedural language, schema, or tablespace)
But the rest is rarely needed. More details:
Grant privileges for a particular database in PostgreSQL
How to grant all privileges on views to arbitrary user
Consider upgrading to a current version.
GRANT ALL PRIVILEGES ON DATABASE "my_db" to my_user;
In PostgreSQL 9.0+ you would do the following:
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA MY_SCHEMA TO MY_GROUP;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA MY_SCHEMA TO MY_GROUP;
If you want to enable this for newly created relations too, then set the default permissions:
ALTER DEFAULT PRIVILEGES IN SCHEMA MY_SCHEMA
GRANT ALL PRIVILEGES ON TABLES TO MY_GROUP;
ALTER DEFAULT PRIVILEGES IN SCHEMA MY_SCHEMA
GRANT ALL PRIVILEGES ON SEQUENCES TO MY_GROUP;
However, seeing that you use 8.1 you have to code it yourself:
CREATE FUNCTION grant_all_in_schema (schname name, grant_to name) RETURNS integer AS $$
DECLARE
rel RECORD;
BEGIN
FOR rel IN
SELECT c.relname
FROM pg_class c
JOIN pg_namespace s ON c.namespace = s.oid
WHERE s.nspname = schname
LOOP
EXECUTE 'GRANT ALL PRIVILEGES ON ' || quote_ident(schname) || '.' || rel.relname || ' TO ' || quote_ident(grant_to);
END LOOP;
RETURN 1;
END; $$ LANGUAGE plpgsql STRICT;
REVOKE ALL ON FUNCTION grant_all_in_schema(name, name) FROM PUBLIC;
This will set the privileges on all relations: tables, views, indexes, sequences, etc. If you want to restrict that, filter on pg_class.relkind. See the pg_class docs for details.
You should run this function as superuser and as regular as your application requires. An option would be to package this in a cron job that executes every day or every hour.
I did the following to add a role 'eSumit' on PostgreSQL 9.4.15 database and provide all permission to this role :
CREATE ROLE eSumit;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO eSumit;
GRANT ALL PRIVILEGES ON DATABASE "postgres" to eSumit;
ALTER USER eSumit WITH SUPERUSER;
Also checked the pg_table enteries via :
select * from pg_roles;
Database queries snapshot :
In PostgreSQL 12 and later, it is possible to grant all privileges of a table in a database to a role/user/account.
The syntax is:
GRANT ALL ON table_name TO role_name;
If you want to grant it to all tables in the database then the syntax will be:
GRANT ALL ON ALL TABLES TO role_name;
If you want to grant it to all tables of a schema in the database then the syntax will be:
GRANT ALL ON ALL TABLES IN SCHEMA schema_name TO role_name;
Note: Remember you will need to select the database before you can grant its privileges to a user.
Resources: PostgreSQL GRANT
That's all
I hope this helps
GRANT USAGE ON SCHEMA schema_name TO user;
GRANT ALL ON SCHEMA schema_name TO user_name;
Give all permissions to a user on a PostgreSQL database:
Command:
grant all privileges on database [database_name] to [database_user_name];
Example:
grant all privileges on database studentdb to shaifullah;
OR
GRANT ALL PRIVILEGES ON DATABASE studentdb TO shaifullah;

How to create a read-only user in PostgreSQL?

I want to create a read-only user in PostgreSQL.
The intention is to have a publicly accessible data explorer, where users can write custom SQL queries.
I do this to create the user:
CREATE USER MyReadOnlyUser WITH ENCRYPTED PASSWORD 'MY_WEAK_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE "MY_DB_NAME" to MyReadOnlyUser;
GRANT ALL ON SCHEMA public TO MyReadOnlyUser;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO MyReadOnlyUser;
The intention is to give the user SELECT access to all tables, then revoke select access on the sensitive tables, and then the user can run custom queries with that db user, without any need for me to sanitize input.
Especially, he may not:
insert, delete, truncate, drop table, drop database, create table, create function/procedure, see/execute/create/drop stored procedure / functions. etc.
Sooo - now my question:
Why does this user have access to information_schema ?
It wasn't granted access to any views, and not to the schema information_schema either...
Why does this user have access to information_schema
I think select privilege is granted to PUBLIC by default on information_schema.
You should be able to do:
revoke all on all tables in schema information_schema from public;
You probably also need to revoke the select privilege on views/tables in the pg_catalog schema. But I'm not sure what this will break if e.g. psql or other client tools cannot access that information.