Filtros de limpieza / mancha de Git para secretos de bóvedas ansibles

20

Estoy tratando de configurar el filtro clean / smudge filter en git para tener un cifrado y descifrado automático de archivos que contienen secretos a través del comando ansible-vault .

La peculiaridad del comando ansible-vault es que no es idempotente (crea un binario diferente cada vez que se invoca en los mismos datos).

Comencé con la implementación sugerida en esta página de blog . Desafortunadamente, no funcionó correctamente, ya que cada vez que se llama mancha (ya sea un pago de git o solo el estado de git), los archivos secretos parecen modificados para git, incluso si no lo es.

Entonces me pregunté si git estaría comparando el binario que tiene en el índice con el archivo actual limpio y filtrado, e intenté construir sobre ese script de la siguiente manera:

#!/bin/sh -x
# clean filter, it is invoked with %f

if [ ! -r "$HOME/.vault_password" ]; then
  exit 1
fi

tmp=`mktemp`
cat > $tmp

# get the plain text from the binary in the index
tmphead=`mktemp`
git show HEAD:$1 > $tmphead
contenthead=`echo "embedded" | ansible-vault view $tmphead --vault-password-file=$HOME/.vault_password`
export PAGER=cat
echo -n "$contenthead" | tee $tmphead

# if current and index plain text version differ
if [ "`md5sum $tmp | cut -d' ' -f1`" != "`md5sum $tmphead | cut -d' ' -f1`" ]; then
  tmpcrypt=`mktemp`
  cp $tmp $tmpcrypt
  # generate a new crypted blob
  echo "embedded" | ansible-vault encrypt $tmpcrypt --vault-password-file=$HOME/.vault_password > /dev/null 2>&1
  cat "$tmpcrypt"
else
  # just return the HEAD version
  cat "$tmphead"
fi

rm $tmp $tmphead $tmpcrypt

La diferencia aquí es que intenta comparar las versiones actual y HEAD de los archivos secretos de texto plano (sin cifrar), y solo en caso de que difieran, generará un nuevo blob binario cifrado con ansible-vault.

Desafortunadamente, después de este cambio, git continúa pensando que el archivo secreto siempre se modifica. Incluso después git addde volver a crear el archivo, para que se calcule el git blob, git piensa que el archivo es diferente y deja que el cambio vaya al commit. Tenga en cuenta que git diffdevolver cambios vacíos, como debería.

Como referencia, esto es mancha:

#!/bin/sh

if [ ! -r "$HOME/.vault_password" ]; then
  exit 1
fi

tmp=`mktemp`
cat > $tmp

export PAGER='cat'
CONTENT="`echo "embedded" | ansible-vault view "$tmp" --vault-password-file=$HOME/.vault_password 2> /dev/null`"

if echo "$CONTENT" | grep 'ERROR: data is not encrypted' > /dev/null; then
  echo "Looks like one file was commited clear text"
  echo "Please fix this before continuing !"
  exit 1
else
  echo -n "$CONTENT"
fi

rm $tmp

y esto es diff:

#!/bin/sh

if [ ! -r "$HOME/.vault_password" ]; then
  exit 1
fi

export PAGER='cat'
CONTENT=`echo "embedded" | ansible-vault view "$1" --vault-password-file=$HOME/.vault_password 2> /dev/null`

if echo "$CONTENT" | grep 'ERROR: data is not encrypted' > /dev/null; then
  cat "$1"
else
  echo "$CONTENT"
fi
ᴳᵁᴵᴰᴼ
fuente
He actualizado scripts que se comportan correctamente, excepto cuando git intenta automatizar conflictos en bóvedas que publicaré en breve
ᴳᵁᴵᴰᴼ
1
Tirar una botella al mar, pero: ¿podría el archivo ser diferente debido a diferentes finales de línea o página de códigos diferente?
Tensibai
Intentaría eliminar el -neco de la mancha, pero eso es una suposición. ¿No hay una opción oculta para git diff que le dice que ignore las terminaciones de una sola línea?
Tensibai
Otra idea más: github.com/dellis23/ansible-toolkit (profundizaré más en este día)
Tensibai

Respuestas:

8

El problema aquí es causado por la sal aleatoria en el cifrado ansible-vault. Puede hackear la clase VaultEditor para pasarle la sal desde un argumento en ansible-vault. La sal aleatoria se genera en lib/ansible/parsing/vault/__init__.pyesta línea . Se llama desde lib / ansible / cli / vault.py donde puede agregar fácilmente el argumento para la sal fija. Si lo cambia, envíe un parche anterior a Ansible, me encantaría usarlo.

Este problema se discute más adelante aquí en noticias de hackers . Y hay otras implementaciones con herramientas que tienen sal, es decir, fijados gitcrypt , Transcrypt . Aquí también hay un enlace a una implementación más usando ansible-vault llamada ansible-vault-tools , pero este tiene el mismo problema de sal que yo sepa.

Jiri Klouda
fuente
Si revisa el código, estoy usando una suma de verificación para solucionar el problema de sal variable, es decir. descifre la caja fuerte HEAD en una carpeta tmp primero y compare las sumas de comprobación de los archivos de texto sin formato antes de generar el nuevo blob binario. Eso es un poco lento pero en realidad está bien. Mi problema está en fusiones ahora; en ciertas situaciones funciona, en otras obtengo el blob automatizado antes de que pueda descifrarlo y se rompe.
ᴳᵁᴵᴰᴼ
Si observa los tres ejemplos que he vinculado, también hay algunas soluciones alternativas para las fusiones. Y también se está discutiendo en los comentarios de las noticias de los hackers.
Jiri Klouda
Por cierto, la fusión es complicada. Lo que debe tener en cuenta es que, en caso de que elija todos sus cambios o todos los cambios aguas arriba durante la fusión, git lo resolvería mediante la comparación de hash, lo que funcionaría si la sal fuera correcta. El archivo temporal no es suficiente para limpiar / manchar. Debería hacer lo mismo al fusionar y, en caso de fusión sin conflicto, verifique la versión correcta ya cifrada de git y use esa en lugar de volver a cifrar con nueva sal aleatoria.
Jiri Klouda
No estoy seguro de entender lo que estás diciendo aquí; la fusión ocurriría en el texto sin formato de las bóvedas (a medida que avanza a través de la diferencia), y tener los secretos siempre se marcará como un conflicto incluso para las fusiones automáticas, por lo tanto, incluir un secreto fusionado y reencriptado dentro de cualquier compromiso de fusión, no Realmente representa un problema (para mí).
ᴳᵁᴵᴰᴼ
¿Puede ser específico sobre los problemas de fusión? Debes proporcionar un estuche reproducible. Pero aún sugeriría buscar ideas en los 3 proyectos mencionados anteriormente. En cuanto a los problemas de fusión, cuando fusiona el contenido A con el contenido B y todos han decidido tomar siempre A o siempre B, para los sistemas de control de versiones es un caso especial y a veces lo harán al vincular la versión. Git lo hace a través del hash en el contenido, por lo que asumirá que el hash será el mismo, pero si vuelve a cifrar, incluso si el contenido es todo A, el hash no será el mismo. Pero podría tener otro problema
Jiri Klouda