Filtry Git Clean / Smudge dla sekretów skarbca ansible

20

Usiłuję skonfigurować filtr czyszczenia / rozmazywania w git, aby mieć automatyczne szyfrowanie i deszyfrowanie plików zawierających sekrety za pomocą polecenia ansible-vault .

Osobliwością polecenia ansible-vault jest to, że nie jest idempotentny (tworzy inny plik binarny za każdym razem, gdy jest wywoływany na tych samych danych).

Zacząłem od implementacji sugerowanej na tej stronie bloga . Niestety, nie działało to poprawnie, ponieważ za każdym razem, gdy wywoływana jest smudge (czy to w kasie git, czy po prostu status git), tajne pliki wyglądają jak zmodyfikowane dla git, nawet jeśli tak nie jest.

Zastanawiałem się więc, czy git porównałby plik binarny, który ma w indeksie z czystym, przefiltrowanym plikiem bieżącym, i próbowałem zbudować na tych skryptach w następujący sposób:

#!/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

Różnica polega na tym, że próbuje porównać bieżące i HEAD wersje tajnych plików zwykłego tekstu (niezaszyfrowane) i tylko w przypadku, gdy różnią się, wyjdzie nowy binarny obiekt blob zaszyfrowany za pomocą usługi ansible-vault.

Niestety po tej zmianie git nadal myśli, że tajny plik jest zawsze modyfikowany. Nawet po git addponownym wczytaniu pliku, aby obliczyć obiekt blob git, git uważa, że ​​plik jest inny i pozwala zmianom przejść do zatwierdzenia. Pamiętaj, że git diffzwracaj puste zmiany, tak jak powinno.

Dla porównania jest to smuga:

#!/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

i to jest 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
ᴳᵁᴵᴰᴼ
źródło
Zaktualizowałem skrypty, które zachowują się poprawnie, z wyjątkiem sytuacji, gdy git próbuje zautomatyzować konflikty w repozytoriach, które wkrótce
opublikuję
1
Rzucanie butelką w morze, ale: czy plik może być inny z powodu różnych zakończeń linii lub innej strony kodowej?
Tensibai
Spróbuję usunąć -necho rozmazywania, ale zgaduję. Czy nie ma ukrytej opcji dla git diff mówiącego, aby ignorowała zakończenia jednej linii?
Tensibai
Jeszcze inny pomysł: github.com/dellis23/ansible-toolkit (pewnego dnia
zagłębię się

Odpowiedzi:

8

Problem jest spowodowany przypadkową solą w szyfrowaniu w ansible-vault. Możesz zhakować klasę VaultEditor, aby przekazać jej sól z argumentu w ansible-vault. Losowa sól jest generowana w lib/ansible/parsing/vault/__init__.pytym wierszu . Jest wywoływany z lib / ansible / cli / vault.py, gdzie można łatwo dodać argument za naprawioną solą. Jeśli to zmienisz, prześlij poprawkę do Ansible, chciałbym jej użyć.

Problem ten jest dalej omawiany tutaj w wiadomościach hakerów . I istnieją inne implementacje z narzędziami, które mają stałych soli, mianowicie gitcrypt , transcrypt . Tutaj jest również link do jeszcze jednej implementacji używającej ansible-vault o nazwie ansible-vault-tools , ale o ile mi wiadomo, ten sam problem dotyczy soli.

Jiri Klouda
źródło
Jeśli sprawdzisz kod, używam sumy kontrolnej do obejścia problemu zmiennej zawartości soli, tj. najpierw odszyfruj skarbiec HEAD w folderze tmp i porównaj sumy kontrolne zwykłych plików tekstowych przed wygenerowaniem nowego binarnego obiektu blob. To trochę powolne, ale właściwie w porządku. Mój problem jest teraz połączony; w niektórych sytuacjach to działa, w innych automatycznie blokuje się obiekt blob, zanim będę mógł go odszyfrować i się zepsuje.
ᴳᵁᴵᴰᴼ
Jeśli spojrzysz na trzy przykłady, które podłączyłem, istnieje również kilka obejść dotyczących połączeń. Jest to również omawiane w komentarzach hakerów.
Jiri Klouda
BTW Scalanie jest trudne. Musisz zdać sobie sprawę, że w przypadku, gdy wybierzesz wszystkie swoje zmiany lub wszystkie zmiany z góry podczas scalania, git odkryje to poprzez porównanie skrótów, które zadziałałoby, gdyby sól była odpowiednia. Plik tymczasowy nie wystarcza przy czyszczeniu / rozmazywaniu. Powinieneś zrobić to samo podczas scalania, a w przypadku kasowania bez konfliktu poprawnej już zaszyfrowanej wersji z git i użyć tej w przeciwieństwie do ponownego szyfrowania za pomocą nowej losowej soli.
Jiri Klouda
Nie jestem pewien, czy rozumiem, co tu mówisz; scalanie odbywałoby się na zwykłym tekście skarbców (w miarę różnic), a posiadanie tajemnic zawsze oznaczanych jako konflikt nawet w przypadku automatycznych scaleń, a więc łączenie ponownie zaszyfrowanych tajemnic w ramach każdego zatwierdzenia scalania, nie naprawdę stanowią problem (dla mnie).
ᴳᵁᴵᴰᴼ
Czy możesz być zatem konkretny w kwestiach dotyczących scalania? Powinieneś podać odtwarzalny przypadek. Ale nadal sugerowałbym poszukiwanie pomysłów w 3 wyżej wymienionych projektach. Jeśli chodzi o problemy z łączeniem, kiedy łączysz zawartość A z treścią B i wszyscy postanowili wziąć zawsze A lub zawsze B, w przypadku systemów kontroli wersji jest to szczególny przypadek i czasami to zrobią, łącząc wersję ze sobą. Git robi to przez haszowanie zawartości, więc zakłada, że ​​hasz będzie taki sam, ale jeśli ponownie zaszyfrujesz, nawet jeśli zawartość to wszystko A, hasz nie będzie taki sam. Ale możesz mieć inny problem
Jiri Klouda