Commit c5dff72d authored by Nick Thomas's avatar Nick Thomas

Standardise on self-signed certificates for PostgreSQL TLS

Additionally, assume Omnibus will automatically generate these files if they do
not already exist.
parent 808a87c7
......@@ -79,78 +79,6 @@ will not be able to perform all necessary configuration steps. Refer to
setting in case you have changed `gitlab_replicator` username to something
else.
1. Set up TLS support for the PostgreSQL primary server
> **Warning**: Only skip this step if you **know** that PostgreSQL traffic
> between the primary and secondary will be secured through some other
> means, e.g., a known-safe physical network path or a site-to-site VPN that
> you have configured.
If you are replicating your database across the open Internet, it is
**essential** that the connection is TLS-secured. Correctly configured, this
provides protection against both passive eavesdroppers and active
"man-in-the-middle" attackers.
To do this, PostgreSQL needs to be provided with a key and certificate to
use. There are two options to do this:
**Option A**: Re-use the same files you're using for your main GitLab
instance.
**Option B**: Generate a self-signed certificate just for PostgreSQL's use.
Prefer option A if you already have a long-lived certificate. Prefer
option B if your certificates expire regularly (e.g., Let's Encrypt), or if
PostgreSQL is running on a different server to the main GitLab services
(this may be the case in a HA configuration, for instance).
For **Option A**:
Copy the SSL keys from your existing GitLab installation. If you're
re-using certificates already in GitLab, they are likely to be in the
`/etc/gitlab/ssl` directory. Copy them into the PostgreSQL directory via
this example:
```bash
##
## Certificate and key currently used by GitLab
## - replace primary.geo.example.com with your domain
##
install -o gitlab-psql -g gitlab-psql -m 0400 -T /etc/gitlab/ssl/primary.geo.example.com.crt ~gitlab-psql/data/server.crt
install -o gitlab-psql -g gitlab-psql -m 0400 -T /etc/gitlab/ssl/primary.geo.example.com.key ~gitlab-psql/data/server.key
```
For **Option B**:
To generate a self-signed certificate and key, run this command:
```bash
openssl req -nodes -batch -x509 -newkey rsa:4096 -keyout server.key -out server.crt -days 3650
```
This will create two files - `server.key` and `server.crt` - that you can
use for authentication.
PostgreSQL's permission requirements are very strict, so whether you're
re-using your certificates or just generated new ones, **copy** the files
to the correct location:
```
##
## Self-signed certificate and key
## - assumes the files are in your current working directory
##
install -o gitlab-psql -g gitlab-psql -m 0400 -T server.crt ~gitlab-psql/data/server.crt
install -o gitlab-psql -g gitlab-psql -m 0400 -T server.key ~gitlab-psql/data/server.key
```
1. Add this configuration to `/etc/gitlab/gitlab.rb`. Additional options are
documented [here](http://docs.gitlab.com/omnibus/settings/database.html#enabling-ssl).
```ruby
postgresql['ssl'] = 'on'
```
1. Configure PostgreSQL to listen on network interfaces
For security reasons, PostgreSQL does not listen on any network interfaces
......@@ -280,6 +208,22 @@ will not be able to perform all necessary configuration steps. Refer to
`netstat -plnt` to make sure that PostgreSQL is listening on port `5432` to
the primary server's private address.
1. Make a copy of the PostgreSQL `server.crt` file
A certificate was automatically generated when GitLab was reconfigured. This
will be used automatically to protect your PostgreSQL traffic from
eavesdroppers, but to protect against active ("man-in-the-middle") attackers,
the secondary needs a copy of the certificate.
Run this command:
```
cat ~gitlab-psql/data/server.crt
```
Copy the output into a file on your local computer called `server.crt`. You
will need it when setting up the secondary! The certificate is not sensitive
data.
1. Verify that clock synchronization is enabled.
>**Important:**
......@@ -317,6 +261,12 @@ because we have not yet configured the secondary server. This is the next step.
### Step 3. Configure the secondary server
1. From your **local machine**, copy `server.crt` to the secondary:
```
scp server.crt secondary.geo.example.com:
```
1. SSH into your GitLab **secondary** server and login as root:
```
......@@ -325,52 +275,21 @@ because we have not yet configured the secondary server. This is the next step.
1. Set up PostgreSQL TLS verification on the secondary
If you configured PostgreSQL to accept TLS connections in
[Step 1](#step-1-configure-the-primary-server), then you need to provide a
list of "known-good" certificates to the secondary. It uses this list to
keep the connection secure against an active "man-in-the-middle" attack.
If you reused your existing certificates on the primary, you can use the
list of valid root certificates provided with omnibus.
Or, if you generated a self-signed certificate, copy the generated
`server.crt` file onto the secondary server from the primary, then install
it in the right location.
Install the `server.crt` file:
```bash
##
## Certificate and key currently used by GitLab
##
mkdir -p ~gitlab-psql/.postgresql
ln -s /opt/gitlab/embedded/ssl/certs/cacert.pem ~gitlab-psql/.postgresql/root.crt
```
```bash
##
## Self-signed certificate and key
##
install -o gitlab-psql -g gitlab-psql -m 0400 -T server.crt -D ~gitlab-psql/.postgresql/root.crt
install -D -o gitlab-psql -g gitlab-psql -m 0400 -T server.crt ~gitlab-psql/.postgresql/root.crt
```
PostgreSQL will now only recognize that exact certificate when verifying TLS
connections.
connections. The certificate can only be replicated by someone with access
to the private key, which is **only** present on the primary node.
1. Test that the remote connection to the primary server works (as the
`gitlab-psql` user):
```
##
## Certificate and key currently used by GitLab, and connecting by FQDN
##
sudo -u gitlab-psql /opt/gitlab/embedded/bin/psql -U gitlab_replicator -d "dbname=gitlabhq_production sslmode=verify-full" -W -h primary.geo.example.com
```
```
##
## Self-signed certificate and key, or connecting by IP address
##
sudo -u gitlab-psql /opt/gitlab/embedded/bin/psql -U gitlab_replicator -d "dbname=gitlabhq_production sslmode=verify-ca" -W -h 1.2.3.4
```bash
sudo -u gitlab-psql /opt/gitlab/embedded/bin/psql --list -U gitlab_replicator -d "dbname=gitlabhq_production sslmode=verify-ca" -W -h 1.2.3.4
```
When prompted enter the password you set in the first step for the
......@@ -379,14 +298,8 @@ because we have not yet configured the secondary server. This is the next step.
A failure to connect here indicates that the TLS or networking configuration
is incorrect. Ensure that you've used the correct certificates and IP
addresses / FQDNs throughout. If you have a firewall, ensure that the
secondary is permitted to access the primary on port 5432.
1. Exit the PostgreSQL console:
```
\q
```
addresses throughout. If you have a firewall, ensure that the secondary is
permitted to access the primary on port 5432.
1. Edit `/etc/gitlab/gitlab.rb` and add the following:
......@@ -442,17 +355,7 @@ data before running `pg_basebackup`.
1. Execute the command below to start a backup/restore and begin the replication:
```
##
## Certificate and key currently used by GitLab, and connecting by FQDN
##
gitlab-ctl replicate-geo-database --slot-name=secondary_example --host=primary.geo.example.com
```
```
##
## Self-signed certificate and key, or connecting by IP
##
gitlab-ctl replicate-geo-database --sslmode=verify-ca --slot-name=secondary_example --host=1.2.3.4
gitlab-ctl replicate-geo-database --slot-name=secondary_example --host=1.2.3.4
```
If PostgreSQL is listening on a non-standard port, add `--port=` as well.
......@@ -461,15 +364,9 @@ data before running `pg_basebackup`.
to increase the timeout, e.g., `--backup-timeout=3600` if you expect the
initial replication to take under an hour.
If you have to connect to a specific IP address, rather than the FQDN of the
primary, to reach your PostgreSQL server, then you should pass
`--sslmode=verify-ca` as well. This should **only** be the case if you have
also used a self-signed certificate. `verify-ca` is **not** safe if you are
connecting to an IP address and re-using an existing TLS certificate!
Pass `--sslmode=prefer` if you are happy to skip PostgreSQL TLS
authentication altogether (e.g., you know the network path is secure, or you
are using a site-to-site VPN).
Pass `--sslmode=disable` to skip PostgreSQL TLS authentication altogether
(e.g., you know the network path is secure, or you are using a site-to-site
VPN). This is **not** safe over the public Internet!
You can read more details about each `sslmode` in the
[PostgreSQL documentation](https://www.postgresql.org/docs/9.6/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION);
......
......@@ -75,15 +75,6 @@ The following guide assumes that:
provides protection against both passive eavesdroppers and active
"man-in-the-middle" attackers.
To do this, PostgreSQL needs to be provided with a key and certificate to
use. You can re-use the same files you're using for your main GitLab
instance, or generate a self-signed certificate just for PostgreSQL's use.
Prefer the first option if you already have a long-lived certificate. Prefer
the second if your certificates expire regularly (e.g. LetsEncrypt), or if
PostgreSQL is running on a different server to the main GitLab services
(this may be the case in a HA configuration, for instance).
To generate a self-signed certificate and key, run this command:
```bash
......@@ -93,23 +84,7 @@ The following guide assumes that:
This will create two files - `server.key` and `server.crt` - that you can
use for authentication.
PostgreSQL's permission requirements are very strict, so whether you're
re-using your certificates or just generated new ones, **copy** the files
to the correct location. Do check that the destination path below is
correct!
If you're re-using certificates already in GitLab, they are likely to be in
the `/etc/ssl` directory. If your domain is `primary.geo.example.com`, the
commands would be:
```bash
# Copying a certificate and key currently used by GitLab
install -o postgres -g postgres -m 0400 -T /etc/ssl/certs/primary.geo.example.com.crt ~postgres/9.x/main/data/server.crt
install -o postgres -g postgres -m 0400 -T /etc/ssl/private/primary.geo.example.com.key ~postgres/9.x/main/data/server.key
```
If you just generated a self-signed certificate and key, the files will be
in your current working directory, so run:
Copy them to the correct location for your PostgreSQL installation:
```bash
# Copying a self-signed certificate and key
......@@ -246,40 +221,22 @@ because we have not yet configured the secondary server. This is the next step.
```
1. Set up PostgreSQL TLS verification on the secondary
If you configured PostgreSQL to accept TLS connections in
[Step 1](#step-1-configure-the-primary-server), then you need to provide a
list of "known-good" certificates to the secondary. It uses this list to
keep the connection secure against an active "man-in-the-middle" attack.
If you reused your existing certificates on the primary, you can use the
list of valid root certificates provided with your distribution. For
Debian/Ubuntu, they can be found in `/etc/ssl/certs/ca-certificates.crt`:
```bash
mkdir -p ~postgres/.postgresql
ln -s /etc/ssl/certs/ca-certificates.crt ~postgres/.postgresql/root.crt
```
If you generated a self-signed certificate, that won't work. Copy the
generated `server.crt` file onto the secondary server from the primary, then
install it in the right place:
Copy the generated `server.crt` file onto the secondary server from the
primary, then install it in the right place:
```bash
install -o postgres -g postgres -m 0400 -T server.crt ~postgres/.postgresql/root.crt
install -D -o postgres -g postgres -m 0400 -T server.crt ~postgres/.postgresql/root.crt
```
PostgreSQL will now only recognize that exact certificate when verifying TLS
connections.
connections. The certificate can only be replicated by someone with access
to the private key, which is **only** present on the primary node.
1. Test that the remote connection to the primary server works:
```
# Certificate and key currently used by GitLab, and connecting by FQDN
sudo -u postgres psql -U gitlab_replicator -d "dbname=gitlabhq_production sslmode=verify-ca" -W -h primary.geo.example.com
# Self-signed certificate and key, or connecting by IP address
sudo -u postgres psql -U gitlab_replicator -d "dbname=gitlabhq_production sslmode=verify-ca" -W -h 1.2.3.4
sudo -u postgres psql --list -U gitlab_replicator -d "dbname=gitlabhq_production sslmode=verify-ca" -W -h 1.2.3.4
```
When prompted enter the password you set in the first step for the
......@@ -288,14 +245,8 @@ because we have not yet configured the secondary server. This is the next step.
A failure to connect here indicates that the TLS or networking configuration
is incorrect. Ensure that you've used the correct certificates and IP
addresses / FQDNs throughout. If you have a firewall, ensure that the
secondary is permitted to access the primary on port 5432.
1. Exit the PostgreSQL console:
```
\q
```
addresses throughout. If you have a firewall, ensure that the secondary is
permitted to access the primary on port 5432.
1. Edit `postgresql.conf` to configure the secondary for streaming replication
(for Debian/Ubuntu that would be `/etc/postgresql/9.*/main/postgresql.conf`):
......@@ -446,19 +397,12 @@ data before running `pg_basebackup`.
```
When prompted, enter the IP/FQDN of the primary, and the password you set up
for the `gitlab_replicator` user in the first step. If you are re-using
existing certificates and connecting to an FQDN, use `verify-full` for the
`sslmode`.
If you have to connect to a specific IP address, rather than the FQDN of the
primary, to reach your PostgreSQL server, then you should use `verify-ca`
for the `sslmode` instead. This should **only** be the case if you have
also used a self-signed certificate. `verify-ca` is **not** safe if you are
connecting to an IP address and re-using an existing TLS certificate!
Use `prefer` if you are happy to skip PostgreSQL TLS
authentication altogether (e.g., you know the network path is secure, or you
are using a site-to-site VPN).
for the `gitlab_replicator` user in the first step.
You should use `verify-ca` for the `sslmode`. You can use `disable` if you
are happy to skip PostgreSQL TLS authentication altogether (e.g., you know
the network path is secure, or you are using a site-to-site VPN). This is
**not** safe over the public Internet!
You can read more details about each `sslmode` in the
[PostgreSQL documentation](https://www.postgresql.org/docs/9.6/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment