====== PostgreSQL: SSL Connections ======
Overview: https://www.postgresql.org/docs/12/ssl-tcp.html
A blog that is likely based on the link above: https://blog.crunchydata.com/blog/ssl-certificate-wauthentication-postgresql-docker-containers
And yet another blog: https://medium.com/@bansal.nidhi/postgresql-authentication-without-password-52dac3d65746
Keywords: postgres sql ssl certificate
===== Encryption-Only Setup =====
The purpose of this mode is to be as lightweight as possible, but **without** actually using certificates.
The setup consists of the server part (1) and the client part (2):
(1) Server setup
In the postgresql.conf, disable 'ssl = off' if present and replace it with:
ssl = on
ssl_cert_file = '/var/lib/postgresql/data/ssl-cert-snakeoil.pem'
ssl_key_file = '/var/lib/postgresql/data/ssl-cert-snakeoil.key'
Both files must be present in mounted folders.
The bogus certificate / private key can be found here:
ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem'
ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'
The path should work for Debian-based systems and might be different otherwise.
HINT: the file permission for the key must be like 600
To prevent non-SSL connections altogether, modify the pg_hba.conf:
hostnossl all all 0.0.0.0/0 reject
hostnossl all all ::/0 reject
This will reject all unencrypted ipv{4,6} connections.
Finally docker restart.
(2) Client support
To use encryption with psycopg2 just use:
conn = psycopg2.connect(db_uri, sslmode='require')
It should be noted that psycopg2 might use sslmode='require' automatically. To verify that you cannot login without SSL, check that the call will //fail//:
conn = psycopg2.connect(db_uri, sslmode='disable')
For asyncpg the setup is almost the same. The option is also named ''%%ssl%%'' and it is also automatically detected, if SSL is required. The negative test is the same as for psycopg2.
HINT: asyncpg 0.22 or newer is required for the auto-ssl mode.
An error looks like this:
asyncpg.exceptions.InvalidAuthorizationSpecificationError: pg_hba.conf rejects connection for host "a.b.c.d", user "docker", database "products", SSL off
AGAIN: **no** certificate-based authentication is performed, but everything, including passwords, is now encrypted. This means everybody with the correct password is allowed to login.
===== Python =====
Work in Progress
Client(!) code: **ssl.Purpose.SERVER_AUTH** forces server authentication
import ssl
ssl_ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile='/path_to_client_root_ca')
ssl_ctx.load_cert_chain('/path_to_client_public_key.pem', '/path_to_client_private_key.pem')
HINT: 'The context is created with secure default values.' .. whatever this means {{/dokuwiki/lib/images/smileys/icon_smile.gif|:-)}}
With asyncpg
connect(, ...)
connect_kwargs: ssl=ssl_ctx
{{/dokuwiki/lib/images/smileys/fixme.gif|FIXME}}: ensure that the server certificate is validated\\
{{/dokuwiki/lib/images/smileys/fixme.gif|FIXME}}: disallow insecure fallbacks\\
{{/dokuwiki/lib/images/smileys/fixme.gif|FIXME}}: need more details
==== References ====
https://docs.python.org/3/library/ssl.html#ssl.CERT_REQUIRED\\
https://magicstack.github.io/asyncpg/current/api/index.html\\
https://www.electricmonk.nl/log/2018/06/02/ssl-tls-client-certificate-verification-with-python-v3-4-sslcontext/\\
https://stackoverflow.com/questions/41701791/aiohttp-and-client-side-ssl-certificates\\
https://www.cybertec-postgresql.com/en/setting-up-ssl-authentication-for-postgresql
Keywords psycopg2 encryption ssl cert