本课目标
围绕 pg_tde 透明数据加密,带你走完从安装到加密强制的部署全链路,循序渐进、一步到位。
· 安装部署:本机/容器多种方式安装 pg_tde
· 密钥管理:对接 Vault / KMIP / OpenBao 等外部 KMS
· 加密强制:校验加密状态并强制所有表加密
一、pg_tde 概述
认识什么是 pg_tde 及其加密范围。
1.1 数据加密应用背景
到目前为止(19版本),PostgreSQL 官方仍未提供内核级透明数据加密(TDE)能力。这意味着:
· 所有数据文件(base/、pg_wal/、global/)均以明文形式存储在磁盘
· 即使设置了强访问控制,一旦磁盘被盗、虚拟机镜像被复制、备份文件泄露,数据即完全暴露
· 不符合信创安保条约
可行方案对比:透明加密不是“能不能做”,而是“是否满足合规审计”——等保、密评、关基。

数据来源:https://blog.csdn.net/m0_61703951/article/details/156358939
1.2 数据加密访问流程

数据来源: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 架构总览

· 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 → 返回客户端 (业务层完全无感知)
隔 离:每张加密表有独立密钥,密钥被主密钥包裹 (轮换单个表不影响其他表)

二、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 初/中/高级证书,证书中明确指定适用于信息技术应用创新人才岗位能力评定要求。


