Postgres: How to verify which certificate is being used for SSL - postgresql

On a Linux host, when I run the command psql --set=sslmode=verify-full -h (rest of connection command...) I connect to my postgres DB successfully. It also print information on the SSL connection cipher when my psql session begins. What confuses me is I can't figure out how the certificate used is being specified as I'm not listing any in my psql command. https://www.postgresql.org/docs/9.2/libpq-connect.html implies it defaults to stuff in a ~/.postgresql folder, but I don't have such a folder currently. I've seen references to environment variables like PGSSLROOTCERT mentioned elsewhere, but I don't have those set.
How do I determine which SSL certificate is being used? If it matters this is for a connection to an AWS RDS database.

psql --set=sslmode=verify-full -h ...
This sets a "psql" variable named sslmode. This variable makes no difference to anything. So you are not actually doing verification of the server's cert.
Try setting sslmode in a supported way, like:
PGSSLMODE=verify-full psql -h ...
or
psql sslmode=verify-full -h ...
(But if you use this last one, then you cannot have a -d option hiding in the ...)

Related

How to Configure postgresql User with SSL connection only?

My steps I did (psql v. 9.3):
create psql user with password
give him access to relevant databases
allow connection from the outside (psql conf)
and put "hostssl all all 0.0.0.0/0 trust" in pg_hba.conf
Do I need to create a key now to be able to connect?
How can I test that key if it works?
Thanks for help.
Read the documentation.
If you didn't do that already, you'll have to configure the PostgreSQL server for SSL: create server.crt and server.key in the PostgreSQL data directory, set ssl = on in postgresql.conf and restart the server.
You don't need a client certificate or key to connect to the server.
To test if your setup works, just connect with psql.
If SSL is used, it will look as follows:
$ psql -d test -h 127.0.0.1
psql (9.3.13)
SSL connection (cipher: DHE-RSA-AES256-GCM-SHA384, bits: 256)
Type "help" for help.
test=#
Change the trust to md5 (EXTREMELY IMPORTANT)
try to connect over psql from another system using different ssl settings (see the psql man page for this).
If you want to require a cert, then there are additional steps to do, but that's not specified in your question. And cert authentication is possible but an advanced topic.

Connect with psql from remote machine to remote postgres database with saved password

I am working on a remote Unix machine where I connect via SSH from my local machine. There is a Postgres database on another host that I need to connect from my remote machine using psql.
I would like to be able to run queries from an input file and save the results to an output file, however I did not manage to automatically set the password, surpassing the need to do it every time I run a query.
I tried the following:
Run
psql "user=username password=password host=hostname port=port dbname=database"`
with my username, password, hostname, port and database values.
This worked OK but I did not find a way to add arguments for input/output files (not needing to go through Postgres interactive environment).
According to another SO question, I created a file ~/.pgpass with the following format: hostname:port:database:username:password
and then chmod 0600 ~/.pgpass but when connecting as: psql -h hostname -U username -d database -w psql ignored this (I got the following failed authentication message.)
psql: fe_sendauth: no password supplied.
Note that my remote machine's name is different than my username, so this might also create a problem when creating the .pgpass file. Is there any other way to do it?
Any ideas?
This worked OK but I did not find a way to add arguments for
input/output files
You can either redirect the input file to psql, or specify it in -f option:
psql < input.sql
psql -f input.sql
As for output file, just redirect psql's output to it:
psql -f input.sql > output.txt

Where to store both passwords for local host and remote server when copying PostgreSQL database

On Windows 7, I try to copy my local database to an already existed empty database on a remote server, so I type the command
pg_dump -h localhost -U postgres -d postgres | psql -h remotehost -U remoteuser -d dbname -W
I've set PGPASSWORD environment variable for my localhost, and I also set password of remote server in C:\Users\Administrator\AppData\Roaming\postgresql\pgpass.conf, but I still have to add -W and type the lengthy password by hand, otherwise I would get a password authentication failure.
What's the relationship between passwords in PGPASSWORD and pgpass.conf? Can I record the lengthy password for remote server in some place so that I don't need to type by hand?
PGPASSWORD overrides pgpass.conf, which is why you're seeing that behavior.
The doc states (emphasis mine):
The file .pgpass in a user's home
directory or the file referenced by PGPASSFILE can contain passwords
to be used if the connection requires a password (and no password
has been specified otherwise).
See the Password File doc for more info.
One option to support both would be to have batch or cmd files wrap the psql commands and set the PGPASSWORD environment variable accordingly, depending on whether it's the local or remote host.
Another would be to keep multiple password files and set the environment variable PGPASSFILE instead. This option is the more secure of the two, since you can set different permissions on the various files, and they aren't directly exposed in a shareable environment variable.
See the Environment Variable doc for more info.
Edit:
And as Richard Huxton mentions in the comment below, both passwords could also be put into the same password file.

psql: FATAL: Peer authentication failed for user "dev"

when i create a new user, but it cannot login the database.
I do that like this:
postgres#Aspire:/home/XXX$ createuser dev
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) y
Shall the new role be allowed to create more new roles? (y/n) y
then create a database:
postgres#Aspire:/home/XXX$ createdb -O dev test_development
after that, I try psql -U dev -W test_development to login, but get the error:
psql: FATAL: Peer authentication failed for user "dev"
I tried to solve the problem but failed.
Try:
psql -U user_name -h 127.0.0.1 -d db_name
where
-U is the database user name
-h is the hostname/IP of the local server, thus avoiding Unix domain sockets
-d is the database name to connect to
This is then evaluated as a "network" connection by Postgresql rather than a Unix domain socket connection, thus not evaluated as a "local" connect as you might see in pg_hba.conf:
local all all peer
Your connection failed because by default psql connects over UNIX sockets using peer authentication, that requires the current UNIX user to have the same user name as psql. So you will have to create the UNIX user dev and then login as dev or use sudo -u dev psql test_development for accessing the database (and psql should not ask for a password).
If you cannot or do not want to create the UNIX user, like if you just want to connect to your database for ad hoc queries, forcing a socket connection using psql --host=localhost --dbname=test_development --username=dev (as pointed out by #meyerson answer) will solve your immediate problem.
But if you intend to force password authentication over Unix sockets instead of the peer method, try changing the following pg_hba.conf* line:
from
# TYPE DATABASE USER ADDRESS METHOD
local all all peer
to
# TYPE DATABASE USER ADDRESS METHOD
local all all md5
peer means it will trust the identity (authenticity) of UNIX user. So not asking for a password.
md5 means it will always ask for a password, and validate it after hashing with MD5.
You can, of course, also create more specific rules for a specific database or user, with some users having peer and others requiring passwords.
After changing pg_hba.conf if PostgreSQL is running you'll need to make it re-read the configuration by reloading (pg_ctl reload) or restarting (sudo service postgresql restart).
* The file pg_hba.conf will most likely be at /etc/postgresql/9.x/main/pg_hba.conf
Edited: Remarks from #Chloe, #JavierEH, #Jonas Eicher, #fccoelho, #Joanis, #Uphill_What comments incorporated into answer.
Peer authentication means that postgres asks the operating system for your login name and uses this for authentication. To login as user "dev" using peer authentication on postgres, you must also be the user "dev" on the operating system.
You can find details to the authentication methods in the Postgresql documentation.
Hint: If no authentication method works anymore, disconnect the server from the network and use method "trust" for "localhost" (and double check that your server is not reachable through the network while method "trust" is enabled).
When you specify:
psql -U user
it connects via UNIX Socket, which by default uses peer authentication, unless specified in pg_hba.conf otherwise.
You can specify:
host database user 127.0.0.1/32 md5
host database user ::1/128 md5
to get TCP/IP connection on loopback interface (both IPv4 and IPv6) for specified database and user.
After changes you have to restart postgres or reload it's configuration.
Restart that should work in modern RHEL/Debian based distros:
service postgresql restart
Reload should work in following way:
pg_ctl reload
but the command may differ depending of PATH configuration - you may have to specify absolute path, which may be different, depending on way the postgres was installed.
Then you can use:
psql -h localhost -U user -d database
to login with that user to specified database over TCP/IP.
md5 stands for encrypted password, while you can also specify password for plain text passwords during authorisation. These 2 options shouldn't be of a great matter as long as database server is only locally accessible, with no network access.
Important note:
Definition order in pg_hba.conf matters - rules are read from top to bottom, like iptables, so you probably want to add proposed rules above the rule:
host all all 127.0.0.1/32 ident
While #flaviodesousa's answer would work, it also makes it mandatory for all users (everyone else) to enter a password.
Sometime it makes sense to keep peer authentication for everyone else, but make an exception for a service user. In that case you would want to add a line to the pg_hba.conf that looks like:
local all some_batch_user md5
I would recommend that you add this line right below the commented header line:
# TYPE DATABASE USER ADDRESS METHOD
local all some_batch_user md5
You will need to restart PostgreSQL using
sudo service postgresql restart
If you're using 9.3, your pg_hba.conf would most likely be:
/etc/postgresql/9.3/main/pg_hba.conf
This works for me when I run into it:
sudo -u username psql
I simply had to add -h localhost
The easiest solution:
CREATE USER dev WITH PASSWORD 'dev';
CREATE DATABASE test_development;
GRANT ALL PRIVILEGES ON DATABASE test_development to dev;
ALTER ROLE dev CREATEROLE CREATEDB;
In my case I was using different port. Default is 5432. I was using 5433. This worked for me:
$ psql -f update_table.sql -d db_name -U db_user_name -h 127.0.0.1 -p 5433
For people in the future seeing this, postgres is in the /usr/lib/postgresql/10/bin on my Ubuntu server.
I added it to the PATH in my .bashrc file, and add this line at the end
PATH=$PATH:/usr/lib/postgresql/10/bin
then on the command line
$> source ./.bashrc
I refreshed my bash environment. Now I can use postgres -D /wherever from any directory
pg_dump -h localhost -U postgres -F c -b -v -f mydb.backup mydb
Try in terminal:
>> psql -U role_name -d database -h hostname.<domain>.com -W

Using psql to connect to PostgreSQL in SSL mode

I am trying to configure ssl certificate for PostgreSQL server. I have created a certificate file (server.crt) and key (server.key) in data directory and update the parameter SSL to "on" to enable secure connection.
I just want only the server to be authenticated with server certificates on the client side and don't require the authenticity of client at server side. I am using psql as a client to connect and execute the commands.
I am using PostgreSQL 8.4 and Linux. I tried with the below command to connect to server with SSL enabled
psql "postgresql://localhost:2345/postgres?sslmode=require"
but I am getting
psql: invalid connection option "postgresql://localhost:2345/postgres?sslmode"
What am doing wrong here? Is the way I am trying to connect to server with SSL mode enabled is correct? Is it fine to authenticate only server and not the client ?
psql below 9.2 does not accept this URL-like syntax for options.
The use of SSL can be driven by the sslmode=value option on the command line or the PGSSLMODE environment variable, but the default being prefer, SSL connections will be tried first automatically without specifying anything.
Example with a conninfo string (updated for psql 8.4)
psql "sslmode=require host=localhost dbname=test"
Read the manual page for more options.
psql --set=sslmode=require -h localhost -p 2345 -U thirunas \
-d postgres -f test_schema.ddl
Another Example for securely connecting to Azure's managed Postgres database:
psql --file=product_data.sql --host=hostname.postgres.database.azure.com --port=5432 \
--username=postgres#postgres-esprit --dbname=product_data \
--set=sslmode=verify-full --set=sslrootcert=/opt/ssl/BaltimoreCyberTrustRoot.crt.pem
Well, you could provide all the information with the following command in CLI, if a connection requires in SSL mode:
psql "sslmode=verify-ca sslrootcert=server-ca.pem sslcert=client-cert.pem sslkey=client-key.pem hostaddr=your_host port=5432 user=your_user dbname=your_db"
Found the following options useful to provide all the files for a self signed postgres instance
psql "host={hostname} sslmode=prefer sslrootcert={ca-cert.pem} sslcert={client-cert.pem} sslkey={client-key.pem} port={port} user={user} dbname={db}"
On psql client v12, I could not find option in psql client to activate sslmode=verify-full.
I ended up using environment variables :
PGSSLMODE=verify-full PGSSLROOTCERT=server-ca.pem psql -h your_host -U your_user -W -d your_db
psql "sslmode=require host=localhost port=2345 dbname=postgres" --username=some_user
According to the postgres psql documentation, only the connection parameters should go in the conninfo string(that's why in our example, --username is not inside that string)
psql -h <host> -p <port> -U <user> -d <db>
and update /var/lib/pgsql/10/data/pg_hba.conf to change the auth method to cert. Check the following link for more information:
https://www.postgresql.org/docs/9.1/auth-pg-hba-conf.html
Another pattern that worked with v8 is
psql -h host_name -p port -U user_name "dbname=db sslmode=require"