Kingbase 身份认证与权限控制实践—数据库安全的第一道防线

0 阅读3分钟

前言

数据库安全体系的建设遵循“纵深防御”原则,而身份认证与权限控制构成了这道防线最核心的基石。本文基于金仓数据库(KingbaseES,简称 KES)的安全架构,结合等保2.0(三级)及行业最佳实践,深入解析如何通过多因素认证、三权分立管理、身份鉴别策略及细粒度访问控制,解决“谁能连”、“连上是谁”以及“能干什么”三大核心安全问题。

本文将从实战角度出发,提供详细的配置案例与生产环境实施建议,帮助数据库管理员构建从网络接入到数据访问的全链路安全闭环。

实验环境统一说明:

数据库版本: KingbaseES V009R002C014
超级管理员: system (密码示例:kingbase)
测试数据库: test
数据目录: $KINGBASE_DATA (通常为安装目录下的/data/kdb/data/kes_oracle文件夹)
核心配置文件: kingbase.conf, sys_hba.conf, sysident.conf

一、 核心安全机制解析

在进入具体案例前,我们需要理解 KES 安全体系的几个关键概念:

基于主机的认证(sys_hba.conf): 这是数据库的大门保安。它通过 IP 地址、连接方式(TCP/IP 或 Local)、数据库对象和用户名来决定是否允许连接,以及使用何种认证方式(如 SSL、SCRAM-SHA-256)。

三权分立: 这是内部管理的权力制衡机制。将传统超级用户的权限拆分为数据库管理员(DBA/SYSTEM)、安全管理员(SSO)和审计管理员(SAO),防止权限滥用和内部威胁。

身份鉴别: 这是对“钥匙”的严格检查。不仅验证密码,还通过密码复杂度、有效期、登录失败锁定等策略,确保账户本身的安全强度。

细粒度访问控制: 这是数据访问的“最小权限原则”。通过行级安全(RLS)和列级权限控制,确保用户只能看到被授权的数据。

二、 详细测试配置案例

案例 1:构建 SSL 加密传输与双向认证通道

场景描述: 生产环境中,客户端与数据库服务器之间的网络传输面临嗅探和中间人攻击的风险。本案例要求客户端必须通过 SSL 加密通道连接,且客户端必须出示由受信任 CA 签发的证书,实现“双向认证”。

实施步骤:

1. 证书准备(在 CA 服务器或数据库服务器执行)

使用 OpenSSL 模拟生成 CA 证书、服务器证书和客户端证书。

# 1.1 创建 CA 私钥与根证书
openssl genrsa -out rootca.key 2048
openssl req -new -x509 -days 3650 -key rootca.key -out rootca.crt -subj "/CN=KingbaseRootCA"

# 1.2 创建服务器证书(CN 必须为服务器主机名或 IP)
openssl genrsa -out kingbase.key 2048
openssl req -new -key kingbase.key -out kingbase.csr -subj "/CN=192.168.40.128" 
openssl x509 -req -days 365 -in kingbase.csr -CA rootca.crt -CAkey rootca.key -CAcreateserial -out kingbase.crt

# 1.3 创建客户端证书(CN 可设为用户标识)
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/CN=app_client"
openssl x509 -req -days 365 -in client.csr -CA rootca.crt -CAkey rootca.key -CAcreateserial -out client.crt

image.png

2. 服务端配置

将 kingbase.crt、kingbase.key、rootca.crt 放入数据目录(/data/kdb/data/kes_oracle),并修改权限。

[kingbase@shanjia ~]$ cp kingbase.crt /data/kdb/data/kes_oracle/
[kingbase@shanjia ~]$ cp kingbase.key /data/kdb/data/kes_oracle/
[kingbase@shanjia ~]$ cp rootca.crt  /data/kdb/data/kes_oracle/
# 修改文件所有者为数据库运行用户(根据需要进行执行)
chown kingbase:kingbase /data/kdb/data/kes_oracle/kingbase.crt /data/kdb/data/kes_oracle/kingbase.key /data/kdb/data/kes_oracle/rootca.crt
# 私钥必须严格限制权限
chmod 600 /data/kdb/data/kes_oracle/kingbase.key

image.png

修改 kingbase.conf 开启 SSL:

ssl = on
ssl_cert_file = 'kingbase.crt'
ssl_key_file = 'kingbase.key'
ssl_ca_file = 'rootca.crt'

image.png

修改 sys_hba.conf,强制要求 SSL 连接且验证客户端证书:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
hostssl all             all             0.0.0.0/0               scram-sha-256 clientcert=verify-ca

image.png PS: clientcert=verify-ca 表示服务器会验证客户端证书是否由受信任的 CA 签发。

重启数据库服务:

sys_ctl restart -D $KINGBASE_DATA

image.png

3. 客户端配置与连接测试

将 rootca.crt(CA 证书)、client.crt(客户端证书)、client.key(客户端私钥)复制到客户端机器。

# 客户端连接命令
ksql "host=192.168.40.128 port=54321 dbname=test user=system sslmode=verify-ca sslrootcert=rootca.crt sslcert=client.crt sslkey=client.key"

连接成功后,在 KSQL 中执行:

image.png

如果感觉上边得命令比较繁琐得话,可以考虑使用下边得方法:

1、在当前用户家目录创建.kingbase的隐藏文件夹。

mkdir .kingbase

2、将rootca.crt、kingbase.crt、kingbase.key拷贝进/home/kingbase/.kingbase的文件夹。

cp rootca.crt /home/kingbase/.kingbase/
cp kingbase.crt /home/kingbase/.kingbase/
cp kingbase.key /home/kingbase/.kingbase/

3、证书私钥重新授权。

ls -l .kingbase

4、客户端连接测试

ksql -h 127.0.0.1 -p 54321 -U system -d test

image.png

经验证也可以达到同样得效果哦。

生产环境提示:

证书轮换:建议建立证书到期监控机制,提前更新证书。 CRL/OCSP:在高安全场景下,建议配置证书吊销列表(CRL),以便及时阻断离职员工的证书访问。

案例 2:实施“三员分立”与权限边界控制

场景描述: 默认情况下,数据库超级用户权力过大。本案例通过三员分立机制,确保 DBA 无法查看审计日志,审计员无法修改业务数据,安全管理员只能管理用户和策略。

实施步骤:

1. 初始化与账户加固

KES 初始化后默认存在 system(DBA)、sso(安全管理员)、sao(审计管理员)。 生产环境第一步:立即修改三个默认账户的密码。

使用 system 登录
ALTER USER system PASSWORD 'ShanjiaPass@2026';

使用 sso 登录
ALTER USER sso PASSWORD 'ShanjiaPass@2026';

使用 sao 登录
ALTER USER sao PASSWORD 'ShanjiaPass@2026';

image.png

2. 权限边界验证测试

测试 A:DBA 权限边界

使用system 用户尝试查看审计记录
SELECT * FROM sysaudit_record_sao LIMIT 1;

image.png

结果:报错 "权限拒绝" 说明:DBA 虽然是超级用户,但在三权分立模式下无法查看审计日志,防止监守自盗。

测试 B:审计管理员(SAO)权限边界

sao 用户登录
\c test sao
查看审计记录(成功)
 SELECT * FROM sysaudit_record_sao LIMIT 1;

尝试创建业务表(失败)
CREATE TABLE illegal_table(id int);
结果:报错 "ERROR:  权限拒绝: sso 和 sao 用户不允许使用DDL和DCL语句"
说明:审计员只能审计,不能进行业务操作。

image.png

测试 C:安全管理员(SSO)权限边界

sso 用户登录

\c - sso
创建业务用户(成功)
CREATE USER shanjia_user PASSWORD 'shanjiaPass@123';

-- 尝试查询业务数据(失败)
SELECT * FROM t01;
结果:报错 "ERROR:  对表 t01 权限不够"
说明:SSO 只能管理用户和权限,不能访问业务数据。

image.png

3. 进阶:启用受限 DBA(生产推荐)

为了进一步限制 DBA 对用户数据的直接访问,可启用 restricted_dba 插件。

修改 kingbase.conf:

shared_preload_libraries = 'restricted_dba'

进行启用和创建插件:
system用户登录
create extension restricted_dba;
\c - sso
ALTER SYSTEM SET restricted_dba.restricted_enable =on;
SELECT sys_reload_conf();

重启后,system 用户将无法直接查询或修改普通用户的表数据,只能进行数据库运维管理。 image.png

restricted_dba插件则极大地限制了超级用户(如SYSTEM)对其他用户对象的越权操作能力,为用户数据资产提供了更强的隔离保护。

案例 3:构建纵深防御的身份鉴别体系

场景描述: 仅依靠密码是不够的。本案例将配置“密码复杂度 + 登录失败锁定 + 密码过期”三重策略,构建强身份鉴别机制。

实施步骤:

1. 加载安全插件

修改 kingbase.conf及后续启用操作:

shared_preload_libraries = 'passwordcheck, identity_pwdexp'
sys_ctl restart -D /data/kdb/data/kes_oracle
创建插件:
CREATE EXTENSION passwordcheck;
CREATE EXTENSION identity_pwdexp;

image.png

2. 配置密码复杂度策略

sso用户登录

\c - sso
#至少包含 1 个大写字母
ALTER SYSTEM SET passwordcheck.password_condition_upper = 1;
#至少包含 2 个数字
ALTER SYSTEM SET passwordcheck.PASSWORD_condition_digit= 2;
#至少包含 1 个特殊字符
ALTER SYSTEM SET passwordcheck.PASSWORD_condition_punct= 1;
#密码最小长度 10 位
ALTER SYSTEM SET passwordcheck.password_length = 10;
#创建用户时,如果指定了密码,不显式指定密码过期时间,默认自动设置密码过期时间为7天
ALTER SYSTEM SET identity_pwdexp.password_change_interval = 7;

SELECT sys_reload_conf();
##PS:可以根据自身公司实际要求进行操作和配置

image.png

测试验证:

尝试创建弱口令用户
CREATE USER weak_user PASSWORD '123456';
结果:报错 "密码长度6太短,应该比最小密码长度10长."

创建符合要求的用户
CREATE USER strong_user PASSWORD 'StrongPass@2026';
结果:成功

image.png

生产环境提示

弱口令扫描:定期运行弱口令扫描工具,检查存量账户是否存在弱密码。 密码历史:启用密码历史管理,防止用户在几次修改后循环使用旧密码。

案例 4:基于 VPD 的行级数据隔离

=====================================================
  案例:基于VPD的银行客户数据行级隔离
  场景描述:银行客户经理只能查看自己负责的客户账户信息
  数据库:KingbaseES (KES)
=====================================================

#### 1. 数据准备(使用system管理员登录)
ksql -h 127.0.0.1 -p 54321 -U system -d test

创建银行业务schema
CREATE SCHEMA IF NOT EXISTS bank;

创建客户账户表
CREATE TABLE bank.customer_account (
    account_id SERIAL PRIMARY KEY,
    customer_name VARCHAR(50) NOT NULL,
    customer_id VARCHAR(20) UNIQUE NOT NULL,  
    account_type VARCHAR(20),                 
    balance DECIMAL(15,2),                    
    manager_name VARCHAR(50),                  
    branch_code VARCHAR(10),                  
    created_date DATE DEFAULT CURRENT_DATE,
    status VARCHAR(10) DEFAULT 'ACTIVE'        
);

创建交易记录表(扩展场景)
CREATE TABLE bank.transaction_log (
    trans_id SERIAL PRIMARY KEY,
    account_id INT REFERENCES bank.customer_account(account_id),
    trans_type VARCHAR(20),                    -- 交易类型:存款、取款、转账等
    amount DECIMAL(15,2),
    trans_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    operator VARCHAR(50)
);

插入测试数据
INSERT INTO bank.customer_account (customer_name, customer_id, account_type, balance, manager_name, branch_code) VALUES
('张三丰', '410101199001011234', '储蓄账户', 158000.00, '张经理', 'BJ001'),
('李四光', '410101199002022345', '理财账户', 500000.00, '王经理', 'SH002'),
('王建国', '410101199003033456', '对公账户', 2500000.00, '张经理', 'BJ001'),
('赵丽颖', '410101199004044567', '储蓄账户', 89200.50, '李经理', 'GZ003'),
('刘德华', '410101199005055678', '理财账户', 1200000.00, '王经理', 'SH002'),
('陈奕迅', '410101199006066789', '储蓄账户', 35000.00, '张经理', 'BJ001');

插入交易记录
INSERT INTO bank.transaction_log (account_id, trans_type, amount, operator) VALUES
(1, '存款', 50000.00, '张经理'),
(1, '取款', 2000.00, '张经理'),
(2, '理财购买', 100000.00, '王经理'),
(3, '转账', 300000.00, '张经理'),
(4, '存款', 10000.00, '李经理'),
(5, '理财赎回', 50000.00, '王经理'),
(1, '转账', 8000.00, '张经理');

启用行级安全
ALTER TABLE bank.customer_account ENABLE ROW LEVEL SECURITY;
ALTER TABLE bank.transaction_log ENABLE ROW LEVEL SECURITY;

image.png

2. 创建用户与授权

创建客户经理用户
CREATE USER manager_zhang PASSWORD 'ZhangMgr@2024';
CREATE USER manager_wang PASSWORD 'WangMgr@2024';
CREATE USER manager_li PASSWORD 'LiMgr@2024';

授予schema权限
GRANT USAGE ON SCHEMA bank TO manager_zhang, manager_wang, manager_li;

授予表权限
GRANT SELECT, UPDATE(balance, status) ON bank.customer_account TO manager_zhang, manager_wang, manager_li;
GRANT SELECT, INSERT ON bank.transaction_log TO manager_zhang, manager_wang, manager_li;
GRANT USAGE ON SEQUENCE bank.transaction_log_trans_id_seq TO manager_zhang, manager_wang, manager_li;

image.png

3. 创建行级安全策略

策略1:客户经理只能查看自己负责的客户账户
CREATE POLICY policy_manager_zhang ON bank.customer_account
    FOR ALL
    TO manager_zhang
    USING (manager_name = '张经理')
    WITH CHECK (manager_name = '张经理');  

CREATE POLICY policy_manager_wang ON bank.customer_account
    FOR ALL
    TO manager_wang
    USING (manager_name = '王经理')
    WITH CHECK (manager_name = '王经理');

CREATE POLICY policy_manager_li ON bank.customer_account
    FOR ALL
    TO manager_li
    USING (manager_name = '李经理')
    WITH CHECK (manager_name = '李经理');

image.png

策略2:交易记录通过关联账户表自动隔离
创建函数用于获取当前用户的关联账户ID列表
CREATE OR REPLACE FUNCTION bank.get_user_accounts()
RETURNS SETOF INT AS $$
BEGIN
    RETURN QUERY 
    SELECT account_id 
    FROM bank.customer_account 
    WHERE manager_name = CURRENT_USER;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

交易记录表的安全策略:只能查看自己负责客户的交易记录
CREATE POLICY policy_transaction_isolation ON bank.transaction_log
    FOR SELECT
    TO manager_zhang, manager_wang, manager_li
    USING (
        account_id IN (
            SELECT account_id 
            FROM bank.customer_account 
            WHERE manager_name = CURRENT_USER
        )
    );

插入交易记录时自动验证权限
CREATE POLICY policy_transaction_insert ON bank.transaction_log
    FOR INSERT
    TO manager_zhang, manager_wang, manager_li
    WITH CHECK (
        account_id IN (
            SELECT account_id 
            FROM bank.customer_account 
            WHERE manager_name = CURRENT_USER
        )
    );

image.png

4. 验证数据隔离效果

4.1 验证张经理的权限
\c test manager_zhang

查看自己的客户列表(应该看到3条记录:张三丰、王建国、陈奕迅)
SELECT account_id, customer_name, account_type, balance, manager_name 
FROM bank.customer_account;

尝试查看其他经理的客户(应该看不到)
预期结果:只显示 manager_name = '张经理' 的记录

image.png

更新客户信息(允许修改余额和状态)
UPDATE bank.customer_account 
SET balance = balance + 10000 
WHERE customer_name = '张三丰';
预期:成功更新

尝试更新其他经理的客户(应该失败或影响0行)
UPDATE bank.customer_account 
SET balance = balance + 10000 
WHERE customer_name = '李四光';
预期:UPDATE 0

image.png

尝试为其他经理的客户插入交易记录(应该失败)
INSERT INTO bank.transaction_log (account_id, trans_type, amount, operator) 
VALUES (2, '存款', 10000.00, '张经理');
预期:违反行级安全策略,插入失败

image.png

4.2 验证王经理的权限
\c test manager_wang
SELECT account_id, customer_name, account_type, balance, manager_name 
FROM bank.customer_account;
预期:只显示李四光、刘德华(manager_name = '王经理')

image.png

4.3 验证李经理的权限
\c test manager_li
SELECT account_id, customer_name, account_type, balance, manager_name 
FROM bank.customer_account;
预期:只显示赵丽颖(manager_name = '李经理')

image.png

生产环境提示:

性能优化:VPD 策略中的 USING 子句会自动追加到查询 WHERE 条件中,建议在过滤列(如 doctname)上建立索引,避免全表扫描。 超级用户豁免:默认情况下,表所有者和超级用户不受 RLS 限制。如需强制限制,可使用 ALTER TABLE ... FORCE ROW LEVEL SECURITY。

三、 总结与生产建议

身份认证与权限控制不是单一的技术点,而是一个动态的、闭环的管理体系。通过上述四个案例,我们构建了从网络传输、身份鉴别、权限分离到数据隔离的立体防御网。 生产环境实施建议:

最小权限原则:默认回收 PUBLIC 角色的所有权限,显式授予用户所需的最小权限。 定期审计:利用 SAO 账户定期审查审计日志,重点关注超级用户的操作和异常登录行为。 应急响应:建立账户被锁定、密码丢失等场景的应急响应流程(如文档中提到的 sys_hba.conf 临时修改为 trust 模式重置密码,操作后立即复原)。 配置备份:sys_hba.conf、kingbase.conf 及证书文件应纳入版本控制并定期备份,防止配置丢失或误修改导致服务不可用。

通过严格的身份认证与精细化的权限控制,金仓数据库能够有效抵御来自外部和内部的安全威胁,为企业的核心数据资产筑起一道坚不可摧的防线。