背景
项目安全性要求,需要达梦开启ssl配置。
配置原理
采用 openssl 生成自签证书,实现dm的ssl连接配置。
前置条件:
服务器已配置 jdk 和 openssl。
java -version
openssl version
我测试用 OpenSSL 1.0.2k-fips 26 Jan 2017 和 OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024) 都可以。
一键生成ssl认证
下面是自己的脚步,参照文档: 达梦数据库主备集群下配置SSL认证加密登录以及问题处理
将文档拷贝到服务器,sh命令执行即可。
bash
#!/bin/bash
set -e # 命令执行失败时立即退出
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # 重置颜色
# 配置变量
PASSWORD="abc123"
CERT_DAYS="3650"
COUNTRY="cn"
STATE="shanghai"
LOCALITY="shanghai"
ORGANIZATION="dameng"
ORG_UNIT="dev"
EMAIL="bac@sensetime.com"
# 证书主题(服务端和客户端需使用不同的 CN,避免 CA 数据库主题冲突)
CA_SUBJECT="/C=${COUNTRY}/ST=${STATE}/L=${LOCALITY}/O=${ORGANIZATION}/OU=${ORG_UNIT}/CN=lw/emailAddress=${EMAIL}"
SERVER_SUBJECT="/C=${COUNTRY}/ST=${STATE}/L=${LOCALITY}/O=${ORGANIZATION}/OU=${ORG_UNIT}/CN=server/emailAddress=${EMAIL}"
CLIENT_SUBJECT="/C=${COUNTRY}/ST=${STATE}/L=${LOCALITY}/O=${ORGANIZATION}/OU=${ORG_UNIT}/CN=SYSDBA/emailAddress=${EMAIL}"
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}DM Database SSL Certificate Generator${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
# ============================== 创建 OpenSSL 配置文件 ==============================
# 生成证书签发所需的 OpenSSL CA 配置
echo -e "${YELLOW}[准备] 创建 OpenSSL 配置文件...${NC}"
cat > /tmp/openssl-ca.cnf << 'EOF'
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /opt/ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
crlnumber = $dir/crlnumber
RANDFILE = $dir/private/.rand
private_key = $dir/ca-key.pem
certificate = $dir/ca-cert.pem
crl = $dir/crl.pem
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
# 为签发的证书附加 usr_cert 扩展
x509_extensions = usr_cert
# 设置证书主题校验策略
policy = policy_match
# 要求申请证书的 C/ST/O 与 CA 保持一致
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 2048
default_md = sha256
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca
string_mask = utf8only
[ req_distinguished_name ]
[ req_attributes ]
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = CA:true
# 定义普通证书扩展项
[ usr_cert ]
basicConstraints = CA:FALSE
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
[ crl_ext ]
authorityKeyIdentifier = keyid:always
EOF
echo -e "${GREEN}✓ OpenSSL 配置文件创建完成${NC}\n"
# ============================== 步骤1: 创建目录结构 ==============================
# 创建 CA、服务端和客户端证书目录
echo -e "${YELLOW}[步骤1] 创建证书目录结构...${NC}"
cd /opt
# 清理旧的证书目录和 CA 数据库
if [ -d "ca" ]; then
echo "清理旧的证书目录..."
rm -rf ca
fi
mkdir -p ca
cd /opt/ca
mkdir -p {certs,crl,newcerts}
# 初始化 CA 数据库文件
# 允许重复主题,便于重复执行脚本
echo "01" > serial
echo "01" > crlnumber
> index.txt
> index.txt.old
echo "unique_subject = no" > index.txt.attr
mkdir -p server_ssl
mkdir -p client_ssl/SYSDBA
echo -e "${GREEN}✓ 目录结构创建完成${NC}\n"
# ============================== 步骤2: 生成CA私钥和根证书 ==============================
# 生成 CA 私钥和自签名根证书
echo -e "${YELLOW}[步骤2] 生成CA私钥和根证书...${NC}"
openssl req -new -x509 -days ${CERT_DAYS} \
-keyout ca-key.pem \
-out ca-cert.pem \
-subj "${CA_SUBJECT}" \
-passout pass:${PASSWORD}
# 去除 CA 私钥密码保护,便于后续自动签发证书
echo -e "${YELLOW}[步骤2.1] 解密CA私钥(去除密码保护)...${NC}"
openssl rsa -in ca-key.pem -out ca-key-decrypted.pem -passin pass:${PASSWORD}
cp ca-key.pem ca-key.pem.bak # 备份原始 CA 私钥
mv ca-key-decrypted.pem ca-key.pem
echo -e "${GREEN}✓ CA证书生成完成${NC}\n"
# ============================== 步骤3: 生成服务端私钥 ==============================
# 生成服务端私钥文件
echo -e "${YELLOW}[步骤3] 生成服务端私钥...${NC}"
openssl genrsa -out server_ssl/server-key.pem 2048
echo -e "${GREEN}✓ 服务端私钥生成完成${NC}\n"
# ============================== 步骤4: 生成服务端证书签名请求 ==============================
# 生成服务端证书签名请求文件
echo -e "${YELLOW}[步骤4] 生成服务端证书签名请求...${NC}"
openssl req -new \
-key server_ssl/server-key.pem \
-out server_ssl/server.csr \
-subj "${SERVER_SUBJECT}"
echo -e "${GREEN}✓ 服务端CSR生成完成${NC}\n"
# ============================== 步骤5: 使用CA签名服务端证书 ==============================
# 使用 CA 为服务端 CSR 签发证书
echo -e "${YELLOW}[步骤5] 使用CA签名服务端证书...${NC}"
openssl ca -config /tmp/openssl-ca.cnf -batch -days ${CERT_DAYS} \
-in server_ssl/server.csr \
-out server_ssl/server-cert.pem \
-notext
echo -e "${GREEN}✓ 服务端证书签名完成${NC}\n"
# ============================== 步骤6: 转换服务端证书格式 ==============================
# 将服务端证书转换为 .cer 格式
echo -e "${YELLOW}[步骤6] 转换服务端证书格式...${NC}"
openssl x509 -in server_ssl/server-cert.pem -out server_ssl/server.cer
echo -e "${GREEN}✓ 证书格式转换完成${NC}\n"
# ============================== 步骤7: 复制CA证书到服务端目录 ==============================
# 将 CA 证书和备份私钥复制到服务端目录
echo -e "${YELLOW}[步骤7] 复制CA证书到服务端目录...${NC}"
cp ca-cert.pem server_ssl/
rm -f server_ssl/ca-key.pem
cp ca-key.pem.bak server_ssl/ca-key.pem
echo -e "${GREEN}✓ CA证书复制完成${NC}\n"
# ============================== 步骤8: 生成客户端私钥(带密码保护) ==============================
# 生成带密码保护的客户端私钥
echo -e "${YELLOW}[步骤8] 生成客户端私钥...${NC}"
openssl genrsa -aes256 \
-out client_ssl/SYSDBA/client-key.pem \
-passout pass:${PASSWORD} 2048
echo -e "${GREEN}✓ 客户端私钥生成完成${NC}\n"
# ============================== 步骤9: 生成客户端证书签名请求 ==============================
# 使用客户端私钥生成证书签名请求文件
echo -e "${YELLOW}[步骤9] 生成客户端证书签名请求...${NC}"
openssl req -new \
-key client_ssl/SYSDBA/client-key.pem \
-out client_ssl/SYSDBA/client.csr \
-subj "${CLIENT_SUBJECT}" \
-passin pass:${PASSWORD}
echo -e "${GREEN}✓ 客户端CSR生成完成${NC}\n"
# ============================== 步骤10: 使用CA签名客户端证书 ==============================
# 使用 CA 为客户端 CSR 签发证书
echo -e "${YELLOW}[步骤10] 使用CA签名客户端证书...${NC}"
openssl ca -config /tmp/openssl-ca.cnf -batch -days ${CERT_DAYS} \
-in client_ssl/SYSDBA/client.csr \
-out client_ssl/SYSDBA/client-cert.pem \
-notext
echo -e "${GREEN}✓ 客户端证书签名完成${NC}\n"
# ============================== 步骤11: 生成PKCS12格式证书 ==============================
# 将客户端证书和私钥打包为 PKCS12 文件
echo -e "${YELLOW}[步骤11] 生成PKCS12格式证书...${NC}"
openssl pkcs12 -export \
-inkey client_ssl/SYSDBA/client-key.pem \
-in client_ssl/SYSDBA/client-cert.pem \
-out client_ssl/SYSDBA/client-pkcs.p12 \
-passin pass:${PASSWORD} \
-passout pass:${PASSWORD}
echo -e "${GREEN}✓ PKCS12证书生成完成${NC}\n"
# ============================== 步骤12: 导入CA证书到keystore ==============================
# 将 CA 证书导入客户端 keystore
echo -e "${YELLOW}[步骤12] 导入CA证书到keystore...${NC}"
keytool -import -alias ca \
-trustcacerts \
-file ca-cert.pem \
-keystore client_ssl/SYSDBA/.keystore \
-deststorepass "${PASSWORD}" \
-noprompt
echo -e "${GREEN}✓ CA证书导入完成${NC}\n"
# ============================== 步骤13: 导入服务端证书到keystore ==============================
# 将服务端证书导入客户端 keystore
echo -e "${YELLOW}[步骤13] 导入服务端证书到keystore...${NC}"
keytool -import -alias server \
-trustcacerts \
-file server_ssl/server.cer \
-keystore client_ssl/SYSDBA/.keystore \
-deststorepass "${PASSWORD}" \
-noprompt
echo -e "${GREEN}✓ 服务端证书导入完成${NC}\n"
# ============================== 步骤14: 导入客户端PKCS12证书到keystore ==============================
# 将客户端 PKCS12 证书导入客户端 keystore
echo -e "${YELLOW}[步骤14] 导入客户端PKCS12证书到keystore...${NC}"
keytool -importkeystore \
-srckeystore client_ssl/SYSDBA/client-pkcs.p12 \
-srcstorepass "${PASSWORD}" \
-srcstoretype PKCS12 \
-keystore client_ssl/SYSDBA/.keystore \
-deststorepass "${PASSWORD}" \
-noprompt
echo -e "${GREEN}✓ 客户端PKCS12证书导入完成${NC}\n"
# ============================== 步骤15: 转换keystore为PKCS12格式 ==============================
# 将客户端 keystore 转换为 PKCS12 格式
echo -e "${YELLOW}[步骤15] 转换keystore为PKCS12格式...${NC}"
keytool -importkeystore \
-srckeystore client_ssl/SYSDBA/.keystore \
-destkeystore client_ssl/SYSDBA/.keystore \
-deststoretype pkcs12 \
-srcstorepass "${PASSWORD}" \
-deststorepass "${PASSWORD}" \
-noprompt
echo -e "${GREEN}✓ Keystore格式转换完成${NC}\n"
# ============================== 步骤16: 复制CA证书到客户端目录 ==============================
# 将 CA 证书复制到客户端目录
echo -e "${YELLOW}[步骤16] 复制CA证书到客户端目录...${NC}"
cp ca-cert.pem client_ssl/SYSDBA/
echo -e "${GREEN}✓ CA证书复制完成${NC}\n"
# ============================== 步骤17: 设置权限 ==============================
# 设置服务端和客户端证书目录权限
echo -e "${YELLOW}[步骤17] 设置目录权限...${NC}"
chmod -R 777 server_ssl
chmod -R 777 client_ssl
echo -e "${GREEN}✓ 权限设置完成${NC}\n"
# 输出证书生成结果
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}证书生成完成!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo -e "证书位置:"
echo -e " 服务端证书: ${YELLOW}/opt/ca/server_ssl/${NC}"
echo -e " 客户端证书: ${YELLOW}/opt/ca/client_ssl/SYSDBA/${NC}"
echo ""
echo -e "统一密码: ${YELLOW}${PASSWORD}${NC}"
echo ""
echo -e "服务端证书文件:"
ls -lh /opt/ca/server_ssl/ | grep -E "\.pem|\.cer"
echo ""
echo -e "客户端证书文件:"
ls -lh /opt/ca/client_ssl/SYSDBA/ | grep -E "\.pem|\.cer|\.p12|\.keystore"
ls -la /opt/ca/server_ssl/
ls -la /opt/ca/client_ssl/SYSDBA/
echo "证书位置:" pwd
其中有几个注意事项:
- 证书主题中,CN=SYSDBA,SYSDBA是登录达梦的账号,如果不正确,握手阶段会失败,自己在这踩坑了
- 步骤2中,生成的ca-key.pem 做了解密,目的是自动化脚步执行不用输入密码,所以步骤7拷贝ca-key.pem的时候,拷贝的是加密的ca-key.pem,这里我没注意,一致报 ssl enviorment init failed
- 如果用k8s部署,一定记得改目录权限:
bash
chmod -R 777 server_ssl
chmod -R 777 client_ssl
自签证书如何用?
docker环境
yaml
version: "3.8"
services:
dm8:
image: dm8_single:latest
container_name: dm8
restart: always
ports:
- "5236:5236"
environment:
# 数据库初始化参数(必须使用 DM_INIT_ 前缀)
- DM_INIT_PATH=/opt/dmdbms/data # 数据库初始化路径
- DM_INIT_PAGE_SIZE=16 # 页大小:16KB(可选,默认8KB)
- DM_INIT_CHARSET=1 # 字符集:0表示GB18030,1表示UTF-8
- DM_INIT_CASE_SENSITIVE=1 # 大小写敏感:0不敏感,1敏感
- DM_INIT_EXTENT_SIZE=16 # 区大小:可选
# 运行时环境
- LD_LIBRARY_PATH=/opt/dmdbms/bin # 动态库搜索路径
- INSTANCE_NAME=dm8_instance # 实例名称
volumes:
# 数据目录
- /home/liuhao7/dm/data:/opt/dmdbms/data
# SSL 证书目录(需要)
- /opt/ca/server_ssl:/opt/dmdbms/bin/server_ssl
- /opt/ca/client_ssl/SYSDBA/:/opt/ca/client_ssl/SYSDBA/
k8s环境
- 先创建secret:
yaml
kubectl create secret generic dm8-server-ssl --from-file=/home/liuhao7/dm_ssl/server_ssl/ -n weave
kubectl create secret generic dm8-client-ssl --from-file=/home/liuhao7/dm_ssl/client_ssl/SYSDBA -n weave
- 将证书挂载到容器目录下:/opt/ca/server_ssl
- 将/opt/ca/下的证书拷贝到 bin目录下,并修改证书权限。
这里分成两步,主要是由于secret直接挂载到bin目录下无法修改目录权限。
yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dm8
namespace: weave
spec:
podManagementPolicy: OrderedReady
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
operator.dameng.com/id: ec74204f-f9ab-4c26-beba-1bea6cf70338
serviceName: mostly-equipped-bunny-hl
template:
metadata:
annotations:
kubectl.kubernetes.io/restartedAt: "2026-03-05T16:17:51+08:00"
labels:
operator.dameng.com/id: ec74204f-f9ab-4c26-beba-1bea6cf70338
spec:
containers:
# k8s中,通过secret创建证书,由于secret无法修改目录权限,采用先拷贝,后改权限的方式。
- command:
- /bin/bash
- -c
- |
echo ">>> 准备 SSL 目录"
cd /opt/dmdbms/bin/
mkdir -p /opt/dmdbms/bin/server_ssl
cp -Lr /opt/ca/server_ssl/* ./server_ssl/
cp -Lr /opt/ca/client_ssl/SYSDBA/* ./client_ssl/SYSDBA/
# 设置证书文件权限
chmod -R 777 server_ssl
chmod -R 777 client_ssl
echo ">>> 启动达梦"
exec /opt/dmdbms/bin/dmserver /opt/dmdbms/data/DAMENG/dm.ini
env:
- name: LD_LIBRARY_PATH
value: /opt/dmdbms/bin
- name: TEMPLATES_PATH
value: /opt/dmdbms/script.d/
- name: BOOTSTRAP_MODEL
value: single
- name: PERSISTENCE_LOGS
value: "false"
- name: REPLICAS
value: "1"
- name: OBJECT_NAME
value: mostly-equipped-bunny
- name: DM_INI_BAK_PATH
value: /opt/dmdbms/backup
- name: DM_INI_MAX_SESSIONS
value: "100"
- name: DM_INIT_SYSDBA_PWD
value: SYSDBA
- name: DM_INIT_PATH
value: /opt/dmdbms/data
- name: DM_INIT_PAGE_SIZE
value: "8"
- name: DM_INIT_EXTENT_SIZE
value: "16"
- name: DM_INIT_CHARSET
value: "0"
- name: DM_INIT_CASE_SENSITIVE
value: "1"
- name: DM_INI_BAK_USE_AP
value: "2"
image: yourDmVersion
imagePullPolicy: IfNotPresent
name: dm8
ports:
- containerPort: 80
name: dmctl
protocol: TCP
- containerPort: 5236
name: dceadbbj
protocol: TCP
resources:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "2"
memory: 4Gi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt/dmdbms/data
name: dm8-data
- mountPath: /opt/ca/server_ssl
name: dm8-server-ssl
- mountPath: /opt/ca/client_ssl/SYSDBA
name: dm8-client-ssl
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: regitsiv
nodeName: host-10-198-20-116
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- hostPath:
path: /opt/dmdbms/data
type: Directory
name: dm8-data
- name: dm8-server-ssl
secret:
secretName: dm8-server-ssl
- name: dm8-client-ssl
secret:
secretName: dm8-client-ssl
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
验证ssl连接
pod内验证
bash
docker exec -it dm8 bash
/opt/dmdbms/bin/disql SYSDBA/SYSDBA001@127.0.0.1:5236#"{SSL_PATH=/opt/ca/client_ssl/SYSDBA/,SSL_PWD=abc123}"
java连接验证
修改数据源url:
bash
dm.ssl.client_ssl.path=/opt/ca/client_ssl/SYSDBA
spring.datasource.url=jdbc:dm://xxx:30236/UUMS?SSL=true&sslFilesPath=${dm.ssl.client_ssl.path}&sslKeystorePass=abc123
k8s环境部署的服务连接ssl
- 创建secret
bash
kubectl create secret generic dm8-client-ssl --from-file=/home/liuhao7/dm_ssl/client_ssl/SYSDBA -n weave
-
挂载到容器内, 并修改权限,这步可以参照 dm k8s部署流程
-
修改数据url,这步可以参照 java连接验证。