Des builds déterministes sont requis pour l'attestation des charges de travail dans l'application Sur l'appareil Environnement d'exécution sécurisé (TEE) de personnalisation (ODP) accessible au public sur Google Cloud en tant qu'espace confidentiel (CS).
Les images de charge de travail doivent générer un hachage d'image déterministe qui peut être utilisé par CS pour l'attestation des charges de travail (qui utilise la norme d'attestation à distance RFC 9334 du NIST RATS (architecture RATS)).
Ce document aborde l'implémentation et la prise en charge de la déterministe dans le odp-federatedcompute un dépôt de clés. Les services ODP Aggregator et Model Updater s'exécuteront dans Espace confidentiel. Le dépôt prend en charge les compilations déterministes pour l'ensemble qui sont requis pour les cas d'utilisation en production.
Compilations déterministes
Les builds déterministes comprennent deux composants principaux:
- Compilation des binaires requis. Cela inclut les jar, les bibliothèques partagées, et des métadonnées.
- L'image de base et les dépendances de l'environnement d'exécution Base de l'environnement d'exécution image utilisée pour exécuter les binaires compilés.
À l'heure actuelle, le dépôt ODP Federated Compute prend en charge les types suivants de charges de travail:
- Charges de travail Java et Spring
- TaskAssignment, TaskManagement, Collecteur
- Java + Spring avec les charges de travail JNI TensorFlow
- ModelUpdater, agrégateur
- Charges de travail Python
- TaskBuilder
Dépendances
La liste suivante répertorie les dépendances sur lesquelles l'ODP s'appuie pour maintenir le déterminisme et disponibilité:
- Bazel
- GitHub
- Maven
- PyPi
- Instantanés Debian
- Registre DockerHub
- Google Container Registry (GCR)
Charges de travail déterministes
Toutes les charges de travail sont compilées à l'aide de Bazel avec des chaînes d'outils propres à un langage et des images de conteneurs créées avec rules_oci L'ESPACE DE TRAVAIL fichier définit toutes les dépendances avec les versions et les hachages correspondants.
Instantanés Debian
Toutes les images de charge de travail doivent être créées dans les dockerfile basé sur un instantané Debian. Debian fournissent un instantané de dépôt stable avec des valeurs déterministes:
- En-têtes système et bibliothèques
- Architecture du système
- linux_x86_64
- Debian
- Compilateur C++
Charges de travail Java Spring
Bazel
remotejdk_17
correspond à
utilisé pour fournir un Java
hermétique pour la compilation. D'autres dépendances Java sont
gérées et définies dans l'espace de travail WORKSPACE
fichier.
Les charges de travail Java Spring se compilent dans un fichier JAR nommé
<service>_application.jar
Le pot contient:
- Fichiers de classe Java
META-INF/
- Données du fichier manifeste Bazel
build-data.properties
- Données de build Bazel
BOOT-INF/
- Dépendances JAR empaquetées, générées par rules_spring.
Calques d'image
L'image de charge de travail Java Spring se compose de deux couches:
- Calque de l'image de base
- Image de base Java:
gcr.io/distroless/java17-debian11
- Image de base Java:
- Couche de charge de travail
binary_tar.tar
<service>_application.jar
Configuration des images
- Point d'entrée
java -jar <service>_application.jar
Charges de travail JNI TensorFlow
Les charges de travail JNI TensorFlow sont basées sur les charges de travail Java Spring. A La chaîne d'outils hermétique Clang+LLVM Bazel est fournie à l'aide de Clang+LLVM prédéfinis 16 par un sysroot fourni par l'image de l'instantané Debian pour compiler le code machine.
Les charges de travail JNI se compilent dans une bibliothèque partagée nommée libtensorflow.so
, ainsi que
avec <service>_application.jar
.
Calques d'image
L'image de charge de travail JNI TensorFlow est composée de plusieurs couches:
- Calque de l'image de base
- Image de base Java:
gcr.io/distroless/java17-debian11
- Image de base Java:
- Couches de dépendance des packages Debian. Les couches sont générées à l'aide de deb
Archives téléchargées à partir de debian-snapshot et réempaquetées en tant que couches d'image
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
- Couche de charge de travail
binary_tar.tar
<service>_application.jar
libtensorflow-jni.so
libaggregation-jni.so
Configuration des images
- Étiquettes (uniquement pour les images conçues pour s'exécuter dans TEE)
"tee.launch_policy.allow_env_override": "FCP_OPTS"
- Permet de définir la variable d'environnement
FCP_OPTS
dans confidentiel espace. La charge de travail utiliseraFCP_OPTS
au démarrage pour configurer paramètres obligatoires. - La variable d'environnement
FCP_OPTS
est définie lors de l'exécution de l'image. (au lieu de "build") pour maintenir le déterminisme de compilation.
- Permet de définir la variable d'environnement
"tee.launch_policy.log_redirect": "always"
"tee.launch_policy.monitoring_memory_allow": "always"
- Point d'entrée
java -Djava.library.path=. -jar <service>_application.jar
Charges de travail Python
Le code rules_python de Bazel est utilisé pour fournir une chaîne d'outils hermétique Python 3.10. Exigences concernant un pip verrouillé fichier est utilisé pour l'extraction déterministe des dépendances pip. L'instantané Debian permet d'extraire des distributions déterministes basées sur la plate-forme compatibilité et fournit une chaîne d'outils C++ pour compiler les distributions sources.
Les charges de travail Python seront empaquetées dans un ensemble de packages pip téléchargés, Distribution Python 3.10, le code source Python de l'ODP et un démarrage Python script.
<service>.runfiles/
- La distribution Python est stockée sous
python_x86_64-unknown-linux-gnu/
. - Le code source est stocké sous
com_google_ondevicepersonalization_federatedcompute/
- Les packages Pip sont stockés sous
pypi_<dependency_name>/
- La distribution Python est stockée sous
<service>.runfiles_manifest
- Fichier manifeste du répertoire
<service>.runfiles/
- Fichier manifeste du répertoire
<service>
- Script Python permettant d'exécuter la charge de travail Python à l'aide des fichiers d'exécution
Calques d'image
L'image de charge de travail Python se compose de quatre couches:
- Calque de l'image de base
- Image de base Python python:slim
- Couche interpréteur
interpreter_layer.jar
<service>/<service>.runfiles/python_x86_64-unknown-linux-gnu/**
- Couche "Packages"
packages_layer.jar
<service>/<service>.runfiles/**/site-packages/**
- Couche de charge de travail
app_tar_manifest.tar
- Contient le code source, le script de démarrage et le fichier manifeste.
<service>/<service>.runfiles_manifest
<service>/<service>
<service>/<service>.runfiles/com_google_ondevicepersonalization_federatedcompute/**
- Contient le code source, le script de démarrage et le fichier manifeste.
Configuration des images
- Point d'entrée
/<service>/<service>
Créer des images
Une fois vos charges de travail choisies, vous pouvez créer et publier images.
Prérequis
Procédure
Les images doivent être créées dans le conteneur Docker créé par la dockerfile. Deux scripts sont fournis pour vous aider à créer les images déterministes finales.
- docker_run.sh
<ph type="x-smartling-placeholder">
- </ph>
docker_run.sh
crée l'image Docker à partir du fichier Dockerfile, effectue l'installation au répertoire professionnel, installez le daemon Docker hôte et exécutez Docker avec le la commande bash fournie. Toutes les variables transmises avant la commande bash être traités comme des indicateurs d'exécution Docker.
- build_images.sh
<ph type="x-smartling-placeholder">
- </ph>
build_images.sh
exécuterabazel build
pour toutes les images et affichera la générés pour chaque image compilée.
Créer toutes les images
./scripts/docker/docker_run.sh "./scripts/build_images.sh"
Les hachages d'image attendus pour chaque version sont disponibles sous GitHub de odp-federatedcompute versions.
Publier des images
La publication est configurée à l'aide de oci_push c'est Bazel. Pour chaque service, le dépôt cible doit être configuré tous:
- agrégateur
- collecteur
- model_updater
- task_assignment
- task_management
- task_scheduler
- task_builder
Publier une seule image
Pour publier une seule image:
./scripts/docker/docker_run.sh "bazel run //shuffler/services/<servicename_no_underscore>:<servicename_with_underscore>_image_publish"
Images créées
Toutes les images compilées devront être stockées et hébergées par le créateur, par exemple dans un GCP Artifact Registry :