安全加密推理服务

EAS支持配置安全加密环境,允许加密后的模型进行安全部署和推理。该方式提供了多层次的安全保障,确保数据和模型在整个生命周期中的安全性。适用于对敏感数据要求较高的场景,例如金融服务、政府、企业级应用等。本文将详细介绍准备加密模型、进行加密部署以及安全推理的完整流程。

使用流程

本方案主要采用以下流程进行安全加密部署和推理:

  1. 准备加密模型

    • 加密模型:使用GocryptfsSam对模型进行加密,并将加密后的模型上传到数据源中(例如对象存储OSS),方便后续在EAS中进行挂载部署。

    • 存储解密密钥:目前,EAS支持阿里云托管的自建Trustee远程证明服务。在阿里云ACK Serverless中部署Trustee远程证明服务,用于对模型部署环境和推理环境进行安全验证,并使用阿里云密钥管理服务KMS作为解密密钥的存储后端。

  2. 步骤二:使用PAI-EAS部署加密模型

    在使用PAI-EAS部署加密模型时,系统会自动连接Trustee远程证明服务对部署环境进行验证。验证通过后,使用KMS中的密钥解密并挂载模型,然后将其部署为EAS服务。

  3. 步骤三:调用服务进行安全推理

    部署完成后,启用可信网关代理容器,确保所有请求都经过安全检查。通过可信网关向服务发送请求进行安全推理,确保推理过程的安全性和可靠性。

步骤一:准备加密模型

在模型正式上云部署之前,您需要先对模型进行加密,然后将其上传到云存储。解密模型的密钥将由远程证明服务控制的KMS(密钥管理服务)负责托管。请在本地或可信环境中执行模型的加密操作。以部署Qwen2.5-3B-Instruct大模型为例,基于本地环境Alibaba Cloud Linux 3.2104 LTS 64(可访问公网),提供如下指导。

1.准备模型(可选)

说明

如果您已有自己的模型,请跳过本章节,直接进入2.模型加密章节。

以使用modelscope工具下载Qwen2.5-3B-Instruct模型为例,在终端中执行如下命令下载模型。

pip3 install modelscope importlib-metadata
modelscope download --model Qwen/Qwen2.5-3B-Instruct

成功执行命令后,模型将被下载到~/.cache/modelscope/hub/models/Qwen/Qwen2.5-3B-Instruct/目录下。

2.模型加密

PAI-EAS支持如下两种加密方式,本方案以Sam为例。

  • Gocryptfs:基于AES256-GCM,符合开源Gocryptfs标准的加密模式。

  • Sam:阿里云可信AI模型加密格式,保护模型机密性和License内容不被篡改和非法使用。

方案一:执行Sam加密

  1. 首先下载并解压Sam加密模块。

    # 下载Sam加密模块压缩包
    wget https://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/rai/RAI_SAM_SDK_2.1.0-20240731.tgz
    
    # 解压Sam加密模块
    tar xvf RAI_SAM_SDK_2.1.0-20240731.tgz
  2. 使用Sam加密模块加密模型。

    # 进入Sam加密模块的加密目录
    cd RAI_SAM_SDK_2.1.0-20240731/tools
    
    # 加密模型
    ./do_content_packager.sh <模型目录> <明文密钥> <密钥ID>

    其中:

    • <模型目录>:待加密模型所在的目录,可以使用相对路径或绝对路径,例如~/.cache/modelscope/hub/models/Qwen/Qwen2.5-3B-Instruct/

    • <明文密钥>:自定义的加密密钥,有效长度为4 ~ 128字节,例如alibaba@1688。明文密钥是需要上传到远程证明服务(Trustee)的模型解密密钥。

    • <密钥ID>:自定义的密钥标识,有效长度为8 ~ 48字节,例如LD_Demo_0001

    加密结束后,模型将以密文形式存储在当前路径的<密钥ID>目录中。image

方案二:执行Gocryptfs加密

  1. 安装用于加密模型的工具Gocryptfs (目前只支持使用默认参数进行加密的Gocryptfs v2.4.0 版本)。您可以选择以下任意一种方式进行安装:

    (推荐)方式一:直接下载预编译binary

    # 下载预编译Gocryptfs压缩包
    wget https://github.jobcher.com/gh/https://github.com/rfjakob/gocryptfs/releases/download/v2.4.0/gocryptfs_v2.4.0_linux-static_amd64.tar.gz
    
    # 解压并安装
    tar xf gocryptfs_v2.4.0_linux-static_amd64.tar.gz
    sudo install -m 0755 ./gocryptfs /usr/local/bin

    方式二:编译安装Gocryptfs

    ## 安装golang
    yum install go -y
    go env -w GO111MODULE=on
    go env -w GOPROXY=https://goproxy.cn,direct
    
    ## 安装 Gocryptfs
    git clone https://github.com/rfjakob/gocryptfs.git
    cd gocryptfs
    git checkout -b v2.4.0 v2.4.0
    ./build-without-openssl.bash
    sudo install -m 0755 ./gocryptfs /usr/local/bin
  2. 创建Gocryptfs密钥文件,作为模型加密的密钥。在后续步骤中,您需要将该密钥上传到远程证明服务(Trustee)进行托管。

    在本方案中,使用alibaba@1688作为加密模型使用的密钥,密钥内容将存储在cachefs-password文件中。您也可以自定义密钥。

    cat << EOF > ~/cachefs-password
    alibaba@1688
    EOF
  3. 使用已创建的密钥对模型进行加密。

    1. 配置明文模型的路径。

      说明

      在此处配置您刚才下载的明文模型所在路径,如果您有其他模型,请将其替换为目标模型的实际路径。

      PLAINTEXT_MODEL_PATH=~/.cache/modelscope/hub/models/Qwen/Qwen2.5-3B-Instruct/
    2. 使用Gocryptfs对模型目录树进行加密。

      加密完成后,模型将以密文形式存储在./cipher目录中。

      mkdir -p ~/mount
      cd ~/mount
      mkdir -p cipher plain
      
      # 安装Gocryptfs运行时依赖
      sudo yum install -y fuse
      
      # initialize gocryptfs
      cat ~/cachefs-password | gocryptfs -init cipher
      
      # mount to plain
      cat ~/cachefs-password | gocryptfs cipher plain
      
      # move AI model to ~/mount/plain
      cp -r ${PLAINTEXT_MODEL_PATH} ~/mount/plain

3.上传模型

EAS支持将加密模型存储在多种存储后端,并在部署服务时,通过挂载的方式将解密后的模型加载到服务实例中。更多信息请参考服务存储挂载

以对象存储OSS为例,请参考控制台快速入门创建一个存储空间(Bucket)和一个名为qwen-encrypted的目录(例如oss://examplebucket/qwen-encrypted/),然后使用ossutil工具将加密模型上传到该目录(您也可以使用自己的方法上传加密模型),以供推理服务挂载。以Sam加密为例,密文模型上传后的结果如下图所示。若采用Gocryptfs加密方式,模型文件的密文文件名将全部变成加密后的乱码。image

4.搭建远程证明服务和上传密钥

将用于解密模型的密钥托管在远程证明服务中。远程证明服务是用户管理的验证服务,负责对模型和推理服务的运行环境做验证。只有当确认EAS模型部署环境的可信度符合预期条件时,才会注入模型解密密钥实现模型解密挂载。

目前,EAS支持阿里云托管的自建Trustee远程证明服务。您可以使用阿里云ACK Serverless来部署远程证明服务,对模型部署环境和推理环境进行验证。同时,利用阿里云KMS为模型解密密钥提供专业的安全保障。具体操作步骤如下:

重要
  • ACK集群的地域不必与EAS部署服务的目标地域相同。

  • 阿里云KMS实例必须和准备部署的阿里云Trustee远程证明服务所在的ACK集群处于相同地域

  • 在创建KMS实例和ACK集群之前,请先创建专有网络和2个交换机。具体操作,请参见创建和管理专有网络

  1. 首先创建一个阿里云KMS实例作为密钥存储后端。

    1. 前往密钥管理服务控制台,在左侧导航栏选择资源 > 实例管理,然后在软件密钥管理页签创建并启动实例。在启动实例时,请选择与ACK集群相同的专有网络。具体操作,请参见购买和启用KMS实例

      等待大约10分钟,即可启动完毕。

    2. 实例启动完成后,在左侧导航栏选择资源 > 密钥管理,然后在密钥管理页面为该实例创建一个用户主密钥。具体操作,请参见步骤一:创建软件密钥

    3. 在左侧导航栏选择应用接入 > 接入点,然后在接入点页面为该实例创建应用接入点。其中作用域选择已创建的KMS实例。更多配置说明,请参见方式一:快速创建

      应用接入点创建成功后,浏览器会自动下载ClientKey***.zip文件,该zip文件解压后包含:

      • 应用身份凭证内容(ClientKeyContent):文件名默认为clientKey_****.json

      • 凭证口令(ClientKeyPassword):文件名默认为clientKey_****_Password.txt

    4. 资源 > 实例管理页面,单击KMS实例名称,然后在基础信息区域,单击实例CA证书后的下载,导出KMS实例的公钥证书文件PrivateKmsCA_***.pem

  2. 创建ACK服务集群并安装csi-provisioner组件。

    1. 前往创建集群页面,创建ACK Serverless集群,其中关键参数配置说明如下,更多配置说明,请参见创建集群

      1. 集群配置:配置以下参数,完成后单击下一步:组件配置

        关键配置

        描述

        专有网络

        选择使用已有,并勾选为专有网络配置SNAT,否则无法拉取Trustee镜像。

        交换机

        请确保在已有专有网络中创建至少两个虚拟交换机,否则无法暴露公网ALB。

      2. 组件配置:配置以下参数,完成后单击下一步:确认配置

        关键配置

        描述

        服务发现

        选择CoreNDS

        Ingress

        选择ALB Ingress,ALB云原生网关实例来源选择新建,并选择两个虚拟交换机。

      3. 确认配置:确认配置信息和使用须知,然后单击创建集群

    2. 集群创建成功后,安装csi-provisioner(托管)组件。具体操作,请参见管理组件

  3. ACK集群中部署Trustee远程证明服务。

    1. 首先通过公网或内网连接集群。具体操作,请参见连接集群

    2. 将已下载的KMS实例的应用身份凭证(clientKey_****.json)、凭证口令(clientKey_****_Password.txt)和CA证书(PrivateKmsCA_***.pem),上传到连接ACK Serverless集群的环境中,并执行以下命令部署Trustee远程证明服务,使用阿里云KMS作为密钥存储后端。

      # 安装插件
      helm plugin install https://github.com/AliyunContainerService/helm-acr
      
      helm repo add trustee acr://trustee-chart.cn-hangzhou.cr.aliyuncs.com/trustee/trustee
      helm repo update
      
      export DEPLOY_RELEASE_NAME=trustee
      export DEPLOY_NAMESPACE=default
      export TRUSTEE_CHART_VERSION=1.0.0
      
      # 设置ACK集群所在的地域信息,比如cn-hangzhou
      export REGION_ID=cn-hangzhou
      
      # 刚才导出的KMS实例相关信息 
      # 替换为您的KMS实例ID
      export KMS_INSTANCE_ID=kst-hzz66a0*******e16pckc
      # 替换为您的KMS实例应用身份凭证所在路径 
      export KMS_CLIENT_KEY_FILE=/path/to/clientKey_KAAP.***.json
      # 替换为您的KMS实例凭证口令所在路径 
      export KMS_PASSWORD_FILE=/path/to/clientKey_KAAP.***_Password.txt
      # 替换为您的KMS实例CA证书所在路径
      export KMS_CERT_FILE=/path/to/PrivateKmsCA_kst-***.pem
      
      helm install ${DEPLOY_RELEASE_NAME} trustee/trustee \
        --version ${TRUSTEE_CHART_VERSION} \
        --set regionId=${REGION_ID} \
        --set kbs.aliyunKms.enabled=true \
        --set kbs.aliyunKms.kmsIntanceId=${KMS_INSTANCE_ID} \
        --set-file kbs.aliyunKms.clientKey=${KMS_CLIENT_KEY_FILE} \
        --set-file kbs.aliyunKms.password=${KMS_PASSWORD_FILE} \
        --set-file kbs.aliyunKms.certPem=${KMS_CERT_FILE} \
        --namespace ${DEPLOY_NAMESPACE}
      说明

      执行代码中第一条安装插件命令(helm plugin install...)可能需要较长时间。如果安装失败,可以先通过helm plugin uninstall cm-push命令卸载该插件,然后重新执行插件安装命令。

      返回结果示例为:

      NAME: trustee
      LAST DEPLOYED: Tue Feb 25 18:55:33 2025
      NAMESPACE: default
      STATUS: deployed
      REVISION: 1
      TEST SUITE: None
    3. 在连接ACK Serverless集群的环境中执行如下命令,来获取Trustee的访问地址。

      export TRUSTEE_URL=http://$(kubectl get AlbConfig alb -o jsonpath='{.status.loadBalancer.dnsname}')/${DEPLOY_RELEASE_NAME}
      echo ${TRUSTEE_URL}

      返回结果示例为http://alb-ppams74szbwg2f****.cn-shanghai.alb.aliyuncsslb.com/trustee

    4. 在连接ACK Serverless集群的环境中执行以下命令,测试Trustee服务的连通性。

      cat << EOF | curl -k -X POST ${TRUSTEE_URL}/kbs/v0/auth -H 'Content-Type: application/json' -d @-
      {
          "version":"0.1.0",
          "tee": "tdx",
          "extra-params": "foo"
      }
      EOF

      Trustee服务运行状态正常,预期输出如下:

      {"nonce":"PIDUjUxQdBMIXz***********IEysXFfUKgSwk=","extra-params":""}
  4. 配置Trustee网络白名单。

    说明

    本项配置的目的是允许PAI-EAS模型部署环境主动访问远程证明服务,进行环境安全性检查。

    1. 前往阿里云ALB负载均衡控制台,创建访问控制策略组,并将访问Trustee权限的地址/地址段添加为IP条目。具体操作,请参见访问控制。其中,需要添加的地址段如下:

      • 部署EAS服务时绑定的专有网络的公网IP地址。

      • 推理客户端的出口IP地址。

    2. 使用如下命令获得集群上Trustee实例使用的ALB负载均衡实例ID。

      kubectl get ing --namespace ${DEPLOY_NAMESPACE} kbs-ingress -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | cut -d'.' -f1 | sed 's/[^a-zA-Z0-9-]//g'

      预期输出如下结果:

      alb-llcdzbw0qivhk0****
    3. 阿里云ALB负载均衡控制台左侧导航栏,选择应用型负载均衡ALB > 实例,在集群所在地域下搜索上一步获得的ALB实例,并单击实例ID进入实例详情页面。然后在页面最下方实例属性区域,单击关闭配置修改保护

    4. 切换到监听页面,单击目标监听实例访问控制列下的启用,并配置白名单为上述步骤创建的访问控制策略组。

  5. 创建凭据来存储模型解密密钥。

    Trustee托管的模型解密密钥实际上存储在KMS中,只有在远程证明服务验证目标环境后,密钥才能被访问。

    前往密钥管理服务控制台,在左侧导航栏选择资源 > 凭据管理,然后在通用凭据页签,单击创建凭据。其中关键配置说明如下:

    • 凭据名称:自定义凭据名称,用于索引该密钥,例如model-decryption-key

    • 设置凭据值:填写加密模型时使用的密钥。例如alibaba@1688,您的密钥以实际为准。

    • 加密主密钥:选择上述步骤创建的主密钥。

步骤二:使用PAI-EAS部署加密模型

  1. 登录PAI控制台,在页面上方选择目标地域,并在右侧选择目标工作空间,然后单击进入EAS

  2. 模型在线服务(EAS)页面,单击部署服务,然后在自定义模型部署区域,单击自定义部署

  3. 自定义部署页面,配置以下关键参数,其他参数配置说明,请参见服务部署:控制台

    参数

    描述

    环境信息

    部署方式

    选择镜像部署

    镜像配置

    选择镜像。在本方案示例场景中,选择官方镜像>chat-llm-webui:3.0-vllm

    模型配置

    单击+OSS按钮,并配置以下参数:

    • OSS:请选择模型密文所在的目录。例如oss://examplebucket/qwen-encrypted/,您的路径以实际为准。

    • 挂载路径:配置为模型明文挂载的目录,例如/mnt/model

    运行命令

    配置示例为python webui/webui_server.py --port=8000 --model-path=/mnt/model --backend=vllm。请注意,--model-path需要与挂载路径保持一致,用于读取解密后的模型。

    端口号

    本方案将端口号配置为8000。

    环境变量

    可添加环境变量,用于Trustee远程证明服务验证使用。本方案添加环境变量为:键eas-test:值123

    资源部署

    部署资源

    本方案资源规格选择ecs.gn7i-c8g1.2xlarge。

    专有网络

    专有网络(VPC)

    配置专有网络设置专有网络的SNAT公网出口IP,为EAS开通公网访问,以便能访问远程证明服务,并进行环境安全性检查。

    交换机

    安全组名称

    服务功能

    配置安全加密环境

    打开配置安全加密环境开关,并配置以下参数:

    • 文件加密方式:模型加密时使用的加密方式。支持SamGocryptfs。本方案选择Sam。

    • 系统信任管理服务地址:部署的Trustee服务地址。例如http://alb-ppams74szbwg2f****.cn-shanghai.alb.aliyuncsslb.com/trustee

    • 解密密钥的KBS URI:使用的模型解密密钥的KBS URI,格式为kbs:///default/aliyun/<密钥的凭据名称>。请将<密钥的凭据名称>替换为上述步骤已创建的凭据名称。

    最终得到的JSON配置示例如下:

    单击此处查看JSON配置

    {
        "cloud": {
            "computing": {
                "instances": [
                    {
                        "type": "ecs.gn7i-c8g1.2xlarge"
                    }
                ]
            },
            "networking": {
                "security_group_id": "sg-2vcbmhs3puagy23k****",
                "vpc_id": "vpc-2vctxcm4qncgriz0j****",
                "vswitch_id": "vsw-2vc0tdylfux849zb7****"
            }
        },
        "confidential": {
            "decryption_key": "kbs:///default/aliyun/model-decryption-key",
            "trustee_endpoint": "http://alb-ppams74szbwg2f****.cn-shanghai.alb.aliyuncsslb.com/trustee"
        },
        "containers": [
            {
                "env": [
                    {
                        "name": "eas-test",
                        "value": "1234"
                    }
                ],
                "image": "eas-registry-vpc.cn-hangzhou.cr.aliyuncs.com/pai-eas/chat-llm-webui:3.0.5-vllm",
                "port": 8000,
                "script": "python webui/webui_server.py --port=8000 --model-path=--model-path=/mnt/data/model --backend=vllm"
            }
        ],
        "metadata": {
            "cpu": 8,
            "gpu": 1,
            "instance": 1,
            "memory": 30000,
            "name": "xynnn_eas_test_gpu"
        },
        "storage": [
            {
                "encryption": {
                    "method": "sam"
                },
                "mount_path": "/mnt/data/model",
                "oss": {
                    "path": "oss://examplebucket/qwen-encrypted/"
                },
                "properties": {
                    "resource_type": "model"
                }
            }
        ]
    }
  4. 参数配置完成后,单击部署

    服务状态为运行中时,表明服务已成功部署。此时,您可以在集群列表页面单击目标集群名称,然后在容器组页面按照下图操作指引,查看attestation-service-*容器日志。日志中会显示Trustee远程证明服务是否已对模型部署环境进行了验证,并详细展示执行环境信息等。image

步骤三:调用服务进行安全推理

1.查看服务访问地址

模型在线服务(EAS)页面,单击目标服务的服务方式列下的调用信息,获取服务访问地址和Token。image

2.调用EAS服务

  1. 在终端中执行如下命令,启动可信网关代理容器。其中${TRUSTEE_URL}需要替换为Trustee地址(请参考4.搭建远程证明服务和上传密钥,查看Trustee地址)。

    说明

    目前可信网关代理服务仅支持容器部署,请在终端上安装Docker

    docker run -d \
        --network=host \
        confidential-ai-registry.cn-shanghai.cr.aliyuncs.com/product/tng:1.0.3 \
        tng launch --config-content '
          {
            "add_ingress": [
              {
                "http_proxy": {
                  "proxy_listen": {
                    "host": "0.0.0.0",
                    "port": 41000
                  },
                  "dst_filters": [
                    {
                      "domain": "*.pai-eas.aliyuncs.com",
                      "port": 80
                    }
                  ]
                },
                "encap_in_http": {
                  "path_rewrites": [
                    {
                      "match_regex": "^/api/predict/([^/]+)([/]?.*)$",
                      "substitution": "/api/predict/\\1"
                    }
                  ]
                },
                "verify": {
                  "as_addr": "${TRUSTEE_URL}/as",
                  "policy_ids": [
                    "default"
                  ]
                }
              }
            ]
          }
    '
  2. 待可信网关代理容器启动完成后,您可以执行如下cURL命令,向推理服务发起推理请求。

    重要

    请将推理客户端的出口IP添加到Trustee ALB的白名单中。具体操作,请参见4.配置Trustee网络白名单。若未添加,服务会调用失败。

    export http_proxy=http://127.0.0.1:41000
    curl <Service_URL> \
      -H "Content-type: application/json" \
      --data-binary @openai_chat_body.json \
      -v \
      -H "Connection: close" \
      -H "Authorization: <Token>"

    其中

    • <Service_URL>:配置为EAS服务访问地址。

    • <Token>:配置为EAS服务Token。

    • openai_chat_body.json为原始推理请求,请求内容示例如下:

      {
          "max_new_tokens": 4096,
          "use_stream_chat": false,
          "prompt": "What is the capital of Canada?",
          "system_prompt": "Act like you are a knowledgeable assistant who can provide information on geography and related topics.",
          "history": [
              [
                  "Can you tell me what's the capital of France?",
                  "The capital of France is Paris."
              ]
          ],
          "temperature": 0.8,
          "top_k": 10,
          "top_p": 0.8,
          "do_sample": true,
          "use_cache": true
      }

    返回结果示例如下:

    {
        "response": "The capital of Canada is Ottawa.",
        "history": [
            [
                "Can you tell me what's the capital of France?",
                "The capital of France is Paris."
            ],
            [
                "What is the capital of Canada?",
                "The capital of Canada is Ottawa."
            ]
        ]
    }