Ansible vaultシークレット用のGit clean / smudgeフィルター


20

ansible-vaultコマンドを使用して、秘密を含むファイルを自動的に暗号化および復号化するために、gitでclean / smudgeフィルターを設定しようとしています。

ansible-vaultコマンドの特徴は、it等ではないことです(同じデータで呼び出されるたびに異なるバイナリを作成します)。

このブログページで提案されている実装から始めました。残念なことに、それは正しく機能しませんでした。汚れが呼び出されると(git checkout、または単にgitステータス)、秘密ファイルはgit用に変更されたように見えます。

だから、gitがインデックスにあるバイナリをクリーンフィルター処理された現在のファイルと比較するのではないかと思い、これらのスクリプトを次のように構築しようとしました。

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

ここでの違いは、プレーンテキスト(暗号化されていない)シークレットファイルの現在のバージョンとHEADバージョンを比較しようとし、それらが異なる場合のみ、ansible-vaultで暗号化された新しいバイナリBLOBを出力することです。

残念ながら、この変更の後、gitは秘密ファイルは常に変更されていると考え続けます。git add再度ファイルを実行した後でも、git blobが計算されるように、gitはファイルが異なると判断し、変更をコミットに反映します。git diff空の変更を返す必要があることに注意してください。

参考までに、これは汚れです。

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

これは差分です:

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

gitがボールトの競合を自動マージしようとする場合を除いて、正しく動作するスクリプトを更新しました。これについては、まもなく投稿します
ᴳᵁᴵᴰᴼ

1
海にボトルを投げますが、行末やコードページが異なるためにファイルが異なる可能性がありますか?
テンシバイ

-nスマッジエコーからを削除してみますが、それは推測です。単一行の終わりを無視するように伝えるgit diffの非表示オプションはありませんか?
テンシバイ

さらに別のアイデア:github.com/dellis23/ansible-toolkit(私はこの1日をより深く掘り下げます)
天柴iba

回答:


8

ここでの問題は、ansible-vault暗号化のランダムソルトが原因です。VaultEditorクラスをハックして、ansible-vaultの引数からソルトを渡すことができます。ランダムソルトはlib/ansible/parsing/vault/__init__.pyこの行で生成されます。lib / ansible / cli / vault.pyから呼び出され、固定ソルトの引数を簡単に追加できます。変更する場合は、アップストリームパッチをAnsibleに送信してください。使用したいと思います。

この問題については、ハッカーのニュースでさらに説明します。その他の固定塩を取るツールと実装、すなわちあるgitcrypttranscryptはansible-vault-toolsと呼ばれるansible-vaultを使用したもう1つの実装へのリンクもありますが、これは私が知る限り同じ塩問題を持っています。


コードをチェックする場合、可変ソルトの問題を回避するためにチェックサムを使用しています。最初にtmpフォルダーのHEADボールトを復号化し、プレーンテキストファイルのチェックサムを比較してから、新しいバイナリblobを生成します。それは少し遅いですが、実際には大丈夫です。私の問題は現在マージ中です。特定の状況では機能しますが、他の状況では、ブロブを解読して破損する前に、ブロブを自動マージします。
ᴳᵁᴵᴰᴼ

私がリンクした3つの例を見ると、マージにもいくつかの回避策があります。そして、それはハッカーのニュースのコメントでも議論されています。
ジリクルーダ

ところで、マージはトリッキーです。実現する必要があるのは、マージ中にすべての変更またはすべての変更をアップストリームから選択した場合、gitはハッシュ比較によってそれを把握し、ソルトが正しい場合に機能することです。一時ファイルは、クリーン/スマッジでは不十分です。マージ時に同じことを行い、非競合マージチェックアウトの場合は、gitから既に暗号化された正しいバージョンを使用し、新しいランダムソルトで再暗号化するのではなく、そのバージョンを使用する必要があります。
ジリクルダ

ここであなたが何を言っているのか理解できません。ヴォールトのプレーンテキストでマージが行われ(差分処理が行われるため)、自動マージでもシークレットが常に競合としてマークされるため、マージコミット内にマージされた再暗号化シークレットが含まれることはありません。本当に問題を表します(私にとって)。
ᴳᵁᴵᴰᴼ

次に、マージの問題について具体的に説明できますか?再現可能なケースを提供する必要があります。しかし、上記の3つのプロジェクトのアイデアを探すことをお勧めします。マージの問題に関しては、コンテンツAとコンテンツBをマージし、すべてが常にAまたは常にBになるように解決した場合、特殊なケースであるバージョン管理システムでは、バージョンをリンクすることでそれを行うことがあります。Gitはコンテンツのハッシュを通じてそれを行うため、ハッシュは同じであると想定しますが、再暗号化すると、コンテンツがすべてAであっても、ハッシュは同じではなくなります。しかし、他の問題がある可能性があります
ジリクルダ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.