I have a PostgreSQL database. I create new READ-ONLY users as follows:
$ sudo -upostgres psql postgres
postgres=# CREATE ROLE readonly;
postgres=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
postgres=# BEGIN;
postgres=# CREATE ROLE "<PUT_READONLY_USERNAME_HERE>" WITH LOGIN ENCRYPTED PASSWORD '<USE_A_NICE_STRONG_PASSWORD_PLEASE' IN ROLE readonly;
postgres=# COMMIT;
Also I have a table "is_admin" where I manually add new users (it happens really rarely). If it is read-only user users.is_admin = false and if it is user with all priveleges users.is_admin = true.
users.oid users.is_admin (bool)
1 true
2 false
3 false
... ...
Then in code I check if user is admin or not with this query:
SELECT users.is_admin
FROM users.users
JOIN pg_authid ON pg_authid.oid = users.oid::oid
WHERE rolname = "PUT_ROLNAME";
So, the main question is how to automatically add new users to "is_admin" table? I read that trigger or smth like that can help me (for example, trigger ON CREATE ROLE).
You can't create triggers on administrative change, like create role.
But I think you don't need is_admin column at all. You can simply use
select pg_has_role('username', 'rolename', 'MEMBER');
to determine if user has some role or not.
Related
Logged in as the superuser, how can I grant user access to a specific table under a specific schema.
I tried this
GRANT SELECT on TABLE this_schema.my_table TO my_user
But when I login as my_user I can't select from the table. I don't want my_user to have access to any other tables in this_schema.
Is this possible?
Yes its possible.
You can use following command, to give select access of specific table to specific user.
GRANT SELECT on SCHEMA_NAME.TABLE_NAME TO USER_NAME;
NOTE: user still list and describe other tables in the given schema.
You need to grant usage on the schema as well
GRANT USAGE ON SCHEMA this_schema TO GROUP my_user;
Without creating user group, you can do:
GRANT SELECT ON TABLE my_table IN SCHEMA this_schema TO my_user;
I created a read only user in PostgreSQL using the command line by:
CREATE USER xyz WITH ENCRYPTED PASSWORD 'xxx';
GRANT SELECT ON DATABASE mydb TO xyz;
In order to delete this user, what's the difference between
DROP USER xyz;
and
DROP ROLE xyz;
There is no difference. From the docs:
DROP USER is simply an alternate spelling of DROP ROLE.
I have very simple db (PostgreSQL)
And i created one role: manage
command: CREATE ROLE manage WITH NOSUPERUSER NOCREATEDB LOGIN;
Then, I executed
set role postgres;
GRANT SELECT ON public.orders TO manage;
SET ROLE manage;
SELECT * FROM orders;
But, when I try to execute:
select * from orders
I see empty output
But, in that table, there are some rows:
Here is the output using the role postgres.
I want give right to read to "manage" role.
Two possibilities:
There are two tables with the same name in different schemas
Row level security is active on the table.
I am having a slight problem getting permissions to work the way I want them.
I have a role that should generally be allowed to SELECT everywhere, there are a bunch of members to this role. One of them should NOT be allowed to select from a certain table.
I thought this would be possible by granting role membership to the general reader role and revoking SELECT from the restricted table.
It seems the the permissions of the parent role apply and not the specific permissions. Is there a way around this without having to maintain the permissions of the more restricted role or am I applying the role concept in PostgreSQL in a wrong way?
Here's a sample script:
-- as superuser
CREATE DATABASE permission_test;
\c permission_test
CREATE ROLE r_general_select;
CREATE ROLE r_restricted_select IN ROLE r_general_select;
-- set the default permissions
ALTER DEFAULT PRIVILEGES IN SCHEMA "public" GRANT SELECT ON TABLES TO "r_general_select";
CREATE TABLE "open"(
id SERIAL,
payload TEXT
);
insert into "open"(payload) values ('test');
-- covered by default privileges
GRANT SELECT ON "open" TO PUBLIC;
-- Tests
-- this is good
SET ROLE r_general_select;
SELECT * FROM "open";
RESET ROLE;
-- this is good
SET ROLE r_restricted_select;
SELECT * FROM "open";
RESET ROLE;
CREATE TABLE "restricted" (
id SERIAL,
payload TEXT
);
insert into "restricted"(payload) values ('test');
-- the role and it's members should be able to read
GRANT SELECT ON "restricted" TO r_general_select;
-- except for this one!
REVOKE SELECT ON "restricted" FROM r_restricted_select;
-- Tests
-- this is good
SET ROLE r_general_select;
SELECT * FROM restricted;
RESET ROLE;
-- this should barf with a permission violation
SET ROLE r_restricted_select;
SELECT * FROM restricted;
RESET ROLE;
--- CLEANUP
DROP OWNED BY "r_restricted_select" CASCADE;
DROP ROLE r_restricted_select ;
DROP OWNED BY "r_general_select" CASCADE;
DROP ROLE r_general_select ;
In PostgreSQL, role permissions are purely additive. There is no way in such a model to revoke from a descendant, inheriting role a permission granted on the inherited one.
To fix this you need to change your permissions approach and base it on permissions that always occur together. I usually do this by looking at functional dependencies and operational dependencies together.
From http://www.postgresql.org/docs/9.1/static/sql-grant.html:
USAGE
...
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. ...
...
However, running the following script through psql seems to show that although the lack of a SELECT permission causes an error, lack on an EXECUTE permission does not, which contradicts the documentation as the 'own privilege requirement' is not met.
CREATE DATABASE testdb WITH OWNER postgres ENCODING 'UTF8';
\connect testdb
CREATE ROLE testrole;
CREATE SCHEMA testschema;
GRANT USAGE ON SCHEMA testschema TO testrole;
SET search_path TO testschema;
CREATE FUNCTION testfunc ()
RETURNS VOID
AS $$
BEGIN
RAISE NOTICE 'IN TESTFUNC';
RAISE NOTICE 'Current user: %', current_user;
END;
$$
LANGUAGE plpgsql;
CREATE TABLE testtable
(
testrow INT
);
INSERT INTO testtable (testrow) VALUES (1), (2), (3);
SET ROLE testrole;
SELECT testfunc();
SELECT * FROM testtable;
RESET ROLE;
Output:
$ psql -f usage.sql
CREATE DATABASE
You are now connected to database "testdb" as user "postgres".
CREATE ROLE
CREATE SCHEMA
GRANT
SET
CREATE FUNCTION
CREATE TABLE
INSERT 0 3
SET
psql:usage.sql:27: NOTICE: IN TESTFUNC
psql:usage.sql:27: NOTICE: Current user: testrole
testfunc
----------
(1 row)
psql:usage.sql:28: ERROR: permission denied for relation testtable
RESET
Have I missed something or am using the permissions incorrectly?
The schema is not what matters here, what you're seeing is the default execute permissions of functions.
Consider this excerpt from the CREATE FUNCTION documentation:
Another point to keep in mind is that by default, execute privilege is
granted to PUBLIC for newly created functions (see GRANT for more
information). Frequently you will wish to restrict use of a security
definer function to only some users. To do that, you must revoke the
default PUBLIC privileges and then grant execute privilege
selectively.