0003-Enable-cluster-encryption-during-initdb.patch
application/octet-stream
Filename: 0003-Enable-cluster-encryption-during-initdb.patch
Type: application/octet-stream
Part: 3
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0003
Subject: Enable cluster encryption during initdb.
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 14 | 0 |
| src/backend/bootstrap/bootstrap.c | 8 | 1 |
| src/backend/utils/misc/guc.c | 33 | 1 |
| src/backend/utils/misc/postgresql.conf.sample | 5 | 0 |
| src/bin/initdb/initdb.c | 72 | 3 |
| src/bin/pg_controldata/pg_controldata.c | 18 | 0 |
| src/include/access/xlog.h | 1 | 0 |
| src/include/catalog/pg_control.h | 3 | 0 |
| src/include/utils/guc_tables.h | 1 | 0 |
From ab9351f83a711acb33656962214dd14d05ee7307 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Thu, 15 Aug 2019 13:11:30 +0900
Subject: [PATCH 3/5] Enable cluster encryption during initdb.
---
src/backend/access/transam/xlog.c | 14 +++++
src/backend/bootstrap/bootstrap.c | 9 +++-
src/backend/utils/misc/guc.c | 34 +++++++++++-
src/backend/utils/misc/postgresql.conf.sample | 5 ++
src/bin/initdb/initdb.c | 75 +++++++++++++++++++++++++--
src/bin/pg_controldata/pg_controldata.c | 18 +++++++
src/include/access/xlog.h | 1 +
src/include/catalog/pg_control.h | 3 ++
src/include/utils/guc_tables.h | 1 +
9 files changed, 155 insertions(+), 5 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 5cc2a40..0040e77 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -55,6 +55,7 @@
#include "replication/walreceiver.h"
#include "replication/walsender.h"
#include "storage/bufmgr.h"
+#include "storage/encryption.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/kmgr.h"
@@ -78,6 +79,7 @@
#include "pg_trace.h"
extern uint32 bootstrap_data_checksum_version;
+extern uint32 bootstrap_data_encryption_cipher;
/* Unsupported old recovery command file names (relative to $PGDATA) */
#define RECOVERY_COMMAND_FILE "recovery.conf"
@@ -4784,6 +4786,10 @@ ReadControlFile(void)
/* Make the initdb settings visible as GUC variables, too */
SetConfigOption("data_checksums", DataChecksumsEnabled() ? "yes" : "no",
PGC_INTERNAL, PGC_S_OVERRIDE);
+
+ SetConfigOption("data_encryption_cipher",
+ EncryptionCipherString(GetDataEncryptionCipher()),
+ PGC_INTERNAL, PGC_S_OVERRIDE);
}
/*
@@ -4826,6 +4832,13 @@ DataChecksumsEnabled(void)
return (ControlFile->data_checksum_version > 0);
}
+int
+GetDataEncryptionCipher(void)
+{
+ Assert(ControlFile != NULL);
+ return ControlFile->data_encryption_cipher;
+}
+
/*
* Returns a fake LSN for unlogged relations.
*
@@ -5255,6 +5268,7 @@ BootStrapXLOG(void)
ControlFile->wal_log_hints = wal_log_hints;
ControlFile->track_commit_timestamp = track_commit_timestamp;
ControlFile->data_checksum_version = bootstrap_data_checksum_version;
+ ControlFile->data_encryption_cipher = bootstrap_data_encryption_cipher;
/* some additional ControlFile fields are set in WriteControlFile() */
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 9238fbe..3882228 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -40,6 +40,8 @@
#include "storage/bufmgr.h"
#include "storage/bufpage.h"
#include "storage/condition_variable.h"
+#include "storage/encryption.h"
+#include "storage/kmgr.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "tcop/tcopprot.h"
@@ -51,6 +53,7 @@
#include "utils/relmapper.h"
uint32 bootstrap_data_checksum_version = 0; /* No checksum */
+uint32 bootstrap_data_encryption_cipher = 0; /* No encryption */
#define ALLOC(t, c) \
@@ -226,7 +229,7 @@ AuxiliaryProcessMain(int argc, char *argv[])
/* If no -x argument, we are a CheckerProcess */
MyAuxProcType = CheckerProcess;
- while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:x:X:-:")) != -1)
+ while ((flag = getopt(argc, argv, "B:c:d:D:e:Fkr:x:X:-:")) != -1)
{
switch (flag)
{
@@ -249,6 +252,10 @@ AuxiliaryProcessMain(int argc, char *argv[])
pfree(debugstr);
}
break;
+
+ case 'e':
+ bootstrap_data_encryption_cipher = EncryptionCipherValue(optarg);
+ break;
case 'F':
SetConfigOption("fsync", "false", PGC_POSTMASTER, PGC_S_ARGV);
break;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index eb78522..53e056e 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -71,7 +71,9 @@
#include "replication/walreceiver.h"
#include "replication/walsender.h"
#include "storage/bufmgr.h"
+#include "storage/encryption.h"
#include "storage/dsm_impl.h"
+#include "storage/kmgr.h"
#include "storage/standby.h"
#include "storage/fd.h"
#include "storage/large_object.h"
@@ -457,6 +459,13 @@ const struct config_enum_entry ssl_protocol_versions_info[] = {
{NULL, 0, false}
};
+const struct config_enum_entry data_encryption_cipher_options[] = {
+ {"off", TDE_ENCRYPTION_OFF, false},
+ {"aes-128", TDE_ENCRYPTION_AES_128, false},
+ {"aes-256", TDE_ENCRYPTION_AES_256, false},
+ {NULL, 0, false}
+};
+
static struct config_enum_entry shared_memory_options[] = {
#ifndef WIN32
{"sysv", SHMEM_TYPE_SYSV, false},
@@ -4108,7 +4117,7 @@ static struct config_string ConfigureNamesString[] =
{"ssl_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
gettext_noop("Sets the list of allowed SSL ciphers."),
NULL,
- GUC_SUPERUSER_ONLY
+ GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&SSLCipherSuites,
#ifdef USE_OPENSSL
@@ -4156,6 +4165,16 @@ static struct config_string ConfigureNamesString[] =
},
{
+ {"cluster_passphrase_command", PGC_POSTMASTER, ENCRYPTION,
+ gettext_noop("Command to obtain passphrases for database encryption."),
+ NULL
+ },
+ &cluster_passphrase_command,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
{"application_name", PGC_USERSET, LOGGING_WHAT,
gettext_noop("Sets the application name to be reported in statistics and logs."),
NULL,
@@ -4537,6 +4556,19 @@ static struct config_enum ConfigureNamesEnum[] =
NULL, NULL, NULL
},
+ {
+ {"data_encryption_cipher", PGC_INTERNAL, PRESET_OPTIONS,
+ gettext_noop("Specify encryption algorithms to use."),
+ NULL,
+ GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE,
+ GUC_SUPERUSER_ONLY
+ },
+ &data_encryption_cipher,
+ TDE_ENCRYPTION_AES_128,
+ data_encryption_cipher_options,
+ NULL, NULL, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 65a6da1..723c984 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -600,6 +600,11 @@
# autovacuum, -1 means use
# vacuum_cost_limit
+#------------------------------------------------------------------------------
+# ENCRYPTION
+#------------------------------------------------------------------------------
+
+#cluster_passphrase_command = ''
#------------------------------------------------------------------------------
# CLIENT CONNECTION DEFAULTS
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 88a261d..613e050 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -114,6 +114,12 @@ static const char *const auth_methods_local[] = {
NULL
};
+static const char *const encryption_ciphers[] = {
+ "aes-128",
+ "aes-256",
+ NULL
+};
+
/*
* these values are passed in by makefile defines
*/
@@ -145,6 +151,8 @@ static bool data_checksums = false;
static char *xlog_dir = NULL;
static char *str_wal_segment_size_mb = NULL;
static int wal_segment_size_mb;
+static char *enc_cipher = NULL;
+static char *cluster_passphrase = NULL;
/* internal vars */
@@ -1208,6 +1216,13 @@ setup_config(void)
"password_encryption = scram-sha-256");
}
+ if (cluster_passphrase)
+ {
+ snprintf(repltok, sizeof(repltok), "cluster_passphrase_command = '%s'",
+ escape_quotes(cluster_passphrase));
+ conflines = replace_token(conflines, "#cluster_passphrase_command = ''", repltok);
+ }
+
/*
* If group access has been enabled for the cluster then it makes sense to
* ensure that the log files also allow group access. Otherwise a backup
@@ -1421,14 +1436,15 @@ bootstrap_template1(void)
unsetenv("PGCLIENTENCODING");
snprintf(cmd, sizeof(cmd),
- "\"%s\" --boot -x1 -X %u %s %s %s",
+ "\"%s\" --boot -x1 -X %u %s %s %s %s %s",
backend_exec,
wal_segment_size_mb * (1024 * 1024),
data_checksums ? "-k" : "",
+ enc_cipher ? "-e" : "",
+ enc_cipher ? enc_cipher : "",
boot_options,
debug ? "-d 5" : "");
-
PG_CMD_OPEN;
for (line = bki_lines; *line != NULL; line++)
@@ -2351,6 +2367,9 @@ usage(const char *progname)
printf(_(" --wal-segsize=SIZE size of WAL segments, in megabytes\n"));
printf(_("\nLess commonly used options:\n"));
printf(_(" -d, --debug generate lots of debugging output\n"));
+ printf(_(" -e --enc-cipher=MODE set encryption cipher for data encryption\n"));
+ printf(_(" -c --cluster-passphrase-command=COMMAND\n"
+ " set command to obtain passphrase for data encryption key\n"));
printf(_(" -k, --data-checksums use data page checksums\n"));
printf(_(" -L DIRECTORY where to find the input files\n"));
printf(_(" -n, --no-clean do not clean up after errors\n"));
@@ -2416,6 +2435,41 @@ check_need_password(const char *authmethodlocal, const char *authmethodhost)
}
}
+static void
+check_encryption_cipher(const char *cipher, const char *passphrase,
+ const char *const *valid_ciphers)
+{
+ const char *const *p;
+
+ if (!cipher && !passphrase)
+ return;
+
+#ifndef USE_OPENSSL
+ pg_log_error("cluster encryption is not supported because OpenSSL is not supported by this build");
+#endif
+
+ /* Check both options must be specified at the same time */
+ if (cipher && !passphrase)
+ {
+ pg_log_error("encryption passphrase command must be specified when encryption cipher is specified");
+ exit(1);
+ }
+
+ if (!cipher && passphrase)
+ {
+ pg_log_error("encryption cipher must be specified when encryption passphrase command is specified");
+ exit(1);
+ }
+
+ for (p = valid_ciphers; *p; p++)
+ {
+ if (strcmp(cipher, *p) == 0)
+ return;
+ }
+
+ pg_log_error("invalid encryption cipher \"%s\"", cipher);
+ exit(1);
+}
void
setup_pgdata(void)
@@ -3029,6 +3083,8 @@ main(int argc, char *argv[])
{"wal-segsize", required_argument, NULL, 12},
{"data-checksums", no_argument, NULL, 'k'},
{"allow-group-access", no_argument, NULL, 'g'},
+ {"enc-cipher", required_argument, NULL, 'e'},
+ {"cluster-passphrase-command", required_argument, NULL, 'c'},
{NULL, 0, NULL, 0}
};
@@ -3070,7 +3126,7 @@ main(int argc, char *argv[])
/* process command-line options */
- while ((c = getopt_long(argc, argv, "dD:E:kL:nNU:WA:sST:X:g", long_options, &option_index)) != -1)
+ while ((c = getopt_long(argc, argv, "c:dD:E:e:kL:nNU:WA:sST:X:g", long_options, &option_index)) != -1)
{
switch (c)
{
@@ -3152,6 +3208,12 @@ main(int argc, char *argv[])
case 9:
pwfilename = pg_strdup(optarg);
break;
+ case 'e':
+ enc_cipher = pg_strdup(optarg);
+ break;
+ case 'c':
+ cluster_passphrase = pg_strdup(optarg);
+ break;
case 's':
show_setting = true;
break;
@@ -3230,6 +3292,8 @@ main(int argc, char *argv[])
check_need_password(authmethodlocal, authmethodhost);
+ check_encryption_cipher(enc_cipher, cluster_passphrase, encryption_ciphers);
+
/* set wal segment size */
if (str_wal_segment_size_mb == NULL)
wal_segment_size_mb = (DEFAULT_XLOG_SEG_SIZE) / (1024 * 1024);
@@ -3289,6 +3353,11 @@ main(int argc, char *argv[])
else
printf(_("Data page checksums are disabled.\n"));
+ if (enc_cipher)
+ printf(_("Data encryption using %s is enabled.\n"), enc_cipher);
+ else
+ printf(_("Data encryption is disabled.\n"));
+
if (pwprompt || pwfilename)
get_su_pwd();
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index ff17804..a1cd638 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -26,6 +26,7 @@
#include "catalog/pg_control.h"
#include "common/controldata_utils.h"
#include "common/logging.h"
+#include "storage/encryption.h"
#include "pg_getopt.h"
#include "getopt_long.h"
@@ -84,6 +85,21 @@ wal_level_str(WalLevel wal_level)
return _("unrecognized wal_level");
}
+static const char *
+encryption_cipher_str(int val)
+{
+ switch (val)
+ {
+ case TDE_ENCRYPTION_OFF:
+ return "off";
+ case TDE_ENCRYPTION_AES_128:
+ return "aes-128";
+ case TDE_ENCRYPTION_AES_256:
+ return "aes-256";
+ }
+
+ return _("unrecognized encryption cipher");
+}
int
main(int argc, char *argv[])
@@ -336,5 +352,7 @@ main(int argc, char *argv[])
ControlFile->data_checksum_version);
printf(_("Mock authentication nonce: %s\n"),
mock_auth_nonce_str);
+ printf(_("Data encryption cipher: %s\n"),
+ encryption_cipher_str(ControlFile->data_encryption_cipher));
return 0;
}
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index d519252..2c260db 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -294,6 +294,7 @@ extern void UpdateControlFile(void);
extern uint64 GetSystemIdentifier(void);
extern char *GetMockAuthenticationNonce(void);
extern bool DataChecksumsEnabled(void);
+extern int GetDataEncryptionCipher(void);
extern XLogRecPtr GetFakeLSNForUnloggedRel(void);
extern Size XLOGShmemSize(void);
extern void XLOGShmemInit(void);
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index ff98d9e..9d05d45 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -221,6 +221,9 @@ typedef struct ControlFileData
/* Are data pages protected by checksums? Zero if no checksum version */
uint32 data_checksum_version;
+ /* Are data pages and WAL encrypted? Zero if encryption is disabled */
+ uint32 data_encryption_cipher;
+
/*
* Random nonce, used in authentication requests that need to proceed
* based on values that are cluster-unique, like a SASL exchange that
diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h
index d68976f..c1ae129 100644
--- a/src/include/utils/guc_tables.h
+++ b/src/include/utils/guc_tables.h
@@ -89,6 +89,7 @@ enum config_group
STATS,
STATS_MONITORING,
STATS_COLLECTOR,
+ ENCRYPTION,
AUTOVACUUM,
CLIENT_CONN,
CLIENT_CONN_STATEMENT,
--
2.10.5