HoteKanの開発担当者です。
gitで管理するプロジェクトに秘密情報が入ったファイルを配置する場合、暗号化してgitリポジトリに含めるという選択肢があります。
前回の記事(cloud-buildでのgithub連携とファイルの暗号化・復号化)ではそられのファイルをcloud KMSを使って暗号化し、Cloud Buildでのビルド中に復号する方法を紹介しました。
今回はそれらのファイルをgit管理する際に暗号化、複合化を意識することなく透過的に行う方法を紹介します。
gitのclean filterとsmudge filter
gitにはclean
フィルタ、smudge
フィルタという機能があります。これらのフィルタを使えば特定のパスにフィルタを設定し、ステージングの直前とチェックアウトの直前に処理を行うスクリプトを設定できます。
フィルタをかける対象の指定とフィルタの指定は.gitattributes
ファイルで行い、フィルタの内容自体はgit config
で設定します。
clean
フィルタに暗号化、smudge
フィルタに復号化のスクリプトを設定すれば、ワーキングツリー内では復号化したファイルとして扱いながら、インデックス、リポジトリでは暗号化した状態で管理できます。
秘密情報ファイルを更新するたびにいちいち暗号化を自分で行う必要はなくgitに任せることもできます。
cloud KMSを使った暗号化・復号化をgitのフィルタに設定する
以下では上記のフィルタでCloud KMSを使って特定のファイルの暗号化・復号化の方法を紹介します。
.git/config
にフィルタを定義します。
[filter "cloud-kms"]
smudge = .gitencrypt/smudge_filter_cloud-kms
clean = .gitencrypt/clean_filter_cloud-kms
.gitattributes
ファイルでフィルタをかける対象とフィルタの名前を指定します。
* filter=cloud-kms
.gitencrypt/smudge_filter_cloud-kms
ではCloud KMSでファイルの中身を復号化します。
#!/bin/bash
gcloud kms decrypt \
--ciphertext-file=- \
--plaintext-file=- \
--location=global \
--keyring=[KEYRING-NAME] \
--key=[KEY-NAME]
smudge
フィルタでは対象ファイルの内容が標準入力からインプットされます。またフィルタ後の内容は標準出力にアウトプットする必要があります。gcloud kms decrypt
コマンドでは--ciphertext-file=-
で入力として標準入力を、--plaintext-file=-
で出力として標準出力を指定できます。
.gitencrypt/clean_filter_cloud-kms
ではCloud KMSでファイルの中身を暗号化します。
#!/bin/bash
gcloud kms encrypt \
--plaintext-file=- \
--ciphertext-file=- \
--location=global \
--keyring=[KEYRING-NAME] \
--key=[KEY-NAME]
clean
フィルタでも標準入力からインプットされ、標準出力にアウトプットします。gcloud kms encrypt
コマンドでも-
で標準入出力を指定できます。
上記の設定でステージングの際に暗号化、check outの際に復号化が自動で行われます。ワーキングツリーでは暗号化を気にせず編集できます。
git diffでは復号化された状態で比較したい
上記設定後もgit diff
ではバイナリファイルとして処理されて変更点は見えません。git diff
でも復号化した状態を利用したい場合は以下の設定を行います。
.gitattributes
では上で説明したフィルタの設定に加えdiffの設定を追記します。
* filter=cloud-kms diff=cloud-kms
.git/config
ではtextconv
属性を設定します。
[diff "cloud-kms"]
textconv = cat
.git/config
ファイルではファイル名が引数として与えられます。ここではそのファイル内容をそのまま表示しています。
リファレンスにも書いてある箇所は見つけられなかったのですが、diff.driver.textconv
にコマンドが与えられると、textconvが適用される前にsmudge
が適用されます。
そのためここではファイルの内容がすでに復号化された状態なので、内容をそのまま出力します。diff.driver.textconv
にコマンドが設定されていないとsmudge
フィルタの適用もないので、この設定が必要になります。
注意すべき点
新規にcheck outしたり、indexを作り直した際に何も変更していなくても、暗号化対象ファイルがmodifiedなになることがあります。
そのため秘密ファイルを扱うローカルリポジトリは1つにして、後のローカルリポジトリでは暗号化された状態で扱うのがいいのかもしえません。
とはいえ、上記に注意すればかなり便利に使えます。