Postgres not following search_path to locate tables - postgresql

I'm not sure the exact point at which this starting happening ( I believe it may have been after launching pgadmin3 for the first time ). Basically this seemed to happen all of a sudden and everything seems to be configured correctly..
PostgreSQL seems to no longer be following the search_path to locate my tables.
\d
No relations found.
My search path has been set (persistently at that):
SHOW search_path;
"public, myschema1, myschema2"
(1 row)
Not only am I the owner of the tables in question, I have run:
GRANT ALL ON SCHEMA public to myusername;
GRANT ALL ON SCHEMA myschema1 to myusername;
GRANT ALL ON SCHEMA myschema2 to myusername;
The data is all there. I can see the schemas when running a \dn. I can also run queries if I fully qualify the schema and table names. The biggest issue is that already created functions that reference an unqualified table name won't work.
Can anyone think of something I might not have tried? Any thoughts as to what caused this issue to start happening?
Thanks for any help!
-hightech

Probably you entered search_path as one string
postgres=# set search_path to public, s1;
SET
postgres=# show search_path ;
search_path
-------------
public, s1
(1 row)
postgres=# set search_path to 'public, s1';
SET
postgres=# show search_path ;
search_path
--------------
"public, s1"
(1 row)
second setting is wrong and doesn't work.

I fixed a similar issue by GRANTing that user USAGE ON SCHEMA, logged on as the OWNER on that schema. Let me develop:
User story: I could reproduce this strange behaviour with Postgres 9.6, see console output below. How bizarre was that? I could \dt preprod.users, but \dt only will not issue anything! I could also SELECT on these tables, which was really confusing me.
(In search_path, note the space after the comma, automatically adjusted by PostgreSQL)
do_preprod=> -- I'm logged on as preprod_www_ro, a read-only user who belongs to readonly ROLE.
do_preprod=> SET search_path TO preprod,public;
SET
do_preprod=> SHOW search_path;
search_path
-----------------
preprod, public
(1 row)
do_preprod=> \dt
Did not find any relations.
do_preprod=> \dt users;
Did not find any relation named "users".
do_preprod=> \dt preprod.users;
List of relations
Schema | Name | Type | Owner
---------+-------+-------+-------------
preprod | users | table | preprod_www
(1 row)
Then, logged on as preprod_www (= schema owner), I GRANTed the readonly ROLE (preprod_www_ro's) the USAGE privilege.
do_preprod=> GRANT USAGE ON SCHEMA preprod TO readonly;
Then, back as preprod_www_ro, I could immediately see the relations with \dt, enjoying fully my search_path, without having to log out log back in.
I would have liked a clearer message from PostgreSQL in the first place, when issuing \dt, or \dt preprod.users: "No USAGE ON SCHEMA granted..." or something like that, as in fact that user COULD use it...but not entirely smoothly.

Related

Unable to drop user because I cannot revoke default priviliges in Redshift

I am having issues with dropping a user becauase it has default privileges, but I am as well unable to revoke those privileges.
To reproduce my issue:
-- executed with master user redshift_master
CREATE USER anton_test_user PASSWORD '***' IN GROUP redshift_dev;
Then using anton_test_user
CREATE SCHEMA anton_test_schema;
CREATE TABLE anton_test_schema.anton_test_table AS SELECT 1 AS anton;
ALTER DEFAULT PRIVILEGES IN SCHEMA anton_test_schema
GRANT SELECT ON TABLES TO GROUP redshift_readonly;
Again with redshift_master
ALTER SCHEMA anton_test_schema OWNER TO redshift_master;
ALTER TABLE anton_test_schema.anton_test_table OWNER TO redshift_master;
Now trying to drop the user it complains about default privileges:
DROP USER anton_test_user;
Result as expected:
owner of default privileges on new relations belonging to user
anton_test_user in schema anton_test_schema;
Now to the weird part, still with redshift_master
ALTER DEFAULT PRIVILEGES FOR USER anton_test_user IN SCHEMA anton_test_schema
REVOKE ALL ON TABLES FROM redshift_readonly;
Gives Invalid operation: permission denied for schema anton_test_schema. What?
If running with anton_test_user
ALTER DEFAULT PRIVILEGES IN SCHEMA anton_test_schema
REVOKE ALL ON TABLES FROM redshift_readonly;
As well gives Invalid operation: permission denied for schema anton_test_schema.
The only way for me to solve this and being able to drop anton_test_user was to, with redshift_master drop the schema and table completely
DROP TABLE anton_test_schema.anton_test_table;
DROP SCHEMA anton_test_schema;
DROP USER anton_test_user; -- it works now
Transfering ownership back to anton_test_user and then revoking default privileges did not help - dropping the table and schema was the only solution I could find.
My completely uninformed guess is that anton_test_user had lost permissions to the schema, so no grants for the user could be applied or revoked in that schema.
Question(s):
Is there any way to avoid dropping anton_test_schema and anton_test_table while also dropping anton_test_user?
Is it supposed to work this way?
Do Postgres behave in the same way?
This is a bit of a follow up to a question already asked, to which I gave an answer - but I have no idea what is going on even though I came up with a "solution" ("" because dropping objects was a solution, albeit a pretty poor one). It might be that I have completely misunderstood user privileges in Redshift as well.
The original question is not completely the same as this - and I would like to know what is going on, so it is not really a repost even though it might look like it.
I had the same issue myself. I was able to avoid dropping the user/schema by first re-granting access of the schema to my end user (my version of anton_test_user).
grant all on schema analyst_data to anton_test_user;
After doing so, I was able to run my alter default privileges command
ALTER DEFAULT PRIVILEGES for user <user> in schema <schema> REVOKE ALL on tables FROM group <group>;
Your uninformed guess was spot on 😀

Set deafult schema while querying in pgAdmin 4 with query tool

Whenever i have to execute sql commands in pgAdmin 4 i have to append schema_name with tables.
Eg :-
SELECT * FROM my_schema.users //where myschema is schema name
ORDER BY id ASC
Is there any way to execute sql commands in pgAdmin 4 without schema name, by setting a default schema in advance.
Some thing like this
SELECT * FROM programme
ORDER BY id ASC
- without specifying schema name with table.
Is there a way to set default schema in pgAdmin 4 for querying in sql tool?
You can do it in 2 ways:
SET search_path = my_schema, "$user", public; -- For current session only
ALTER ROLE your_role SET search_path = my_schema, "$user", public; -- Persistent, for role
You can also set it for whole database, same way as for role.
EDIT: Just to explain what this does - it will change where and in what order Postgres will search for objects matching object identifiers that did not get prefixed with schema name.
You might need also to restart pgAdmin4 in order for the search_path to start working. At least it was my case.
A good double check if the search_path was set in pgAdmin4 is to go to:
Login/Group Roles -> Right click on the user (by default it is 'postgres') -> Properties -> Parameters tab. Here you should see your new parameter 'search_path' with the value 'your_schema_name'.

Postgres query fails without schema

THis doesn't work, resulting in ERROR: relation "user" does not exist
select * from "user"
This one does
select * from "dbo"."user"
Tables that aren't schema-qualified are searched for on the search_path. This doesn't search every schema. By default it only searches:
pg_catalog (implicitly always first, not listed on search_path)
pg_temp tablespaces (implicit, not listed on search_path)
A schema named after the current user, listed as $user in search_path
The public schema
If you want PostgreSQL to look elsewhere you have to modify the search_path to tell it so, or fully schema-qualify the name.
See the PostgreSQL manual on search_path.
Also, note that unlike some databases the name dbo has no particular significance in PostgreSQL. It's just another name.

PostgreSQL Revoking Permissions from pg_catalog tables

Is there a way I can revoke permissions from a user to the catalog objects (i.e. information_schema) and PostgreSQL tables (i.e. pg_catalog)? I've tried several things and scoured the net. I'm not having any luck. The only thing I read that is partially helpful is I may not want to remove "public" from the system tables in case user defined functions rely on an object in one of those schemas. The commands below are a small snap shot of what I have not gotten to work with the exception of a single table.
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM PUBLIC; -- didn't work
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM public; -- didn't work
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM user1; -- didn't work
REVOKE SELECT ON pg_catalog.pg_roles FROM user1; -- worked
REVOKE SELECT ON pg_catalog.pg_database FROM user1; -- didn't work
REVOKE ALL PRIVILEGES ON SCHEMA pg_catalog FROM g_users; -- didn't work
REVOKE SELECT ON pg_catalog.pg_database FROM g_users; -- didn't work
Any ideas? Or is this just not possible? Thanks...
Leslie
let me help you about this:
1st: because the pg_catalog is owned by the superuser postgres, so make sure you login to the server with this role:
pg_catalog schema permission
2nd: make sure you connect to the right database that needs to GRANT/REVOKE permissions on. GRANT/REVOKE only affect to the current database that you connected to. That means after you login with superuser account, issue: \c [the db] to connect to that database, the shell will change to: [the db]=>
3rd: tables in pg_catalog defaults granted SELECT to PUBLIC: tables in pg_catalog. So, you have to run REVOKE SELECT FROM PUBLIC and then GRANT SELECT to appropriate users:
REVOKE SELECT ON ALL TABLES IN SCHEMA pg_catalog FROM PUBLIC;
GRANT SELECT ON TABLE [table] TO [user];
For list tables in a database: pg_class and pg_namespace.
And that's all :)
What you are trying to accomplish is denied in PostgreSQL by design.
If a user could not access pg_catalog schema (as you try to do with REVOKE commands), he/she would not be able to run even simplest SELECT query - planner would have no access to table definitions.
Your goal might be achieved by REVOKE'ing access to all schemas - hence locking user only in his private schema (with CREATE SCHEMA AUTHORIZATION username).
If any rights are already GRANT'ed to public, you cannot block them selectively for one user - you can only REVOKE ... FROM public.
Relevant documentation:
Creating a Schema
Schemas and Privileges

PostgreSQL: making a schema restricted/unchangable?

We like our production environment with a restricted/unchangable schema -- the development side can be owned by the developers and changed as they like -- and we like to vet changes as they are promoted.
I'm wondering if this may be a solution to making that happen:
postgres% create proddb with owner=postgres;
unixside% pg_restore --dbname=devdb [--schema-only] --no-owner proddb
/* grants to users on schema objects appear to remain intact */
/* here's the magic, I hope... */
postgres% revoke create on schema public from public;
postgres% grant usage on schema public to produser(s);
Some testing seems to show that a user in this new proddb can interact with tables normally (with appropriate grants) and cannot alter the schema (alter table, create table, drop table, etc). But I'm paranoid and very new to Postgres, so...
Q: Is this correct?
Q: Am I missing anything?
Thanks muchly.
Yes, that is correct. The only addition is that the owner of a table can always delete or modify it. So it may not work if you have existing tables in the schema.
Discovered a missing element: sequences.
The user was finding errors in his scripts; similar errors appeared in the logs:
ERROR: permission denied for sequence <sequence>
The production schema showed that although sequences were created, they were owned by postgres and no explicit grants were given to the users. As per the GRANT documentation:
Granting permission on a table does not automatically extend permissions to any sequences used by the table, including sequences tied to SERIAL columns. Permissions on sequence must be set separately.
Our fix (verbose for this demonstration) was to find all sequences:
unixside% pg_dump --schema-only proddb > proddb.schema
unixside% grep -i 'create sequence' proddb.schema
...and apply appropriate grants (select to prevent table scans, update to prevent the above errors):
postgres% grant select,update on <sequence> to produser(s);
So far, the user says it's working and errors to the log have stopped...
I forget what version PostgreSQL added the syntax, but one of the easiest ways to administer permissions in PostgreSQL is through the "GRANT foo, priv ON ALL something IN SCHEMA" syntax.
BEGIN;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA my_schema TO my_role;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA my_schema TO my_role;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA my_schema TO my_role;
COMMIT;
Very handy for making sure that permissions are always set correctly.
The EXECUTE for FUNCTIONS may seem spooky, but shouldn't be unless your functions were created with the SECURITY DEFINER attribute (and if you are using SECURITY DEFINER, you'd better be cautious since you're playing around with the PostgreSQL version of a "setuid" function). If you space out your TABLES across different SCHEMAS based on the expected permissions, then this becomes a pretty handy convention when used with the search_path variable.
ALTER ROLE my_role SET search_path = my_schema, auth_schema, public;
-- Avoid using the public schema (pretty please)
Where auth_schema has a collection of tables that my_role shouldn't have direct read or write privileges on. Assigning privs to GROUPS is also useful.
Here are some relevant docs:
http://developer.postgresql.org/pgdocs/postgres/sql-grant.html
Don't forget you can use "\h GRANT" in psql to easily figure out the syntax or remember what can be done on all objects in a schema (search for "IN SCHEMA").