可信空间 Codelab

1. 概览

您是否已准备好提升 GPU 加速工作负载的安全性和隐私性?本 Codelab 将引导您了解 Trusted Space 的功能,Trusted Space 是一项服务,可为处理敏感 AI/机器学习工作负载提供强大的操作员隔离和加速器支持。

保护有价值的数据、模型和密钥比以往任何时候都更加重要。Trusted Space 提供了一种解决方案,可确保您的工作负载在安全可信的环境中运行,即使工作负载操作员也无法访问。

Trusted Space 提供以下功能

  • 增强的隐私性和安全性: Trusted Space 提供可信执行环境,您的敏感资产(例如模型、有价值的数据和密钥)将受到保护,并有加密证明作为后盾。
  • 操作员隔离: 无需担心操作员干扰。借助 Trusted Space,即使您的工作负载操作员也无法访问,从而防止他们通过 SSH 访问、访问数据、安装软件或篡改您的代码。
  • 加速器支持: Trusted Space 旨在与各种硬件加速器无缝协作,包括 H100、A100、T4 和 L4 等 GPU。这可确保对性能至关重要的 AI/机器学习应用顺利运行。

学习内容

  • 了解 Trusted Space 的主要服务。
  • 了解如何部署和配置 Trusted Space 环境,以保护 AI/机器学习工作负载的有价值的资产。

所需条件

使用 Primus 公司保护敏感的代码生成提示

在本 Codelab 中,我们将扮演 Primus 公司的角色,该公司优先考虑员工数据的隐私和安全。Primus 希望部署一个代码生成模型来帮助开发者完成编码任务。不过,他们担心保护员工提交的提示的机密性,因为这些提示通常包含敏感的代码段、内部项目详细信息或专有算法。

为什么 Primus 公司不信任操作员?

Primus 公司在竞争激烈的市场中运营。他们的代码库包含有价值的知识产权,包括专有算法和敏感的代码段,这些代码段提供了竞争优势。他们担心工作负载操作员可能会进行企业间谍活动。此外,员工提示可能包含 Primus 公司想要保护的机密“按需知密”部分的代码。

为了解决此问题,Primus 公司将利用 Trusted Space 来隔离运行代码生成模型的推理服务器。其工作原理如下:

  • 提示加密: 在将提示发送到推理服务器之前,每位员工都将使用 Primus 公司在 Google Cloud 中管理的 KMS 密钥对其进行加密。这可确保只有 Trusted Space 环境(其中提供相应的解密密钥)才能对其进行解密并访问明文提示。在实际场景中,客户端加密功能可以由可用的库(例如 tink)处理。在本 Codelab 中,我们将使用 此示例客户端应用 进行信封加密。
  • 操作员隔离: 只有在 Trusted Space 环境中运行的推理服务器才能访问用于加密的密钥,并且能够在可信的环境下解密提示。加密密钥的访问权限将受到工作负载身份池的保护。由于 Trusted Space 的隔离保证,即使工作负载操作员也无法访问用于加密的密钥和解密的内容。
  • 使用加速器进行安全推理: 推理服务器将在安全强化型虚拟机(作为 Trusted Space 设置的一部分)上启动,这将确保工作负载实例不会受到启动级或内核级 恶意软件rootkit 的危害。此服务器在 Trusted Space 环境中解密提示,使用代码生成模型执行推理,并将生成的代码返回给员工。

2. 设置 Cloud 资源

准备工作

  • 使用以下命令克隆 此代码库,以获取本 Codelab 中使用的必要脚本。
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
  • 更改此 Codelab 的目录。
cd confidential-space/codelabs/trusted_space_codelab/scripts
  • 确保您已设置所需项目环境变量,如下所示。如需详细了解如何设置 GCP 项目,请参阅 此 Codelab。您可以参阅 此文档,详细了解如何检索项目 ID,以及项目 ID 与项目名称和项目编号有何不同。
export PRIMUS_PROJECT_ID=<GCP project id of Primus>
gcloud services enable \
    cloudapis.googleapis.com \
    cloudresourcemanager.googleapis.com \
    cloudkms.googleapis.com \
    cloudshell.googleapis.com \
    container.googleapis.com \
    containerregistry.googleapis.com \
    iam.googleapis.com \
    confidentialcomputing.googleapis.com
  • 使用以下命令为上面指定的资源名称的变量分配值。借助这些变量,您可以根据需要自定义资源名称,也可以使用已创建的现有资源。(例如 export PRIMUS_SERVICE_ACCOUNT='my-service-account'
  1. 您可以使用 Primus 项目中的现有 Cloud 资源名称设置以下变量。如果设置了变量,则会使用 Primus 项目中的相应现有 Cloud 资源。如果未设置变量,则会根据项目名称生成 Cloud 资源名称,并使用该名称创建新的 Cloud 资源。以下是资源名称支持的变量:

$PRIMUS_PROJECT_REGION

Primus 公司将在其下创建区域资源的区域。

$PRIMUS_SERVICE_LOCATION

Primus 公司将在其下创建资源的物理位置。

$PRIMUS_PROJECT_ZONE

Primus 公司将在其下创建可用区资源的可用区。

$PRIMUS_WORKLOAD_IDENTITY_POOL

Primus 公司用于保护 Cloud 资源的工作负载身份池。

$PRIMUS_WIP_PROVIDER

Primus 公司的工作负载身份池提供方,其中包含用于由证明验证器服务签名的令牌的授权条件。

$PRIMUS_SERVICEACCOUNT

Primus 公司的服务账号,$PRIMUS_WORKLOAD_IDENTITY_POOL 使用该账号访问受保护的资源。在此步骤中,它有权查看存储在 $PRIMUS_INPUT_STORAGE_BUCKET 存储分区中的客户数据。

$PRIMUS_ENC_KEY

KMS 密钥用于加密 Primus 公司员工提供的提示。

$PRIMUS_ENC_KEYRING

KMS 密钥环,将用于为 Primus 公司创建加密密钥 $PRIMUS_ENC_KEY

$PRIMUS_ENC_KEYVERSION

加密密钥 $PRIMUS_ENC_KEY 的 KMS 密钥版本。默认值为 1。如果您使用的是过去轮替过的现有密钥,并且其版本已更新,请更新此值。

$PRIMUS_ARTIFACT_REPOSITORY

工作负载 Docker 映像将推送到的制品库。

$PRIMUS_PROJECT_REPOSITORY_REGION

制品库的区域,其中包含已发布的工作负载 Docker 映像。

$WORKLOAD_VM

工作负载虚拟机的名称。

$WORKLOAD_IMAGE_NAME

工作负载 Docker 映像的名称。

$WORKLOAD_IMAGE_TAG

工作负载容器映像的标记。

$WORKLOAD_SERVICEACCOUNT

有权访问运行工作负载的机密虚拟机的服务账号。

$CLIENT_VM

客户端虚拟机的名称,该虚拟机将运行推理服务器的客户端应用。

$CLIENT_SERVICEACCOUNT

$CLIENT_VM 使用的服务账号

  • 您需要为项目 $PRIMUS_PROJECT_ID 拥有 Storage Admin、Artifact Registry Administrator、Cloud KMS Admin、Service Account Admin、IAM 工作负载身份池管理员 角色。您可以参阅 此指南,了解如何使用 GCP 控制台授予 IAM 角色。
  • 对于 $PRIMUS_PROJECT_ID,运行以下 脚本,将剩余的变量名称设置为基于项目 ID 的资源名称值。
source config_env.sh

设置 Primus 公司资源

在此步骤中,您将为 Primus 设置所需的 Cloud 资源。运行以下 脚本 为 Primus 设置资源。在脚本执行过程中,将创建以下资源:

  • KMS 中的加密密钥 ($PRIMUS_ENC_KEY) 和密钥环 ($PRIMUS_ENC_KEYRING),用于加密 Primus 公司的客户数据文件。
  • 工作负载身份池 ($PRIMUS_WORKLOAD_IDENTITY_POOL),用于根据其提供方下配置的特性条件验证声明。
  • 附加到上述工作负载身份池 ($PRIMUS_WORKLOAD_IDENTITY_POOL) 的服务账号 ($PRIMUS_SERVICE_ACCOUNT) 有权使用 KMS 密钥解密数据(使用 roles/cloudkms.cryptoKeyDecrypter 角色)、使用 KMS 密钥加密数据(使用 roles/cloudkms.cryptoKeyEncrypter 角色)、从 Cloud Storage 存储分区读取数据(使用 objectViewer 角色)以及将服务账号连接到工作负载身份池(使用 roles/iam.workloadIdentityUser)。
./setup_primus_resources.sh

3. 创建工作负载

创建工作负载服务账号

现在,您将为工作负载创建具有所需角色和权限的服务账号。运行以下 脚本,在 Primus 项目中创建工作负载服务账号。此服务账号将由运行推理服务器的虚拟机使用。

此工作负载服务账号 ($WORKLOAD_SERVICEACCOUNT) 将具有以下角色:

  • confidentialcomputing.workloadUser,用于获取证明令牌
  • logging.logWriter,用于将日志写入 Cloud Logging。
./create_workload_service_account.sh

创建工作负载

在此步骤中,您将创建工作负载 Docker 映像。工作负载将由 Primus 公司编写。本 Codelab 中使用的工作负载是 Python 代码,该代码使用公开提供的 GCS 存储分区(Vertex 模型花园)中的 codegemma 模型。工作负载将加载 codegemma 模型并启动推理服务器,该服务器将为 Primus 的开发者提供代码生成请求。

在代码生成请求中,工作负载将获取封装的 DEK 以及加密的提示。然后,工作负载将调用 KMS API 来解密 DEK,然后使用此 DEK 解密提示。加密密钥(适用于 DEK)将通过工作负载身份池受到保护,并且将向满足特性条件的工作负载授予访问权限。下一部分将详细介绍有关授权工作负载的这些属性条件。推理服务器获得解密的提示后,将使用加载的模型生成代码,并返回响应。

运行以下 脚本 以创建工作负载,其中执行以下步骤:

  • 创建由 Primus 拥有的 Artifact Registry($PRIMUS_ARTIFACT_REGISTRY)。
  • 使用所需的资源名称更新工作负载代码。
  • 构建推理服务器工作负载,并创建 Dockerfile 以构建工作负载代码的 Docker 映像。以下是本 Codelab 中使用的 Dockerfile。
  • 构建 Docker 映像并将其发布到由 Primus 拥有的 Artifact Registry ($PRIMUS_ARTIFACT_REGISTRY)。
  • $PRIMUS_ARTIFACT_REGISTRY 授予 $WORKLOAD_SERVICEACCOUNT 读取权限。这是工作负载容器从 Artifact Registry 中拉取工作负载 Docker 映像所必需的。
./create_workload.sh

供您参考,以下是本 Codelab 中创建和使用的工作负载的 generate() 方法(您可以在此处找到完整的工作负载代码)。

def generate():
  try:
    data = request.get_json()
    ciphertext = base64.b64decode(data["ciphertext"])
    wrapped_dek = base64.b64decode(data["wrapped_dek"])
    unwrapped_dek_response = kms_client.decrypt(
        request={"name": key_name, "ciphertext": wrapped_dek}
    )
    unwrapped_dek = unwrapped_dek_response.plaintext
    f = Fernet(unwrapped_dek)
    plaintext = f.decrypt(ciphertext)
    prompt = plaintext.decode("utf-8")
    tokens = tokenizer(prompt, return_tensors="pt")
    outputs = model.generate(**tokens, max_new_tokens=128)
    generated_code = tokenizer.decode(outputs[0])
    generated_code_bytes = generated_code.encode("utf-8")

    response = f.encrypt(generated_code_bytes)
    ciphertext_base64 = base64.b64encode(response).decode("utf-8")
    response = {"generated_code_ciphertext": ciphertext_base64}
    return jsonify(response)

  except (ValueError, TypeError, KeyError) as e:
    return jsonify({"error": str(e)}), 500

4. 授权并运行工作负载

授权工作负载

Primus 希望根据以下资源的特性,授权工作负载访问用于提示加密的 KMS 密钥:

  • 内容:已验证的代码
  • 位置:安全的环境
  • 人员:可信的操作员

Primus 使用 工作负载身份联合 来根据这些要求强制执行访问权限政策。借助工作负载身份联合,您可以指定 属性条件。这些条件限制了哪些身份可以使用 工作负载身份池 (WIP) 进行身份验证。您可以将证明验证器服务作为 工作负载身份池提供方 添加到 WIP,以呈现衡量指标并强制执行政策。

工作负载身份池已在之前的 Cloud 资源设置步骤中创建。现在,Primus 将创建一个新的 OIDC 工作负载身份池提供方。指定的 --attribute-condition 授权访问工作负载容器。它需要:

  • 内容:上传到 $PRIMUS_ARTIFACT_REPOSITORY 制品库的最新 $WORKLOAD_IMAGE_NAME
  • 位置:Confidential Space 可信执行环境在完全受支持的 Confidential Space 虚拟机映像上运行。
  • 人员:Primus $WORKLOAD_SERVICE_ACCOUNT 服务账号。
export WORKLOAD_IMAGE_DIGEST=$(gcloud artifacts docker images describe ${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG  --format="value(image_summary.digest)" --project ${PRIMUS_PROJECT_ID})
gcloud iam workload-identity-pools providers create-oidc $PRIMUS_WIP_PROVIDER \
  --location="global" \
  --project="$PRIMUS_PROJECT_ID" \
  --workload-identity-pool="$PRIMUS_WORKLOAD_IDENTITY_POOL" \
  --issuer-uri="https://confidentialcomputing.googleapis.com/" \
  --allowed-audiences="https://sts.googleapis.com" \
  --attribute-mapping="google.subject='assertion.sub'" \
  --attribute-condition="assertion.swname == 'HARDENED_SHIELDED' && assertion.hwmodel == 'GCP_SHIELDED_VM' && 
assertion.submods.container.image_digest == '${WORKLOAD_IMAGE_DIGEST}' &&
 assertion.submods.container.image_reference == '${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG' && 
'$WORKLOAD_SERVICEACCOUNT@$PRIMUS_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts"

上述命令通过检查 hwmodel 是否设置为“GCP_SHIELDED_VM”以及 swname 是否设置为“HARDENED_SHIELDED”,验证工作负载是否在可信空间环境中运行。此外,它还包含特定于工作负载的断言,例如 image_digestimage_reference,以增强安全性并确保运行的工作负载的完整性。

运行工作负载

在此步骤中,我们将在附加了加速器的 Trusted Space 虚拟机中运行工作负载。必需的 TEE 实参使用 元数据标志 传递。工作负载容器的实参使用标志的“tee-cmd”部分传递。为了为工作负载虚拟机配备 Nvidia Tesla T4 GPU,我们将使用 --accelerator=type=nvidia-tesla-t4,count=1 标志。这会将一个 GPU 附加到虚拟机。我们还需要在元数据标志中添加 tee-install-gpu-driver=true,以触发安装相应的 GPU 驱动程序。

gcloud compute instances create ${WORKLOAD_VM} \
  --accelerator=type=nvidia-tesla-t4,count=1 \
  --machine-type=n1-standard-16 \
  --shielded-secure-boot \
  --image-project=conf-space-images-preview \
  --image=confidential-space-0-gpupreview-796705b \
  --zone=${PRIMUS_PROJECT_ZONE} \
  --maintenance-policy=TERMINATE \
  --boot-disk-size=40 \
  --scopes=cloud-platform \
  --service-account=${WORKLOAD_SERVICEACCOUNT}@${PRIMUS_PROJECT_ID}.iam.gserviceaccount.com \
  --metadata="^~^tee-image-reference=${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/${PRIMUS_PROJECT_ID}/${PRIMUS_ARTIFACT_REPOSITORY}/${WORKLOAD_IMAGE_NAME}:${WORKLOAD_IMAGE_TAG}~tee-install-gpu-driver=true~tee-restart-policy=Never"

运行推理查询

工作负载推理服务器成功启动后,Primus 公司的员工现在可以向推理服务器发送代码生成请求。

在本 Codelab 中,我们将使用以下脚本来设置将与推理服务器交互的客户端应用。运行 此脚本 以设置客户端虚拟机。

./setup_client.sh

以下步骤演示了如何通过 SSH 登录到客户端虚拟机,并在 Python 虚拟环境中执行示例客户端应用。此示例应用使用 Fernet 库进行信封加密,但请注意,可以调整特定的加密库以适应不同的应用场景。

gcloud compute ssh ${CLIENT_VM} --zone=${PRIMUS_PROJECT_ZONE}

运行以下命令以在客户端虚拟机中激活 Python 虚拟环境并执行客户端应用。

source venv/bin/activate
python3 inference_client.py

此示例客户端应用的输出将显示加密和明文提示请求及其相应的加密和解密响应。

5. 清理

以下脚本可用于清理我们在本 Codelab 中创建的资源。在此清理过程中,将删除以下资源:

  • Primus 服务账号 ($PRIMUS_SERVICEACCOUNT)。
  • Primus 加密密钥 ($PRIMUS_ENC_KEY)。
  • Primus 的制品库 ($PRIMUS_ARTIFACT_REPOSITORY)。
  • Primus 工作负载身份池 ($PRIMUS_WORKLOAD_IDENTITY_POOL) 及其提供方。
  • Primus 的工作负载服务账号 ($WORKLOAD_SERVICEACCOUNT)。
  • 工作负载虚拟机 ($WORKLOAD_VM) 和客户端虚拟机 ($CLIENT_VM)。
./cleanup.sh

如果您已完成探索,请考虑删除您的项目。

  • 前往 Cloud Platform 控制台
  • 选择要关停的项目,然后点击顶部的“删除”:这会将项目安排为删除