Schema created in Docker by postgres user does not exist - postgresql

I am building a Docker container for my PostgresSQL 9.4.5 database and I'd like to create the table structures when the container starts. In the script included in my /docker-entrypoint-initdb.d/ directory is this series of commands:
#!/usr/bin/env bash
export PGUSER=postgres
echo "***CREATING DATABASE, USERS, AND ROLES***"
psql <<-EOSQL
CREATE USER vpager WITH PASSWORD '<pass>';
CREATE DATABASE vpager;
GRANT ALL PRIVILEGES ON DATABASE vpager TO vpager;
REVOKE ALL ON DATABASE vpager FROM PUBLIC;
CREATE ROLE standarduser;
CREATE USER vpageruser WITH PASSWORD '<pass>';
\connect vpager
CREATE SCHEMA ticketing;
GRANT ALL PRIVILEGES ON SCHEMA ticketing TO vpager;
GRANT CONNECT ON DATABASE vpager TO standarduser;
GRANT SELECT, UPDATE, INSERT, DELETE ON ALL TABLES IN SCHEMA ticketing TO standarduser;
GRANT standarduser TO vpageruser;
EOSQL
echo "***CREATING TABLE STRUCTURES***"
psql -U vpager vpager < /docker-entrypoint-initdb.d/create-vpager-tables.sql
The SQL script:
CREATE TABLE ticketing.merchant
(
merchant_id SERIAL PRIMARY KEY,
now_serving INT
);
CREATE TABLE ticketing.ticket
(
ticket_id SERIAL,
merchant_id INT REFERENCES ticketing.merchant(merchant_id),
create_ts TIMESTAMP,
PRIMARY KEY (ticket_id, merchant_id)
);
As you can see, the idea is to create a non-privileged user for doing CRUD operations. The problem is that when the create-vpager-tables.sql command runs, it can't see the schema that postgres created:
ERROR: schema "ticketing" does not exist
STATEMENT: CREATE TABLE ticketing.merchant
(
merchant_id SERIAL PRIMARY KEY,
now_serving INT
);
ERROR: schema "ticketing" does not exist
ERROR: schema "ticketing" does not exist
Yet, if I add a CREATE SCHEMA statement to the top of create-vpager-tables.sql, it says it already exists:
ERROR: schema "ticketing" already exists
How do I resolve these errors? I tried setting my search path at the top of the SQL file, but the same thing happened; it's like a "Schrodinger" schema.

I figured it out. I put the create-vpager-tables.sql in the /docker-entrypoint-initdb.d directory, and apparently the image also tries to source SQL files there. Moving it to /tmp (and granting USAGE on the schema to standarduser) fixed the problem.

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.

Granting local user permissions to a foreign db table in postgres

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));

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.

PostgreSQL to Oracle - Can i change OWNER in Oracle?

I am trying to edit PostgreSQL schema script and make it executable in Oracle (Oracle Express). In PostgreSQL were under the each CREAT TABLE these commands:
ALTER TABLE table_name OWNER TO user;
For example table_name is appuser and user is projectX.
The table is successfully created, but there is an error: ORA-01735: invalid ALTER TABLE option
I have also created another user in my scheme (projectX), but the error is still there. So I am confused. Does this command ALTER TABLE table_name OWNER TO user; even exists in Oracle database?