设备端个性化联合计算确定性 build

设备端工作负载认证需要使用确定性 build 个性化 (ODP) 可信执行环境 (TEE),公开提供于 Google Cloud 作为机密空间 (CS)。

工作负载映像必须生成确定性映像哈希,供 工作负载证明的 CS(使用 NIST 的 RFC 9334 远程证明) 过程 (RATS) 架构)。

本文档将介绍确定性 构建在 odp-federatedcompute 存储库ODP Aggregator 和 Model Updater 服务将在 机密空间。该代码库支持确定性构建 是生产用例所必需的

确定性 build

确定性 build 包含两个主要组成部分:

  1. 编译所需二进制文件。这包括 jar、共享库 和元数据
  2. 基础映像和运行时依赖项。运行时环境的基础 用于执行已编译的二进制文件的映像。

截至目前,ODP 联合计算代码库支持以下类型的 工作负载:

  • Java + Spring 工作负载
    • TaskAssignment、TaskManagement、Collector
  • Java + Spring 搭配 JNI TensorFlow 工作负载
    • ModelUpdater、Aggregator
  • Python 工作负载
    • TaskBuilder

依赖项

以下列表是 ODP 维护确定性所依赖的依赖项 和可用性:

  • Bazel
  • GitHub
  • Maven
  • PyPi
  • Debian 快照
  • DockerHub 注册表
  • Google Container Registry (GCR)

确定性工作负载

所有工作负载都使用 Bazel 和 使用 API 构建特定于语言的工具链和容器映像 rules_oci工作区 文件 定义具有相应版本和哈希的所有依赖项。

Debian 快照

所有工作负载映像都应在提供的 dockerfile 基于 Debian 快照构建的应用。Debian 快照提供具有确定性的稳定代码库快照:

Java Spring 工作负载

Bazel 的 remotejdk_17为 用于为编译提供封闭的 Java。其他 Java 依赖项包括 在WORKSPACE 文件

Java Spring 工作负载编译为名为 <service>_application.jar。jar 包含:

  • Java 类文件
  • META-INF/
    • Bazel 清单数据
  • build-data.properties
    • Bazel 构建数据
  • BOOT-INF/

图像层

Java Spring 工作负载映像由两层组成:

映像配置

  • 入口点
    • java -jar <service>_application.jar

JNI Tensorflow 工作负载

JNI Tensorflow 工作负载基于 Java Spring 工作负载构建而成。答 封闭的 Clang+LLVM Bazel 工具链是使用预构建的 Clang+LLVM 16,其中包含 sysroot 来编译机器代码。

JNI 工作负载编译到名为 libtensorflow.so 的共享库中 与 <service>_application.jar 相关联。

图像层

JNI TensorFlow 工作负载映像由多个层组成:

  • 基础映像层
  • Debian 软件包依赖项层。这些层使用 deb 生成。 从 debian-snapshot 下载并重新打包为映像层的归档
    • libc++1-16_amd64.tar
    • libc++abi1-16_amd64.tar
    • libc6_amd64.tar
    • libunwind-16_amd64.tar
    • libgcc-s1_amd64.tar
    • gcc-13-base_amd64.tar
  • 工作负载层
    • binary_tar.tar
      • <service>_application.jar
      • libtensorflow-jni.so
      • libaggregation-jni.so

映像配置

  • 标签(仅适用于在 TEE 中运行的映像)
    • "tee.launch_policy.allow_env_override": "FCP_OPTS"
      • 允许在以下位置设置 FCP_OPTS 环境变量: 机密 空格。 工作负载将在启动时使用 FCP_OPTS 进行配置 必需参数。
      • FCP_OPTS 环境变量在映像运行时设置 (而不是 build)以保持 build 确定性。
    • "tee.launch_policy.log_redirect": "always"
    • "tee.launch_policy.monitoring_memory_allow": "always"
  • 入口点
    • java -Djava.library.path=. -jar <service>_application.jar

Python 工作负载

Bazel 的 rules_python 用于 提供封闭的 Python 3.10 工具链。锁定 pip 要求 文件 用于确定性地提取 pip 依赖项。Debian 快照 可确保系统根据平台 兼容性 并提供用于编译源发行版的 C++ 工具链。

Python 工作负载会被打包成一组下载的 pip 软件包, Python 3.10 发行版、ODP Python 源代码和 Python 启动 脚本。

  • <service>.runfiles/
    • Python 发行版存储在 python_x86_64-unknown-linux-gnu/
    • 源代码存储在 com_google_ondevicepersonalization_federatedcompute/
    • Pip 软件包存储在 pypi_<dependency_name>/
  • <service>.runfiles_manifest
    • <service>.runfiles/ 目录的清单文件
  • <service>
    • 使用 runfile 运行 Python 工作负载的 Python 脚本

图像层

Python 工作负载映像包含以下四个层:

  • 基础映像层
  • 口译层
    • interpreter_layer.jar
      • <service>/<service>.runfiles/python_x86_64-unknown-linux-gnu/**
  • 软件包层
    • packages_layer.jar
      • <service>/<service>.runfiles/**/site-packages/**
  • 工作负载层
    • app_tar_manifest.tar
      • 包含源代码、启动脚本和清单。
        • <service>/<service>.runfiles_manifest
        • <service>/<service>
        • <service>/<service>.runfiles/com_google_ondevicepersonalization_federatedcompute/**

映像配置

  • 入口点
    • /<service>/<service>

构建映像

选择工作负载后,您就可以构建和发布 图片。

前提条件

过程

映像应在由提供的 Docker 容器构建的 Docker 容器中构建, dockerfile。 提供了两个脚本来帮助构建最终的确定性图像。

  • docker_run.sh
    • docker_run.sh 将基于 dockerfile 构建 Docker 映像, 安装工作目录,装载主机 Docker 守护程序,并使用 提供的 bash 命令在 bash 命令之前传递的所有变量 视为 Docker 运行标志
  • build_images.sh
    • build_images.sh 将针对所有映像运行 bazel build,并输出 为每个已构建的映像生成的映像哈希

构建所有映像

./scripts/docker/docker_run.sh "./scripts/build_images.sh"

您可以在下面找到每个版本的预期映像哈希 odp-federatedcompute GitHub 版本

发布图片

发布是使用 oci_push Bazel 规则。对于每项服务,都应为以下服务配置目标代码库: 全部:

  • 聚合信息网站
  • 收集器
  • model_updater
  • task_assignment
  • task_management
  • task_scheduler
  • task_builder

发布单张图片

./scripts/docker/docker_run.sh "bazel run //shuffler/services/<servicename_no_underscore>:<servicename_with_underscore>_image_publish"

构建的映像

所有构建的映像都需要由创建者存储和托管,例如 GCP Artifact Registry