Для аттестации рабочих нагрузок в среде доверенного выполнения On Device Personalization (ODP) Trusted Execution Environment (TEE), общедоступной в Google Cloud как Confidential Space (CS), требуются детерминированные сборки.
Образы рабочей нагрузки должны генерировать детерминированный хэш изображения, который может использоваться CS для аттестации рабочей нагрузки (с использованием архитектуры процедуры удаленной аттестации (RATS) согласно RFC 9334 NIST).
В этом документе будет рассмотрена реализация и поддержка детерминированных сборок в репозитории odp-federatedcompute . Сервисы ODP Aggregator и Model Updater будут работать в конфиденциальном пространстве. Репозиторий поддерживает детерминированные сборки для всех наших сервисов, что необходимо для использования в производственных сценариях.
Детерминированные сборки
Детерминированная сборка состоит из двух основных компонентов:
- Компиляция необходимых бинарных файлов. Сюда входят JAR-файлы, разделяемые библиотеки и метаданные.
- Базовый образ и зависимости среды выполнения. Базовый образ среды выполнения, используемый для выполнения скомпилированных бинарных файлов.
На данный момент репозиторий ODP Federated Compute поддерживает следующие типы рабочих нагрузок:
- Java + Spring рабочие нагрузки
- Назначение задач, Управление задачами, Сборщик
- Java + Spring с JNI и рабочими нагрузками TensorFlow
- ModelUpdater, Aggregator
- Нагрузки Python
- TaskBuilder
Зависимости
Ниже приведён список зависимостей, на которые опирается ODP для поддержания детерминизма и доступности:
- Базель
- GitHub
- Мэйвен
- PyPi
- Снимки Debian
- Реестр DockerHub
- Реестр контейнеров Google (GCR)
Детерминированные рабочие нагрузки
Все рабочие нагрузки компилируются с помощью Bazel с использованием языковых движков и образов контейнеров, созданных с помощью rules_oci . В файле WORKSPACE определены все зависимости с соответствующими версиями и хешами.
Снимки Debian
Все образы рабочих нагрузок должны быть собраны в рамках предоставленного Dockerfile , построенного на основе снимка Debian . Снимки Debian предоставляют стабильный снимок репозитория с детерминированными параметрами:
- Системные заголовочные файлы и библиотеки
- Архитектура системы
- linux_x86_64
- Дебиан
- Компилятор C++
Рабочие нагрузки Java Spring
Пакет ` remotejdk_17 из библиотеки Bazel используется для обеспечения герметичной среды Java для компиляции. Другие зависимости Java управляются и определяются в файле `WORKSPACE` .
Рабочие нагрузки Java Spring компилируются в JAR-файл с именем <service>_application.jar . JAR-файл содержит:
- файлы классов Java
-
META-INF/- манифестные данные Bazel
-
build-data.properties- Данные сборки Bazel
-
BOOT-INF/- Зависимости в виде JAR-файлов, сгенерированные программой rules_spring .
Слои изображений
Образ рабочей нагрузки Java Spring состоит из двух слоев:
- Базовый слой изображения
- Базовый образ Java:
gcr.io/distroless/java17-debian11
- Базовый образ Java:
- Уровень рабочей нагрузки
-
binary_tar.tar-
<service>_application.jar
-
-
Конфигурация изображения
- Точка входа
-
java -jar <service>_application.jar
-
Рабочие нагрузки JNI TensorFlow
Рабочие нагрузки JNI Tensorflow построены на основе рабочих нагрузок Java Spring. Предоставляется герметичный набор инструментов Clang+LLVM Bazel, использующий предварительно собранный Clang+LLVM 16 с системным корневым каталогом, предоставленным образом Debian snapshot, для компиляции машинного кода.
JNI-загрузки компилируются в разделяемую библиотеку с именем libtensorflow.so вместе с файлом <service>_application.jar .
Слои изображений
Образ рабочей нагрузки JNI TensorFlow состоит из нескольких слоев:
- Базовый слой изображения
- Базовый образ Java:
gcr.io/distroless/java17-debian11
- Базовый образ Java:
- Слои зависимостей пакетов 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устанавливается при запуске образа (а не при его сборке) для обеспечения детерминированности сборки.
- Позволяет установить переменную среды
-
"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 snapshot гарантирует детерминированную загрузку дистрибутивов на основе совместимости платформ и предоставляет набор инструментов C++ для компиляции исходных дистрибутивов.
Задания на Python будут упакованы в набор загружаемых пакетов pip, дистрибутив Python 3.10, исходный код Python из ODP и скрипт запуска Python.
-
<service>.runfiles/- Дистрибутив Python находится в папке
python_x86_64-unknown-linux-gnu/ - Исходный код хранится в папке
com_google_ondevicepersonalization_federatedcompute/ - Пакеты Pip хранятся в папке
pypi_<dependency_name>/
- Дистрибутив Python находится в папке
-
<service>.runfiles_manifest- Файл манифеста для каталога
<service>.runfiles/
- Файл манифеста для каталога
-
<service>- Скрипт на Python для запуска рабочей нагрузки Python с использованием исполняемых файлов.
Слои изображений
Образ рабочей нагрузки Python состоит из четырех слоев:
- Базовый слой изображения
- Базовый образ Python python:slim
- Слой интерпретатора
-
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, построенного с помощью предоставленного Dockerfile . Для создания окончательных детерминированных образов предоставляются два скрипта.
- docker_run.sh
-
docker_run.shсоздаст образ Docker из файла dockerfile, смонтирует рабочий каталог, смонтирует демон Docker на хосте и запустит Docker с помощью предоставленной команды bash. Любые переменные, переданные перед командой bash, будут рассматриваться как флаги запуска Docker.
-
- build_images.sh
-
build_images.shзапуститbazel buildдля всех образов и выведет сгенерированные хеши образов для каждого собранного образа.
-
Собрать все изображения
./scripts/docker/docker_run.sh "./scripts/build_images.sh"
Ожидаемые хеши изображений для каждого релиза можно найти в репозитории GitHub odp-federatedcompute .
Опубликовать изображения
Публикация настраивается с помощью правил Bazel oci_push . Для каждой службы целевой репозиторий должен быть настроен следующим образом:
- агрегатор
- коллекционер
- модель_обновитель
- задание
- управление задачами
- планировщик задач
- task_builder
Опубликовать одно изображение
Чтобы опубликовать одно изображение:
./scripts/docker/docker_run.sh "bazel run //shuffler/services/<servicename_no_underscore>:<servicename_with_underscore>_image_publish"
Созданные изображения
Все созданные образы должны храниться и размещаться создателем, например, в реестре артефактов GCP .