https://github.com/riboseinc/transcryptor
Assists your everyday re-encryption needs, in Rails.
https://github.com/riboseinc/transcryptor
encryptor migration rails
Last synced: about 2 months ago
JSON representation
Assists your everyday re-encryption needs, in Rails.
- Host: GitHub
- URL: https://github.com/riboseinc/transcryptor
- Owner: riboseinc
- License: mit
- Created: 2017-05-25T08:32:28.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2018-05-31T06:40:37.000Z (almost 7 years ago)
- Last Synced: 2025-04-05T23:32:31.875Z (about 2 months ago)
- Topics: encryptor, migration, rails
- Language: Ruby
- Size: 78.1 KB
- Stars: 2
- Watchers: 5
- Forks: 1
- Open Issues: 15
-
Metadata Files:
- Readme: README.adoc
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
= Transcryptor
image:https://travis-ci.org/riboseinc/transcryptor.svg?branch=master["Build Status", link="https://travis-ci.org/riboseinc/transcryptor"]
image:https://codeclimate.com/github/riboseinc/transcryptor/badges/gpa.svg["Code Climate Quality", link="https://codeclimate.com/github/riboseinc/transcryptor"]
image:https://codeclimate.com/github/riboseinc/transcryptor/badges/coverage.svg["Code Climate Quality", link="https://codeclimate.com/github/riboseinc/transcryptor/coverage"]Transcryptor provides utility functions to help migrate records encrypted with https://github.com/attr-encrypted/attr_encrypted[`attr_encrypted`] from one encryption configuration to another.
== Installation
Add this line to your application's Gemfile:
[source,ruby]
----
gem 'transcryptor', github: 'riboseinc/transcryptor'
----And then execute:
----
bundle
----Or install it yourself as:
----
gem install transcryptor
----== Usage
=== ActiveRecord::Migration
You have a `User` with `ssn` attribute which needs to be re-encrypted. `User` has next configuration:
[source,ruby]
----
class User < ActiveRecord::Base
attr_encrypted :ssn, key: ->(u) { ENV['USER_SSN_ENC_KEY'] },
mode: :per_attribute_iv_and_salt,
algorithm: 'aes-256-gcm'
end
----To re-ecrypt this column with new key (`ENV['NEW_USER_SSN_ENC_KEY']`), algorithm (`aes-256-cbc`) and mode (`per_attribute_iv`) you can easily define migration.
[source,ruby]
----
class ReEncryptUserSsn < ActiveRecord::Migration
def up
re_encrypt_column :users, :ssn,
{ # old configuration of attr_encrypted for :ssn column
key: ->(u) { ENV['USER_SSN_ENC_KEY'] },
mode: :per_attribute_iv_and_salt,
algorithm: 'aes-256-gcm'
},
{ # new configuration of attr_encrypted for :ssn column
key: ->(u) { ENV['NEW_USER_SSN_ENC_KEY'] },
mode: :per_attribute_iv,
algorithm: 'aes-256-cbc'
}
end
end
----
Run `bundle exec rake db:migrate`. Done!=== DataMapper::Migration
See link:#activerecordmigration[ActiveRecord::Migration] for initial data. And then `DataMapper` migration is:
[source,ruby]
----
require 'dm-migrations/migration_runner'migration 1, :re_encrypt_user_ssn do
up do
re_encrypt_column :users, :ssn,
{ # old configuration of attr_encrypted for :ssn column
key: ->(u) { ENV['USER_SSN_ENC_KEY'] },
mode: :per_attribute_iv_and_salt,
algorithm: 'aes-256-gcm'
},
{ # new configuration of attr_encrypted for :ssn column
key: ->(u) { ENV['NEW_USER_SSN_ENC_KEY'] },
mode: :per_attribute_iv,
algorithm: 'aes-256-cbc'
}
end
endmigrate_up!
----=== Additional options
Taking `ActiveRecord` as an example (the following applies to `DataMapper` as well):
==== `where`
Specify an SQL string (or a `proc` returning one) inside the `where` option to
limit the range on which transcryption is run:[source,ruby]
----
class ReEncryptUserSsn < ActiveRecord::Migration
def up
re_encrypt_column :users, :ssn,
{ # old configuration of attr_encrypted for :ssn column
key: ->(u) { ENV['USER_SSN_ENC_KEY'] },
mode: :per_attribute_iv_and_salt,
algorithm: 'aes-256-gcm'
},
{ # new configuration of attr_encrypted for :ssn column
key: ->(u) { ENV['NEW_USER_SSN_ENC_KEY'] },
mode: :per_attribute_iv,
algorithm: 'aes-256-cbc'
},
where: -> { "encrypted_ssn IS NOT NULL" }
end
end
----== Zero Downtime Migration
=== ActiveRecord
Create new columns in database.
[source,ruby]
----
class Migration1 < ActiveRecord::Migration
def up
add_column :users, :encrypted_new_ssn
add_column :users, :encrypted_new_ssn_iv
end
end
----Add `attr_encrypted` for new columns, `include Transcryptor::ActiveRecord::ZeroDowntime`, and `transcryptor_migrate :old_attribute_name, :new_attribute_name`.
[source,ruby]
----
class User < ActiveRecord::Base
include Transcryptor::ActiveRecord::ZeroDowntimeattr_encrypted :ssn, key: '1qwe1qwe1qwe1qwe1qwe1qwe1qwe1qwe', algorithm: 'aes-256-cbc'
attr_encrypted :new_ssn, key: '2asd2asd2asd2asd2asd2asd2asd2asd', algorithm: 'aes-256-gcm'transcryptor_migrate :ssn, :new_ssn
end
----Create `rake` task for zero downtime migration. Or any other way you prefer.
[source,ruby]
----
namespace :zero_downtime
desc 'migrate attr_encrypted for User'
task user: :environment do
User.find_each { |user| user.save! }
end
end
----Remove & rename columns in database after finishing of `rake` task.
[source,ruby]
----
class Migration2 < ActiveRecord::Migration
def up
remove_column :users, :encrypted_ssn
remove_column :users, :encrypted_ssn_ivrename_column :users, :encrypted_new_ssn, :encrypted_ssn
rename_column :users, :encrypted_new_ssn_iv, :encrypted_ssn_iv
end
end
----Move `attr_encrypted` configuration to original attribute and remove all migration code.
[source,ruby]
----
class User < ActiveRecord::Base
attr_encrypted :ssn, key: '2asd2asd2asd2asd2asd2asd2asd2asd', algorithm: 'aes-256-gcm'
end
----Done!
== Default Options
Default options for old and new configuration are absolutelly the same as it is defined in `attr_encrypted` gem.
[source,ruby]
----
{
prefix: 'encrypted_',
suffix: '',
if: true,
unless: false,
encode: true, # changed from false to true as transcryptor works with DB rows
encode_iv: true,
encode_salt: true,
default_encoding: 'm',
marshal: false,
marshaler: Marshal,
dump_method: 'dump',
load_method: 'load',
encryptor: Encryptor,
encrypt_method: 'encrypt',
decrypt_method: 'decrypt',
mode: :per_attribute_iv,
algorithm: 'aes-256-gcm',
}
----== Zero downtime migration using VersionedFields (from version 0.3.0)
You can use transcryptor to migrate your encrypted fields in zero downtime
using https://github.com/riboseinc/versioned_fields[versioned_fields] gem.Just include `Transcryptor::Decoder` module and use `decode_with_previous_settings`
to decode your fields with specific settings:```ruby
# db/migrate_versioned_fields/user/ssn.rbVersionedFields::Migration.draw_for(User, :ssn) do
config.include Transcryptor::Decoderversion 1
version(2) do
decode_with_previous_settings(migration,
key: '67c3800d1572d9d964a6ff3bd821ed02',
algorithm: 'aes-256-gcm'
)
endversion(3) do |migration|
decode_with_previous_settings(migration,
key: '94dd7e2c40a3d51a8dd0a9137356a18e',
algorithm: 'RC2-64-CBC'
)
end
```== Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run
`rake spec` to run the tests. You can also run `bin/console` for an interactive
prompt that will allow you to experiment.== Contributing
Bug reports and pull requests are welcome on GitHub at
https://github.com/riboseinc/transcryptor. This project is intended to be a
safe, welcoming space for collaboration, and contributors are expected to
adhere to the http://contributor-covenant.org[Contributor Covenant] code of
conduct.== License
The gem is available as open source under the terms of the
http://opensource.org/licenses/MIT[MIT License].