Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable SSL connection #152

Closed
wants to merge 11 commits into from
Closed

Enable SSL connection #152

wants to merge 11 commits into from

Conversation

adrienkohlbecker
Copy link

Hello,

This PR adds a new configuration $POSTGRES_ENABLE_SSL which:

  • Automatically generates an SSL keypair on init using OpenSSL
  • Forces the use of an SSL connection to connect to Postgres

Best

@mmarzantowicz
Copy link
Contributor

What about listening port? Is it still 5432 for SSL connections?

Also what happens if someone passes -e 'POSTGRES_ENABLE_SSL=NO' to docker run? To my knowledge if evaluates to true in that case which might be not so clear for users. Maybe better try to check for some finite set of true equivalents like yes, true, y (cases insensitive)?

@adrienkohlbecker
Copy link
Author

Yes the port is the same. From http://www.postgresql.org/docs/current/static/ssl-tcp.html

The server will listen for both normal and SSL connections on the same TCP port, and will negotiate with any connecting client on whether to use SSL.

Then it's the switch from host to hostssl in pg_hba.conf which forces the SSL connection.

I've added support for case-insensitive no, n, false, f and 0. I prefer to handle negation explicitly since the variable is named ENABLE

@adrienkohlbecker
Copy link
Author

It's now using the default paths for the SSL keys since 9.1 does not allow changing them

@mmarzantowicz
Copy link
Contributor

What do you think @tianon and/or @yosifkit ?

@hazcod
Copy link

hazcod commented May 27, 2016

Any news on this?

@tianon
Copy link
Member

tianon commented Jul 6, 2016

I'm +1 on being able to somehow use hostssl instead of host, but I'm very wary of us generating the certificates. Do you have any ideas for clean ways to reconcile that?

@yosifkit
Copy link
Member

yosifkit commented Jul 7, 2016

Agree that we should not generate ssl files. I actually got this working with a simple bash script and certs in docker-entrypoint-initdb.d:

#!/bin/bash
set -e

# this line is not actually required since "host records match either SSL or non-SSL connection attempts"
#sed -i 's/host/hostssl/g' "$PGDATA"/pg_hba.conf

cp /docker-entrypoint-initdb.d/server.{crt,key} "$PGDATA"
chown postgres:postgres "$PGDATA"/server.{crt,key}
chmod 0600 "$PGDATA"/server.key

Then I ran postgres with ssl on (-l):

docker run -it --rm -v $PWD/certs/:/docker-entrypoint-initdb.d/ --name pg postgres -l

@hazcod hazcod mentioned this pull request Jul 7, 2016
@adrienkohlbecker
Copy link
Author

adrienkohlbecker commented Jul 8, 2016

Thanks for the review!

I can provide an option to mount the certs as a volume for use in production environments, but I still think a simpler solution would be interesting for development environments. As a developper, I don't want to have or know how to setup SSL certs when working, but I do want to test my app with SSL enabled.

Would a batteries included but removable approach work for you here?

@adrienkohlbecker
Copy link
Author

Regarding @yosifkit comment on host vs hostssl: As a developper, if I choose to enable SSL it means I expect to connect to postgres with SSL, thus I would expect an error if that's not the case. If we leave host then a silent connection to postgres without SSL is allowed.

@mmarzantowicz
Copy link
Contributor

@adrienkohlbecker do you mean another config option for embedded SSL certs? Maybe it'd be better to create ssl certs on startup if non are provided in mounted volume? This will allow developers to just enable dummy certs. On production deployments admins could use specific certificates provided on run time.

@adrienkohlbecker
Copy link
Author

Yes I meant automatically generating certificates if none are mounted.
On Jul 8, 2016 7:36 PM, "Mateusz Marzantowicz" [email protected]
wrote:

@adrienkohlbecker https://github.com/adrienkohlbecker do you mean
another config option for embedded SSL certs? Maybe it'd be better to
create ssl certs on startup if non are provided in mounted volume? This
will allow developers to just enable dummy certs. On production deployments
admins could use specific certificates provided on run time.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#152 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AAETRXfHz4gPCbeomb2MysdEw2zttpA_ks5qToqagaJpZM4IXDx9
.

@joaocc
Copy link

joaocc commented Jul 22, 2016

@adrienkohlbecker: Have you thought of using the "snakeoil" certs installed by the "ssl-cert" package?

apt-get update
apt-get install -y ssl-cert
find /etc/ssl

It seems to be easier using an existing OS-level package to generate the self-signed certificates.

@adrienkohlbecker
Copy link
Author

PR rebased on the latest master.

  • Added support for 9.6
  • Use the ssl-cert package instead of generating the cert ourselves
  • Allow mounting production certificates (+warning when none are mounted)

@adrienkohlbecker
Copy link
Author

One issue I can think of is with the ssl-cert package, the snakeoil cert is generated during apt-get install and is baked into the image. So everybody will have the same cert

@joaocc
Copy link

joaocc commented Jul 22, 2016

@adrienkohlbecker: well spotted... suggestion below to be run on docker-entrypoint.sh

make-ssl-cert generate-default-snakeoil --force-overwrite

@adrienkohlbecker
Copy link
Author

Thanks, added 👍

@adrienkohlbecker
Copy link
Author

Any updates on this?

@yosifkit
Copy link
Member

Looking back on my previous comment, I was able to get ssl working with only a 6 line bash script (if you keep the sed that fixes hostssl in the pg_hba.conf file). So my thought is that we don't really need to add complexity to the image when it is accomplished through such a simple script. If desired, we could add this to the docs so that other users could find it easier.

@adrienkohlbecker
Copy link
Author

Fair enough, I'm closing the PR.
Thanks for taking the time to review and discuss!

msakrejda pushed a commit to heroku/heroku-pg that referenced this pull request Dec 7, 2017
All `PG*` environment variables can be overridden when using `pg:pull`
or `pg:push` since #97, except `PGSSLMODE`, probably because there was
no obvious use case to let users decide to insecurely bypass SSL.

But when using a PostgreSQL server in Docker Comnpose using the
official Postgres image, it's usually hosted on a different
container than the user app and can be reached through Docker virtual
network, and thus (rightously) considered remote.

Unfortunately, the official Postgres image does not support SSL.

It seems like a use case where it is safe to bypass SSL, even though
the server is considered remote. And it might be a growing use case
since even the official Postgres image do not intend to support SSL:
docker-library/postgres#152

Thus I'd love to be able to use `pg:pull` from my app container to
load a database in a PG server in another container 😍
jdx pushed a commit to heroku/cli that referenced this pull request Jun 19, 2018
All `PG*` environment variables can be overridden when using `pg:pull`
or `pg:push` since #97, except `PGSSLMODE`, probably because there was
no obvious use case to let users decide to insecurely bypass SSL.

But when using a PostgreSQL server in Docker Comnpose using the
official Postgres image, it's usually hosted on a different
container than the user app and can be reached through Docker virtual
network, and thus (rightously) considered remote.

Unfortunately, the official Postgres image does not support SSL.

It seems like a use case where it is safe to bypass SSL, even though
the server is considered remote. And it might be a growing use case
since even the official Postgres image do not intend to support SSL:
docker-library/postgres#152

Thus I'd love to be able to use `pg:pull` from my app container to
load a database in a PG server in another container 😍
@vlsi
Copy link

vlsi commented Feb 13, 2020

@yosifkit , sorry for pinging you, however, it looks your script does not work for the latest postgresql image (I don't know if it worked before :-( )

Here's what I do:

docker run -it --rm --name pgdb -p 5432:5432\
 -v $(pwd)/.github/workflows/init-user-db.sh:/docker-entrypoint-initdb.d/init-user-db.sh\
 -v $(pwd)/certdir/server:/home/certdir\
 -e "POSTGRES_USER=postgres" -e "POSTGRES_PASSWORD=" -e "POSTGRES_DB=postgres" -e GITHUB_ACTIONS=true\
 postgres:latest \
 -c 'hba_file=/home/certdir/pg_hba_all_client_hosts.conf' \
 -c 'ssl=on' \
 -c 'ssl_cert_file=/home/certdir/server.crt' \
 -c 'ssl_key_file=/home/certdir/server.key' \
 -c 'ssl_ca_file=/home/certdir/root.crt' \
 -c 'max_prepared_transactions=64'

My init-user-db.sh looks as follows:

#!/bin/bash
set -e

echo test test
...

Log output looks as follows (note: test test is not there!).

creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... Etc/UTC
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

initdb: warning: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    pg_ctl -D /var/lib/postgresql/data -l logfile start

waiting for server to start....2020-02-13 19:10:28.457 UTC [47] FATAL:  private key file "/home/certdir/server.key" has group or world access
2020-02-13 19:10:28.457 UTC [47] DETAIL:  File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.
2020-02-13 19:10:28.457 UTC [47] LOG:  database system is shut down
 stopped waiting
pg_ctl: could not start server
Examine the log output.

The problem with SSL keys is PostgreSQL requires the keys to have 600 permissions.
However, docker-entrypoint-initdb.d/... scripts are executed after the database is started :(

Do you think yet another set of init scripts can be added and executed before the DB is even launched?

I guess the culprit is

docker_temp_server_start "$@"
docker_setup_db
docker_process_init_files /docker-entrypoint-initdb.d/*

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants