kms_encrypted 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dcfe0e3ccdefdbde5b05b879a8f2badf3337fd0e
4
+ data.tar.gz: 8866251c5210f0c67845f99a221931db0a77446f
5
+ SHA512:
6
+ metadata.gz: 664d6f021217bbd3e3740943bc91b60d1ad7af84c6f2081512f03956ba48488a98666a94417a61a1e68a15ccd36a8a4b31c541a6c40422a7cb8f21f079761d0f
7
+ data.tar.gz: dbd76c23ee501e1e7c8cb28d4cd1e45430e6ea3904ef4afa8053973b034f8637627c01646e9b5782079f24c151702aa2e3006940df99f572b73be9a8adad7a56
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## 0.1.0
2
+
3
+ - First release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # KMS Encrypted
2
+
3
+ [KMS](https://aws.amazon.com/kms/) + [attr_encrypted](https://github.com/attr-encrypted/attr_encrypted)
4
+
5
+ The attr_encrypted gem is great for encryption, but:
6
+
7
+ 1. Leaves you to manage the security of your keys
8
+ 2. Doesn’t provide a great audit trail to see how data has been accessed
9
+
10
+ KMS addresses both of the issues and it’s easy to use them together.
11
+
12
+ **Note:** This has not been battle-tested in a production environment, so use with caution
13
+
14
+ ## Getting Started
15
+
16
+ Add this line to your application’s Gemfile:
17
+
18
+ ```ruby
19
+ gem 'kms_encrypted'
20
+ ```
21
+
22
+ Add a column to store encrypted KMS data keys
23
+
24
+ ```ruby
25
+ add_column :users, :encrypted_kms_key, :string
26
+ ```
27
+
28
+ Create a [KMS master key](https://console.aws.amazon.com/iam/home#/encryptionKeys) and set it in your environment (we recommend [dotenv](https://github.com/bkeepers/dotenv))
29
+
30
+ ```sh
31
+ KMS_KEY_ID=arn:aws:kms:...
32
+ ```
33
+
34
+ And update your model
35
+
36
+ ```ruby
37
+ class User < ApplicationRecord
38
+ has_kms_key ENV["KMS_KEY_ID"]
39
+
40
+ attr_encrypted :email, key: :kms_key
41
+ end
42
+ ```
43
+
44
+ For each encrypted attribute, use the `kms_key` method for its key.
45
+
46
+ ## Auditing
47
+
48
+ [AWS CloudTrail](https://aws.amazon.com/cloudtrail/) logs all decryption calls. However, to know what data is being decrypted, you’ll need to add context.
49
+
50
+ Add a `kms_encryption_context` method to your model.
51
+
52
+ ```ruby
53
+ class User < ApplicationRecord
54
+ def kms_encryption_context
55
+ self.id ||= self.class.connection.execute("select nextval('#{self.class.sequence_name}')").first["nextval"]
56
+ {"Record" => "#{model_name}/#{id}"}
57
+ end
58
+ end
59
+ ```
60
+
61
+ The context is used as part of the encryption and decryption process, so it must be a value that doesn’t change. Otherwise, you won’t be able to decrypt.
62
+
63
+ Read more about [encryption context here](http://docs.aws.amazon.com/kms/latest/developerguide/encryption-context.html).
64
+
65
+ ## How It Works
66
+
67
+ KMS allows you to generate data keys from your master key. Data keys are encrypted and stored with each record. Whenever you want to decrypt data, you need to first decrypt the data key with KMS. Once you have the decrypted key, you can then use it to decrypt the data with attr_encrypted.
68
+
69
+ ## TODO
70
+
71
+ - add support for multiple data keys per record
72
+
73
+ ## History
74
+
75
+ View the [changelog](https://github.com/ankane/kms_encrypted/blob/master/CHANGELOG.md)
76
+
77
+ ## Contributing
78
+
79
+ Everyone is encouraged to help improve this project. Here are a few ways you can help:
80
+
81
+ - [Report bugs](https://github.com/ankane/kms_encrypted/issues)
82
+ - Fix bugs and [submit pull requests](https://github.com/ankane/kms_encrypted/pulls)
83
+ - Write, clarify, or fix documentation
84
+ - Suggest or add new features
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ t.warning = false
9
+ end
10
+
11
+ task default: :test
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "kms_encrypted/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "kms_encrypted"
8
+ spec.version = KmsEncrypted::VERSION
9
+ spec.authors = ["Andrew Kane"]
10
+ spec.email = ["andrew@chartkick.com"]
11
+
12
+ spec.summary = "KMS + attr_encrypted"
13
+ spec.homepage = "https://github.com/ankane/kms_encrypted"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ end
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "aws-sdk-kms"
23
+ spec.add_dependency "activesupport"
24
+
25
+ spec.add_development_dependency "bundler"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "minitest"
28
+ spec.add_development_dependency "sqlite3"
29
+ spec.add_development_dependency "activerecord"
30
+ spec.add_development_dependency "attr_encrypted"
31
+ end
@@ -0,0 +1,56 @@
1
+ require "kms_encrypted/version"
2
+ require "active_support"
3
+ require "aws-sdk-kms"
4
+
5
+ module KmsEncrypted
6
+ def self.kms
7
+ @kms ||= Aws::KMS::Client.new
8
+ end
9
+
10
+ module Model
11
+ def has_kms_key(key_id)
12
+ raise ArgumentError, "Missing key id" unless key_id
13
+
14
+ class_eval do
15
+ class << self
16
+ attr_accessor :kms_key_id
17
+ end
18
+ self.kms_key_id = key_id
19
+
20
+ def kms_key
21
+ unless @kms_key
22
+ key_id = self.class.kms_key_id
23
+ context = respond_to?(:kms_encryption_context) ? kms_encryption_context : {}
24
+ default_encoding = "m"
25
+
26
+ unless encrypted_kms_key
27
+ resp = KmsEncrypted.kms.generate_data_key(
28
+ key_id: key_id,
29
+ encryption_context: context,
30
+ key_spec: "AES_256"
31
+ )
32
+ @kms_key = resp.plaintext
33
+ ciphertext = resp.ciphertext_blob
34
+ self.encrypted_kms_key = [resp.ciphertext_blob].pack(default_encoding)
35
+ end
36
+
37
+ unless @kms_key
38
+ ciphertext = encrypted_kms_key.unpack(default_encoding).first
39
+ resp = KmsEncrypted.kms.decrypt(
40
+ ciphertext_blob: ciphertext,
41
+ encryption_context: context
42
+ )
43
+ @kms_key = resp.plaintext
44
+ end
45
+ end
46
+
47
+ @kms_key
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ ActiveSupport.on_load(:active_record) do
55
+ extend KmsEncrypted::Model
56
+ end
@@ -0,0 +1,3 @@
1
+ module KmsEncrypted
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kms_encrypted
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Kane
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-09-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk-kms
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sqlite3
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: activerecord
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: attr_encrypted
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description:
126
+ email:
127
+ - andrew@chartkick.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - CHANGELOG.md
134
+ - Gemfile
135
+ - README.md
136
+ - Rakefile
137
+ - kms_encrypted.gemspec
138
+ - lib/kms_encrypted.rb
139
+ - lib/kms_encrypted/version.rb
140
+ homepage: https://github.com/ankane/kms_encrypted
141
+ licenses: []
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.6.13
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: KMS + attr_encrypted
163
+ test_files: []