From cc6a1b316952876a7212791a88661499db0af2e5 Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Tue, 26 May 2020 13:48:17 +0900 Subject: [PATCH v11 6/7] Documentation update. --- doc/src/sgml/config.sgml | 47 ++++ doc/src/sgml/database-encryption.sgml | 381 ++++++++++++++++++++++++++ doc/src/sgml/filelist.sgml | 1 + doc/src/sgml/func.sgml | 99 +++++++ doc/src/sgml/installation.sgml | 5 +- doc/src/sgml/postgres.sgml | 1 + doc/src/sgml/ref/initdb.sgml | 19 ++ doc/src/sgml/ref/pgupgrade.sgml | 7 + doc/src/sgml/storage.sgml | 5 + 9 files changed, 563 insertions(+), 2 deletions(-) create mode 100644 doc/src/sgml/database-encryption.sgml diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index a2694e548a..dad0b3aef7 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -7627,6 +7627,39 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; + + Encryption Key Management + + + + cluster_passphrase_command (string) + + cluster_passphrase_command configuration parameter + + + + + This option specifies an external command to be invoked when a passphrase + for key management system needs to be obtained. + + + The command must print the passphrase to the standard output and exit + with code 0. In the parameter value, %p is + replaced by a prompt string. (Write %% for a + literal %.) Note that the prompt string will + probably contain whitespace, so be sure to quote adequately. A single + newline is stripped from the end of the output if present. The passphrase + must be at least 64 bytes. + + + This parameter can only be set in the postgresql.conf + file or on the server command line. + + + + + + Client Connection Defaults @@ -9471,6 +9504,20 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' + + key_management_enabled (boolean) + + Key management configuration parameter parameter + + + + + Reports whether encryption key management is enabled for this cluster. + 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 0000000000..617f31bf28 --- /dev/null +++ b/doc/src/sgml/database-encryption.sgml @@ -0,0 +1,381 @@ + + + + Database Encryption + + + Server Side Encryption + + + + The purpose of database encryption is to protect the confidential data + stored in a database from being revealed. PostgreSQL + provides a way to encrypt database data with the encryption key managed + inside PostgreSQL when + key manager is enabled. This section describes + how PostgreSQL manages encryption keys and + how encryption process works. + + + + Encryption Key Management + + + PostgreSQL supports internal + Encryption Key Management System, which is designed + to manage the life cycles of cryptographic keys within the + PostgreSQL. This includes dealing with their + generation, storage, usage and rotation. + + + + Encryption key management system is enabled when + PostgreSQL is built with + --with-openssl and + is specified during + initdb. The cluster passphrase provided by + option during + initdb and the one generated by + in the + postgresql.conf must match, otherwise, the database + cluster will not start up. Please note that the cluster passphrase command + passed to initdb must return a passphrase equal or longer + than 64 bytes and less than 1024 bytes. For example. + +initdb -D dbname --cluster-passphrase-command="cat /path/to/passphrase-file" + + + + + Key Encryption Key(<acronym>KEK</acronym>) + + + During initdb process, the cluster passphrase provided + by is derived into + Key Encryption Key (KEK). + KEK encapsulates cryptographic keys managed inside + PostgreSQL described in + using by a way of authenticated + encryption described in + before storing the keys to a persistent storage. KEK + must be stored in a trusted key store, such as key vault software or + services, or a hardware security module. + + + + When a PostgreSQL server with encryption key + management enabled is started, the cluster_passphrase_command + parameter in postgresql.conf will be evaluated and + the cluster passphrase will be derived into + Key Encryption Key (KEK) in similar + ways as initdb. + + + + After that, the cryptographic keys will be retrieved from pg_cryptokeys + directory to be restored and integrity-checked by the key management + system using KEK. If this process fails, it is likely + that the cluster passphrase supplied to the cluster is not the same as that + supplied to the initdb process. The cluster will refuse + to start in this case and user has to manually correct the cluster passphrase. + + + + KEK is not stored physically within the + PostgreSQL server as they are designed + to be derived from the correctly configured cluster passphrase. + + + + + Key Derivations + + + Encryption key management system can manage multiple cryptographic keys + that have different purposes and usages within PostgreSQL. + Currently, encryption key management system manages one cryptographic key + which is generated using pg_strong_random() during + initdb process. + + + + + SQL Key + + + SQL Key is used to encrypt and decrypt data via + pg_encrypt() and pg_decrypt() + SQL functions. + + + + + + + + Key Rotation Process + + + Encryption keys in general are not interminable, the longer the same key + is in use, the chance of it being breached increases. Performing key + rotation on a regular basis help meet standardized security practices + such as PCI-DSS + and it is a good practice in security to limit the number of encrypted + bytes available for a specific key version. The key lifetimes are based + on key length, key strength, algorithm and total number of bytes + enciphered. The key management system provides a efficient method to + perform key rotation. + + + + Please be aware that the phrase "key rotation" here + only refers to the rotation of KEK. The cryptographic + keys managed by encryption key management system are not rotated; they + will in fact be the same before and after a "key rotation". + This can be justified because the actual keys are never stored anywhere + physically, presented to user or captured in logging. What is being + rotated here is the KEK who is responsible for + encapsulating and restoring cryptographic keys. + + + + Since KEK is derived from a cluster passphrase, the + "key rotation" ultimately refers to the rotation of + cluster passphrase and deriving a new KEK from the + new cluster passphrase. The new KEK can then be used + to encapsulate all encryptions keys and store the new results in + pg_cryptokeys directory. + + + + To complete the cluster passphrase rotation, user needs to follow the + steps below: + + + + + Ensure the PostgreSQL server is running + correctly with KMS enabled. Passphrase rotation cannot be completed + with the server shut down. + + + + + Update parameter and + load such that the new command will return a new cluster passphrase. + + + + + In a session, execute pg_rotate_cluster_passphrase() + SQL function to initiate the rotation. The function returns true upon + successful key rotation and false if otherwise. + +=# SELECT pg_rotate_cluster_passphrase(); +pg_rotate_cluster_passphrase +------------------------------ + t +(1 row) + + + + + + + Upon successful cluster passphrase rotation, all managed cryptographic keys + will be re-encapsulated by the new KEK derived from the + new cluster passphrase. The new encapsulated keys will be stored in + pg_cryptokeys directory. Please note that the cryptographic + keys are the same as before; the rotation process only changes the + KEK that is used to encapsulate and verify the actual + cryptographic keys. This way, there is no need to decrypt all the encrypted + data with the old keys and re-encrypt them with the new. + + + + In case of a crash during the cluster passphrase rotation process, the key + management system is able to recover to the previous sets of cryptographic + keys the next time server starts up. This is possible because the key rotation + and encapsulation process are done on a separate temporary key directory called + pg_cryptokeys_tmp and it will replace + pg_cryptokeys and be deleted only when everything is + successfully finished. If the server starts with pg_cryptokeys_tmp folder present, + it would indicate that previous attempt of cluster passphrase rotation was not + completed. In this case, the server will discard pg_cryptokeys_tmp + folder and load the keys in pg_cryptokeys as usual. + + + + + + Encryption SQL Functions + + See for available encryption + functions. + + + + These two functions can be used not only to encrypt data stored in a database + but also in conjunction with the cryptographic functions provided by + pgcrypto extension to perform column level encryption/decryption + without having to supply a clear text user secret or passphrase that is required + by many pgcrypto functions as input. Please refer to + for usage examples. + + + + Authenticated Encryption with AES-CBC and HMAC-SHA + + + Authenticated Encryption with Associated Data (AEAD), is + a form of encryption. In addition to provide a way to protect confidential + data from being revealed, it provides a way to check its integrity and + authenticity of some associated data. + + + + This section describes the authenticated encryption algorithm + PostgreSQL provides. This + PostgreSQL AEAD algorithm + is derived from the specification draft of + + Authenticated Encryption with AEAD-CBC and HMAC-SHA. It follows + Encrypt-Then-MAC approach, basing on the composition of theAdvanced Encryption + Standard (AES) in the Cipher Block Chaining + (CBC) mode of operation for encryption with random + initialization vector(IV) and the HMAC-SHA + message authentication code (MAC). + + + + PostgreSQL AEAD algorithm uses + two kinds of cryptographic keys: + + + + + + Encryption Key + + + Encryption key is 256 bits long randomly generate key. It is primarily used + to a key for encapsulate or restore data with AES256 + algorithm. + + + + + MAC Key + + + MAC key is 512 bits long randomly generated key. + SHA512 is the algorithm used along with the + MAC key to compute a cryptographic hash for integrity + check purposes. + + + + + + + + PostgreSQL AEAD algorithm is as + follows: + + + + Generate random IV. + + + Add padding to the plaintext following PKCS#7 described in + RFC2315. + + + Encrypt padded plain text with the IV + using AES256 in CBC + mode. + + + Compute HMAC over the encrypted data. + + + Concatenate HMAC, IV + and encrypted ciphertext as the result of ciphertext. + + + + + + The length of the result ciphertext can be inferred from that of the plaintext + by following formula: + + Ciphertext Length = 64 + 16 + 16 * (floor(input_size / 16) + 1) + + + + + + Wrap and Unwrap User Secret + + + This section describes a use case where combining pg_encrypt() + and pg_decrypt() with . User wraps + the user encryption secret with pg_encrypt() function and + passes the wrapped encryption secret to pg_decrypt() function + for the pgcrypto encryption functions. The wrapped secret + can be stored in the application server or somewhere secured and should be obtained + promptly for cryptographic operation with pgcrypto. + + + + Here is an example that shows how to encrypt and decrypt data together with + these functions: + + + + Wrap user secret key by pg_encrypt() function. In this example, + wrapped user secret is stored into key variable. + +=# SELECT pg_encrypt('my secret password') as key; + pg_encrypt +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + \x6ddff999f4b00206048e420839e9f0639d53537b7e66ee6d3609f5bbd01ad9c9244e487c3dc235fe0abd10d2bade46610ec381180b4d149725a8b8967edcbb5287a1ff05ae80fdb9f5bf7b5c1861632daf8677ef8c4448a0645b6c4b42a3e2f16396b11768148916331a65c42f40a2ed +(1 row) +=# \gset + + + + + Once wrapping the user secret key, user can encrypt and decrypt user data + using the wrapped user key together with the + pg_decrypt() function: + + + + + =# INSERT INTO tbl (col) + VALUES (pgp_sym_encrypt('secret data', pg_decrypt(:'key'))); + INSERT 1 + + =# SELECT * FROM tbl; + col +-------------------------------------------------------------------------------------------------------------------------------------------------------------- + \xc30d04070302a199ee38bea0320b75d23c01577bb3ffb315d67eecbeca3e40e869cea65efbf0b470f805549af905f94d94c447fbfb8113f585fc86b30c0bd784b10c9857322dc00d556aa8de14 +(1 row) + + =# SELECT pgp_sym_decrypt(col, pg_decrypt(:'key')) as col FROM tbl; + col +-------------- + secret data +(1 row) + + + + + The data 'secret data' is practically encrypted by the + user secret 'my secret password' but using key wrapping + users don't need to know the actual user secret during operation. + + + + diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index 68179f71cd..52e353cafa 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -48,6 +48,7 @@ + diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 7c06afd3ea..dabdb7c311 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -26679,4 +26679,103 @@ SELECT m.* FROM pg_statistic_ext join pg_statistic_ext_data on (oid = stxoid), + + Encryption Functions + + + Data Encryption Function + + The functions shown in + are for encrypting + and decrypting data with the SQL key described in + . + + + + Encryption <acronym>SQL</acronym> Functions + + + + Function + Return Type + Description + + + + + + + + pg_encrypt + + pg_encrypt(data text) + + + bytea + + + Encrypt the given data with the internal SQL key + + + + + + + pg_unwrap + + pg_decrypt(data bytea) + + + text + + + Decrypt the given data with the internal SQL key + + + + +
+
+ + + Key Management Functions + + The function shown in + are for encryption + key management described in . + + + + Encryption Key Management <acronym>SQL</acronym> Functions + + + + Function + Return Type + Description + + + + + + + pg_rotate_cluster_passphrase + + pg_rotate_cluster_passphrase() + + + boolean + + + Rotate the cluster passphrase. See + for details. + + + + + +
+
+
+ diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index 4f89b4e930..2bf6a297b6 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -979,8 +979,9 @@ build-postgresql: Build with support for SSL (encrypted) - connections. This requires the OpenSSL - package to be installed. configure will check + connections and key management. 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 c41ce9499b..a96196c85d 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -170,6 +170,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 a04a180165..d5e8862516 100644 --- a/doc/src/sgml/ref/initdb.sgml +++ b/doc/src/sgml/ref/initdb.sgml @@ -165,6 +165,25 @@ PostgreSQL documentation + + + + + This option specifies an external command to be invoked when a passphrase + for key management system needs to be obtained. + + + The command must print the passphrase to the standard output and exit + with code 0. In the parameter value, %p is + replaced by a prompt string. (Write %% for a + literal %.) Note that the prompt string will + probably contain whitespace, so be sure to quote adequately. A single + newline is stripped from the end of the output if present. The passphrase + must be at least 64 bytes. + + + + diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 905167690b..61a386a2ff 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -823,6 +823,13 @@ psql --username=postgres --file=script.sql postgres is down. + + During the upgrade pg_upgrade copies the all internal keys + to the new cluster. If you want to upgrade from the old cluster that enables + the key management to the new cluster that also enables, you must use the same + cluster_passphrase_command to both clusters. Otherwise + pg_upgrade fails due to mismatching the cluster passphrase. + diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml index ea08d0b614..3d1f02ef83 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 cryptographic keys + + pg_dynshmem Subdirectory containing files used by the dynamic shared memory -- 2.23.0