はじめに
HashiCorpからVaultとRailsを連携させるためのgemvault-rails
が提供されていたのでサンプルアプリを作成して動作確認してみました。
HashiCorp Vaultとは?
HashiCorpが提供している機密情報の管理ツールです。
vault-railsとは?
HashiCorpから提供されているVaultとRailsを連携させるためのgemです。
データの暗号化・復号化をvault-rails
が透過的に処理してくれるため、利用するデータの暗号化・復号化をあまり意識せずにコードを記述することができます。
データの暗号化・復号化に利用するKeyがVaultに格納され、暗号化したデータ自体はRailsのDBに格納されるようです。
参考
公式サイト : Vault by HashiCorp
Gihub : hashicorp/vault-rails
バージョン
Vault
v0.8.0
Rails
rails(5.1.3)
vault (0.10.1)
vault-rails (0.3.2)
Vault
起動
Vaultを起動して「127.0.0.1:8200」でHTTPリクエストを受信できる状態にしておく。
(unsealも忘れずに)
参考:HashiCorp Vault で HTTP API を利用する - Qiita
補足:
Vaultがunsealされてないとデータの読み込みが出来ず、以下のようなエラーが発生します。
The Vault server at `http://127.0.0.1:8200' responded with a 503.
Any additional information the server supplied is shown below:
* Vault is sealed
mount
vault-rails
ではsecret backendとしてtransit
を利用するので、マウントしておく。
$ vault mount transit
Successfully mounted 'transit' at 'transit'!
補足:
transit
のマウントを忘れるとRailsでデータを読み書きする際に以下のようなエラーが発生します。
The Vault server at `http://127.0.0.1:8200' responded with a 404.
Any additional information the server supplied is shown below:
* no handler for route 'transit/encrypt/my_app_users_ssn//'
* Please refer to the documentation for help.
Rails
hashicorp/vault-railsのREADMEを参考にアプリを準備していきます。
Gemfile
gem "vault-rails", "~> 0.1", require: false
initializer
READMEのサンプルはProduction環境だけで動作させる内容になっていたので、develop環境でも利用できるようにvault.enabled
を書き換えました。vault.address
やvault.token
は環境変数でも指定できるようですが、今回は動作確認なのでベタ書きしました。
require "vault/rails"
Vault::Rails.configure do |vault|
# Use Vault in transit mode for encrypting and decrypting data. If
# disabled, vault-rails will encrypt data in-memory using a similar
# algorithm to Vault. The in-memory store uses a predictable encryption
# which is great for development and test, but should _never_ be used in
# production.
#vault.enabled = Rails.env.production?
vault.enabled = true
# The name of the application. All encrypted keys in Vault will be
# prefixed with this application name. If you change the name of the
# application, you will need to migrate the encrypted data to the new
# key namespace.
vault.application = "my_app"
# The address of the Vault server. Default: ENV["VAULT_ADDR"].
vault.address = "http://127.0.0.1:8200"
# The token to communicate with the Vault server.
# Default: ENV["VAULT_TOKEN"].
vault.token = "xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"
end
Model
READMEではperson
でしたが、user
でモデルを作成しました。
暗号化の対象はREADMEと同じくssn
とします。
暗号化したデータを格納するssn_encrypted
も合わせて用意します。
$ rails g scaffold user name:string ssn:string ssn_encrypted:string
$ rake db:migrate
class User < ApplicationRecord
include Vault::EncryptedModel
vault_attribute :ssn
end
データの暗号化・復号化
http://localhost:3000/users/new にアクセスして、scaffoldで自動生成されたフォームからデータを入力します。ssn_encrypted
には自動的にデータが挿入されるため、空のままにします。
データの保存に成功するとssn_encrypted
に暗号化したデータが保存されます。
画面を見た時に「あれ?入力した値がssn
に表示されてるぞ?暗号化されてないんじゃない?」と思いますが、テーブルをselectするとssn
カラムに実データが保存されてないことがわかります。
user.ssn
を呼び出す際にrails-vault
が自動的にデータを復号化してくれていたようです。
データの暗号化・復号化をvault-rails
が透過的に処理してくれるのは便利ですね。