From 978f869b992f9fca343e99d6fdb71073c76e869a Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Fri, 25 Dec 2020 10:19:44 -0500 Subject: Add key management system This adds a key management system that stores (currently) two data encryption keys of length 128, 192, or 256 bits. The data keys are AES256 encrypted using a key encryption key, and validated via GCM cipher mode. A command to obtain the key encryption key must be specified at initdb time, and will be run at every database server start. New parameters allow a file descriptor open to the terminal to be passed. pg_upgrade support has also been added. Discussion: https://postgr.es/m/CA+fd4k7q5o6Nc_AaX6BcYM9yqTbC6_pnH-6nSD=54Zp6NBQTCQ@mail.gmail.com Discussion: https://postgr.es/m/20201202213814.GG20285@momjian.us Author: Masahiko Sawada, me, Stephen Frost --- doc/src/sgml/config.sgml | 62 ++++++++++++++++++++++ doc/src/sgml/database-encryption.sgml | 97 +++++++++++++++++++++++++++++++++++ doc/src/sgml/filelist.sgml | 1 + doc/src/sgml/installation.sgml | 5 +- doc/src/sgml/postgres.sgml | 1 + doc/src/sgml/ref/initdb.sgml | 46 +++++++++++++++++ doc/src/sgml/ref/pg_ctl-ref.sgml | 13 +++++ doc/src/sgml/ref/pgupgrade.sgml | 18 ++++++- doc/src/sgml/ref/postgres-ref.sgml | 13 +++++ doc/src/sgml/storage.sgml | 5 ++ 10 files changed, 258 insertions(+), 3 deletions(-) create mode 100644 doc/src/sgml/database-encryption.sgml (limited to 'doc/src') diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 4b60382778f..426928f6800 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -7816,6 +7816,52 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; + + Cluster File Encryption + + + + cluster_key_command (string) + + cluster_key_command configuration parameter + + + + + This option specifies an external command to obtain the cluster-level + key for cluster file encryption during server initialization and + server start. + + + The command must print the cluster key to the standard output as + 64 hexadecimal characters, and exit with code 0. The command + can prompt for the passphrase or PIN from the terminal if + is used. In the parameter value, + %R represents the file descriptor number opened + to the terminal that started the server. A file descriptor is only + available if enabled at server start. If %R + is used and no file descriptor is available, the server will not + start. Value %p is replaced by a pre-defined + prompt string. Value %d is replaced by the + directory containing the keys; this is useful if the command + must create files with the keys, e.g., to store a cluster-level + key encryped by a key stored in a hardware security module. + (Write %% for a literal %.) + Note that the prompt string will probably contain whitespace, + so be sure to quote its use adequately. Newlines are stripped + from the end of the output if present. + + + This parameter can only be set by + initdb, in the + postgresql.conf file, or on the server + command line. + + + + + + Client Connection Defaults @@ -9637,6 +9683,22 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' + + file_encryption_keylen (boolean) + + Cluster file encryption key length + + + + + Reports the bit length of the cluster file + encryption key, or zero if disabled. See for more + information. + + + + data_directory_mode (integer) diff --git a/doc/src/sgml/database-encryption.sgml b/doc/src/sgml/database-encryption.sgml new file mode 100644 index 00000000000..f938c9f574a --- /dev/null +++ b/doc/src/sgml/database-encryption.sgml @@ -0,0 +1,97 @@ + + + + Cluster File Encryption + + + Cluster File Encryption + + + + The purpose of cluster file encryption is to prevent users with read + access to the directories used to store database files and write-ahead + log from being able to access the data stored in those files. + For example, when using cluster file encryption, users who have read + access to the cluster directories for backup purposes will not be able + to decrypt the data stored in the these files. + + + + Cluster file encryption uses two levels of encryption. The first level + is data encryption keys, specifically keys zero and one. Key zero is + the key used to encrypt database heap and index files which are stored in + the file system, plus temporary files created during database operation. + Key one is used to encrypt write-ahead log (WAL) files. Two different + keys are used so that primary and standby servers can use different zero + (heap/index/temp) keys, but the same one (WAL) key, so that these keys + can eventually be rotated by switching the primary to the standby as + and then changing the WAL key. + + + + The second level of encryption is a key used to encrypt first-level + keys. This type of key is often referred to as a Key Encryption Key + (KEK). This key is not stored + in the file system, but provided at initdb time and + each time the server is started. This key prevents anyone with access + to the database directories from decrypting the data because they do + not know the second-level key which encrypted the first-level keys + which encrypted the database cluster files. + + + + Initialization + + + Cluster file encryption is enabled when + PostgreSQL is built + with --with-openssl and is specified + during initdb. The cluster key + provided by the + option during initdb and the one generated + by in the + postgresql.conf must match for the database + cluster to start. Note that the cluster key command + passed to initdb must return a key of + 64 hexadecimal characters. For example. + +initdb -D dbname --cluster-key-command='ckey_passphrase.sh' + + + + + + Internals + + + During the initdb process, if + is specified, two data-level + encryption keys are created. These two keys are then encrypted with + the key enryption key (KEK) supplied by the cluster key command before + being stored in the database directory. The key or passphrase that + derives the key must be supplied from the terminal or stored in a + trusted key store, such as key vault software, hardware security module. + + + + If the PostgreSQL server has + been initialized to require a cluster key, each time the + server starts the postgresql.conf + cluster_key_command command will be executed + and the cluster key retrieved. The data encryption keys in the + pg_cryptokeys directory will then be decrypted + using the supplied key and integrity-checked to ensure it + matches the initdb-supplied key. If this check fails, the + server will refuse to start. + + + + The data encryption keys are randomly generated and are of 128, 192, + or 256-bits in length. They are encrypted by the key encryption key + (KEK) using Advanced Encryption Standard (AES256) + encryption in Galois/Counter Mode (GCM), which also + provides KEK authentication. + + + diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index 38e8aa0bbf9..b96f4ace6cf 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -49,6 +49,7 @@ + diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index 0ac1cb99999..bcc80240498 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -976,8 +976,9 @@ build-postgresql: Build with support for SSL (encrypted) - connections. This requires the OpenSSL - package to be installed. configure will check + connections and cluster file encryption. This requires the + OpenSSL package to be installed. + configure will check for the required header files and libraries to make sure that your OpenSSL installation is sufficient before proceeding. diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index 730d5fdc348..0ea7da604b3 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -171,6 +171,7 @@ break is not needed in a wider output rendering. &wal; &logical-replication; &jit; + &database-encryption; ®ress; diff --git a/doc/src/sgml/ref/initdb.sgml b/doc/src/sgml/ref/initdb.sgml index 385ac251506..44a2d69d326 100644 --- a/doc/src/sgml/ref/initdb.sgml +++ b/doc/src/sgml/ref/initdb.sgml @@ -163,6 +163,17 @@ PostgreSQL documentation + + + + + This option specifies an external command to obtain the cluster-level + key for cluster file encryption during server initialization and + server start; see for details. + + + + @@ -223,6 +234,18 @@ PostgreSQL documentation + + + + + + Specifies the number of bits for the file encryption keys. The + default is 128 bits. + + + + @@ -285,6 +308,17 @@ PostgreSQL documentation + + + + + + Allows the command + to prompt for a passphrase or PIN. + + + + @@ -307,6 +341,18 @@ PostgreSQL documentation + + + + + + Copies cluster file encryption keys from another cluster; required + when using pg_upgrade on a cluster + with cluster file encryption enabled. + + + + diff --git a/doc/src/sgml/ref/pg_ctl-ref.sgml b/doc/src/sgml/ref/pg_ctl-ref.sgml index 3946fa52eab..f04e417745f 100644 --- a/doc/src/sgml/ref/pg_ctl-ref.sgml +++ b/doc/src/sgml/ref/pg_ctl-ref.sgml @@ -38,6 +38,7 @@ PostgreSQL documentation options path + @@ -72,6 +73,7 @@ PostgreSQL documentation seconds options + @@ -373,6 +375,17 @@ PostgreSQL documentation + + + + + + Allows the command + to prompt for a passphrase or PIN. + + + + diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 92e1d09a55c..98be3921cb1 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -167,6 +167,13 @@ PostgreSQL documentation + + + + allows prompting for a passphrase or PIN + + + dir dir @@ -309,7 +316,9 @@ make prefix=/usr/local/pgsql.new install Again, use compatible initdb flags that match the old cluster. Many prebuilt installers do this step automatically. There is no need to - start the new cluster. + start the new cluster. If upgrading a cluster that uses + cluster file encryption, the initdb option + must be specified. @@ -838,6 +847,13 @@ psql --username=postgres --file=script.sql postgres is down. + + If the old cluster uses file encryption, the new cluster must use + the same keys, so pg_upgrade copies them to the + new cluster. It is necessary to initialize the new cluster with + the same cluster_key_command and the same + file encryption key length. + diff --git a/doc/src/sgml/ref/postgres-ref.sgml b/doc/src/sgml/ref/postgres-ref.sgml index 4aaa7abe1a2..805da81e073 100644 --- a/doc/src/sgml/ref/postgres-ref.sgml +++ b/doc/src/sgml/ref/postgres-ref.sgml @@ -297,6 +297,19 @@ PostgreSQL documentation + + + + + Makes postgres prompt for a passphrase or PIN + from the specified open numeric file descriptor. The descriptor + is closed after the key is read. The file descriptor number + -1 duplicates standard error for the terminal; + this is useful for single-user mode. + + + + diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml index 3234adb639f..cdbc214a510 100644 --- a/doc/src/sgml/storage.sgml +++ b/doc/src/sgml/storage.sgml @@ -77,6 +77,11 @@ Item Subdirectory containing transaction commit timestamp data + + pg_cryptokeys + Subdirectory containing file encryption keys + + pg_dynshmem Subdirectory containing files used by the dynamic shared memory -- cgit v1.2.3