How do I whitelist access to a PostgreSQL schema? - postgresql

I have a certain schema in a PG database that contains some very sensitive data. I'd like to prevent access to it for every role except one, but I can't figure it out from the documentation on permissions.
To begin with, I figured I'd only give CONNECT access to that one special role, but then every other role can connect to the schema. To make things worse, every role can also CREATE, DROP, and do everything else.
What have I missed?
Side question: in time, this schema will be a streaming destination from another instance of postgresql. In short, we have a master db server that supports a live web site, and we need a secondary, read-only copy of it on another machine to perform some computationally intensive queries on. We figured that streaming was the answer. Does this make sense? Is it still possible to protect access to it?
We are using version 9.5, in case this is relevant.

You can edit the file /etc/postgresql/9.5/main/pg_hba.conf and put this content:
# Database administrative login by Unix domain socket
local all postgres peer
# TYPE DATABASE USER ADDRESS METHOD
# IPv4 local connections:
host all YOUR_USER [USER_IP]/32 md5
It will allow connections with a password for this specific user from this specific LAN/WAN IP.
Only this user and postgres will be allowed.
in time, this database will be a streaming destination from another instance of postgresql.
When this database becomes a replication master you can add the following to the same file:
# Allow replication connections from localhost, by a user with the
# replication privilege.
host replication REPL_USER [REPL_HOST]/32 md5
More info on how to set up the replication here: https://www.gab.lc/articles/replication_postgresql
After the changes you need to reload PostgreSQL with:
service postgresql reload
You can drop the roles you don't want to allow.
Update:
If you wish to revoke privileges with a query you can run:
-- Grant privileges to whitelisted user:
GRANT ALL PRIVILEGES ON [database name] TO [good_user];
-- Revoke privileges for other users:
REVOKE ALL PRIVILEGES ON [database name] FROM [bad_user];

Related

Limited access for postgreSQL user

is it possible to create PostgreSQL user so that he can connect and see only one specific database? So that he could only see one database (he couldn't see the others). Ideally, I could also set the visibility of the tables in the database.
I create user like this:
create user user with encrypted password 'password';
GRANT CONNECT ON DATABASE db TO user;
although I have given the user connect privilege to only one database, he can see all other databases :(
By default the connect privilege to every database is granted to the role public, so you need to run:
revoke connect on database ... from public;
for all other databases. Make sure you grant connect back to existing users.
Another option is to restrict connections for this specific user through pg_hba.conf

Create read only user for postgres replica

I've recently implemented streaming replication and need to create a "report user" for the replica. This user will be used to access the database via ODBC to generate reports with.
On the slave (replica DB), It seems I cannot create new users. I also need to change the password of 'postgres' user on the slave. Here's what I've tried and the errors I get:
CREATE ROLE readaccess;
ERROR: cannot execute CREATE ROLE in a read-only transaction
\password postgres
ERROR: cannot execute ALTER ROLE in a read-only transaction
How can I create a new read only user for my replica?
How can I change the password of the user 'postgres' on the replica?
Note: I do realize that for a replica, you can (or should) only have read-only access.
Thank you.
As you have discovered, the replica is read-only anyway. So you have a few choices.
Just use any of your accounts from the primary. They will have the same permissions on the replica (except that they cannot change data).
Create a special user that only has 'select' permissions on the primary, and that user flow through to the replica.
As for having different passwords on the primary and replica, you can't. If that is a hard requirement for you, you'll have to look into "logical replication".

Updated User Permissions Don't Reflect In Replica in Postgres

I have a master-slave configuration of PostgreSQL servers and there are multiple schemas defined in the database. Now both of master and replication servers have a user readonly which initially had only access to the public schema.
I have another schema, let's say alt_schema; and I want to give readonly user access to all it's tables.
Henceforth, I run the following query in master server to provide access of the schema to the user.
GRANT ALL ON ALL TABLES IN SCHEMA alt_schema TO readonly;
The above command successfully provided access of the schema's tables to the user.
But, the permissions are not propagated to the replication server (I waited for about 30 mins expecting there maybe some lag). Since, the automated replication failed, I tried to run the above query manually in the replication server itself, but obviously it gave me the below error:
ERROR: cannot execute GRANT in a read-only transaction
Is there way to achieve the above.
Note: My Postgres Servers are hosted in Google Cloud SQL.

Database named "postgres"

I've just set up Postgres for use by different users on my network. Every user has his own username/password/database, but when I connect to Pg I can also see a 'postgres' database (and even create tables etc). I tried to REVOKE access to that database from public but then it won't let me connect. What exactly is the postgres database and why is it needed? Can I disable it so that users only see the database(s) I've created for them?
The postgres database is created by default when you run initdb.
Quote from the manual:
Creating a database cluster consists of creating the directories in which the database data will live (...) creating the template1 and postgres databases. When you later create a new database, everything in the template1 database is copied. (...) The postgres database is a default database meant for use by users, utilities and third party applications.
There is nothing special about it, and if you don't need it, you can drop it:
drop database postgres;
You need to do that as a superuser of course. The only downside of this is that when you run psql as the postgres operating system user, you need to explicitly provide a database name to connect to
If you drop the postgres database you'll find a few things to be confusing. Most tools default to using it as the default database to connect to, for one thing. Also, anything run under the postgres user will by default expect to connect to the postgres database.
Rather than dropping it, REVOKE the default connect right to it.
REVOKE connect ON DATABASE postgres FROM public;
The superuser (usually postgres), and any users you explicitly grant rights to access the database can still use it as a convenience DB to connect to. But others can't.
To grant connect rights to a user, simply:
GRANT connect ON DATABASE postgres TO myuser;

Postgres accepts any password

I have the following code which connects to a database on my remote server (the connection script resides on the same server):
Database::$ErrorHandle = new PDO('pgsql:host=111.222.33.44;dbname=mydatabase;', 'postgres', 'mypassword', $db_settings);
The problem is I can change the password to be anything at all and the connection is still made! Like seriously what the hell!?!
Can my database be connected to (providing you know the IP and db name) by anyone from a PHP script running on a different server?
How can I enforce passwords, I have looked at the following stack overflow page and did what they said but still no luck:
How to change PostgreSQL user password?
I am running Ubuntu 12.04 server with PHP 5.5 and Apache2
Off course your postgresql database can be properly configured to only connect with authenticated users even certain users (Roles in Postgres) from certain IPs/sockets.
Some considerations:
Do you see data? Or can you just connect to the server? Can you list the databases?
Look at your pg_hba.conf and setup the proper permissions, per role per database per source
Did you grant access to the mydatabase to everyone? Which roles did you grant access?
Does the database have its tables in the public scheme? And granted access to the public?
Yes, with this configuration everyone who knows your IP and database name can connect to your database.