通过在ACK容器环境中集成JCE Provider,可以调用非中国内地GVSM(NIST FIPS)密码机的加密服务,对运行在容器中的应用数据进行加密与解密操作。本文介绍如何制作包含JCE Provider的业务容器镜像,并将其部署到ACK集群中调用密码机。
方案概述
在ACK容器环境中,业务应用通过JCE Provider调用密码机的加密服务。容器启动时,hsm_proxy进程会作为HSM客户端代理运行,负责与密码机实例建立安全连接。业务应用通过JCE Provider接口发起加解密请求,JCE Provider将请求转发给hsm_proxy,由hsm_proxy与密码机实例通信完成实际的密码运算。
整体部署流程如下:
制作业务容器镜像:将HSM客户端工具、JCE Provider和业务应用JAR打包到Docker镜像中。
推送镜像至ACR:将构建好的镜像推送到阿里云容器镜像服务。
部署应用到ACK:在ACK集群中创建保密字典存储认证信息,然后部署业务镜像。
ACK集群与密码机实例必须在同一VPC下,否则容器内的hsm_proxy无法连接到密码机实例。
步骤一:制作业务容器镜像
将HSM客户端工具、JCE Provider和业务应用打包为Docker镜像,并根据操作系统选择对应的镜像构建方案。
CentOS系
下载安装包
请参见使用GVSM(NIST FIPS)密码机集群,下载rpm格式v2.03密码机实例管理工具(如
hsm-client-v2.03.15.10-1.x86_64.rpm)。请参见安装JCE Provider,下载rpm格式JCE Provider安装包(如
hsm-client-jce-v2.03.15.10-2.el8.x86_64.rpm)。
在业务代码中集成JCE Provider
准备文件目录
将安装包和JAR文件放置到
/home/deploy/centos目录,目录结构如下:/home/deploy/centos/ ├── pkg/ │ ├── hsm-client-v2.03.15.10-1.x86_64.rpm # 密码机管理工具 │ ├── hsm-client-jce-v2.03.15.10-2.el8.x86_64.rpm # JCE Provider │ └── jdk-8xxxx-linux-x64.rpm # JDK(仅centos:7需要) ├── app.jar # 业务应用JAR └── Dockerfile创建Dockerfile
本文以centos:7作为基础镜像时的Dockerfile的编写方法为例。
说明由于CentOS 7自带的OpenSSL版本较低,需要编译安装OpenSSL 1.1.1d以满足HSM客户端的依赖要求。
# 使用CentOS 7镜像作为基础镜像 FROM centos:7 WORKDIR / # 将安装包和JAR文件拷贝到镜像 COPY pkg/jdk-8xxxx-linux-x64.rpm . COPY pkg/hsm-client-v2.03.15.10-1.x86_64.rpm . COPY pkg/hsm-client-jce-v2.03.15.10-2.el8.x86_64.rpm . COPY app.jar /app.jar # 安装依赖和HSM客户端,编译安装OpenSSL 1.1.1d RUN yum install -y wget perl gcc zlib-devel make jq \ /jdk-8xxxx-linux-x64.rpm \ /hsm-client-jce-v2.03.15.10-2.el8.x86_64.rpm \ /hsm-client-v2.03.15.10-1.x86_64.rpm && \ yum clean all && \ wget https://www.openssl.org/source/old/1.1.1/openssl-1.1.1d.tar.gz && \ tar -xzf openssl-1.1.1d.tar.gz && \ cd openssl-1.1.1d && \ ./config --prefix=/usr --openssldir=/usr/local/openssl shared -pthread && \ make && make install && \ cd .. && rm -rf openssl-1.1.1d.tar.gz openssl-1.1.1d # 修改HSM客户端配置文件 RUN jq --arg host "$HOSTNAME" --arg crtpath "$CRTPATH" -r \ '.server.hostname=$host | .client.e2e_owner_crt_path=$crtpath' \ /opt/hsm/etc/hsm_proxy.cfg > /opt/hsm/etc/hsm_proxy.tmp && \ mv /opt/hsm/etc/hsm_proxy.tmp /opt/hsm/etc/hsm_proxy.cfg # 设置启动命令 RUN echo '#!/bin/sh' > /entrypoint.sh && \ echo 'printf "%s" "$ISSUERCA" > "$CRTPATH" ' >> /entrypoint.sh && \ echo '/opt/hsm/bin/hsm_proxy /opt/hsm/etc/hsm_proxy.cfg && sleep 1 && java -classpath "/app.jar:/opt/hsm/java/*" app' >> /entrypoint.sh && \ chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]构建镜像
docker build -t <镜像名称>:<版本号> /home/deploy/centos验证镜像是否创建成功
构建完成后,使用以下命令验证镜像是否创建成功:
docker images | grep <镜像名称>
Debian系
下载安装包
请参见使用GVSM(NIST FIPS)密码机集群,下载deb格式v2.03密码机实例管理工具(如
hsm-client-2.03.15.10-20240710_1.x86_64.deb)。请参见安装JCE Provider,下载deb格式JCE Provider安装包(如
hsm-client-jce-2.03.15.10-20240710_1.x86_64.deb)。
在业务代码中集成JCE Provider
准备文件目录将安装包和JAR文件放置到
/home/deploy/debian目录,目录结构如下:/home/deploy/debian/ ├── pkg/ │ ├── hsm-client-2.03.15.10-20240710_1.x86_64.deb # 密码机管理工具 │ └── hsm-client-jce-2.03.15.10-20240710_1.x86_64.deb # JCE Provider ├── app.jar # 业务应用JAR └── Dockerfile创建Dockerfile
本文以openjdk:8-jdk-jre作为基础镜像时的Dockerfile的编写方法为例。
# 使用openjdk:8-jre镜像作为基础镜像 FROM openjdk:8-jre WORKDIR / # 将安装包和JAR文件拷贝到镜像 COPY pkg/hsm-client-2.03.15.10-20240710_1.x86_64.deb . COPY pkg/hsm-client-jce-2.03.15.10-20240710_1.x86_64.deb . COPY app.jar /app.jar # 安装依赖和HSM客户端,编译安装OpenSSL 1.1.1d RUN apt-get update && \ apt-get install -y libncurses5 libtinfo5 dpkg wget make perl libtool zlib1g-dev jq && \ rm -rf /var/lib/apt/lists/* && \ dpkg -i /hsm-client-2.03.15.10-20240710_1.x86_64.deb \ /hsm-client-jce-2.03.15.10-20240710_1.x86_64.deb && \ wget https://www.openssl.org/source/old/1.1.1/openssl-1.1.1d.tar.gz && \ tar -xzf openssl-1.1.1d.tar.gz && \ cd openssl-1.1.1d && \ ./config --prefix=/usr --openssldir=/usr/local/openssl shared -pthread && \ make && make install && \ cd .. && rm -rf openssl-1.1.1d.tar.gz openssl-1.1.1d # 修改HSM客户端配置文件 RUN jq --arg host "$HOSTNAME" --arg crtpath "$CRTPATH" -r \ '.server.hostname=$host | .client.e2e_owner_crt_path=$crtpath' \ /opt/hsm/etc/hsm_proxy.cfg > /opt/hsm/etc/hsm_proxy.tmp && \ mv /opt/hsm/etc/hsm_proxy.tmp /opt/hsm/etc/hsm_proxy.cfg # 设置启动命令 RUN echo '#!/bin/sh' > /entrypoint.sh && \ echo 'printf "%s" "$ISSUERCA" > "$CRTPATH" ' >> /entrypoint.sh && \ echo '/opt/hsm/bin/hsm_proxy /opt/hsm/etc/hsm_proxy.cfg && sleep 1 && java -classpath "/app.jar:/opt/hsm/java/*" app' >> /entrypoint.sh && \ chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]构建镜像
docker build --build-arg HOSTNAME=<主密码机IP地址> --build-arg CRTPATH=/opt/hsm/etc/issuerCA.crt -t <镜像名称>:<版本号> /home/deploy/debian验证镜像是否创建成功
构建完成后,使用以下命令验证镜像是否创建成功:
docker images | grep <镜像名称>
步骤二:推送镜像至ACR镜像仓库
登录容器镜像服务控制台,在容器镜像服务实例中创建镜像仓库。
创建ACR镜像仓库
ACR个人版实例:请参考使用个人版实例推送拉取镜像,登录ACR个人版实例并向指定仓库推送如上构建的业务镜像。
ACR企业版实例:请参考使用企业版实例推送和拉取镜像,登录ACR企业版实例并向指定仓库推送如上构建的业务镜像。
执行以下命令登录镜像仓库并推送镜像
# 登录ACR镜像仓库 docker login --username=<用户名> registry.<地域>.aliyuncs.com # 为镜像设置标签 docker tag <镜像名称>:<版本号> registry.<地域>.aliyuncs.com/<命名空间>/<镜像仓库>:<版本号> # 推送镜像 docker push registry.<地域>.aliyuncs.com/<命名空间>/<镜像仓库>:<版本号>说明请将
<地域>替换为ACK集群所在地域(如cn-hongkong),<命名空间>和<镜像仓库>替换为在ACR中创建的命名空间和仓库名称。
步骤三:部署应用
创建ACK集群
如果尚未创建ACK集群,请参见创建ACK托管集群,创建时需注意:
ACK集群与密码机集群必须在同一VPC下,否则容器内的hsm_proxy无法连接到密码机实例。
选择与密码机集群相同的专有网络(VPC),确保容器能通过内网访问密码机实例。
确保节点的安全组规则允许访问密码机实例的通信端口。
配置保密字典
业务程序使用JCE Provider时,需要通过密码机中的加密用户(CU)的用户名和密码进行认证。为避免将敏感信息硬编码到部署参数中,建议使用ACK的保密字典(Secret)机制安全存储认证信息。请参考管理保密字典配置ACK集群的保密字典,配置说明如下:
键 | 示例值 | 说明 |
| crypto_user | 密码机加密用户(CU)的用户名。 |
| 密码机加密用户(CU)的密码。 | |
| -----BEGIN CERTIFICATE----- ********* -----END CERTIFICATE----- | 创建并激活密码机集群时生成的自签名证书内容。 |
通过YAML文件创建
Base64编码:使用YAML创建保密字典时,需要先对值进行Base64编码。
# 生成Base64编码值,以下以生成 HSM_USER为例 echo -n "crypto_user" | base64 # 创建保密字典 kubectl apply -f secret.yaml创建
secret.yaml文件。apiVersion: v1 kind: Secret metadata: name: app-secret type: Opaque data: HSM_USER: <HSM_USER的Base64编码值> HSM_PASSWORD: <HSM_PASSWORD的Base64编码值> ISSUERCA: <ISSUERCA证书内容的Base64编码值>
通过控制台创建
登录容器镜像服务控制台。
在目标集群的> 页面中创建保密字典,逐一添加
HSM_USER、HSM_PASSWORD和ISSUERCA三个键值对。
部署镜像
将ACR镜像仓库中的业务镜像部署至ACK集群的Pod中,具体操作请参见创建无状态工作负载Deployment。
通过YAML文件部署
创建
deployment.yaml文件:在配置中指定保密字典中的数据挂载到/srt目录,并引用环境变量。环境变量参数说明,请参见附录:参数说明。apiVersion: apps/v1 kind: Deployment metadata: name: hsm-jce-app labels: app: hsm-jce-app spec: replicas: 1 selector: matchLabels: app: hsm-jce-app template: metadata: labels: app: hsm-jce-app spec: containers: - name: jce-app image: registry.<地域>.aliyuncs.com/<命名空间>/<镜像仓库>:<版本号> env: - name: HSM_USER valueFrom: secretKeyRef: name: app-secret key: HSM_USER - name: HSM_PASSWORD valueFrom: secretKeyRef: name: app-secret key: HSM_PASSWORD - name: ISSUERCA valueFrom: secretKeyRef: name: app-secret key: ISSUERCA - name: LD_LIBRARY_PATH value: /opt/hsm/lib - name: HSM_PARTITION value: PARTITION_1 - name: CRTPATH value: /path/to/issuerCA.crt - name: HOSTNAME value: <hostname> volumeMounts: - name: secret-volume mountPath: /srt readOnly: true volumes: - name: secret-volume secret: secretName: app-secret执行以下命令部署应用:
kubectl apply -f deployment.yaml
通过控制台部署
登录容器镜像服务控制台。
在目标集群中通过页面创建Deployment。在镜像配置中指定ACR镜像地址,在环境变量中以保密字典方式引用
HSM_USER、HSM_PASSWORD和ISSUERCA。说明请勾选对数据值进行 base64 编码。
验证部署
部署完成后,按照以下步骤验证业务容器是否能正常调用密码机的加密服务。
确认Pod运行状态
预期输出中,Pod状态为
Running且READY列显示1/1。kubectl get pods -l app=hsm-jce-app检查hsm_proxy连接状态
进入Pod查看hsm_proxy进程日志,如果日志中显示连接密码机实例成功的信息,表示hsm_proxy已正常运行。
kubectl exec -it <pod-name> -- cat /opt/hsm/log/hsm_proxy.log验证JCE Provider调用
查看业务应用的运行日志,确认JCE Provider能正常调用密码机的加密服务,如果业务应用能正常完成加解密操作且无异常报错,表示部署成功。
kubectl logs <pod-name>
常见问题
hsm_proxy启动失败,提示连接超时?
确认ACK集群与密码机实例在同一VPC下。
检查安全组规则是否允许ACK节点访问密码机实例的通信端口。
确认Dockerfile中通过
--build-arg HOSTNAME传入的是正确的主密码机IP地址。
JCE Provider认证失败?
确认保密字典中
HSM_USER和HSM_PASSWORD的值与密码机中创建的加密用户(CU)凭证一致。确认保密字典中
ISSUERCA的证书内容完整,包含-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----。如果使用YAML创建保密字典,确认值已正确进行Base64编码。
Docker镜像构建失败,提示OpenSSL编译错误?
确认Dockerfile中已安装编译OpenSSL所需的依赖包(
gcc、make、perl、zlib-devel)。如果编译环境存在网络限制,可先在外部下载OpenSSL源码包,然后通过
COPY指令添加到镜像中。
Pod启动后立即退出(CrashLoopBackOff)?
检查entrypoint.sh脚本是否正确执行:
kubectl logs <pod-name>。确认
CRTPATH环境变量指定的路径存在且有写入权限。确认业务应用JAR文件路径正确且可执行。
附录:参数说明
变量名称 | 值 | 描述 |
| /opt/hsm/lib | HSM客户端动态链接库路径。 |
| PARTITION_1 | HSM分区名称。 |
| 示例:/opt/hsm/etc/issuerCA.crt | 自签名证书在容器中的存储路径。 |
| 无 | 主密码机实例的IP地址,可在密码机实例控制台查看。 |