Granting local user permissions to a foreign db table in postgres - postgresql

I set up a connection to a foreign db using dblink_connect according to the docs:
CREATE SERVER fdtest FOREIGN DATA WRAPPER dblink_fdw OPTIONS (hostaddr '127.0.0.1', dbname 'foreign_test_db');
CREATE USER test_user WITH PASSWORD 'secret';
CREATE USER MAPPING FOR test_user SERVER fdtest OPTIONS (user 'test_user', password 'secret');
GRANT USAGE ON FOREIGN SERVER fdtest TO regress_dblink_user;
GRANT SELECT ON TABLE foo TO test_user;
\c - regress_dblink_user
SELECT dblink_connect('myconn', 'fdtest');
SELECT * FROM dblink('myconn','SELECT * FROM foo') AS t(a int, b text, c text[]);
The final 'GRANT SELECT' appears to infer that if it is meant to grant select permissions to local user test_user to the table foo on the fdtest foreign data wrapper. However, how I would interpret this command is that it is granting permissions to test_user to select on local table foo (which does not exist). As expected, when I run this command I get an error:
ERROR: relation "foo" does not exist
I would love to know how to actually accomplish this. I would like to be able to restrict local users to only access certain tables from a foreign data wrapper.

You'll have to connect to the remote database and run the GRANT statement there.
Of course you could do that via dblink, but then you'd have to connect with a superuser or the owner of the table.

The connection they show is a loop back connection, it just connects back to the same server and (apparently) database you are already in. This is useful for testing purposes. So granting the permission on the local server is the same thing as granting it on the remote server, as they are the same server.
They do not show the creation of the table, you can find it in the regression test contrib/dblink/sql/dblink.sql (from which the example in the doc derives) as:
CREATE TABLE foo(f1 int, f2 text, f3 text[], primary key (f1,f2));

Related

Setting privileges on foreign table on Postgres

How do foreign table privileges work? A simple example where both source_db and destination_db are Postgres databases.
source_db:
-- create user for user mapping
CREATE USER fdw_user WITH PASSWORD 'secret';
-- create table
CREATE TABLE data (value TEXT);
-- set privileges
GRANT ALL ON TABLE data TO fdw_user;
destination_db:
-- create extension
CREATE EXTENSION postgres_fdw;
-- create server
CREATE SERVER remote_source
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'source.domain.com', dbname 'source_db');
-- create user mapping
CREATE USER MAPPING
FOR PUBLIC
SERVER remote_source
OPTIONS (user 'fdw_user', password 'secret');
-- create foreign table
CREATE FOREIGN TABLE data_from_source(value TEXT)
SERVER remote_source
OPTIONS (table_name 'data');
Now setting privileges for any user in destination_db seems to have no effect, like
GRANT SELECT ON TABLE data_from_source TO localuser;
How can I set privileges on foreign table?
The problem was PgAdmin III. ACL of foreign table changed but PgAdmin did not show it. Psql on command line \dp+ data_from_source shows the ACL as expected.

GCLOUD Postgres, using foreign data wrapper extesion results permission denied for relation

I'm really stuck with the following problem.
At GCloud SQL I have a running postgres' instance.
That instance contains two databases. From one database (source_db) I want to access to another database's (another_db) table (foreign_table) using postgres_fdw extension. The recipe I'm employing currently is this:
1)
CREATE EXTENSION postgres_fdw;
CREATE SERVER foreign_db
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (dbname 'another_db', port '5432', host '<A_PRIVATE_IP>');
CREATE USER MAPPING for guest
SERVER foreign_db
OPTIONS (user 'guest', password 's3cr3t');
CREATE FOREIGN TABLE foreign_table
(
// columns descripions
)
SERVER foreign_db OPTIONS (table_name 'foreign_table');
-- Alternatively I also tried with
CREATE SCHEMA external;
IMPORT FOREIGN SCHEMA public from SERVER foreign_db into external;
GRANT SELECT ON TABLE foreign_table TO guest;
The above commands runs without error, but when I tried to actually access the table I got this:
If using "external" schema
source_db=> select 1 from external.foreign_table limit 1;
ERROR: permission denied for relation foreign_table
CONTEXT: Remote SQL command: SELECT NULL FROM public.foreign_table (*)
If not using "external" schema
source_db=> select 1 from foreign_table limit 1;
ERROR: permission denied for relation foreign_table
CONTEXT: Remote SQL command: SELECT NULL FROM public.foreign_table
The only thing that smells a little is that the error message (at *) displays "public.foreign_table" instead of "external.foreign_table" even when I'm using external schema... but i don't know is that actually means something :S
As far I researched there is no way to login into the posgres instance as a superuser as that is not allowed by the Gcloud's SQL services neither a way to edit the pg_hba.conf file in order to adjust client's authentication affairs.
I searched in a lot of places but without finding what i can do to sort this out. Among the sites and pages i looked are the below list
The official documentation
A personal blog's post
This other SO post having a related issue
This post and this other post regarding permissions and authorizations.
A Nice tutorial about authentication and authorization
P.S.
I was able to make this on a postgres' instance that i ran locally.
User guest on the remote server doesn't have permissions to SELECT from the table. Since the query on the remote server is executed as user guest, you get an error.
GRANT the SELECT privilege on the table on the remote server to the user.

PostgreSql user did not find any relations

I am trying to setup database permissions in the following manner.
1. The postgres user will be the owner of postgres and only responsible to create database and roles
2. Create a schema for the database and the make the user app_root the schema and table owner
3. Create a user api_user that will only have DML access
Here are the commands that I have executed. I do not want the apiuser to have any more privileges than SELECT/INSERT/UPDATE/DELETE and ONLY on the schema disclosures. Both app_root user and api_user should not have any public schema access.
But when I login to the database as api_user, I get a Permission Denied. I am unable to figure out:
How to grant the minimum set per permissions to the api_user
How to ensure that these permissions hold true for any new tables created
in future
Here are the commands that I've used to setup the db, schema, table and users.
Switch to user postgres and connect to database
~$ sudo su postgres
~$ psql
Create new user and database
-- Create the schema owner
CREATE USER app_root WITH PASSWORD 'approot';
-- Create database
CREATE DATABASE apps;
-- Connect to the apps database
\connect apps;
-- Create new schema for the apps
CREATE SCHEMA apps AUTHORIZATION app_root;
-- Remove ability for all users to do everything in public schema
REVOKE ALL ON SCHEMA public FROM public;
-- Ensure users can list down objects in public schema
GRANT USAGE ON SCHEMA public TO public;
Disconnect the database and now connect as the app_root user that we created to perform table operations on the database and schema.
~$ psql -hlocalhost -Uapp_root -dapps -W
(enter your database user password to login)
-- Create a table for contacts in the apps schema
CREATE TABLE apps.contacts
(
id serial,
customer_code text,
contact_name text,
contact_email text,
contact_phone text
);
-- Insert some sample data into the table
INSERT INTO apps.contacts(customer_code, contact_name, contact_email, contact_phone) VALUES('apollo', 'John Doe', 'jdoe#apollo.com', '536-847-5857');
INSERT INTO apps.contacts(customer_code, contact_name, contact_email, contact_phone) VALUES('apollo', 'David Brown', 'dbrown#apollo.com', '254-457-8452');
INSERT INTO apps.contacts(customer_code, contact_name, contact_email, contact_phone) VALUES('ryndall', 'Mary Miller', 'mmiller#ryndall.com', '235-654-7845');
INSERT INTO apps.contacts(customer_code, contact_name, contact_email, contact_phone) VALUES('ryndall', 'Tommy Smith', 'tsmith#ryndall.com', '854-965-6514');
Connect to the database using postgres user and create a new DB user with only DML (SELECT/INSERT/UPDATE/DELETE) privileges.
CREATE USER api_user WITH PASSWORD 'apiuser';
\connect apps;
GRANT USAGE ON SCHEMA apps TO api_user;
You need to grant explicitely privileges on schema tables (usage on schema is not enough):
For example:
grant all privileges on all tables in schema apps to api_user;

Cannot access foreign table using Postgres FDW

I had a foreign table set up in Postgres 10. The role "role1" has been granted usage on the foreign server (fs) that was set up using the postgres superuser.
I imported the table using the import schema command:
IMPORT FOREIGN SCHEMA f_schema LIMIT TO (my_fdw_table) FROM fs INTO ls;
That worked fine.
However, when I try to query the table I get the following error:
SELECT * FROM my_fdw_table LIMIT 1;
ERROR: permission denied for view my_fdw_table
CONTEXT: remote SQL command: ...
My understanding is that FDW should treat views and tables the same.
It looks like the remote user that you used in the user mapping for your local user and the foreign server does not have the required permissions on the table (or the schema that contains it).
User "role1" should create user mapping for itself like:
CREATE USER MAPPING FOR role1 SERVER fs OPTIONS (USER 'role1', PASSWORD 'password1');
IMPORT FOREIGN SCHEMA f_schema LIMIT TO (my_fdw_table) FROM SERVER fs INTO ls;
Also, if "role1" is not an owner of the database, it should get access from its owner:
GRANT USAGE ON SCHEMA ls TO role1;
Assuming ls is local schema.

No privilege for this operation

Extracted code from documentation,
create table sales_catalog(
item_id varchar(10) not null primary key,
item_name_desc varchar(50) not null,
item_desc varchar(50));
Error after using SYSDBA as the user in Firebird SQL3.
Statement failed, SQLSTATE = 42000
unsuccessful metadata update
CREATE TABLE SALES_CATALOG failed
There is no privilege for this operation.
I did some experimenting, and the problem seems to be that if you connect to a database using ISQL without specifying a host name, it will use Firebird embedded to connect to the database (previous versions of Firebird didn't do that on Windows).
Firebird embedded does not require a username and password as it assumes that if you have direct read/write access to the database, that you are allowed to connect to it.
When you connect without specifying a username and password (eg using connect 'database.fdb' instead of connect 'database.fdb' user sysdba, Firebird embedded will use your OS username to connect.
This can be checked because ISQL reports the username when connecting:
SQL> connect 'd:\data\db\fb3\dbofnormal.fdb';
Database: 'd:\data\db\fb3\dbofnormal.fdb', User: MARK
Firebird 3 added new metadata privileges, for example creating a table in a database now requires that you are either the owner of the database (the username used in the create database statement), sysdba (or another admin user), or that you have the create table privilege. See also User Privileges for Metadata Changes. In earlier version any user would be allowed to create tables once they had access to the database.
Now on to the problem: the user (in my example MARK), does not have the create table privilege, so attempting to do so will fail:
SQL> create table testmark ( id integer generated by default as identity primary key);
Statement failed, SQLSTATE = 42000
unsuccessful metadata update
-CREATE TABLE TESTMARK failed
-There is no privilege for this operation
There are a few ways to solve this:
Specify a user with sufficient privileges in the connect statement (eg sysdba):
connect 'database.fdb' user sysdba;
Include the host name in the connect statement to connect through Firebird server instead of Firebird embedded, so that you are required to specify user name and password:
connect 'localhost:database.fdb' user sysdba password 'masterkey';
Connect once to your database as sysdba (see first item), and give the necessary privileges to the user (in my case mark):
grant create table to user mark;
From this moment forward this user can create tables (you may need to grant additional privileges, eg create view, create procedure, etc).