78
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Gitリポジトリ暗号化のススメ - git-secret -

Last updated at Posted at 2018-10-26

はじめに

先日、「git-secretsはじめました」というエントリを公開しました。git-secretsは、APIキーなど秘密情報を含んだファイルがgitリポジトリへ誤ってcommitされないようにするためのツールです。一方で、非常に名前が似通った git-secret (sなし) というものが存在します。このgit-secret (sなし) は、git-secrets (sあり) 1 とは全く別のアプローチ、すなわちgitリポジトリに安全に秘密情報をアップロードしちゃおうという思想で開発が進められているbashツールです。本エントリではこの git-secret をざっくり紹介します。

Q: git-secretは何ができる?

A: 指定ファイルを暗号化、許可した人のみが復号できるようにすることで、公開gitリポジトリを通じて秘密情報を共有できます。

そのためにgit-secretがやってることは割と単純で、以下に簡単にまとめます。

  1. まず暗号化したいファイルを指定、そのファイル自身は.gitignoreに追加することで2度とリポジトリにcommitされないようにする。
  2. 暗号化の設定として、相手のGPG公開鍵をインポート。
  3. GPGによる公開鍵暗号化。
  4. 共有先の情報と一緒に暗号化済ファイルをgit addしてcommit/push。

「漏洩防止のための水際防止策」であるところのgit-secrets (sあり) とは異なり、「水際防止策を講じるよりも前に考慮すべき点を一歩突っ込んだ形で実現するためのツール」だということがなんとなくおわかりになるかと思います。すなわち、「gitに秘密情報の入ったファイルをcommitしない」ということを暗号化を用いて実現しています。

準備

実際に使ってみて動作を確かめるため、準備を進めます。ここではmacOS Xあるいは*nixを利用することとします。また、git-secretはbashを前提としたツールですので、bashの利用を仮定しています。

GPGの導入

git-secretは GnuPG (GPG) を利用して暗号化・復号を行います。そのため、GPGが導入されていない場合は、その準備から必要になります。GPGそのものについての説明はここでは割愛します。QiitaにはGPGについての良エントリがありますので、そちらを参照してください。2

GPG Suiteのインストール

macOS Xの場合は、GPG Suite を導入しましょう。GPG Suiteの中に含まれるGPG Mailは不要であれば削除しても良いでしょう。homebrewでの導入も可能です。

$ brew install gnupg

*nixの場合は、お好きなパッケージ管理ツールないしソースからインストールしてください。Debian/Ubuntuの場合は、以下でインストール可能です。

$ sudo apt-get install gnupg

GPG Keyの生成

続いて、自分のGPG公開鍵・秘密鍵ペアを生成します。コンソールを開き、gpg --gen-keyコマンドを実行することで、以下のように対話型でGPG鍵ペアを生成できます。 このとき指定するメールアドレスがgitのuser.emailに指定するものと同じものとなるようにしてください。 これは、git-secretにおいて、user.emailがデフォルトでアクセス権限を与える相手 = 自分という設定となっているためです。GPG Suiteを導入したmacOS XではGPG Keychain.appからGUI経由でも生成できます。3

$ gpg --gen-key
gpg (GnuPG/MacGPG2) 2.2.10; Copyright (C) 2018 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: Test User
Email address: xxxx@xxxxxx.org
You selected this USER-ID:
    "Test User <xxxx@xxxxxx.org>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key 028D26D9DF49446A marked as ultimately trusted
gpg: revocation certificate stored as '/Users/xxx/.gnupg/openpgp-revocs.d/041E87E64316B3685E352B0B028D26D9DF49446A.rev'
public and secret key created and signed.

pub   rsa2048 2018-10-25 [SC] [expires: 2020-10-24]
      041E87E64316B3685E352B0B028D26D9DF49446A
uid                      Test User <xxxx@xxxxxx.org>
sub   rsa2048 2018-10-25 [E] [expires: 2020-10-24]

gpg --list-keys で鍵が正しくインポートされているか確認してみましょう。

$ gpg --list-keys
/Users/xxx/.gnupg/pubring.kbx
-----------------------------
pub   rsa2048 2018-10-25 [SC] [expires: 2020-10-24]
      041E87E64316B3685E352B0B028D26D9DF49446A
uid                      Test User <xxxx@xxxxxx.org>
sub   rsa2048 2018-10-25 [E] [expires: 2020-10-24]

上記の状態になればひとまずGPGの準備完了です。

git-secretのインストール

macOS Xの場合、homebrewからインストール可能です。

$ brew install git-secret

それ以外の場合、ソースからインストールが可能です。aptやrpmにも対応しています。4

$ git clone https://github.com/sobolevn/git-secret.git
$ cd git-secret && make build
$ PREFIX="/usr/local" make install

簡単な使い方

まずは、自分自身だけに秘密情報へのアクセスを許す例を使って、簡単に使い方を紹介しましょう。テスト用のディレクトリ./git-secretにgitリポジトリを作って説明します。

$ mkdir git-secret
$ cd git-secret
$ git init

まずは git secret init コマンドにより.gitsecretディレクトリを生成します。

$  git secret init
'/Users/xxx/git-secret/.gitsecret/' created.
cleaning up...

.gitsecret ディレクトリは、暗号化対象ファイルの設定や、復号できる相手の公開鍵情報などが格納されます。これらをアクセスを許す相手と共有しないとデータが復号できないため、git addします。セキュリティ上、.gitsecretは公開しても実際に保護したいファイルのセキュリティに影響を与えませんが、暗号化対象ファイルの名前は秘匿されないので注意しましょう。

$ git add .gitsecret

まずは必ず自分だけは復号できるよう、自分のメールアドレス (この例ではxxx@xxxxxx.org) に対してアクセス権限を与えます。このとき、gitのuser.emailに自分のメールアドレスが正しく指定されていることを確認してください。

$ git secret tell -m
gpg: keybox '/Users/xxx/git-secret/.gitsecret/keys/pubring.kbx' created
gpg: /Users/xxx/git-secret/.gitsecret/keys/trustdb.gpg: trustdb created
done. xxx@xxxxxx.org added as someone who know(s) the secret.
cleaning up...

このリポジトリに設定されたgit-secretにおいて、誰がアクセスを許可されているのか調べるにはgit secret whoknowsコマンドを実行します。

$ git secret whoknows
xxx@xxxxxx.org

自分だけがアクセス許可されていることがわかります。

続いて、秘密情報を入れたファイルを生成して、git-secretに秘匿するように設定します。secret.txtを生成して、.gitignoreに追加、git secret addでgit-secretへ設定します。このとき、.gitignoreに登録しないままだと、後の暗号化時にエラーが出ます。

$ echo "this is my secret" > secret.txt
$ echo "secret.txt" > .gitignore
$ git secret add secret.txt
1 item(s) added.

git secret hideコマンドを実行すると、git secret addコマンドで設定されたファイルが暗号化され、拡張子.secretのファイルが生成されます。

$ git secret hide
done. all 1 files are hidden.
$ ls
secret.txt        secret.txt.secret

このときgitのリモートリポジトリを通じて共有するのは、.gitsecretディレクトリに加えて、暗号化されたファイル本体である拡張子.secretのファイルとなります。このため、secret.txt.secretgit addし、commitしてみます。あとはよしなにリモートリポジトリを設定してpushしてみてください。

$ git add secret.txt.secret .gitsecret
$ git commit -m 'initial secret commit'
$ git remote add origin https://github.com/xxxxxx/x.......git
$ git push -u origin master

今度は、pushしたリモートリポジトリから別のディレクトリへgit cloneして、自分がsecret.txtを得られるか、試してみましょう。secret.txt.secretは、あんまり確認したことにはならないですが、catで中身を見ても元のテキストでない暗号文であることがわかります。

$ mkdir -p git-secret-clone
$ git clone https://github.com/xxxxxx/x.......git git-secret-clone
$ cd git-secret-clone
$ ls
.                 ..                .git              .gitignore        .gitsecret        secret.txt.secret
$ cat secret.txt.secret

secret.txtへ復号するには、git secret revealコマンドを実行します。これにより、git-secretに設定されたすべての暗号化ファイルについて、自分のgpg公開鍵に対応する秘密鍵で復号処理が実行されます。

$ git secret reveal
done. all 1 files are revealed.
$ ls
.                 ..                .git              .gitignore        .gitsecret        secret.txt        secret.txt.secret
$ cat secret.txt
this is my secret

GPG鍵ペアを生成したときに設定したパスフレーズの入力を求められ、無事に復号できました。

続いて、せっかくのgitリポジトリですので秘密情報のファイルを更新してcommitしてみましょう。秘密情報ファイルを更新した場合、改めてgit secret hideを実行して再暗号化、暗号化ファイルの方のアップデートを行ってからcommitをすることになります。

$ echo 'updated' >> secret.txt

$ cat secret.txt
this is my secret
updated

$ git commit -a -m 'updated'
[master 5631f69] updated
 1 file changed, 0 insertions(+), 0 deletions(-)
 rewrite secret.txt.secret (100%)

$ git push

元のディレクトリに戻ってgit pullgit secret revealをすることで、更新された秘密情報ファイルもリモートリポジトリ経由で取得できていることがわかります。

$ cd ../git-secret
$ git pull
remote: Counting objects: 5, done
remote: Finding sources: 100% (3/3)
remote: Getting sizes: 100% (3/3)
remote: Total 3 (delta 1), reused 3 (delta 1)
Unpacking objects: 100% (3/3), done.
From https://github.com/xxxxxx/x.......
   7dea230..5631f69  master     -> origin/master
Updating 7dea230..5631f69
Fast-forward
 secret.txt.secret | Bin 1409 -> 1416 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)

$ git secret reveal
File '/Users/xxx/git-secret/secret.txt' exists. Overwrite? (y/N) y
done. all 1 files are revealed.

$ cat secret.txt
this is my secret
updated

gitリポジトリを介した秘密情報のやり取りについてイメージはつかめましたでしょうか? 次の節では、この節で作ったgit-secretディレクトリとリポジトリを複数ユーザで利用することを想定し、秘密情報へアクセスできるユーザを追加したり削除したりする、もうちょっと突っ込んだ使い方について紹介します。

複数ユーザでの秘密情報の共有

アクセス可能ユーザの追加

アクセス権限を与えたい相手から、メールなどでその相手のGPG公開鍵を受け取ります。その鍵を適当な名前のファイルにして保存し、自分のローカルgpg鍵リポジトリ ~/.gnupg/ へインポートしましょう。追加したい相手全員に対して鍵を取得し、この作業を繰り返します。

$ gpg --import member_public_key.pub

gpg --list-keysを実行すると自分の鍵に加えてその相手の鍵が正しくインポートされていることがわかります。

$ gpg --list-keys
/Users/xxx/.gnupg/pubring.kbx
-----------------------------
pub   rsa2048 2018-10-25 [SC] [expires: 2020-10-24]
      041E87E64316B3685E352B0B028D26D9DF49446A
uid                      Test User <xxxx@xxxxxx.org>
sub   rsa2048 2018-10-25 [E] [expires: 2020-10-24]

pub   rsa4096 2018-10-25 [SC] [expires: 2022-10-25]
      DE22B0EC5E6A5B7B0E6D4FF871AF954BA86FDEED
uid           [ unknown] Test User2 <yyyy@yyyy.org>
sub   rsa4096 2018-10-25 [E] [expires: 2022-10-25]

続いて、git-secretを設定したgitリポジトリのディレクトリで、当該のユーザのメールアドレス (この例だとyyyy@yyyy.org) に対してアクセス権限を与えてみましょう。

$ git secret tell yyyy@yyyy.org
done. yyyy@yyyy.org added as someone who know(s) the secret.

$ git secret whoknows
xxxx@xxxxxx.org
yyyy@yyyy.org

上記のように、2人に対してアクセス権限が与えられたことがわかりました。このアクセス権限の追加処理を、許可したいユーザごとに繰り返します。

アクセス権限を持つユーザは追加できましたが、この段階では暗号化されたファイルの方はまだ更新されておらず、権限を持つユーザ全員がアクセス可能なものにはなっていません。そのため、改めてgit secret hideコマンドを実行して再暗号化を行う必要があります。

$ git secret hide
done. all 1 files are hidden.

$ git commit -a -m 'added yyyy'
[master cf53b2d] added yyyy
 3 files changed, 0 insertions(+), 0 deletions(-)
 rewrite secret.txt.secret (100%)
$ git push

上記の処理で、yyyy@yyyy.orgさんもこのリモートリポジトリをcloneすることでsecret.txtを復号して取得できるようになりました。

ユーザの失効

今度はyyyy@yyyy.orgさんからアクセス権限を剥奪してみます。

$ git secret killperson yyyy@yyyy.org
removed keys.
now [yyyy@yyyy.org] do not have an access to the repository.
make sure to hide the existing secrets again.

$ git secret whoknows
xxxx@xxxxxx.org

この段階では、まだyyyy@yyyy.orgさんは暗号化ファイルsecret.txt.secretの復号が可能です。なので、アクセス権限の付与のときと同様に、git secret hideコマンドで再暗号化し、リモートリポジトリのファイルも二度とアクセスできないようにします。

$ git secret hide
done. all 1 files are hidden.

$ git commit -a -m 'revoked yyyy'
[master ec49af1] revoked yyyy
 2 files changed, 0 insertions(+), 0 deletions(-)
 rewrite secret.txt.secret (100%)
$ git push

注意しなければいけないことは、過去のcommitには再暗号化前のファイルが入っているということです。このため、失効したユーザもcommitを遡ればファイルを復号することが可能です。このため、ユーザを失効した後は秘密情報そのものも更新しておくことが重要です。アクセスキーなどは再発行してファイルに上書きして更新しておきましょう。

Q&A

Q: git-secretの暗号化設定対象ファイル一覧はどう見るの?

A: git secret listコマンドで一覧できます。

$ git secret list
secret.txt

Q: git-secretの暗号化設定対象からの解除はどうするのか?

A: git secret remove <file name>で可能です。

$ git secret remove secret.txt
secret.txt -> secret.txt -> /Users/xxxx/git-secret/secret.txt
removed from index.
ensure that files: [secret.txt] are now not ignored.
cleaning up...

removeした後に再暗号化は不要ですが、gitリポジトリで生ファイルを共有をするならば.gitignoreの編集などを行いましょう。

Q: git-secrets (sあり) と併用できるの?

A: できます。git-secrets (sあり) の検査で引っかかるような秘密情報が入ったファイルは、必ず暗号化してから git commit するというようなルール付けをすると、ヒューマンエラーも減るしgitを通じた秘密情報の共有もできるし良いのでは。

まとめ

GPGがとてもめんどくさいが何よりも気になるところではありますが、git-secretを利用することで、サーバのアクセスキーなどの秘密情報を「外に出さない」という運用から「安全に共有する」という運用に切り替えることができるようになります。アクセスキーの共有がし辛いなど、利便性が損なわれている場合には導入を検討してみてもいいと思います。

また、git-secretの現状バージョンでは

  • git secret tell後などに必要となるgit secret hideによる再暗号化
  • git secret addしたファイルの.gitignoreへの追加

などの煩雑な処理が必要です。これら、gitのhooksを編集することでgit commit実行時などに自動的に行われるように対応すればgit-secretのめんどくさい手順が大幅にが大きく向上するでしょう。このあたりはまずは自前で編集してしばらく運用してみるつもりです。

参考

おまけ:アクセス制御について

実際の使い方を紹介したところで、最後におまけとしてgit-secret (ひいてはGPG)の思想をなんとなく理解するために重要な、データのアクセス制御の概念を紹介しておきましょう。

情報セキュリティにおけるアクセス制御には、ざっくり2種類のアプローチがあります。1つは「セッションベースのアクセス制御」、もう1つは「暗号化ベースのアクセス制御」です。git-secretは、後者の「暗号化ベースのアクセス制御」の概念を利用したアプリケーションです。

セッションベースのアクセス制御

セッションベースのアクセス制御は非常に理解しやすいと思います。これは、ID/Passwordなどによる「認証」を基礎としています。認証により、アクセスを許可する主体 (例えばデータのオーナー) が

  • 認証を要求してきた相手は誰なのか
  • その相手にどこまでアクセスを許していいのか

を確認した上で、相手と安全かつ一時的な「セッション」を構築します。そのセッションを通じた場合のみ、データへのアクセスが許されるという方法です。ユーザ管理が必要なWebサービスなどは、通常こちらの考えでアクセス制御がなされています。もっと言っちゃえば、SSL/TLSなんかはこの考えで作られています。

暗号化ベースのアクセス制御

こちらは、セッションベースのアクセス制御とは全く異なる思想の方法です。非常に端的に言えば、暗号化ベースのアクセス制御とは、アクセスを許可する主体が「アクセスを許したい相手だけが復号できるように適切に暗号化した上で、暗号化データを配布してしまおう」という方法です。これは言い換えれば、アクセス許可を与えられた人以外に復号されることがなければ、暗号化データそのものは公開してしまっても構わないという考え方です。データそのものがわかんなきゃいいでしょ、ってことですね。5

ご理解の通り、適切に暗号化を行った上でgitリポジトリで全世界に公開してしまおうというgit-secretは、完全にこの思想に則ったアプリケーションです。その他、メディアデータは暗号化してContent Delivery Network (CDN) で公開・配布してしまって、復号するための権限として復号鍵を購入するようなのDRMのサービスはこちらの考えで作られていると言ってもよいでしょう。

それぞれのpros/cons

それぞれ非常に簡単に以下にまとめてみます。

セッションベースのアクセス制御

  • pros:
    • アクセスユーザの追加、失効、権限(アクセス範囲)変更が容易。
  • cons:
    • アクセスユーザ管理、認証、セッション管理のインフラ整備が比較的大変。
    • アクセス制御するデータが1ファイルであったとしても、アクセスユーザ数分のセッション構築・帯域確保が必要。

暗号化ベースのアクセス制御

  • pros:
    • 各ユーザの公開鍵を用いて、(適切な暗号アルゴリズムにより) データを暗号化するのみでアクセス制御が可能。
    • データを復号するために必要なのは、全ユーザで同じ暗号化データとなり、データ再利用性が高い。6
  • cons:
    • 一度配信してしまったデータに対しては、アクセスユーザの追加、失効、権限変更が困難。7

どちらがいい悪いというものではなく、一長一短なのは見てお分かりになる通りです。利用シーンやアクセス制御したいデータに応じて使い分けることが重要ですね。

  1. git-secretsとgit-secret、名前が非常にややこしいため、強調して区別したいときには「sなし」と「sあり」と記載します。

  2. 例えば https://qiita.com/moutend/items/5c22d6e57a74845578f6

  3. New → 名前・パスワード入力 → Generate で生成。

  4. http://git-secret.io/installation

  5. ただし、法制度と技術は乖離しているので、一概に適用していい考えかどうかはその利用形態に応じて変わります。例えば経済産業省の個人情報保護ガイドラインの解釈では、数年前まで個人情報は暗号化していても個人情報という扱いで、暗号化された個人情報データが外部に出ること=個人情報漏洩とされていました。ちょっとあたまおかしい。

  6. ただし、暗号アルゴリズムや暗号の利用方法次第です。最悪の場合、各ユーザごとに別の暗号化データを用意することになります。

  7. 前述したように、過去のcommitは失効したユーザでも依然アクセス可能なことなど、追加・失効・変更などが未来のデータに対してのみしか有効ではないことを意味します。

78
56
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
78
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?