docker 和k8s 环境下达梦数据库开启ssl连接配置流程

背景

项目安全性要求,需要达梦开启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

其中有几个注意事项:

  1. 证书主题中,CN=SYSDBA,SYSDBA是登录达梦的账号,如果不正确,握手阶段会失败,自己在这踩坑了
  2. 步骤2中,生成的ca-key.pem 做了解密,目的是自动化脚步执行不用输入密码,所以步骤7拷贝ca-key.pem的时候,拷贝的是加密的ca-key.pem,这里我没注意,一致报 ssl enviorment init failed
  3. 如果用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环境

  1. 先创建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
  1. 将证书挂载到容器目录下:/opt/ca/server_ssl
  2. 将/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

  1. 创建secret
bash 复制代码
kubectl create secret generic dm8-client-ssl --from-file=/home/liuhao7/dm_ssl/client_ssl/SYSDBA -n weave
  1. 挂载到容器内, 并修改权限,这步可以参照 dm k8s部署流程

  2. 修改数据url,这步可以参照 java连接验证。

相关推荐
瀚高PG实验室2 小时前
表空间迁移
数据库·瀚高数据库
Andy Dennis2 小时前
1panel阿里云部署
阿里云·docker·云计算·1panel
无级程序员2 小时前
k8s部署nacos 3.1.1服务,java.net.UnknownHostException问题终极解决方案
java·nacos·kubernetes
从入门到放弃-咖啡豆2 小时前
服务器部署docker 运行.NET 8 项目
服务器·docker·容器
2401_873587822 小时前
Linux——高级IO
服务器·数据库·php
liux35282 小时前
使用DataX实现MySQL到MySQL的批量表同步(灵活配置方案)
数据库·mysql
程序员夏末2 小时前
【JchatMind智能体 | 第二天】为何选 PostgreSQL + pgvector 而非 MySQL?
数据库·mysql·postgresql·ai编程·ai agent
SMF19192 小时前
【Docker】Linux系统上卸载旧Docker、卸载Podman并重新安装Docker及配置国内镜像源
linux·docker·podman
qq_297574672 小时前
K8s系列第二篇:CentOS7/Ubuntu 一键搭建 K8s 集群(kubeadm 完整版)
ubuntu·容器·kubernetes