Crear y personalizar cargas de trabajo


Un autor de cargas de trabajo crea una carga de trabajo que procesa los datos confidenciales con los que quieren trabajar los colaboradores de datos.

El autor de una carga de trabajo debe reunir los siguientes recursos para crear una carga de trabajo:

  • Una aplicación para procesar los datos confidenciales. Puedes escribir tu aplicación en el idioma que quieras, siempre que crees una imagen en contenedor que lo admita.

  • Una imagen en contenedor para empaquetar la aplicación con Docker.

  • Un repositorio en Artifact Registry para almacenar la imagen de Docker.

  • Las políticas de inicio se definen en la imagen de contenedor y controlan cómo se puede ejecutar una carga de trabajo, así como restringen la capacidad de un operador de carga de trabajo malintencionado.

Para desplegar la carga de trabajo, un operador de carga de trabajo ejecuta una VM confidencial basada en la imagen de Confidential Space. De esta forma, se obtiene la imagen en contenedor de Artifact Registry y se ejecuta.

Los colaboradores de datos deben validar las certificaciones de una carga de trabajo antes de que pueda acceder a sus datos.

Antes de empezar

Escribir una carga de trabajo para Confidential Space es más que escribir código y depurar. También debes hablar con los colaboradores de datos para evaluar sus necesidades, configurar tu entorno, empaquetar tu código en una imagen contenerizada y trabajar con un operador de cargas de trabajo para asegurarte de que todo se implementa correctamente.

Hablar con los colaboradores de datos

Antes de empezar a escribir tu aplicación, debes hablar con tus colaboradores de datos sobre los datos privados con los que quieres trabajar. Puedes hacer preguntas como las siguientes:

  • ¿Cuáles son los IDs de organización implicados?

  • ¿Cuáles son los números de proyecto implicados?

  • ¿A qué Google Cloud recursos necesito acceder y cuáles son sus IDs y nombres?

  • ¿Hay recursos a los que necesito acceder que no están gestionados por Google Cloud IAM?

  • ¿Cómo debe comparar y procesar la aplicación los datos privados?

  • ¿En qué formato debe estar el resultado?

  • ¿Dónde se debe almacenar la salida y si debe cifrarse?

  • ¿Todos los colaboradores de datos ven el mismo resultado o los resultados son únicos para cada uno?

Además, cada colaborador de datos puede tener requisitos de privacidad únicos que debes cumplir. Es de vital importancia que no se expongan datos privados como resultado de una carga de trabajo.

Crear una solución de Confidential Space

Es útil configurar dos (o más) proyectos con los permisos adecuados como entorno de pruebas, como se explica en el artículo Crear tu primer entorno de Confidential Space. Intenta replicar la configuración de los proyectos de los colaboradores de datos lo mejor posible. De esta forma, podrás adquirir experiencia con los permisos entre proyectos y recuperar los datos que necesites de recursos específicos de Google Cloud . También puede ayudarte a entender los roles de operador de cargas de trabajo y colaborador de datos y sus responsabilidades.

Durante la fase inicial de desarrollo, es útil seguir estas prácticas:

  • Cuando trabajes como colaborador de datos, reduce al mínimo la validación de la certificación para no ralentizar el desarrollo.

  • Cuando trabajes como operador de cargas de trabajo, usa la imagen de depuración de Confidential Space en lugar de la de producción al desplegar la carga de trabajo. De esta forma, tendrás más opciones para solucionar los problemas de la carga de trabajo.

A medida que tu aplicación madure y su estado sea más predecible, podrás proteger tu solución cada vez más con la validación de certificación y las políticas de lanzamiento, y cambiar a la imagen de espacio confidencial de producción.

Una vez que tu carga de trabajo funcione correctamente en tu entorno de pruebas, podrás pasar a probarla en los proyectos de tus colaboradores de datos con recursos reales, pero con datos falsos para que puedas mostrarles cómo funciona todo. En este momento, puedes empezar a trabajar con un operador de cargas de trabajo independiente.

Cuando todo funcione y el resultado sea el esperado, puede empezar a hacer pruebas con datos de producción. Una vez que se hayan completado las pruebas y todas las partes hayan dado su conformidad con los resultados, la carga de trabajo estará lista para pasar a producción.

Ten cuidado con los resultados

Durante las pruebas de tu código, puede que te resulte tentador depurar imprimiendo en STDOUT o STDERR. Si lo haces, ten cuidado de no exponer datos privados que terceros puedan leer accediendo a los registros. Antes de que tu código empiece a funcionar en producción, asegúrate de que no genere nada más que lo estrictamente necesario.

Lo mismo ocurre con el resultado final. Solo proporciona un resultado final que no ponga en peligro la privacidad ni la confidencialidad de los datos originales.

Crear una imagen en contenedores con Docker

Las aplicaciones deben empaquetarse en una imagen contenerizada creada por Docker, que se almacena en Artifact Registry. Cuando se implementa una carga de trabajo, la imagen Docker se extrae del repositorio de Artifact Registry mediante la imagen de Confidential Space, se ejecuta y la aplicación puede empezar a trabajar en los recursos del proyecto correspondientes.

Cuando compiles tu imagen de Docker, ten en cuenta lo siguiente:

Funciones adicionales de Linux

La carga de trabajo de Confidential Space se ejecuta en un contenedor Linux mediante containerd. Este contenedor se ejecuta con capacidades de Linux predeterminadas.

Para añadir funciones, puedes usar tee-added-capabilities.

Límites de disco y memoria

Espacio Confidencial cambia automáticamente el tamaño de la partición con estado del disco de arranque cuando se usan tamaños de disco de arranque más grandes. El tamaño de la partición es aproximadamente el tamaño del disco de arranque menos 5 GB.

Como parte de las protecciones del sistema de archivos de integridad de Confidential Space, Confidential Space almacena etiquetas de integridad de disco en la memoria. Esto supone una sobrecarga de memoria de aproximadamente el 1% por cada byte de disco. Por ejemplo, un disco de 100 GB requiere 1 GB de memoria y un disco de 10 TB requiere 100 GB de memoria.

Asegúrate de no superar los límites de memoria de la máquina virtual. La memoria de intercambio está inhabilitada en las VMs de Confidential Space, lo que significa que un uso excesivo de la memoria puede provocar un fallo en la carga de trabajo. Asegúrate de que la máquina que elijas admita el uso de memoria de tu carga de trabajo, además de la sobrecarga de integridad del disco.

Tokens de OIDC caducados

Cuando se inicia tu carga de trabajo, se pone a su disposición un token de OIDC para que lo consuma. Contiene reclamaciones de certificación verificadas sobre la máquina virtual de tu carga de trabajo y se almacena en el contenedor de la carga de trabajo en /run/container_launcher/attestation_verifier_claims_token. El token caduca al cabo de 60 minutos.

Si el token caduca, se intenta actualizar en segundo plano con un tiempo de espera exponencial hasta que se consigue. Si se produce un error en la actualización (debido a problemas de red, una interrupción del servicio de atestación o cualquier otro motivo), el código de tu carga de trabajo debe poder gestionar ese error.

Tu carga de trabajo puede gestionar un fallo de actualización de tokens de una de las siguientes formas:

  • Ignora el token caducado, ya que no es necesario después del uso inicial.

  • Espera a que el token caducado se actualice correctamente.

  • Sal de la carga de trabajo.

Montajes de espacio de trabajo en memoria

Confidential Space permite añadir espacios de borrador en la memoria. Para ello, se usa la memoria disponible en la VM de Confidential Space. Como el espacio de trabajo usa la memoria de la máquina virtual confidencial, tiene las mismas propiedades de integridad y confidencialidad que la máquina virtual confidencial.

Puedes usar tee-dev-shm-size para aumentar el tamaño del montaje de memoria compartida /dev/shm de la carga de trabajo. El tamaño /dev/shm se especifica en KB.

Puedes usar tee-mount para especificar montajes de tmpfs en el contenedor en ejecución mediante configuraciones separadas por punto y coma. type y source siempre son tmpfs. El destination es el punto de montaje, que interactúa con la política de lanzamiento tee.launch_policy.allow_mount_destinations. También puede especificar el tamaño tmpfs en bytes. El tamaño predeterminado es el 50% de la memoria de la VM.

Puertos de entrada

De forma predeterminada, las máquinas virtuales de Confidential Space funcionan con una regla de cortafuegos que bloquea todos los puertos entrantes. Si usas una versión de imagen de Confidential Space 230600 o posterior, puedes especificar los puertos de entrada que deben permanecer abiertos en Dockerfile al crear la imagen de tu carga de trabajo.

Para abrir puertos, añade la palabra clave EXPOSE a tu Dockerfile, junto con el número de puerto que quieras mantener abierto y un protocolo opcional de tcp o udp. Si no especificas el protocolo de un puerto, se permitirán tanto TCP como UDP. A continuación, se muestra un ejemplo de Dockerfile que expone puertos de entrada:

FROM alpine:latest
EXPOSE 80
EXPOSE 443/tcp
EXPOSE 81/udp
WORKDIR /test
COPY salary /test
ENTRYPOINT ["/test/salary"]
CMD []

En función de la imagen base que utilices, es posible que algunos puertos ya estén expuestos. Tu Dockerfile solo expone puertos adicionales; no puede bloquear puertos que ya haya abierto la imagen base.

Los operadores de cargas de trabajo deben asegurarse de que los puertos expuestos estén abiertos en su cortafuegos de VPC antes de ejecutar la carga de trabajo. El autor de la carga de trabajo puede proporcionar los números de puerto o extraerlos de la información de la imagen de Docker.

Los puertos expuestos se registran en la consola y se redirigen a Cloud Logging cuando se usa la variable de metadatos tee-container-log-redirect.

Políticas de lanzamiento

Las políticas de lanzamiento anulan las variables de metadatos de la VM definidas por los operadores de cargas de trabajo para restringir las acciones maliciosas. El autor de una carga de trabajo puede definir políticas con una etiqueta como parte de la creación de su imagen de contenedor.

Por ejemplo, en una Dockerfile:

LABEL "tee.launch_policy.allow_cmd_override"="true"

En un archivo BUILD de Bazel:

container_image(
    ...
    labels={"tee.launch_policy.allow_cmd_override":"true"}
    ...
)

En la siguiente tabla se muestran las políticas de lanzamiento disponibles:

Política Tipo Descripción

tee.launch_policy.allow_capabilities

Interactúa con:

Booleano (el valor predeterminado es false) Determina si el operador de carga de trabajo puede añadir capacidades de Linux adicionales al contenedor de carga de trabajo.

tee.launch_policy.allow_cgroups

Interactúa con:

  • Operador de carga de trabajo: la variable de metadatos tee-cgroup-ns.
Booleano (el valor predeterminado es false) Determina si el contenedor de carga de trabajo puede incluir un montaje de cgroup con espacio de nombres en /sys/fs/cgroup.

tee.launch_policy.allow_cmd_override

Interactúa con:

Booleano (el valor predeterminado es false) Determina si el valor de CMD especificado en el campo Dockerfile del contenedor de la carga de trabajo se puede sustituir por un operador de carga de trabajo con el valor de metadatos de tee-cmd.

tee.launch_policy.allow_env_override

Interactúa con:

Cadena separada por comas Cadena separada por comas de nombres de variables de entorno permitidos que puede definir un operador de carga de trabajo con valores de metadatos tee-env-ENVIRONMENT_VARIABLE_NAME.

tee.launch_policy.allow_mount_destinations

Interactúa con:

  • Operador de carga de trabajo: la variable de metadatos tee-mount.
Cadena separada por dos puntos

Cadena separada por dos puntos de los directorios de montaje permitidos en los que el operador de la carga de trabajo puede montar con tee-mount.

Por ejemplo: /run/tmp:/var/tmp:/tmp

tee.launch_policy.log_redirect

Interactúa con:

Cadena definida

Determina cómo funciona el registro si tee-container-log-redirect se define como true por un operador de carga de trabajo.

Los valores válidos son:

  • debugonly (predeterminado): solo permite redirecciones stdout y stderr cuando se usa una imagen de depuración.
  • always: permite siempre las redirecciones stdout y stderr.
  • never: no permitir nunca las redirecciones stdout y stderr.

tee.launch_policy.monitoring_memory_allow

Interactúa con:

Cadena definida

Determina cómo funciona la monitorización del uso de memoria de la carga de trabajo si un operador de carga de trabajo asigna el valor true a tee-memory-monitoring-enable .

Los valores válidos son:

  • debugonly (predeterminado): solo permite monitorizar el uso de memoria cuando se usa una imagen de depuración.
  • always: permite siempre la monitorización del uso de memoria.
  • never: no permitir nunca la monitorización del uso de memoria.

Varias ejecuciones de cargas de trabajo

Para garantizar un entorno limpio, se debe reiniciar una VM para reiniciar una carga de trabajo. De esta forma, se encripta el disco de la VM con una clave efímera para abordar el vector de ataque de modificar una imagen de carga de trabajo en el disco después de que se haya descargado y medido.

Esto también añade sobrecarga, como el tiempo de arranque y la extracción de la imagen de la carga de trabajo en cada ejecución de la carga de trabajo. Si estos gastos generales afectan demasiado al rendimiento de tu carga de trabajo, puedes codificar un reinicio de la carga de trabajo en la propia carga de trabajo, lo que aumentará tu perfil de riesgo.

Cgroups con espacio de nombres

La carga de trabajo de Confidential Space se ejecuta sin un montaje de cgroup de forma predeterminada.

Para gestionar los cgroups en el contenedor de la carga de trabajo, puedes usar tee-cgroup-ns. De esta forma, se crea un montaje en /sys/fs/cgroup en el sistema de archivos del contenedor.

Imágenes de contenedor reproducibles

Crear una imagen de contenedor de forma reproducible puede ayudar a aumentar la confianza entre las partes. Puedes crear imágenes reproducibles con Bazel.

Recursos no gestionados por Google Cloud IAM

Para acceder a recursos que no gestiona Google Cloud IAM, tu carga de trabajo debe especificar una audiencia personalizada.

Para obtener más información, consulta Acceder a recursos no gestionados por Google Cloud IAM.

Imágenes de contenedor firmadas

Puedes firmar una imagen de contenedor con una clave pública, que un colaborador de datos puede usar para la certificación en lugar de especificar un digest de imagen en su política WIP.

Esto significa que los colaboradores de datos no tienen que actualizar sus políticas de WIP cada vez que se actualiza una carga de trabajo, y la carga de trabajo puede seguir accediendo a los recursos protegidos sin interrupciones.

Puedes usar Sigstore Cosign para firmar la imagen de contenedor. Para asegurarse de que Confidential Space pueda obtener las firmas, los operadores de cargas de trabajo deben añadir la información de la firma a la variable de metadatos tee-signed-image-repos antes de implementar la carga de trabajo.

Durante el tiempo de ejecución, las firmas se envían al servicio de certificación de Confidential Space para su verificación. El servicio de certificación devuelve un token de reclamaciones de certificación que contiene las reclamaciones de firma verificadas. Aquí tienes un ejemplo de reclamación de firma:

"image_signatures": [
  {
    "key_id": "hexadecimal-sha256-fingerprint-public-key1",
    "signature": "base64-encoded-signature",
    "signature_algorithm": "RSASSA_PSS_SHA256"
  },
  {
    "key_id": "hexadecimal-sha256-fingerprint-public-key2",
    "signature": "base64-encoded-signature",
    "signature_algorithm": "RSASSA_PSS_SHA256",
  },
  {
    "key_id": "hexadecimal-sha256-fingerprint-public-key3",
    "signature": "base64-encoded-signature",
    "signature_algorithm": "RSASSA_PSS_SHA256",
  }
]

Para configurar la firma de imágenes de contenedor, consulta el codelab de imágenes de contenedor firmadas.