Project

active_kms

0.01
The project is in a healthy, maintained state
Simple, secure key management for Active Record encryption
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

 Project Readme

Active KMS

Simple, secure key management for Active Record encryption

Note: At the moment, encryption requires three encryption requests and one decryption request. See this Rails issue for more info. As a result, there’s no way to grant encryption and decryption permission separately.

For Lockbox and attr_encrypted, check out KMS Encrypted

Build Status

Installation

Add this line to your application’s Gemfile:

gem "active_kms"

And follow the instructions for your key management service:

  • AWS KMS
  • Google Cloud KMS
  • Vault

AWS KMS

Add this line to your application’s Gemfile:

gem "aws-sdk-kms"

Create an Amazon Web Services account if you don’t have one. KMS works great whether or not you run your infrastructure on AWS.

Create a KMS master key and set it in your environment along with your AWS credentials (dotenv is great for this)

KMS_KEY_ID=alias/my-key
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...

And add to config/application.rb:

config.active_record.encryption.key_provider = ActiveKms::AwsKeyProvider.new(key_id: ENV["KMS_KEY_ID"])

Google Cloud KMS

Add this line to your application’s Gemfile:

gem "google-cloud-kms"

Create a Google Cloud Platform account if you don’t have one. KMS works great whether or not you run your infrastructure on GCP.

Create a KMS key ring and key and set it in your environment along with your GCP credentials (dotenv is great for this)

KMS_KEY_ID=projects/my-project/locations/global/keyRings/my-key-ring/cryptoKeys/my-key

And add to config/application.rb:

config.active_record.encryption.key_provider = ActiveKms::GoogleCloudKeyProvider.new(key_id: ENV["KMS_KEY_ID"])

Vault

Add this line to your application’s Gemfile:

gem "vault"

Enable the transit secrets engine

vault secrets enable transit

And create a key

vault write -f transit/keys/my-key

Set it in your environment along with your Vault credentials (dotenv is great for this)

KMS_KEY_ID=my-key
VAULT_ADDR=http://127.0.0.1:8200
VAULT_TOKEN=secret

And add to config/application.rb:

config.active_record.encryption.key_provider = ActiveKms::VaultKeyProvider.new(key_id: ENV["KMS_KEY_ID"])

Per-Attribute Keys

Specify per-attribute keys

class User < ApplicationRecord
  encrypts :email, key_provider: ActiveKms::AwsKeyProvider.new(key_id: "...")
end

Testing

For testing, you can prevent network calls to KMS by adding to config/environments/test.rb:

config.active_record.encryption.key_provider = ActiveKms::TestKeyProvider.new

Key Rotation

Key management services allow you to rotate the master key without any code changes.

  • For AWS KMS, you can use automatic key rotation
  • For Google Cloud, use the Google Cloud Console or API
  • For Vault, use:
vault write -f transit/keys/my-key/rotate

New data will be encrypted with the new master key version. To encrypt existing data with new master key version, run:

User.find_each do |user|
  user.encrypt
end

Switching Keys

You can change keys within your current KMS or move to a different KMS without downtime.

Set globally in config/application.rb:

config.active_record.encryption.previous = [{key_provider: ActiveKms::AwsKeyProvider.new(key_id: "...")}]

Or per-attribute:

class User < ApplicationRecord
  encrypts :email, previous: [{key_provider: ActiveKms::AwsKeyProvider.new(key_id: "...")}]
end

Reference

Specify a client

ActiveKms::AwsKeyProvider.new(client: Aws::KMS::Client.new, ...)
# or
ActiveKms::GoogleCloudKeyProvider.new(client: Google::Cloud::Kms.key_management_service, ...)
# or
ActiveKms::VaultKeyProvider.new(client: Vault::Client.new, ...)

History

View the changelog

Contributing

Everyone is encouraged to help improve this project. Here are a few ways you can help:

To get started with development:

git clone https://github.com/ankane/active_kms.git
cd active_kms
bundle install
bundle exec rake test