Actually enable TLS/SSL for old clusters by default

Before this commit clusters created with a version lower than 8.1.0
would not have SSL enabled by default. This changes that to enable it by
default always. The only difference is that old clusters (created before
8.1.0), will have "sslmode=prefer" in their `citus.node_conninfo`
setting. New clusters will have "sslmode=require". These settings are
equivalent from an attackers point of view. They both protect against
passive eavesdropping, but are vulnerable to an active MITM attack.
pull/3638/head
Jelte Fennema 2020-03-21 01:35:41 +01:00
parent 3e980c81e9
commit cc46534797
4 changed files with 62 additions and 33 deletions

View File

@ -5,10 +5,21 @@
CREATE SCHEMA citus;
-- Enable SSL to encrypt all trafic by default
-- Enable SSL to encrypt all traffic by default
-- create temporary UDF that has the power to change settings within postgres and drop it
-- after ssl has been setup.
-- create temporary UDF that has the power to change settings within postgres
-- and drop it after ssl has been setup.
-- This was placed here in version 8.1.0. This means that this code has not
-- been executed for clusters created before 8.1.0. This is a somewhat hacky
-- way to detect that we can safely set sslmode=require for citus.node_conninfo
-- in the upgrade script to 8.1.0. We will do so only if ssl is enabled before
-- running that upgrade script. For upgrades where this is not the case this is
-- not safe, since that probably means not all nodes have SSL setup yet. In
-- that case we would get connection errors with "sslmode=require" during the
-- cluster upgrade. We will later setup SSL anyway in the upgrade script for
-- Citus 9.2.3, but by that time citus.node_conninfo will contain
-- "sslmode=prefer", so upgrades are safe.
CREATE FUNCTION citus_setup_ssl()
RETURNS void
LANGUAGE C STRICT

View File

@ -0,0 +1,37 @@
-- Enable SSL to encrypt all traffic by default
-- create temporary UDF that has the power to change settings within postgres and drop it
-- after ssl has been setup.
-- This exact same function has already been run for clusters that were
-- originally created with Citus 8.1.0 or later. However, this is not the case
-- for clusters originally created with a version before 8.1.0.
-- That's why we run it again here. If SSL is already set up this is a no-op,
-- else this sets up self signed certificates and enables SSL.
-- There will still be a difference between clusters from before 8.1.0 and
-- clusters after 8.1.0. This difference is that for old clusters
-- citus.node_conninfo will be "sslmode=prefer", and for new clusters it will
-- be "sslmode=require".
-- The reason for this difference is that using "sslmode=require" does not
-- allow connections to nodes without SSL at all. So this does not work with
-- clusters where some nodes don't have SSL enabled. A situation like that will
-- happen during rolling upgrades, where part of the cluster has Citus version
-- lower than 8.1.0 and part of it has a higher version. In that case there
-- will be unwanted downtime of the cluster until all nodes have been upgraded.
CREATE FUNCTION citus_setup_ssl()
RETURNS void
LANGUAGE C STRICT
AS 'MODULE_PATHNAME', $$citus_setup_ssl$$;
DO LANGUAGE plpgsql
$$
BEGIN
-- setup ssl when postgres is OpenSSL-enabled
IF current_setting('ssl_ciphers') != 'none' THEN
PERFORM citus_setup_ssl();
END IF;
END;
$$;
DROP FUNCTION citus_setup_ssl();

View File

@ -49,7 +49,6 @@ static void GloballyReloadConfig(void);
#ifdef USE_SSL
/* forward declaration of functions used when compiled with ssl */
static bool ShouldUseAutoSSL(void);
static bool CreateCertificatesWhenNeeded(void);
static EVP_PKEY * GeneratePrivateKey(void);
static X509 * CreateCertificate(EVP_PKEY *privateKey);
@ -73,10 +72,12 @@ citus_setup_ssl(PG_FUNCTION_ARGS)
ereport(WARNING, (errmsg("can not setup ssl on postgres that is not compiled with "
"ssl support")));
#else /* USE_SSL */
if (!EnableSSL && ShouldUseAutoSSL())
if (!EnableSSL)
{
/* Only enable it when it's not already on */
ereport(LOG, (errmsg("citus extension created on postgres without ssl enabled, "
"turning it on during creation of the extension")));
"turning it on now")));
/* execute the alter system statement to enable ssl on within postgres */
Node *enableSSLParseTree = ParseTreeNode(ENABLE_SSL_QUERY);
@ -85,19 +86,20 @@ citus_setup_ssl(PG_FUNCTION_ARGS)
if (strcmp(SSLCipherSuites, POSTGRES_DEFAULT_SSL_CIPHERS) == 0)
{
/*
* postgres default cipher suite is configured, these allow TSL 1 and TLS 1.1,
* citus will upgrade to TLS1.2+HIGH and above.
* postgres default cipher suite is configured, these allow TSL 1
* and TLS 1.1, citus will upgrade to TLS1.2+HIGH and above.
*/
Node *citusSSLCiphersParseTree = ParseTreeNode(SET_CITUS_SSL_CIPHERS_QUERY);
AlterSystemSetConfigFile((AlterSystemStmt *) citusSSLCiphersParseTree);
}
/*
* ssl=on requires that a key and certificate are present, since we have
* enabled ssl mode here chances are the user didn't install credentials already.
* ssl=on requires that a server private key and server certificate are
* present. Since we have enabled ssl mode here, chances are the user
* didn't install credentials already.
*
* This function will check if they are available and if not it will generate a
* self singed certificate.
* This function will check if they are available and if not it will
* generate a private key and a matching self signed certificate.
*/
CreateCertificatesWhenNeeded();
@ -179,27 +181,6 @@ GloballyReloadConfig()
#ifdef USE_SSL
/*
* ShouldUseAutoSSL checks if citus should enable ssl based on the connection settings it
* uses for outward connections. When the outward connection is configured to require ssl
* it assumes the other nodes in the network have the same setting and therefor it will
* automatically enable ssl during installation.
*/
static bool
ShouldUseAutoSSL(void)
{
const char *sslmode = NULL;
sslmode = GetConnParam("sslmode");
if (sslmode != NULL && strcmp(sslmode, "require") == 0)
{
return true;
}
return false;
}
/*
* CreateCertificatesWhenNeeded checks if the certificates exists. When they don't exist
* they will be created. The return value tells whether or not new certificates have been