Secretos de construir y reenviar SSH a Docker 18/09

imagen

Usando Dockerfile, siempre ha sido difícil acceder a recursos privados. Simplemente no había una buena solución. No es bueno usar variables de entorno o simplemente eliminar archivos secretos después del uso: permanecen en los metadatos de la imagen. Los usuarios a veces recurrían a trucos: creaban ensamblajes de varias etapas, sin embargo, se debía tener extrema precaución para que no hubiera valores secretos en la etapa final, y los archivos secretos se almacenaban en la caché de ensamblados local hasta el recorte.


El equipo de compilación de Docker el 18 de septiembre incluye muchas actualizaciones. La característica principal es que ha aparecido una versión completamente nueva de la implementación del lado del servidor; se ofrece como parte del proyecto Moby BuildKit. La aplicación del servidor BuildKit ha adquirido nuevas características, incluida la compatibilidad con los secretos de compilación de Dockerfile.


Usando secretos


En primer lugar, debe habilitar el lado del servidor BuildKit. BuildKit en la versión 18.09 es una función de selección que se puede habilitar utilizando la variable de entorno DOCKER_BUILDKIT=1 antes de iniciar la docker build . En la próxima versión, está previsto que BuildKit sea la parte del servidor de forma predeterminada.


 export DOCKER_BUILDKIT=1 

La implementación de secretos de compilación se basa en dos nuevas características de BuildKit. Una de ellas es la capacidad de usar una interfaz de usuario cargada de imágenes en el registro; el segundo es la capacidad de usar puntos de montaje en comandos RUN para el Dockerfile. Para usar la función de implementación con soporte de secretos (en lugar de la estándar), defina la imagen del enlazador utilizando la directiva de sintaxis en la primera línea del Dockerfile, que indica la imagen del contenedor que desea usar. Hasta ahora, los secretos en el canal estable de Dockerfiles externos no están disponibles: necesitará una de las versiones en el canal experimental, por ejemplo, docker/dockerfile:experimental o docker/dockerfile/1.0.0-experimental .


 # syntax=docker/dockerfile:1.0.0-experimental 

Si usted, como autor del Dockerfile, sabe que el comando RUN instalado en el Dockerfile requiere un valor secreto, use la etiqueta --mount para ello, que indica qué secreto necesita el comando y dónde montarlo. La etiqueta --mount acepta una estructura separada por comas como en --mount para la docker run --mount .


 # syntax=docker/dockerfile:1.0.0-experimental FROM alpine RUN --mount=type=secret,id=mysite.key command-to-run 

Esta etiqueta indica que durante la operación el comando tiene acceso al archivo secreto a lo largo de la ruta /run/secrets/mysite.key . El secreto está disponible solo para el equipo con la etiqueta de montaje, y no para otras partes del ensamblaje. Los datos de este archivo se descargan del almacén secreto en función del identificador especificado "mysite.key". La interfaz de línea de comandos de Docker actualmente admite la divulgación de secretos de archivos de clientes locales utilizando la etiqueta --secret .


 docker build --secret id=mysite.key,src=path/to/mysite.key . 

Como se describió anteriormente, los secretos se establecen por defecto en /run/secrets , sin embargo, puede especificar cualquier ruta utilizando la tecla "objetivo". Si se especifica "destino", pero no "id", entonces "id" se convierte de manera predeterminada en el nombre base de la ruta de destino.


No es necesario estar limitado a un secreto. Puede usar cualquier número de ellos, lo que indica diferentes identificadores.


Si el autor del Dockerfile indica que la instrucción RUN puede usar el secreto, y el usuario que invoca el ensamblado no lo proporciona, entonces el secreto se ignora y no se instala ningún archivo en la ruta especificada. Si esta situación no es deseable, use la tecla "requerida": esto indicará que sin un valor el ensamblaje fallará.


 # syntax=docker/dockerfile:1.0.0-experimental FROM alpine RUN --mount=type=secret,id=mysite.key,required <command-to-run> 

Implementación


El archivo secreto se instala automáticamente solo en un sistema de archivos tmpfs separado para evitar fugas en la imagen final o en el siguiente comando, y para que no se almacene en la memoria caché de compilación local.


Los valores secretos también se excluyen de los cálculos de la memoria caché de compilación para que la memoria caché de metadatos no se pueda usar.


Ssh


Muy a menudo, probablemente intentan acceder a repositorios privados a través del protocolo SSH. Sí, puede usar elementos secretos para revelar la clave privada SSH para el ensamblado, pero hay una mejor solución. El protocolo SSH utiliza criptografía de clave pública y, gracias a este diseño, no necesita revelar su clave privada a nadie. Por ejemplo, si usa varias computadoras con SSH, no necesita transferir su clave, solo proporcione una conexión a través del protocolo ssh-A .


--ssh una característica similar en --ssh , donde puede usar la etiqueta --ssh para dirigir una clave o conexión de agente SSH existente al enlazador. En lugar de transmitir información clave, Docker simplemente le dice al vinculador que está disponible. Si el vinculador necesita acceder al servidor remoto a través de SSH, se pondrá en contacto con el cliente y solicitará la confirmación de la solicitud específica requerida para la conexión. La clave en sí misma no abandona el programa cliente, y después de completar el programa que requería acceso, no quedan datos del vinculador para volver a conectar la conexión remota.


El acceso a la transferencia de archivos a través del protocolo SSH se otorga solo a los comandos en el Dockerfile que solicitaron directamente el acceso a SSH especificando el bloque type=ssh . Otros comandos no tienen datos sobre el agente SSH disponible.


También vale la pena señalar otro aspecto de SSH: el uso del modelo de seguridad TOFU. Cuando se conecta al servidor SSH por primera vez, solicitará información sobre el host desconocido, ya que no tiene una clave pública disponible localmente para este servidor y, en consecuencia, no puede verificar si la clave pública proporcionada por la parte remota es válida para esta dirección.


Al ensamblar con Dockerfile, no se puede verificar la exactitud de esta solicitud y, en consecuencia, la clave pública del servidor ya debe existir en el contenedor que intenta utilizar SSH. Hay varias formas de obtener esta clave pública. Por ejemplo, la imagen base la proporcionará o la copiará del contexto de compilación. Si desea una solución más simple, ejecute el programa ssh–keyscan como parte del ensamblado; cargará la clave pública actual del host.


Para solicitar acceso SSH al comando RUN en el Dockerfile, debe especificar un bloque de tipo "ssh". Luego, durante el proceso, se instalará un socket con acceso de solo lectura al agente SSH. Esto también establecerá la variable de entorno SSH_AUTH_SOCK para que los programas que usan el protocolo SSH usen automáticamente este socket.


 # syntax=docker/dockerfile:experimental FROM alpine # install ssh client and git RUN apk add --no-cache openssh-client git # download public key for github.com RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts # clone our private repository RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git myproject 

En el lado del cliente Docker, use la etiqueta --ssh indicar que el reenvío SSH está permitido para este ensamblado.


 docker build --ssh default . 

La etiqueta acepta un par de valores clave que determinan la ubicación del socket del agente SSH local o las claves privadas. Si desea utilizar el valor default=$SSH_AUTH_SOCK , puede dejar la ruta del socket vacía.


En el bloque Dockerfile, también puede usar la clave de identificación para separar los distintos servidores en el mismo ensamblaje. Por ejemplo, el acceso a varios repositorios en el Dockerfile se puede obtener con diferentes claves de implementación. En este caso, en el Dockerfile usará:


 … RUN --mount=type=ssh,id=projecta git clone projecta … RUN --mount=type=ssh,id=projectb git clone projectb … 

y expanda los datos del cliente con --ssh projecta=./projecta.pem --ssh projectb=./projectb.pem build --ssh projecta=./projecta.pem --ssh projectb=./projectb.pem . Tenga en cuenta que incluso si especifica las claves reales, solo se envía la conexión del agente al vinculador, no el contenido real de estas claves privadas.


Con esto, se completa la revisión de las nuevas características de los secretos de compilación en Docker 18.09. Espero que las nuevas características ayuden a hacer un mayor uso de las capacidades de Dockerfile en los proyectos y proporcionen un mayor nivel de seguridad para la línea de ensamblaje.

Source: https://habr.com/ru/post/es432682/


All Articles