diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml
index ac501d00..7225dbbb 100644
--- a/.github/workflows/docker.yaml
+++ b/.github/workflows/docker.yaml
@@ -17,7 +17,7 @@ jobs:
steps:
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
+ uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0
- name: Build
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0
diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
index 136d59ac..8ef6d4c4 100644
--- a/.github/workflows/docs.yaml
+++ b/.github/workflows/docs.yaml
@@ -1,5 +1,6 @@
name: Docs
on:
+ workflow_dispatch: {}
push:
branches:
- main
@@ -7,7 +8,7 @@ on:
- "documentation/**"
permissions:
- contents: read
+ contents: write
jobs:
release:
@@ -20,6 +21,8 @@ jobs:
steps:
- name: Chekout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ fetch-depth: 0 # fetch all commits/branches
- name: Set up Python
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
@@ -27,14 +30,9 @@ jobs:
python-version: "3.x"
- name: Configure git
- env:
- ROBOT_TOKEN: ${{ secrets.ROBOT_TOKEN }}
run: |
- git config --global url."https://percona-platform-robot:${ROBOT_TOKEN}@github.com".insteadOf "https://github.com"
git config user.name "GitHub Action"
git config user.email "github-action@users.noreply.github.com"
- git config user.password "${ROBOT_TOKEN}"
- echo "GIT_USER=percona-platform-robot:${ROBOT_TOKEN}" >> $GITHUB_ENV
- name: Install MkDocs
run: |
@@ -44,6 +42,6 @@ jobs:
- name: Deploy
run: |
- mike deploy main -p
mike set-default main -p
mike retitle main "Beta" -p
+ mike deploy main -p
diff --git a/.github/workflows/postgresql-16-ppg-package-pgxs.yml b/.github/workflows/postgresql-16-ppg-package-pgxs.yml
index 03759366..93c3b015 100644
--- a/.github/workflows/postgresql-16-ppg-package-pgxs.yml
+++ b/.github/workflows/postgresql-16-ppg-package-pgxs.yml
@@ -107,7 +107,7 @@ jobs:
working-directory: src/pg_tde
- name: Report on test fail
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
if: ${{ failure() }}
with:
name: Regressions diff and postgresql log
@@ -130,7 +130,7 @@ jobs:
sudo cp /usr/lib/postgresql/16/lib/pg_tde* pgtde-ppg16/usr/lib/postgresql/16/lib/
- name: Upload tgz
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
with:
name: pg_tde_ppg16_binary
path: pgtde-ppg16
@@ -152,7 +152,7 @@ jobs:
sudo dpkg -i --debug=7777 pgtde-ppg16.deb
- name: Upload deb
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
with:
name: pg_tde_deb
path: pgtde-ppg16.deb
diff --git a/.github/workflows/postgresql-16-src-make-ssl11.yml b/.github/workflows/postgresql-16-src-make-ssl11.yml
index 05ab327b..adfae4ea 100644
--- a/.github/workflows/postgresql-16-src-make-ssl11.yml
+++ b/.github/workflows/postgresql-16-src-make-ssl11.yml
@@ -97,7 +97,7 @@ jobs:
working-directory: src/contrib/pg_tde
- name: Report on test fail
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
if: ${{ failure() }}
with:
name: Regressions diff and postgresql log
diff --git a/.github/workflows/postgresql-16-src-make.yml b/.github/workflows/postgresql-16-src-make.yml
index 994dd561..0f20716d 100644
--- a/.github/workflows/postgresql-16-src-make.yml
+++ b/.github/workflows/postgresql-16-src-make.yml
@@ -97,7 +97,7 @@ jobs:
working-directory: src/contrib/pg_tde
- name: Report on test fail
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
if: ${{ failure() }}
with:
name: Regressions diff and postgresql log
diff --git a/.github/workflows/postgresql-16-src-meson.yml b/.github/workflows/postgresql-16-src-meson.yml
index a2f35eb0..c305ebed 100644
--- a/.github/workflows/postgresql-16-src-meson.yml
+++ b/.github/workflows/postgresql-16-src-meson.yml
@@ -85,7 +85,7 @@ jobs:
working-directory: src/build
- name: Report on test fail
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
if: ${{ failure() }}
with:
name: Regressions diff and postgresql log
diff --git a/.github/workflows/postgresql-17-src-make.yml b/.github/workflows/postgresql-17-src-make.yml
index cc3fbcba..6dd648bc 100644
--- a/.github/workflows/postgresql-17-src-make.yml
+++ b/.github/workflows/postgresql-17-src-make.yml
@@ -97,7 +97,7 @@ jobs:
working-directory: src/contrib/pg_tde
- name: Report on test fail
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
if: ${{ failure() }}
with:
name: Regressions diff and postgresql log
diff --git a/.github/workflows/postgresql-17-src-meson-perf.yml b/.github/workflows/postgresql-17-src-meson-perf.yml
index 9409140d..91e5b8a9 100644
--- a/.github/workflows/postgresql-17-src-meson-perf.yml
+++ b/.github/workflows/postgresql-17-src-meson-perf.yml
@@ -79,7 +79,7 @@ jobs:
working-directory: src/build
- name: Report on test fail
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
if: ${{ failure() }}
with:
name: Regressions diff and postgresql log
@@ -139,7 +139,7 @@ jobs:
echo "EOF" >> $GITHUB_ENV
working-directory: inst
- - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
with:
name: pr_perf_results
path: inst/pr_perf_results
diff --git a/.github/workflows/postgresql-17-src-meson.yml b/.github/workflows/postgresql-17-src-meson.yml
index fdb5daf8..0c6a374a 100644
--- a/.github/workflows/postgresql-17-src-meson.yml
+++ b/.github/workflows/postgresql-17-src-meson.yml
@@ -80,7 +80,7 @@ jobs:
working-directory: src/build
- name: Report on test fail
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
if: ${{ failure() }}
with:
name: Regressions diff and postgresql log
diff --git a/.github/workflows/postgresql-perf-results.yml b/.github/workflows/postgresql-perf-results.yml
index fb32d1bc..830ed8e6 100644
--- a/.github/workflows/postgresql-perf-results.yml
+++ b/.github/workflows/postgresql-perf-results.yml
@@ -8,6 +8,7 @@ on:
permissions:
contents: read
+ pull-requests: write
jobs:
download:
@@ -38,17 +39,10 @@ jobs:
run: |
unzip pr_perf_results.zip
- - name: Clone pg_tde repository
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- with:
- path: 'src'
- ref: ${{ github.event.workflow_run.head_branch }}
-
- name: 'Create comment'
run: |
- gh pr comment ${PR_NUMBER} -F ../pr_perf_results --edit-last || \
- gh pr comment ${PR_NUMBER} -F ../pr_perf_results
+ gh pr comment ${PR_NUMBER} -F pr_perf_results --repo ${{ github.repository }} --edit-last || \
+ gh pr comment ${PR_NUMBER} -F pr_perf_results --repo ${{ github.repository }}
env:
PR_NUMBER: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- working-directory: src
diff --git a/.github/workflows/postgresql-pgdg-package-pgxs.yml b/.github/workflows/postgresql-pgdg-package-pgxs.yml
index 6fa071e1..55439095 100644
--- a/.github/workflows/postgresql-pgdg-package-pgxs.yml
+++ b/.github/workflows/postgresql-pgdg-package-pgxs.yml
@@ -104,7 +104,7 @@ jobs:
working-directory: src/pg_tde
- name: Report on test fail
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
if: ${{ failure() }}
with:
name: Regressions diff and postgresql log
@@ -131,7 +131,7 @@ jobs:
- name: Upload tgz
env:
POSTGRESQL_VERSION: ${{ matrix.postgresql-version }}
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
with:
name: pg_tde_pgdg$POSTGRESQL_VERSION_binary
path: pgtde-pgdg$POSTGRESQL_VERSION
@@ -159,7 +159,7 @@ jobs:
- name: Upload deb
env:
POSTGRESQL_VERSION: ${{ matrix.postgresql-version }}
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
with:
name: pg_tde_deb
path: pgtde-pgdg$POSTGRESQL_VERSION.deb
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index 70634cd2..95de836e 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -35,7 +35,7 @@ jobs:
publish_results: true
- name: Upload results
- uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
with:
name: SARIF file
path: results.sarif
@@ -43,6 +43,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard (optional).
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6
+ uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
with:
sarif_file: results.sarif
diff --git a/Makefile b/Makefile
index f17f0ae5..4b6a32cb 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
PGFILEDESC = "pg_tde access method"
MODULE_big = pg_tde
EXTENSION = pg_tde
-DATA = pg_tde--1.0.sql
+DATA = pg_tde--1.0-beta2.sql
REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/pg_tde/pg_tde.conf
REGRESS = toast_decrypt_basic \
diff --git a/documentation/docs/_images/tde-flow.png b/documentation/docs/_images/tde-flow.png
index 08e3bdbb..09c4da2e 100644
Binary files a/documentation/docs/_images/tde-flow.png and b/documentation/docs/_images/tde-flow.png differ
diff --git a/documentation/docs/faq.md b/documentation/docs/faq.md
new file mode 100644
index 00000000..9e9d5afd
--- /dev/null
+++ b/documentation/docs/faq.md
@@ -0,0 +1,30 @@
+# FAQ
+
+## Why do I need TDE?
+
+- Compliance to security and legal regulations like GDPR, PCI DSS and others
+- Encryption of backups
+- Granular encryption of specific data sets and reducing the performance overhead that encryption brings
+- Additional layer of security to existing security measures
+
+## I use disk-level encryption. Why should I care about TDE?
+
+Encrypting a hard drive encrypts all data including system and application files that are there. However, disk encryption doesn’t protect your data after the boot-up of your system. During runtime, the files are decrypted with disk-encryption.
+
+TDE focuses specifically on data files and offers a more granular control over encrypted data. It also ensures that files are encrypted on disk during runtime and when moved to another system or storage.
+
+Consider using TDE and storage-level encryption together to add another layer of data security
+
+## Is TDE enough to ensure data security?
+
+No. TDE is an additional layer to ensure data security. It protects data at rest. Consider introducing also these measures:
+
+* Access control and authentication
+* Strong network security like TLS
+* Disk encryption
+* Regular monitoring and auditing
+* Additional data protection for sensitive fields (e.g., application-layer encryption)
+
+## What happens to my data if I lose a principal key?
+
+If you lose encryption keys, especially, the principal key, the data is lost. That's why it's critical to back up your encryption keys securely.
\ No newline at end of file
diff --git a/documentation/docs/functions.md b/documentation/docs/functions.md
index 2ddd4006..a83d812a 100644
--- a/documentation/docs/functions.md
+++ b/documentation/docs/functions.md
@@ -21,7 +21,7 @@ Creates a new key provider for the database using a remote HashiCorp Vault serve
The specified access parameters require permission to read and write keys at the location.
```
-SELECT pg_tde_add_key_provider_vault_v2('provider-name',:'secret_token','url','mount','ca_path');
+SELECT pg_tde_add_key_provider_vault_v2('provider-name','secret_token','url','mount','ca_path');
```
where:
@@ -33,6 +33,24 @@ where:
All parameters can be either strings, or JSON objects [referencing remote parameters](external-parameters.md).
+## pg_tde_add_key_provider_kmip
+
+Creates a new key provider for the database using a remote KMIP server.
+
+The specified access parameters require permission to read and write keys at the server.
+
+```
+SELECT pg_tde_add_key_provider_kmip('provider-name','kmip-IP', 5696, '/path_to/server_certificate.pem', '/path_to/client_key.pem');
+```
+
+where:
+
+* `provider-name` is the name of the provider. You can specify any name, it's for you to identify the provider.
+* `kmip-IP` is the IP address of a domain name of the KMIP server
+* The port to communicate with the KMIP server. The default port is `5696`.
+* `server-certificate` is the path to the certificate file for the KMIP server.
+* `client key` is the path to the client key.
+
## pg_tde_set_principal_key
Sets the principal key for the database using the specified key provider.
@@ -72,12 +90,19 @@ SELECT pg_tde_rotate_principal_key('name-of-the-new-principal-key', NULL);
SELECT pg_tde_rotate_principal_key(NULL, 'name-of-the-new-provider');
```
+
## pg_tde_is_encrypted
-Tells if a table is using the `pg_tde` access method or not.
+Tells if a table is encrypted using the `tde_heap` access method or not.
+
+To verify a table encryption, run the following statement:
```
SELECT pg_tde_is_encrypted('table_name');
```
+You can also verify if the table in a custom schema is encrypted. Pass teh schema name for the function as follows:
+```
+SELECT pg_tde_is_encrypted('schema.table_name');
+```
diff --git a/documentation/docs/index.md b/documentation/docs/index.md
index 86787bed..bf3b12fd 100644
--- a/documentation/docs/index.md
+++ b/documentation/docs/index.md
@@ -1,8 +1,10 @@
# `pg_tde` documentation
-`pg_tde` is the extension that brings in [Transparent Data Encryption (TDE)](tde.md) to PostgreSQL and enables users to keep sensitive data safe and secure. The encryption is transparent for users allowing them to access and manipulate the data and not to worry about the encryption process.
+`pg_tde` is the open source PostgreSQL extension that provides Transparent Data Encryption (TDE) to protect data at rest. This ensures that the data stored on disk is encrypted, and no one can read it without the proper encryption keys, even if they gain access to the physical storage media.
-Users can configure encryption differently for each database, encrypting specific tables in some databases with different encryption keys, while keeping others non encrypted.
+You can configure encryption differently for each database, encrypting specific tables in some databases with different encryption keys while keeping others unencrypted.
+
+Lear more [what is Transparent Data Encryption](tde.md#how-does-it-work) and [why you need it](tde.md#why-do-you-need-tde).
!!! important
@@ -23,8 +25,14 @@ Users can configure encryption differently for each database, encrypting specifi
## Known limitations
-* Keys in the local keyfile are stored unencrypted. We encourage you to use Key management storage.
+* Keys in the local keyfile are stored unencrypted. For better security we recommend using the Key management storage.
* System tables are currently not encrypted.
+* Currently you cannot update the configuration of an existing Key Management Store (KMS). If its configuration changes (e.g. your Vault server has a new URL), you must set up a new key provider in `pg_tde` and create new keys there. Both the KMS and PostgreSQL servers must be up and running during these changes. [Reach out to our experts](https://www.percona.com/about/contact) for assistance and to outline the best update path for you.
+
+ We plan to introduce the way to update the configuration of an existing KMS in future releases.
+
+* `pg_rewind` doesn't work with encrypted WAL for now. We plan to fix it in future releases.
+
:material-alert: Warning: Note that introducing encryption/decryption affects performance. Our benchmark tests show less than 10% performance overhead for most situations. However, in some specific applications such as those using JSONB operations, performance degradation might be higher.
@@ -42,10 +50,9 @@ The `pg_tde` extension comes in two distinct versions with specific access metho
### Which version to chose?
-The answer is pretty straightforward: if you don't use indexes and don't need index encryption, use the community version and the `tde_heap_basic` access method. Check the [upstream documentation :octicons-link-external-16:](https://github.com/percona/pg_tde/blob/main/README.md) how to get started.
+The answer is pretty straightforward: for data sets where indexing is not mandatory or index encryption is not required, use the community version and the `tde_heap_basic` access method. Check the [upstream documentation :octicons-link-external-16:](https://github.com/percona/pg_tde/blob/main/README.md) how to get started.
Otherwise, enjoy full encryption with the Percona Server for PostgreSQL version and the `tde_heap` access method.
Still not sure? [Contact our experts](https://www.percona.com/about/contact) to find the best solution for you.
-
diff --git a/documentation/docs/replication.md b/documentation/docs/replication.md
deleted file mode 100644
index f0e505df..00000000
--- a/documentation/docs/replication.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Streaming replication configuration
-
diff --git a/documentation/docs/setup.md b/documentation/docs/setup.md
index bd4ce103..e6e6c7e0 100644
--- a/documentation/docs/setup.md
+++ b/documentation/docs/setup.md
@@ -4,7 +4,7 @@
Load the `pg_tde` at the start time. The extension requires additional shared memory; therefore, add the `pg_tde` value for the `shared_preload_libraries` parameter and restart the `postgresql` instance.
-1. Use the [ALTER SYSTEM](https://www.postgresql.org/docs/current/sql-altersystem.html) command from `psql` terminal to modify the `shared_preload_libraries` parameter.
+1. Use the [ALTER SYSTEM](https://www.postgresql.org/docs/current/sql-altersystem.html) command from `psql` terminal to modify the `shared_preload_libraries` parameter. This requires superuser privileges.
```
ALTER SYSTEM SET shared_preload_libraries = 'pg_tde';
@@ -14,14 +14,14 @@ Load the `pg_tde` at the start time. The extension requires additional shared me
* On Debian and Ubuntu:
- ```{.bash data-prompt="$"}
- $ sudo systemctl restart postgresql.service
+ ```sh
+ sudo systemctl restart postgresql.service
```
* On RHEL and derivatives
- ```{.bash data-prompt="$"}
- $ sudo systemctl restart postgresql-17
+ ```sh
+ sudo systemctl restart postgresql-17
```
3. Create the extension using the [CREATE EXTENSION](https://www.postgresql.org/docs/current/sql-createextension.html) command. You must have the privileges of a superuser or a database owner to use this command. Connect to `psql` as a superuser for a database and run the following command:
@@ -36,69 +36,103 @@ Load the `pg_tde` at the start time. The extension requires additional shared me
You can have the `pg_tde` extension automatically enabled for every newly created database. Modify the template `template1` database as follows:
- ```
+ ```sh
psql -d template1 -c 'CREATE EXTENSION pg_tde;'
```
## Key provider configuration
-1. Set up a key provider for the database where you have enabled the extension
+1. Set up a key provider for the database where you have enabled the extension.
- === "With HashiCorp Vault"
+ === "With KMIP server"
+
+ Make sure you have obtained the root certificate for the KMIP server and the keypair for the client. The client key needs permissions to create / read keys on the server. Find the [configuration guidelines for the HashiCorp Vault Enterprise KMIP Secrets Engine](https://developer.hashicorp.com/vault/tutorials/enterprise/kmip-engine).
+
+ For testing purposes, you can use the PyKMIP server which enables you to set up required certificates. To use a real KMIP server, make sure to obtain the valid certificates issued by the key management appliance.
+
+ ```
+ SELECT pg_tde_add_key_provider_kmip('provider-name','kmip-IP', 5696, '/path_to/server_certificate.pem', '/path_to/client_key.pem');
+ ```
+
+ where:
+
+ * `provider-name` is the name of the provider. You can specify any name, it's for you to identify the provider.
+ * `kmip-IP` is the IP address of a domain name of the KMIP server
+ * `port` is the port to communicate with the KMIP server. Typically used port is 5696.
+ * `server-certificate` is the path to the certificate file for the KMIP server.
+ * `client key` is the path to the client key.
+
+ :material-information: Warning: This example is for testing purposes only:
+
+ The Vault server setup is out of scope of this document.
```
- SELECT pg_tde_add_key_provider_vault_v2('provider-name',:'secret_token','url','mount','ca_path');
+ SELECT pg_tde_add_key_provider_kmip('kmip','127.0.0.1', 5696, '/tmp/server_certificate.pem', '/tmp/client_key_jane_doe.pem');
+ ```
+
+ === "With HashiCorp Vault"
+
+ The Vault server setup is out of scope of this document.
+
+ ```sql
+ SELECT pg_tde_add_key_provider_vault_v2('provider-name','root_token','url','mount','ca_path');
```
where:
* `url` is the URL of the Vault server
* `mount` is the mount point where the keyring should store the keys
- * `secret_token` is an access token with read and write access to the above mount point
+ * `root_token` is an access token with read and write access to the above mount point
* [optional] `ca_path` is the path of the CA file used for SSL verification
+ :material-information: Warning: This example is for testing purposes only:
- === "With keyring file"
+ ```
+ SELECT pg_tde_add_key_provider_file_vault_v2('my-vault','https://vault.example.com','secret/data','hvs.zPuyktykA...example...ewUEnIRVaKoBzs2', NULL);
+ ```
+
+ === "With a keyring file"
This setup is intended for development and stores the keys unencrypted in the specified data file.
- ```
+ ```sql
SELECT pg_tde_add_key_provider_file('provider-name','/path/to/the/keyring/data.file');
```
- :material-information: Warning: Example for testing purposes only:
+ :material-information: Warning: This example is for testing purposes only:
- ```
- SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_local_keyring.per');
- ```
+ ```sql
+ SELECT pg_tde_add_key_provider_file('file-keyring','/tmp/pg_tde_test_local_keyring.per');
+ ```
2. Add a principal key
- ```
+ ```sql
SELECT pg_tde_set_principal_key('name-of-the-principal-key', 'provider-name');
```
- :material-information: Warning: Example for testing purposes only:
+ :material-information: Warning: This example is for testing purposes only:
- ```
+ ```sql
SELECT pg_tde_set_principal_key('test-db-master-key','file-vault');
```
- :material-information: Info: The key provider configuration is stored in the database catalog in an unencrypted table. See [how to use external reference to parameters](external-parameters.md) to add an extra security layer to your setup.
+ The key is auto-generated.
-## WAL encryption configuration (tech preview)
+ :material-information: Info: The key provider configuration is stored in the database catalog in an unencrypted table. See [how to use external reference to parameters](external-parameters.md) to add an extra security layer to your setup.
-After you [enabled `pg_tde`](#enable-extension) and started the Percona Server for PostgreSQL, a principal key and internal keys for WAL encryption are created. They are stored in the data directory so that after WAL encryption is enabled, any process that requires access to WAL (a recovery or a checkpointer) can use them for decryption.
-Now you need to instruct `pg_tde ` to encrypt WAL files by configuring WAL encryption. Here's how to do it:
+## WAL encryption configuration
-### Enable WAL level encryption
+After you [enabled `pg_tde`](#enable-extension) and started the Percona Server for PostgreSQL, a principal key and a keyring for WAL are created. Now you need to instruct `pg_tde ` to encrypt WAL files by configuring WAL encryption.
-1. Use the `ALTER SYSTEM SET` command. You need the privileges of the superuser to run this command:
+Here's how to do it:
- ```
+1. Enable WAL level encryption using the `ALTER SYSTEM SET` command. You need the privileges of the superuser to run this command:
+
+ ```sql
ALTER SYSTEM set pg_tde.wal_encrypt = on;
```
@@ -106,29 +140,23 @@ Now you need to instruct `pg_tde ` to encrypt WAL files by configuring WAL encry
* On Debian and Ubuntu:
- ```{.bash data-prompt="$"}
- $ sudo systemctl restart postgresql.service
+ ```sh
+ sudo systemctl restart postgresql.service
```
* On RHEL and derivatives
- ```{.bash data-prompt="$"}
- $ sudo systemctl restart postgresql-17
+ ```sh
+ sudo systemctl restart postgresql-17
```
-On the server start
-
-### Rotate the principal key
-
-We highly recommend you to create your own keyring and rotate the principal key. This is because the default principal key is created from the local keyfile and is stored unencrypted.
+3. We highly recommend you to create your own keyring and rotate the principal key. This is because the default principal key is created from the local keyfile and is stored unencrypted.
-Rotating the principal key means re-encrypting internal keys used for WAL encryption with the new principal key. This process doesn't stop the database operation meaning that reads and writes can take place as usual during key rotation.
-
-1. Set up the key provider for WAL encryption
+ Set up the key provider for WAL encryption
=== "With HashiCorp Vault"
- ```
+ ```sql
SELECT pg_tde_add_key_provider_vault_v2('PG_TDE_GLOBAL','provider-name',:'secret_token','url','mount','ca_path');
```
@@ -146,32 +174,17 @@ Rotating the principal key means re-encrypting internal keys used for WAL encryp
This setup is intended for development and stores the keys unencrypted in the specified data file.
- ```
+ ```sql
SELECT pg_tde_add_key_provider_file('provider-name','/path/to/the/keyring/data.file');
```
-2. Rotate the principal key. Don't forget to specify the `PG_TDE_GLOBAL` constant to rotate only the principal key for WAL.
+4. Rotate the principal key. Don't forget to specify the `PG_TDE_GLOBAL` constant to rotate only the principal key for WAL.
- ```
+ ```sql
SELECT pg_tde_rotate_principal_key('PG_TDE_GLOBAL', 'new-principal-key', 'provider-name');
```
- Now all WAL files are encrypted for both encrypted and unencrypted tables.
-
-3. Verify the encryption by checking the `pg_tde.wal_encrypt` GUC (Grand Unified Configuration) parameter as follows:
-
- ```
- SELECT name, setting FROM pg_settings WHERE name = 'pg_tde.wal_encrypt';
- ```
-
- ??? example "Sample output"
-
- ```{.text .no-copy}
-
- name | setting
- --------------------+---------
- pg_tde.wal_encrypt | on
- ```
+Now all WAL files are encrypted for both encrypted and unencrypted tables.
## Next steps
diff --git a/documentation/docs/tde.md b/documentation/docs/tde.md
index bd90b958..a33ea97f 100644
--- a/documentation/docs/tde.md
+++ b/documentation/docs/tde.md
@@ -1,23 +1,26 @@
# What is Transparent Data Encryption (TDE)
-Transparent Data Encryption offers encryption at the file level and solves the problem of protecting data at rest. The encryption is transparent for users allowing them to access and manipulate the data and not to worry about the encryption process.
+Transparent Data Encryption is a technology to protect data at rest. The encryption process happens transparently in the background, without affecting database operations. Data is automatically encrypted as it's written to the disk and decrypted as it's read, all in real-time. Users and applications interact with the data as usual without noticing any difference.
## How does it work?
To encrypt the data, two types of keys are used:
-* Database keys to encrypt user data. These are stored internally, near the data that they encrypt.
-* The principal key to encrypt database keys. It is kept separately from the database keys and is managed externally.
+* Internal encryption keys to encrypt user data. They are stored internally, near the data that they encrypt.
+* The principal key to encrypt database keys. It is kept separately from the database keys and is managed externally in the key management store.
-`pg_tde` is integrated with HashiCorp Vault server to store and manage principal keys. Only the back end KV Secrets Engine - Version 2 (API) is supported.
+You have the following options to store and manage principal keys externally:
+
+* Use the HashiCorp Vault server. Only the back end KV Secrets Engine - Version 2 (API) is supported.
+* Use the KMIP-compatible server. `pg_tde` has been tested with the [PyKMIP](https://pykmip.readthedocs.io/en/latest/server.html) server and [the HashiCorp Vault Enterprise KMIP Secrets Engine](https://www.vaultproject.io/docs/secrets/kmip).
The encryption process is the following:
![image](_images/tde-flow.png)
-When a user creates an encrypted table using `pg_tde`, a new random key is generated for that table. This key is used to encrypt all data the user inserts in that table. Eventually the encrypted data gets stored in the underlying storage.
+When a user creates an encrypted table using `pg_tde`, a new random key is generated for that table using the AES128 (AES-ECB) cipher algorithm. This key is used to encrypt all data the user inserts in that table. Eventually the encrypted data gets stored in the underlying storage.
-The table itself is encrypted using the principal key. The principal key is stored externally in the Vault key management store.
+The table itself is encrypted using the principal key. The principal key is stored externally in the key management store.
Similarly when the user queries the encrypted table, the principal key is retrieved from the key store to decrypt the table. Then the same unique internal key for that table is used to decrypt the data, and unencrypted data gets returned to the user. So, effectively, every TDE table has a unique key, and each table key is encrypted using the principal key.
@@ -27,13 +30,13 @@ Using TDE has the following benefits:
* For organizations:
- - Ensure data safety when at rest and in motion
- - Comply with security standards like HIPAA, PCI DSS, SOC 2, ISO 27001
+ - Ensure data safety when it is stored on disk and in backups
+ - Comply with security and legal standards like HIPAA, PCI DSS, SOC 2, ISO 27001
* For DBAs:
- - Allows defining what to encrypt in the table and with what key
- - Encryption on storage level is not a must to provide data safety. However, using TDE and storage-level encryption together adds another layer of data security
+ - Granular encryption of specific tables and reducing the performance overhead that encryption brings
+ - Additional layer of security to existing security measures like storage-level encryption, data encryption in transit using TLS, access control and more.
!!! admonition "See also"
diff --git a/documentation/docs/test.md b/documentation/docs/test.md
index c0936e90..ac610953 100644
--- a/documentation/docs/test.md
+++ b/documentation/docs/test.md
@@ -2,10 +2,6 @@
Enabling `pg_tde` extension for a database creates the table access method `tde_heap` . This access method enables you to encrypt the data.
-!!! warning
-
- This is the tech preview functionality. Its scope is not yet finalized and can change anytime. **Use it only for testing purposes.**
-
Here's how to do it:
1. Create a table in the database for which you have [enabled `pg_tde`](setup.md) using the `tde_heap` access method as follows:
diff --git a/documentation/mkdocs.yml b/documentation/mkdocs.yml
index 097a9148..63968981 100644
--- a/documentation/mkdocs.yml
+++ b/documentation/mkdocs.yml
@@ -166,11 +166,11 @@ nav:
- functions.md
- Concepts:
- "What is TDE": tde.md
- # - wal-encryption.md
- table-access-method.md
- How to:
- Use reference to external parameters: external-parameters.md
- Decrypt an encrypted table: decrypt.md
+ - faq.md
- Release notes:
- "pg_tde release notes": release-notes/release-notes.md
- uninstall.md
diff --git a/expected/cache_alloc.out b/expected/cache_alloc.out
new file mode 100644
index 00000000..7b6bf201
--- /dev/null
+++ b/expected/cache_alloc.out
@@ -0,0 +1,125 @@
+-- We test cache so AM doesn't matter
+-- Just checking there are no mem debug WARNINGs during the cache population
+CREATE EXTENSION pg_tde;
+SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per');
+ pg_tde_add_key_provider_file
+------------------------------
+ 1
+(1 row)
+
+SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault');
+ pg_tde_set_principal_key
+--------------------------
+ t
+(1 row)
+
+do $$
+ DECLARE idx integer;
+begin
+ for idx in 0..700 loop
+ EXECUTE format('CREATE TABLE t%s (c1 int) USING tde_heap_basic', idx);
+ end loop;
+end; $$;
+DROP EXTENSION pg_tde cascade;
+NOTICE: drop cascades to 701 other objects
+DETAIL: drop cascades to table t0
+drop cascades to table t1
+drop cascades to table t2
+drop cascades to table t3
+drop cascades to table t4
+drop cascades to table t5
+drop cascades to table t6
+drop cascades to table t7
+drop cascades to table t8
+drop cascades to table t9
+drop cascades to table t10
+drop cascades to table t11
+drop cascades to table t12
+drop cascades to table t13
+drop cascades to table t14
+drop cascades to table t15
+drop cascades to table t16
+drop cascades to table t17
+drop cascades to table t18
+drop cascades to table t19
+drop cascades to table t20
+drop cascades to table t21
+drop cascades to table t22
+drop cascades to table t23
+drop cascades to table t24
+drop cascades to table t25
+drop cascades to table t26
+drop cascades to table t27
+drop cascades to table t28
+drop cascades to table t29
+drop cascades to table t30
+drop cascades to table t31
+drop cascades to table t32
+drop cascades to table t33
+drop cascades to table t34
+drop cascades to table t35
+drop cascades to table t36
+drop cascades to table t37
+drop cascades to table t38
+drop cascades to table t39
+drop cascades to table t40
+drop cascades to table t41
+drop cascades to table t42
+drop cascades to table t43
+drop cascades to table t44
+drop cascades to table t45
+drop cascades to table t46
+drop cascades to table t47
+drop cascades to table t48
+drop cascades to table t49
+drop cascades to table t50
+drop cascades to table t51
+drop cascades to table t52
+drop cascades to table t53
+drop cascades to table t54
+drop cascades to table t55
+drop cascades to table t56
+drop cascades to table t57
+drop cascades to table t58
+drop cascades to table t59
+drop cascades to table t60
+drop cascades to table t61
+drop cascades to table t62
+drop cascades to table t63
+drop cascades to table t64
+drop cascades to table t65
+drop cascades to table t66
+drop cascades to table t67
+drop cascades to table t68
+drop cascades to table t69
+drop cascades to table t70
+drop cascades to table t71
+drop cascades to table t72
+drop cascades to table t73
+drop cascades to table t74
+drop cascades to table t75
+drop cascades to table t76
+drop cascades to table t77
+drop cascades to table t78
+drop cascades to table t79
+drop cascades to table t80
+drop cascades to table t81
+drop cascades to table t82
+drop cascades to table t83
+drop cascades to table t84
+drop cascades to table t85
+drop cascades to table t86
+drop cascades to table t87
+drop cascades to table t88
+drop cascades to table t89
+drop cascades to table t90
+drop cascades to table t91
+drop cascades to table t92
+drop cascades to table t93
+drop cascades to table t94
+drop cascades to table t95
+drop cascades to table t96
+drop cascades to table t97
+drop cascades to table t98
+drop cascades to table t99
+and 601 other objects (see server log for list)
diff --git a/expected/vault_v2_test.out b/expected/vault_v2_test.out
index 789a6ec7..b1037d72 100644
--- a/expected/vault_v2_test.out
+++ b/expected/vault_v2_test.out
@@ -2,12 +2,27 @@
\i sql/vault_v2_test.inc
CREATE EXTENSION pg_tde;
\getenv root_token ROOT_TOKEN
-SELECT pg_tde_add_key_provider_vault_v2('vault-v2',:'root_token','http://127.0.0.1:8200','secret',NULL);
+SELECT pg_tde_add_key_provider_vault_v2('vault-incorrect',:'root_token','http://127.0.0.1:8200','DUMMY-TOKEN',NULL);
pg_tde_add_key_provider_vault_v2
----------------------------------
1
(1 row)
+-- FAILS
+SELECT pg_tde_set_principal_key('vault-v2-principal-key','vault-incorrect');
+psql:sql/vault_v2_test.inc:7: ERROR: Failed to store key on keyring. Please check the keyring configuration.
+CREATE TABLE test_enc(
+ id SERIAL,
+ k INTEGER DEFAULT '0' NOT NULL,
+ PRIMARY KEY (id)
+ ) USING :tde_am;
+psql:sql/vault_v2_test.inc:13: ERROR: failed to retrieve principal key. Create one using pg_tde_set_principal_key before using encrypted tables.
+SELECT pg_tde_add_key_provider_vault_v2('vault-v2',:'root_token','http://127.0.0.1:8200','secret',NULL);
+ pg_tde_add_key_provider_vault_v2
+----------------------------------
+ 2
+(1 row)
+
SELECT pg_tde_set_principal_key('vault-v2-principal-key','vault-v2');
pg_tde_set_principal_key
--------------------------
diff --git a/expected/vault_v2_test_basic.out b/expected/vault_v2_test_basic.out
index c3cc0204..5fcedd36 100644
--- a/expected/vault_v2_test_basic.out
+++ b/expected/vault_v2_test_basic.out
@@ -2,12 +2,27 @@
\i sql/vault_v2_test.inc
CREATE EXTENSION pg_tde;
\getenv root_token ROOT_TOKEN
-SELECT pg_tde_add_key_provider_vault_v2('vault-v2',:'root_token','http://127.0.0.1:8200','secret',NULL);
+SELECT pg_tde_add_key_provider_vault_v2('vault-incorrect',:'root_token','http://127.0.0.1:8200','DUMMY-TOKEN',NULL);
pg_tde_add_key_provider_vault_v2
----------------------------------
1
(1 row)
+-- FAILS
+SELECT pg_tde_set_principal_key('vault-v2-principal-key','vault-incorrect');
+psql:sql/vault_v2_test.inc:7: ERROR: Failed to store key on keyring. Please check the keyring configuration.
+CREATE TABLE test_enc(
+ id SERIAL,
+ k INTEGER DEFAULT '0' NOT NULL,
+ PRIMARY KEY (id)
+ ) USING :tde_am;
+psql:sql/vault_v2_test.inc:13: ERROR: failed to retrieve principal key. Create one using pg_tde_set_principal_key before using encrypted tables.
+SELECT pg_tde_add_key_provider_vault_v2('vault-v2',:'root_token','http://127.0.0.1:8200','secret',NULL);
+ pg_tde_add_key_provider_vault_v2
+----------------------------------
+ 2
+(1 row)
+
SELECT pg_tde_set_principal_key('vault-v2-principal-key','vault-v2');
pg_tde_set_principal_key
--------------------------
diff --git a/meson.build b/meson.build
index e1566e6a..800a8b8a 100644
--- a/meson.build
+++ b/meson.build
@@ -81,7 +81,7 @@ endif
install_data(
'pg_tde.control',
- 'pg_tde--1.0.sql',
+ 'pg_tde--1.0-beta2.sql',
kwargs: contrib_data_args,
)
@@ -104,6 +104,7 @@ sql_tests = [
'kmip_test_basic',
'alter_index_basic',
'merge_join_basic',
+ 'cache_alloc',
]
tap_tests = [
diff --git a/pg_tde--1.0.sql b/pg_tde--1.0-beta2.sql
similarity index 100%
rename from pg_tde--1.0.sql
rename to pg_tde--1.0-beta2.sql
diff --git a/pg_tde.control b/pg_tde.control
index e72bb8d4..b36c1429 100644
--- a/pg_tde.control
+++ b/pg_tde.control
@@ -1,5 +1,5 @@
# pg_tde extension
comment = 'pg_tde access method'
-default_version = '1.0'
+default_version = '1.0-beta2'
module_pathname = '$libdir/pg_tde'
relocatable = true
diff --git a/sql/cache_alloc.sql b/sql/cache_alloc.sql
new file mode 100644
index 00000000..de791ec1
--- /dev/null
+++ b/sql/cache_alloc.sql
@@ -0,0 +1,17 @@
+-- We test cache so AM doesn't matter
+-- Just checking there are no mem debug WARNINGs during the cache population
+
+CREATE EXTENSION pg_tde;
+
+SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per');
+SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault');
+
+do $$
+ DECLARE idx integer;
+begin
+ for idx in 0..700 loop
+ EXECUTE format('CREATE TABLE t%s (c1 int) USING tde_heap_basic', idx);
+ end loop;
+end; $$;
+
+DROP EXTENSION pg_tde cascade;
diff --git a/sql/vault_v2_test.inc b/sql/vault_v2_test.inc
index 221e6390..70c71906 100644
--- a/sql/vault_v2_test.inc
+++ b/sql/vault_v2_test.inc
@@ -1,6 +1,17 @@
CREATE EXTENSION pg_tde;
\getenv root_token ROOT_TOKEN
+
+SELECT pg_tde_add_key_provider_vault_v2('vault-incorrect',:'root_token','http://127.0.0.1:8200','DUMMY-TOKEN',NULL);
+-- FAILS
+SELECT pg_tde_set_principal_key('vault-v2-principal-key','vault-incorrect');
+
+CREATE TABLE test_enc(
+ id SERIAL,
+ k INTEGER DEFAULT '0' NOT NULL,
+ PRIMARY KEY (id)
+ ) USING :tde_am;
+
SELECT pg_tde_add_key_provider_vault_v2('vault-v2',:'root_token','http://127.0.0.1:8200','secret',NULL);
SELECT pg_tde_set_principal_key('vault-v2-principal-key','vault-v2');
diff --git a/src/access/pg_tde_tdemap.c b/src/access/pg_tde_tdemap.c
index a3cb8c5a..198f6a12 100644
--- a/src/access/pg_tde_tdemap.c
+++ b/src/access/pg_tde_tdemap.c
@@ -177,7 +177,7 @@ pg_tde_create_key_map_entry(const RelFileLocator *newrlocator, uint32 entry_type
if (!RAND_bytes(int_key.key, INTERNAL_KEY_LEN))
{
LWLockRelease(lock_pk);
- ereport(FATAL,
+ ereport(ERROR,
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("could not generate internal key for relation \"%s\": %s",
"TODO", ERR_error_string(ERR_get_error(), NULL))));
@@ -439,8 +439,9 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags,
{
char db_map_path[MAXPGPATH] = {0};
+ // TODO: this seems like a bad idea?
pg_tde_set_db_file_paths(rlocator->dbOid, db_map_path, NULL);
- ereport(FATAL,
+ ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not write tde map file \"%s\": %m",
db_map_path)));
@@ -449,6 +450,7 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags,
{
char db_map_path[MAXPGPATH] = {0};
+ // TODO: this seems like a bad idea?
pg_tde_set_db_file_paths(rlocator->dbOid, db_map_path, NULL);
ereport(data_sync_elevel(ERROR),
(errcode_for_file_access(),
@@ -500,7 +502,8 @@ pg_tde_write_one_keydata(int fd, int32 key_index, RelKeyData *enc_rel_key_data)
/* TODO: pgstat_report_wait_start / pgstat_report_wait_end */
if (pg_pwrite(fd, &enc_rel_key_data->internal_key, INTERNAL_KEY_DAT_LEN, curr_pos) != INTERNAL_KEY_DAT_LEN)
{
- ereport(FATAL,
+ // TODO: what now? File is corrupted
+ ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not write tde key data file: %m")));
}
@@ -1022,10 +1025,11 @@ pg_tde_process_map_entry(const RelFileLocator *rlocator, uint32 key_type, char *
if (curr_pos == -1)
{
- ereport(FATAL,
+ ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not seek in tde map file \"%s\": %m",
db_map_path)));
+ return curr_pos;
}
}
else
@@ -1117,7 +1121,7 @@ tde_decrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *enc_rel_key_data
* Open and Validate File Header [pg_tde.*]:
* header: {Format Version, Principal Key Name}
*
- * Returns the file descriptor in case of a success. Otherwise, fatal error
+ * Returns the file descriptor in case of a success. Otherwise, error
* is raised.
*
* Also, it sets the is_new_file to true if the file is just created. This is
@@ -1160,7 +1164,7 @@ pg_tde_open_file(char *tde_filename, TDEPrincipalKeyInfo *principal_key_info, bo
/*
* Open a TDE file [pg_tde.*]:
*
- * Returns the file descriptor in case of a success. Otherwise, fatal error
+ * Returns the file descriptor in case of a success. Otherwise, error
* is raised except when ignore_missing is true and the file does not exit.
*/
static int
@@ -1456,40 +1460,49 @@ pg_tde_put_key_into_cache(RelFileNumber rel_num, RelKeyData *key)
elog(ERROR, "could not mlock internal key initial cache page: %m");
tde_rel_key_cache->len = 0;
- tde_rel_key_cache->cap = pageSize / sizeof(RelKeyCacheRec);
+ tde_rel_key_cache->cap = (pageSize - 1) / sizeof(RelKeyCacheRec);
}
/*
* Add another mem page if there is no more room left for another key. We
* allocate `current_memory_size` + 1 page and copy data there.
*/
- if (tde_rel_key_cache->len + 1 >
- (tde_rel_key_cache->cap * sizeof(RelKeyCacheRec)) / sizeof(RelKeyCacheRec))
+ if (tde_rel_key_cache->len == tde_rel_key_cache->cap)
{
size_t size;
size_t old_size;
- RelKeyCacheRec *chachePage;
+ RelKeyCacheRec *cachePage;
- size = TYPEALIGN(pageSize, (tde_rel_key_cache->cap + 1) * sizeof(RelKeyCacheRec));
old_size = TYPEALIGN(pageSize, (tde_rel_key_cache->cap) * sizeof(RelKeyCacheRec));
+ /* TODO: consider some formula for less allocations when caching a lot
+ * of objects. But on the other, hand it'll use more memory...
+ * E.g.:
+ * if (old_size < 0x8000)
+ * size = old_size * 2;
+ * else
+ * size = TYPEALIGN(pageSize, old_size + ((old_size + 3*256) >> 2));
+ *
+ */
+ size = old_size + pageSize;
+
#ifndef FRONTEND
oldCtx = MemoryContextSwitchTo(TopMemoryContext);
- chachePage = palloc_aligned(size, pageSize, MCXT_ALLOC_ZERO);
+ cachePage = palloc_aligned(size, pageSize, MCXT_ALLOC_ZERO);
MemoryContextSwitchTo(oldCtx);
#else
- chachePage = aligned_alloc(pageSize, size);
- memset(chachePage, 0, size);
+ cachePage = aligned_alloc(pageSize, size);
+ memset(cachePage, 0, size);
#endif
- memcpy(chachePage, tde_rel_key_cache->data, old_size);
+ memcpy(cachePage, tde_rel_key_cache->data, old_size);
pfree(tde_rel_key_cache->data);
- tde_rel_key_cache->data = chachePage;
+ tde_rel_key_cache->data = cachePage;
- if (mlock(tde_rel_key_cache->data, pageSize) == -1)
- elog(ERROR, "could not mlock internal key cache page: %m");
+ if (mlock(tde_rel_key_cache->data, size) == -1)
+ elog(WARNING, "could not mlock internal key cache pages: %m");
- tde_rel_key_cache->cap = size / sizeof(RelKeyCacheRec);
+ tde_rel_key_cache->cap = (size - 1) / sizeof(RelKeyCacheRec);
}
rec = tde_rel_key_cache->data + tde_rel_key_cache->len;
diff --git a/src/catalog/tde_principal_key.c b/src/catalog/tde_principal_key.c
index c3326c5a..5316cbe5 100644
--- a/src/catalog/tde_principal_key.c
+++ b/src/catalog/tde_principal_key.c
@@ -262,7 +262,7 @@ set_principal_key_with_keyring(const char *key_name, GenericKeyring *keyring,
keyInfo = load_latest_versioned_key_name(&principalKey->keyInfo, keyring, ensure_new_key);
if (keyInfo == NULL)
- keyInfo = KeyringGenerateNewKeyAndStore(keyring, principalKey->keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false);
+ keyInfo = KeyringGenerateNewKeyAndStore(keyring, principalKey->keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, true);
if (keyInfo == NULL)
{
@@ -424,7 +424,7 @@ RotatePrincipalKey(TDEPrincipalKey *current_key, const char *new_key_name, const
keyInfo = load_latest_versioned_key_name(&new_principal_key.keyInfo, keyring, ensure_new_key);
if (keyInfo == NULL)
- keyInfo = KeyringGenerateNewKeyAndStore(keyring, new_principal_key.keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false);
+ keyInfo = KeyringGenerateNewKeyAndStore(keyring, new_principal_key.keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, true);
if (keyInfo == NULL)
{
@@ -496,9 +496,10 @@ load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, GenericK
*/
if (kr_ret != KEYRING_CODE_SUCCESS && kr_ret != KEYRING_CODE_RESOURCE_NOT_AVAILABLE)
{
- ereport(FATAL,
+ ereport(ERROR,
(errmsg("failed to retrieve principal key from keyring provider :\"%s\"", keyring->provider_name),
errdetail("Error code: %d", kr_ret)));
+ return NULL;
}
if (keyInfo == NULL)
{
@@ -531,6 +532,7 @@ load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, GenericK
{
ereport(ERROR,
(errmsg("failed to retrieve principal key. %d versions already exist", MAX_PRINCIPAL_KEY_VERSION_NUM)));
+ return NULL;
}
}
return NULL; /* Just to keep compiler quite */
diff --git a/src/keyring/keyring_api.c b/src/keyring/keyring_api.c
index 076779db..8fa56716 100644
--- a/src/keyring/keyring_api.c
+++ b/src/keyring/keyring_api.c
@@ -164,6 +164,8 @@ KeyringGenerateNewKeyAndStore(GenericKeyring *keyring, const char *key_name, uns
if (KeyringStoreKey(keyring, key, throw_error) != KEYRING_CODE_SUCCESS)
{
pfree(key);
+ ereport(ereport_level,
+ (errmsg("Failed to store key on keyring. Please check the keyring configuration.")));
return NULL;
}
return key;
diff --git a/src/pg_tde_event_capture.c b/src/pg_tde_event_capture.c
index 8d7794ae..1a7518f5 100644
--- a/src/pg_tde_event_capture.c
+++ b/src/pg_tde_event_capture.c
@@ -68,7 +68,6 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS)
trigdata = (EventTriggerData *) fcinfo->context;
parsetree = trigdata->parsetree;
- elog(LOG, "EVENT TRIGGER (%s) %s", trigdata->event, nodeToString(parsetree));
reset_current_tde_create_event();
if (IsA(parsetree, IndexStmt))
diff --git a/t/001_basic.pl b/t/001_basic.pl
index 45b885f6..914f4af9 100644
--- a/t/001_basic.pl
+++ b/t/001_basic.pl
@@ -30,6 +30,9 @@
ok($cmdret == 0, "CREATE PGTDE EXTENSION");
PGTDE::append_to_file($stdout);
+my ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT extname, extversion FROM pg_extension WHERE extname = \'pg_tde\';', extra_params => ['-a']);
+ok($cmdret == 0, "SELECT PGTDE VERSION");
+PGTDE::append_to_file($stdout);
$rt_value = $node->psql('postgres', 'CREATE TABLE test_enc(id SERIAL,k INTEGER,PRIMARY KEY (id)) USING tde_heap_basic;', extra_params => ['-a']);
ok($rt_value == 3, "Failing query");
diff --git a/t/expected/001_basic.out b/t/expected/001_basic.out
index c91f77dc..ab41e680 100644
--- a/t/expected/001_basic.out
+++ b/t/expected/001_basic.out
@@ -1,4 +1,6 @@
CREATE EXTENSION pg_tde;
+SELECT extname, extversion FROM pg_extension WHERE extname = 'pg_tde';
+pg_tde|1.0-beta2
-- server restart
CREATE TABLE test_enc(id SERIAL,k VARCHAR(32),PRIMARY KEY (id)) USING tde_heap_basic;
INSERT INTO test_enc (k) VALUES ('foobar'),('barfoo');