Vault を使ってチーム内のセンシティブな情報を安全に管理する

多人数でのアプリケーション開発や運用、様々なところでセンシティブな情報が存在しています。
AWS のアクセスキー、Github のトークン、DB のユーザ・パスワードなどなど。
このようなセンシティブな情報の管理はとても大変で、

- シェアをどうするのか
- アクセスコントロールをどうするのか
- セキュリティ的な観点

についてはみなさんも悩んでいることかと思います。
(諦めて Dropbox とか Google Drive で管理している光景が...)

そんなセンシティブな情報をスマート且つ安全に管理するためのツールが **Vault** です。

Official Web Site: https://www.vaultproject.io/
Github: https://github.com/hashicorp/vault

## Vault とは
HashiCorp 製のシークレットマネージメントツールです。

Vault は以下のことを可能にしてくれます。

### Secret の管理
- Secret は Key/Value の形で管理されます
- Secret は Vault によって暗号化され、ストレージに安全に保管されます
- S3, Consul, MySQL, PostgreSQL, ローカルストレージなど様々なプラットフォームに対応しています

### アクセスコントロールと認証
- Policy (role) 毎に細かくアクセスコントロールを設定できます
- Username/Password はもちろん Github Organization, LDAP, MFA などで認証が行えます
- Github Organization の Team 毎に Policy を設定できます:+1: 

### 運用
- Vault で行われたオペレーションをすべてロギングすることが出来ます
- 複数サーバーによる High Availability Mode に対応しています
- 認証方法やシークレットはストレージに格納されているため、サーバーを立ち上げ直すだけで復旧が出来ます

これだけで便利なことがわかりますね？

## Vault を使ってみる
実際に Vault を触ってみましょう。

### 環境構築
OSX は Homebrew でインストールすることが出来ます。

```bash
$ brew install vault
==> Downloading https://homebrew.bintray.com/bottles/vault-0.5.2.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring vault-0.5.2.el_capitan.bottle.tar.gz
🍺  /usr/local/Cellar/vault/0.5.2: 2 files, 37.8M
```

今回は Development mode で実行します。
Development mode で起動するとメモリにデータが書き込まれるようになります。
もちろんサーバーを停止すればデータも消去されます。
ローカルストレージが汚れないため気軽に試せますね。

```bash
$ export VAULT_ADDR="http://127.0.0.1:8200"
$ vault server -dev &
```

さてこれで準備は完了です。

### Secret の読み書き、削除をしてみる
CLI を使って Secret の読み書き、削除をしてみましょう。
Vault は filesystem のように Path 毎に Secret が保存されます。
デフォルトで用意されているマウントポイントである ``secret/`` に Secret を書き込んでみましょう。

```bash
$ vault write secret/hello secretkey=secretvalue
Success! Data written to: secret/hello
```

確認をしてみます。

```bash
$ vault read secret/hello
Key           	Value
lease_duration	2592000
secretkey     	secretvalue
```

ちゃんと保存されていました。

よく見ると ``lease_duration 259200`` という謎の Key/Value があります。
Vault には TTL(Time To Live) の概念があります。
259200秒(180日)でこの Secret は削除されることを示しています。
**ただし ``secret/`` に関してはこれは無効になっています。**
この事については Secret backends で詳しく説明します。

さて今度は Secret を file から登録してみましょう。
JSON で Key/Value を記載する必要があります。
[jo](https://github.com/jpmens/jo) などで生成すると楽かもしれません。

```bash
$ jo -p fileformat=json method=file
{
   "fileformat": "json",
   "method": "file"
}

$ jo -p fileformat=json method=file > secret.json
$ vault write secret/hello @secret.json
Success! Data written to: secret/hello

$ vault read secret/hello
Key           	Value
lease_duration	2592000
fileformat    	json
method        	file
```
先ほどと同じ Path に write しました。
Vault には ``vault update`` のようなコマンドは存在しません。
**write で同じ Path に書き込んだ場合は update 扱い** になります。
アクセスコントロールで update 禁止の制限も出来ますので注意しましょう。

最後にこの Secret を削除します。

```bash
$ vault delete secret/hello
Success! Deleted 'secret/hello'
```

確認をしてみます。

```bash
$ vault list secret
No value found at secret
```
きちんと削除されました。

ちなみに Key/Value で管理されるのでバイナリも base64 にエンコードすれば扱えます。

## アーキテクチャ
Vault は様々なコンポーネントによって構成されています。
データの管理もそれぞれのコンポーネントに一任される仕組みとなっています。

![layers-2909a77d.png](https://qiita-image-store.s3.amazonaws.com/0/72289/833b18b6-98c0-30bf-3401-2cf187798d43.png "layers-2909a77d.png")
> https://www.vaultproject.io/assets/images/layers-2909a77d.png

ここでは特に重要な以下の3つのコンポーネントについて説明します。

- Secret Backends
- Auth Backends
- Audit Backends

### Secret Backends
Secret の管理を行っているコンポーネントです。
Vault ではこの Secret Backend をマウントしたマウントポイントにデータを書き込んでいきます。
Secret Backends は複数の Backend をサポートしており、それぞれで管理するデータや振る舞いが異なります。
中でもよく使われる **Generic Backend** と **AWS Backend** について説明します。

#### Generic Backend
Generic Backend は一般的な Secret を取り扱う Backend です。
先ほど ``secret/`` といったマウントポイントに Secret を書き込んでいました。
``secret/`` は Vault がデフォルトで用意しているマウントポイントで、この Backend をマウントしています。
Generic Backend には TTL が過ぎてもデータを削除しないという仕様があります。
``secret/`` に書き込んだ Secret が削除されないと言った理由はこれです。

#### AWS Backend
AWS Backend は AWS の IAM を取り扱う Backend です。
Policy にもとづいて IAM を作成し、そのまま Vault がトークンを管理します。
これがあると ``インターン用に S3 の全権限をもった IAM を一週間だけ作成する`` みたいなことが簡単にできるようになります。
こういった Secret の管理を **Dynamic Secrets** と呼んでいます。

### Auth Backends
Vault の認証の管理を行っているコンポーネントです。
またユーザーに Policy を紐付けるのもこのコンポーネントの役割です。

- Github
- LDAP
- MFA
- User/Password

などなど様々な認証方法を提供しています。

### Audit Backend
Vault での作業内容をロギングするコンポーネントです。
センシティブな情報に関しては HMAC-SHA256 でハッシュ化しているため、吐き出されたログを見られても問題はありません。

## 終わりに
Vault は今まで苦労していたシークレットの管理をスマートに行えるツールです。
デプロイや設定は簡単で、特に Github Organization でユーザー及びアクセスコントロールを管理できるのはとても素晴らしいです。

シークレット管理で悩んでいる皆さん、是非 Vault を使ってみてください。

AWS EC2(CoreOS, Docker) + S3 環境で動かすための user-data のサンプルを用意してあります。
よろしければ参考にしてください。
https://github.com/munisystem/vault-coreos/blob/master/coreos/user-data.yml.erb