本课目标

围绕 pg_tde 透明数据加密,带你走完从安装到加密强制的部署全链路,循序渐进、一步到位。

·         安装部署:本机/容器多种方式安装 pg_tde

·         密钥管理:对接 Vault / KMIP / OpenBao 等外部 KMS

·         加密强制:校验加密状态并强制所有表加密

 

一、pg_tde 概述

认识什么是 pg_tde 及其加密范围。

1.1 数据加密应用背景

到目前为止(19版本),PostgreSQL 官方仍未提供内核级透明数据加密(TDE)能力。这意味着:

·         所有数据文件(base/、pg_wal/、global/)均以明文形式存储在磁盘

·         即使设置了强访问控制,一旦磁盘被盗、虚拟机镜像被复制、备份文件泄露,数据即完全暴露

·         不符合信创安保条约

可行方案对比:透明加密不是能不能做,而是是否满足合规审计”——等保、密评、关基。

                                               1.jpg

数据来源:https://blog.csdn.net/m0_61703951/article/details/156358939

1.2 数据加密访问流程

2.jpg

数据来源:https://blog.csdn.net/m0_61703951/article/details/156358939

1.3 什么是 pg_tde

透明数据加密(TDE)

pg_tde 是开源、社区驱动、面向未来的 PostgreSQL 扩展,提供透明数据加密,保护静态数据(data at rest)。即使攻击者拿到物理存储介质,没有正确密钥也无法读取数据。加密过程在后台透明运行,对业务影响极小。

依赖:作为 Percona Server for PostgreSQL 组件打包,依赖其核心扩展点补丁,不直接运行于社区版 PostgreSQL

加密能力一览

加密对象

是否加密

数据表(user data)

✅ 加密

索引 / TOAST / 临时表

✅ 加密

WAL 日志

✅ 加密

表元数据(列名/类型)

❌ 不加密

超过 work_mem 的临时文件

❌ 明文

 

差异化能力:表级粒度加密 + /单租户支持 + 多种 KMS 集成,PostgreSQL 下的企业级静态数据加密方案。

1.4 TDE 架构总览

4.jpg

·         Core Server 变更(Percona Postgres):提供了一组可扩展的 Hook 函数,允许插件拦截底层 I/O 操作;让命令行工具感知加密表与加密 WAL。

·         pg_tde 扩展:实际的加密逻辑,通过 GUC 变量 + SQL 函数控制。

·         Keyring API / 库:密钥存储的抽象层;同一进程可对接多种外部 KMS。

1.5 加密架构与工作原理

两级密钥(two-key hierarchy):内部密钥加密用户数据,主密钥再加密内部密钥——实现数据与密钥的彻底分离。

写 入:数据 → Buffer Manager → TDE SMGR 加密后落盘      (加密发生在存储管理器层,对业务透明)

读 取:TDE SMGR 解密 → 载入 Buffer Cache → 返回客户端   (业务层完全无感知)

 离:每张加密表有独立密钥,密钥被主密钥包裹          (轮换单个表不影响其他表)

5.jpg

二、pg_tde 安装

apt / yum / Docker 多种方式。

2.1 版本兼容性与安装前提

pg_tde 与 PostgreSQL 版本对照

PostgreSQL 版本

自动安装

所需动作

17.x – 17.6

✅ 是

17.7 及以后

❌ 否

手动装包

18.x 及以后

❌ 否

手动装包

17.6 内置随包安装,17.7+/18.x 起改为独立包;版本决定部署方式的关键差异。

安装前准备

① 移除冲突包

Debian/Ubuntu 删除上游 postgresql-* 包,避免与 Percona 冲突

② 启用 Percona 仓库

用 percona-release 工具配置 ppg-18 等通道

③ 确认平台支持

查阅 Percona 软件与平台生命周期支持矩阵

ARM64 Rocky Linux 8:默认 mlock 上限仅 64KB,会导致 pg_tde 子进程内存分配失败,需用 ulimit -l 或 limits.conf 提高。

2.2 安装方式:包管理器 / Docker

Debian / Ubuntu(apt)

sudo apt-get install -y wget gnupg2 curl lsb-release

sudo wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb

sudo dpkg -i percona-release_latest.generic_all.deb

sudo percona-release enable-only ppg-18

sudo apt-get update

sudo apt-get install -y percona-pg-tde18

RHEL / 衍生(yum)

sudo yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm

sudo percona-release enable-only ppg-18

sudo yum install -y percona-pg_tde18

Docker

docker run -d --name pg-tde \

  -e POSTGRES_PASSWORD=secret \

  -e ENABLE_PG_TDE=1 -p 5432:5432 \

  percona/percona-distribution-postgresql:17

 

三、pg_tde 基础配置

让 PostgreSQL 启动时加载 pg_tde 扩展。

3.1 配置 shared_preload_libraries 并启用扩展

① 编辑 postgresql.conf

把 pg_tde 加入预加载库,数据库启动时自动装载。

shared_preload_libraries = 'pg_tde'

pg_tde 是唯一必填项;其他扩展(如 pgaudit)按需追加。

② 在每个数据库中启用扩展

连接到目标数据库后执行,必须在每个使用加密的数据库内单独启用。

CREATE EXTENSION pg_tde;

修改 postgresql.conf 后需重启 PostgreSQL 实例生效。

③ 验证安装

返回版本号即说明安装、加载、启用三步全部成功。

SELECT * FROM pg_available_extensions

WHERE name = 'pg_tde';

返回版本号 → 流程通过。

 

四、密钥管理(KMS)

主密钥的安全保管与外部集成。

4.1 KMS 总览:7 类 Key Provider

pg_tde 通过 Key Provider 接口对接外部密钥管理服务,统一管理主密钥的存储、轮换与生命周期。

Key Provider

配置函数

典型场景

HashiCorp Vault

pg_tde_add_key_provider_vault_v2

通用 KMS、动态密钥

OpenBao

pg_tde_add_key_provider_openbao

开源 Vault 兼容方案

KMIP

pg_tde_add_key_provider_kmip

企业级 KMIP 服务器

Fortanix

pg_tde_add_key_provider_kmip

Fortanix DSM /   Data Security Manager

Thales

pg_tde_add_key_provider_kmip

Thales   CipherTrust Manager

Akeyless

pg_tde_add_key_provider_akeyless

SaaS 化密钥管理

本地文件

pg_tde_add_key_provider_file

开发测试、单节点演示

 

选择建议:生产环境优先使用 Vault / KMIP;本地文件 Provider 仅适合演示与本地实验。

4.2 Vault KV v2 配置与密钥读写流程

配置 Vault KV v2 Provider

SQL 调用(连接数据库后)

SELECT pg_tde_add_key_provider_vault_v2(

  'vault-server',                 -- provider 名称

  'http://vault:8200',            -- Vault URL

  '00000000-0000-...',            -- Vault Token

  'secret',                       -- mount path

  NULL                            -- secret path (NULL=自动生成)

);

完成 Provider 注册后,仍需为每张表使用 pg_tde_set_key 创建内部密钥。

参数说明

·         token —— 由 Vault 策略绑定 pg_tde 写入路径的 capabilities

·         mount path —— 即 KV v2 engine 挂载的根路径

·         secret path —— 留空则 pg_tde 自动生成密钥路径

生产建议:Token 通过环境变量注入,policy 限定 capabilities

4.3 本地 Keyring File(仅开发测试)

1、添加数据库级文件 Provider

SELECT pg_tde_add_database_key_provider_file(

    'file-keyring',

    '/tmp/pg_tde_test_local_keyring.per'

);

2、创建主密钥

SELECT pg_tde_create_key_using_database_key_provider(

    'my_default_key',

    'file-keyring'

);

3、设置为主密钥

SELECT pg_tde_set_key_using_database_key_provider(

    'my_default_key',

    'file-keyring'

);

4、查看当前密钥

SELECT pg_tde_default_key_info();

5、验证

CREATE TABLE customer_table (a INT) USING tde_heap;

\d+ customer_table

-- 应显示:Access method: tde_heap

SELECT pg_tde_is_encrypted('customer_table');

-- 应返回 t

 

五、多租户配置

不同数据库使用不同的主密钥。

5.1 为不同数据库绑定不同的主密钥

为什么需要多租户配置?

在多租户或多业务线场景中,不同业务的数据需要独立的主密钥。当某个租户被怀疑泄露或需合规审计时,可以只轮换或吊销该租户的主密钥,而不影响其他租户的数据可访问性。

数据库级映射函数

数据库级映射函数(示例):

SELECT pg_tde_set_default_key_using_global_key_provider(

  'tenant_a_key',        -- 内部密钥名

  'vault',               -- Provider 名(已注册)

  '{"key_id": "..."}'    -- Provider 端参数

);

关键点:必须在每个数据库的会话中独立执行一次,绑定动作是数据库级而非实例级。

典型多租户拓扑

PG · PostgreSQL 实例

­——tenant_a_db --Provider A -- KMS 主密钥 A

——tenant_a_db -- Provider B -- KMS 主密钥 B

——tenant_a_db -- Provider C -- 本地文件

每个数据库独立登记、加密、解密,密钥完全隔离。

5.2 多租户配置操作

1、创建扩展

CREATE EXTENSION pg_tde;

2、添加数据库级 Provider

SELECT pg_tde_add_database_key_provider_vault_v2(

    'db1-provider', 'http://vault:8200', 'tde/data/db1',

    '/etc/postgresql/secrets/token.txt', NULL

);

-- 也可选 KMIP、File、OpenBao 等

-- SELECT pg_tde_add_database_key_provider_kmip('db1-kmip', '127.0.0.1', 5696, '...', '...', '...');

-- SELECT pg_tde_add_database_key_provider_file('db1-file', '/tmp/db1.per');

3、创建主密钥

SELECT pg_tde_create_key_using_database_key_provider('db1-master', 'db1-provider');

4、设置主密钥

SELECT pg_tde_set_key_using_database_key_provider('db1-master', 'db1-provider');

 

六、tde_heap 表访问方法

创建加密表与移除加密。

6.1 使用 tde_heap 创建、加密与移除加密表

① 创建加密表

CREATE TABLE users (

  id BIGSERIAL PRIMARY KEY,

  email TEXT NOT NULL,

  age INT

) USING tde_heap;

② 对已存在的表启用加密

ALTER TABLE users SET ACCESS METHOD tde_heap;

③ 移除加密(回退到 heap)

ALTER TABLE users SET ACCESS METHOD heap;

 验证表的访问方法

SELECT relname, amname

FROM pg_class c

JOIN pg_am am ON c.relam = am.oid

WHERE relname = 'users';

 切换访问方法会触发表重写;大表需评估停机窗口与磁盘空间。

 限制:暂不支持物化视图、外键引用、列引用、复制分区。

 

七、加密校验、加密强制

检查加密状态 + 阻止明文建表。

7.1 校验加密状态 + 强制所有表加密

① 校验数据库中的加密表

SELECT pg_tde_is_encrypted('table_name');

返回值:true 表示表使用 tde_heap 且已绑定密钥,false 表示未加密或密钥缺失。

②开启后任何使用默认 heap 访问方法的 CREATE TABLE 都会被拒绝。

ALTER SYSTEM SET pg_tde.enforce_encryption = ON;

 

-- 重载配置生效

SELECT pg_reload_conf();

 强制开启前务必完成未加密表排查。

 

官方资源与回顾

板块

链接 / 内容

官方文档

docs.percona.com/pg-tde

GitHub

github.com/percona/pg_tde

学习回顾

安装 · 基础配置 · 密钥管理 · 多租户 · tde_heap · 校验与强制

 

结语

PostgreSQL 中文社区认证

与工信部人才交流中心合作,推出 PostgreSQL 初/中/高级证书,证书中明确指定适用于信息技术应用创新人才岗位能力评定要求。

 

PG中级电子-2026.5.jpg

CUUG-公众号名片-900x300.jpg