EMQX AWS KMS + Secrets Manager + 内存文件系统完整方案

📅 2026/6/29 22:15:58
EMQX AWS KMS + Secrets Manager + 内存文件系统完整方案
1. Dashboard 上传证书的存储位置当你在 EMQX Dashboard 中粘贴或上传证书内容时这些数据不会以文件形式写入/etc/emqx/certs/或任何磁盘目录。存储位置证书内容包括私钥被序列化后存储在 EMQX 的内置 Mnesia/RocksDB 数据库中作为集群配置数据的一部分。运行时加载EMQX 在启动监听器或刷新配置时直接从内存中的配置树读取证书 PEM 字符串并传递给 Erlang/OTP 的 SSL 模块全程不落盘。与静态文件的区别/etc/emqx/certs/下的文件仅用于emqx.conf中通过文件路径引用的场景。Dashboard 配置的证书与这些文件完全独立互不覆盖。⚠️安全提示这意味着通过 Dashboard 上传的私钥安全性依赖于 EMQX 内部数据库的访问控制。确保 Dashboard API 启用了强认证且数据库目录权限受严格保护。2. AWS KMS Secrets Manager 内存文件系统完整方案架构概览AWS KMS (加密密钥) ↓ 信封加密 AWS Secrets Manager (存储加密后的 key.pem) ↓ 启动时拉取 解密 Init Script / Sidecar ↓ 写入 tmpfs 内存文件系统 (/run/emqx-secrets/) ↓ 文件路径引用 EMQX (emqx.conf 静态配置)步骤一准备 KMS 密钥并加密私钥存入 Secrets Manager# 1. 创建 KMS 密钥记录 KeyId KEY_ID$(aws kms create-key --description EMQX TLS Key \ --query KeyMetadata.KeyId --output text) # 2. 将 key.pem 加密后存入 Secrets Manager aws secretsmanager create-secret \ --name emqx/tls/server-key \ --description EMQX Server TLS Private Key \ --secret-string file:///etc/emqx/certs/key.pem \ --kms-key-id $KEY_ID 如果 Secret 已存在使用update-secret代替create-secret。步骤二创建 tmpfs 挂载点# 创建专用目录 mkdir -p /run/emqx-secrets chown emqx:emqx /run/emqx-secrets chmod 700 /run/emqx-secrets # 挂载 tmpfs大小按需设置1M 足够存放私钥 mount -t tmpfs -o size1M,mode700,uidemqx,gidemqx tmpfs /run/emqx-secrets # 持久化挂载重启后自动生效 echo tmpfs /run/emqx-secrets tmpfs size1M,mode700,uidemqx,gidemqx,noexec,nosuid,nodev 0 0 \ /etc/fstab步骤三编写启动前拉取脚本创建/usr/local/bin/emqx-fetch-secrets.sh#!/bin/bash set -euo pipefail SECRET_NAMEemqx/tls/server-key OUTPUT_PATH/run/emqx-secrets/key.pem # 从 Secrets Manager 获取并解密KMS 自动解密 aws secretsmanager get-secret-value \ --secret-id $SECRET_NAME \ --query SecretString \ --output text $OUTPUT_PATH # 严格权限 chown emqx:emqx $OUTPUT_PATH chmod 400 $OUTPUT_PATH echo [INFO] EMQX TLS key fetched to $OUTPUT_PATHchmod x /usr/local/bin/emqx-fetch-secrets.sh步骤四集成到 EMQX 启动流程方式 ASystemd Override推荐systemctl edit emqx添加以下内容[Service] ExecStartPre/usr/local/bin/emqx-fetch-secrets.sh # 确保 tmpfs 已挂载 ExecStartPre/bin/mountpoint -q /run/emqx-secrets || /bin/mount /run/emqx-secrets然后重载并重启systemctl daemon-reload systemctl restart emqx方式 BDocker / ECS / EKS 环境在容器 entrypoint 或 init container 中执行拉取脚本确保在 EMQX 主进程启动前完成。步骤五修改 EMQX 配置指向内存文件由于私钥现在通过文件路径提供你需要在emqx.conf中配置而非 Dashboard因为 Dashboard 不支持引用外部文件路径来替代其内部存储listeners.ssl.default { bind 0.0.0.0:9993 ssl_options { certfile /etc/emqx/certs/cert.pem keyfile /run/emqx-secrets/key.pem # ← 指向内存文件系统 cacertfile /etc/emqx/certs/cacert.pem verify verify_peer fail_if_no_peer_cert true } }⚠️重要冲突提醒如果你之前已在 Dashboard 上为同一监听器配置了证书Dashboard 的配置优先级高于emqx.conf。你需要先在 Dashboard 中删除该监听器的 SSL 证书配置或删除整个监听器后重新通过配置文件创建否则 EMQX 仍会使用 Dashboard 中存储的旧证书数据而忽略文件路径。步骤六验证# 1. 确认内存文件存在且权限正确 ls -la /run/emqx-secrets/key.pem # 期望输出: -r-------- 1 emqx emqx ... key.pem # 2. 确认是 tmpfs df -h /run/emqx-secrets # 期望输出: tmpfs 1.0M ... /run/emqx-secrets # 3. 重启 EMQX 后测试 mTLS 连接 mosquitto_pub -h 127.0.0.1 -p 9993 \ --cafile cacert.pem --cert client-cert.pem --key client-key.pem \ -t test/mtls -m hello -d --insecure安全加固清单项目措施tmpfs 防交换noexec,nosuid,nodev已在 fstab 中设置私钥生命周期仅存在于内存EMQX 停止后可选清理rm -f /run/emqx-secrets/key.pemAWS 权限最小化EC2/ECS 角色仅授予secretsmanager:GetSecretValuekms:Decrypt对应密钥审计开启 CloudTrail 监控 Secrets Manager 和 KMS 的访问记录轮换更新 Secrets Manager 中的值后执行systemctl reload emqx触发重新拉取需配合 SIGHUP 处理或重启使用curl -s https://packagecloud.io/install/repositories/emqx/emqx/script.deb.sh | sudo bash sudo apt-get update sudo apt-get install emqx systemctl start emqx systemctl enable emqx emqx ctl status emqx ctl config show mosquitto_pub \ -h 0.0.0.0 \ -p 9993 \ --cafile cacert.pem \ --cert client-cert.pem \ --key client-key.pem \ -t test/mtls \ -m hello mtls \ -d --insecure mosquitto_sub \ -h 0.0.0.0 \ -p 9993 \ --cafile cacert.pem \ --cert client-cert.pem \ --key client-key.pem \ -t test/mtls \ -d --insecure -v