kms_encrypted 0.3.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore DELETED
@@ -1,9 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
@@ -1,11 +0,0 @@
1
- language: ruby
2
- rvm: 2.4.2
3
- gemfile:
4
- - Gemfile
5
- sudo: false
6
- before_install: gem install bundler
7
- script: bundle exec rake test
8
- notifications:
9
- email:
10
- on_success: never
11
- on_failure: change
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec
data/Rakefile DELETED
@@ -1,11 +0,0 @@
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
@@ -1,262 +0,0 @@
1
- # Amazon KMS
2
-
3
- Add this line to your application’s Gemfile:
4
-
5
- ```ruby
6
- gem 'aws-sdk-kms'
7
- gem 'kms_encrypted'
8
- ```
9
-
10
- Add columns for the encrypted data and the encrypted KMS data keys
11
-
12
- ```ruby
13
- add_column :users, :encrypted_email, :text
14
- add_column :users, :encrypted_email_iv, :text
15
- add_column :users, :encrypted_kms_key, :text
16
- ```
17
-
18
- Create an [Amazon Web Services](https://aws.amazon.com/) account if you don’t have one. KMS works great whether or not you run your infrastructure on AWS.
19
-
20
- Create a [KMS master key](https://console.aws.amazon.com/iam/home#/encryptionKeys) and set it in your environment along with your AWS credentials ([dotenv](https://github.com/bkeepers/dotenv) is great for this)
21
-
22
- ```sh
23
- KMS_KEY_ID=arn:aws:kms:...
24
- AWS_ACCESS_KEY_ID=...
25
- AWS_SECRET_ACCESS_KEY=...
26
- ```
27
-
28
- You can also use the alias
29
-
30
- ```sh
31
- KMS_KEY_ID=alias/my-alias
32
- ```
33
-
34
- And update your model
35
-
36
- ```ruby
37
- class User < ApplicationRecord
38
- has_kms_key
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
- # some hash
56
- end
57
- end
58
- ```
59
-
60
- 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. Read more about [encryption context here](https://docs.aws.amazon.com/kms/latest/developerguide/encryption-context.html).
61
-
62
- The primary key is a good choice, but auto-generated ids aren’t available until a record is created, and we need to encrypt before this. One solution is to preload the primary key. Here’s what it looks like with Postgres:
63
-
64
- ```ruby
65
- class User < ApplicationRecord
66
- def kms_encryption_context
67
- self.id ||= self.class.connection.execute("select nextval('#{self.class.sequence_name}')").first["nextval"]
68
- {"Record" => "#{model_name}/#{id}"}
69
- end
70
- end
71
- ```
72
-
73
- [Amazon Athena](https://aws.amazon.com/athena/) is great for querying CloudTrail logs. Create a table (thanks to [this post](http://www.1strategy.com/blog/2017/07/25/auditing-aws-activity-with-cloudtrail-and-athena/) for the table structure) with:
74
-
75
- ```sql
76
- CREATE EXTERNAL TABLE cloudtrail_logs (
77
- eventversion STRING,
78
- userIdentity STRUCT<
79
- type:STRING,
80
- principalid:STRING,
81
- arn:STRING,
82
- accountid:STRING,
83
- invokedby:STRING,
84
- accesskeyid:STRING,
85
- userName:String,
86
- sessioncontext:STRUCT<
87
- attributes:STRUCT<
88
- mfaauthenticated:STRING,
89
- creationdate:STRING>,
90
- sessionIssuer:STRUCT<
91
- type:STRING,
92
- principalId:STRING,
93
- arn:STRING,
94
- accountId:STRING,
95
- userName:STRING>>>,
96
- eventTime STRING,
97
- eventSource STRING,
98
- eventName STRING,
99
- awsRegion STRING,
100
- sourceIpAddress STRING,
101
- userAgent STRING,
102
- errorCode STRING,
103
- errorMessage STRING,
104
- requestId STRING,
105
- eventId STRING,
106
- resources ARRAY<STRUCT<
107
- ARN:STRING,
108
- accountId:STRING,
109
- type:STRING>>,
110
- eventType STRING,
111
- apiVersion STRING,
112
- readOnly BOOLEAN,
113
- recipientAccountId STRING,
114
- sharedEventID STRING,
115
- vpcEndpointId STRING,
116
- requestParameters STRING,
117
- responseElements STRING,
118
- additionalEventData STRING,
119
- serviceEventDetails STRING
120
- )
121
- ROW FORMAT SERDE 'com.amazon.emr.hive.serde.CloudTrailSerde'
122
- STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
123
- OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
124
- LOCATION 's3://my-cloudtrail-logs/'
125
- ```
126
-
127
- Change the last line to point to your CloudTrail log bucket and query away
128
-
129
- ```sql
130
- SELECT
131
- eventTime,
132
- userIdentity.userName,
133
- requestParameters
134
- FROM
135
- cloudtrail_logs
136
- WHERE
137
- eventName = 'Decrypt'
138
- AND resources[1].arn = 'arn:aws:kms:...'
139
- ORDER BY 1
140
- ```
141
-
142
- There will also be `GenerateDataKey` events.
143
-
144
- ## Alerting
145
-
146
- We recommend setting up alerts on suspicious behavior.
147
-
148
- ## Key Rotation
149
-
150
- KMS supports [automatic key rotation](https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html). No action is required in this case.
151
-
152
- To manually rotate keys, replace the old KMS key id with the new key id in your model. Your app does not need the old key id to perform rotation (however, the key must still be enabled in your AWS account).
153
-
154
- ```sh
155
- KMS_KEY_ID=arn:aws:kms:...
156
- ```
157
-
158
- and run
159
-
160
- ```ruby
161
- User.find_each do |user|
162
- user.rotate_kms_key!
163
- end
164
- ```
165
-
166
- ## IAM Permissions
167
-
168
- A great feature of KMS is the ability to grant encryption and decryption permission separately.
169
-
170
- To encrypt the data, use a policy with:
171
-
172
- ```json
173
- {
174
- "Version": "2012-10-17",
175
- "Statement": [
176
- {
177
- "Sid": "EncryptData",
178
- "Effect": "Allow",
179
- "Action": "kms:GenerateDataKey",
180
- "Resource": "arn:aws:kms:..."
181
- }
182
- ]
183
- }
184
- ```
185
-
186
- If a system can only encrypt, you must clear out existing data and data keys before updates.
187
-
188
- ```ruby
189
- user.encrypted_email = nil
190
- user.encrypted_kms_key = nil
191
- # before user.save or user.update
192
- ```
193
-
194
- To decrypt the data, use a policy with:
195
-
196
- ```json
197
- {
198
- "Version": "2012-10-17",
199
- "Statement": [
200
- {
201
- "Sid": "DecryptData",
202
- "Effect": "Allow",
203
- "Action": "kms:Decrypt",
204
- "Resource": "arn:aws:kms:..."
205
- }
206
- ]
207
- }
208
- ```
209
-
210
- Be extremely selective of systems you allow to decrypt.
211
-
212
- ## Testing
213
-
214
- For testing, you can prevent network calls to KMS by setting:
215
-
216
- ```sh
217
- KMS_KEY_ID=insecure-test-key
218
- ```
219
-
220
- ## Multiple Keys Per Record
221
-
222
- You may want to protect different columns with different data keys (or even master keys).
223
-
224
- To do this, add more columns
225
-
226
- ```ruby
227
- add_column :users, :encrypted_phone, :text
228
- add_column :users, :encrypted_phone_iv, :text
229
- add_column :users, :encrypted_kms_key_phone, :text
230
- ```
231
-
232
- And update your model
233
-
234
- ```ruby
235
- class User < ApplicationRecord
236
- has_kms_key
237
- has_kms_key name: :phone, key_id: "..."
238
-
239
- attr_encrypted :email, key: :kms_key
240
- attr_encrypted :phone, key: :kms_key_phone
241
- end
242
- ```
243
-
244
- For context, use:
245
-
246
- ```ruby
247
- class User < ApplicationRecord
248
- def kms_encryption_context_phone
249
- # some hash
250
- end
251
- end
252
- ```
253
-
254
- To rotate keys, use:
255
-
256
- ```ruby
257
- user.rotate_kms_key_phone!
258
- ```
259
-
260
- ## File Uploads
261
-
262
- While outside the scope of this gem, you can also use KMS for sensitive file uploads. Check out [this guide](https://ankane.org/aws-client-side-encryption) to learn more.
@@ -1,131 +0,0 @@
1
- # Google KMS
2
-
3
- Add this line to your application’s Gemfile:
4
-
5
- ```ruby
6
- gem 'google-api-client'
7
- gem 'kms_encrypted'
8
- ```
9
-
10
- Add columns for the encrypted data and the encrypted KMS data keys
11
-
12
- ```ruby
13
- add_column :users, :encrypted_email, :text
14
- add_column :users, :encrypted_email_iv, :text
15
- add_column :users, :encrypted_kms_key, :text
16
- ```
17
-
18
- Create a [Google Cloud Platform](https://cloud.google.com/) account if you don’t have one. KMS works great whether or not you run your infrastructure on GCP.
19
-
20
- Create a [KMS key ring and key](https://console.cloud.google.com/iam-admin/kms) and set it in your environment along with your GCP credentials ([dotenv](https://github.com/bkeepers/dotenv) is great for this)
21
-
22
- ```sh
23
- KMS_KEY_ID=projects/.../locations/.../keyRings/.../cryptoKeys/...
24
- ```
25
-
26
- And update your model
27
-
28
- ```ruby
29
- class User < ApplicationRecord
30
- has_kms_key
31
-
32
- attr_encrypted :email, key: :kms_key
33
- end
34
- ```
35
-
36
- For each encrypted attribute, use the `kms_key` method for its key.
37
-
38
- ## Auditing
39
-
40
- Follow the [instructions here](https://cloud.google.com/kms/docs/logging) to set up data access logging. To know what data is being decrypted, you’ll need to add context.
41
-
42
- Add a `kms_encryption_context` method to your model.
43
-
44
- ```ruby
45
- class User < ApplicationRecord
46
- def kms_encryption_context
47
- # some hash
48
- end
49
- end
50
- ```
51
-
52
- 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.
53
-
54
- The primary key is a good choice, but auto-generated ids aren’t available until a record is created, and we need to encrypt before this. One solution is to preload the primary key. Here’s what it looks like with Postgres:
55
-
56
- ```ruby
57
- class User < ApplicationRecord
58
- def kms_encryption_context
59
- self.id ||= self.class.connection.execute("select nextval('#{self.class.sequence_name}')").first["nextval"]
60
- {"Record" => "#{model_name}/#{id}"}
61
- end
62
- end
63
- ```
64
-
65
- ## Alerting
66
-
67
- We recommend setting up alerts on suspicious behavior.
68
-
69
- ## Key Rotation
70
-
71
- To manually rotate keys, replace the old key id with the new key id in your model. Your app does not need the old key id to perform rotation (however, the key must still be enabled in your GCP account).
72
-
73
- ```sh
74
- KMS_KEY_ID=...
75
- ```
76
-
77
- and run
78
-
79
- ```ruby
80
- User.find_each do |user|
81
- user.rotate_kms_key!
82
- end
83
- ```
84
-
85
- ## Testing
86
-
87
- For testing, you can prevent network calls to KMS by setting:
88
-
89
- ```sh
90
- KMS_KEY_ID=insecure-test-key
91
- ```
92
-
93
- ## Multiple Keys Per Record
94
-
95
- You may want to protect different columns with different data keys (or even master keys).
96
-
97
- To do this, add more columns
98
-
99
- ```ruby
100
- add_column :users, :encrypted_phone, :text
101
- add_column :users, :encrypted_phone_iv, :text
102
- add_column :users, :encrypted_kms_key_phone, :text
103
- ```
104
-
105
- And update your model
106
-
107
- ```ruby
108
- class User < ApplicationRecord
109
- has_kms_key
110
- has_kms_key name: :phone, key_id: "..."
111
-
112
- attr_encrypted :email, key: :kms_key
113
- attr_encrypted :phone, key: :kms_key_phone
114
- end
115
- ```
116
-
117
- For context, use:
118
-
119
- ```ruby
120
- class User < ApplicationRecord
121
- def kms_encryption_context_phone
122
- # some hash
123
- end
124
- end
125
- ```
126
-
127
- To rotate keys, use:
128
-
129
- ```ruby
130
- user.rotate_kms_key_phone!
131
- ```
@@ -1,143 +0,0 @@
1
- # Vault
2
-
3
- Add this line to your application’s Gemfile:
4
-
5
- ```ruby
6
- gem 'vault'
7
- gem 'kms_encrypted'
8
- ```
9
-
10
- Add columns for the encrypted data and the encrypted KMS data keys
11
-
12
- ```ruby
13
- add_column :users, :encrypted_email, :text
14
- add_column :users, :encrypted_email_iv, :text
15
- add_column :users, :encrypted_kms_key, :text
16
- ```
17
-
18
- Enable the [transit](https://www.vaultproject.io/docs/secrets/transit/index.html) backend
19
-
20
- ```sh
21
- vault secrets enable transit
22
- ```
23
-
24
- And create a key
25
-
26
- ```sh
27
- vault write -f transit/keys/my-key
28
- ```
29
-
30
- Set it in your environment along with your Vault credentials ([dotenv](https://github.com/bkeepers/dotenv) is great for this)
31
-
32
- ```sh
33
- KMS_KEY_ID=vault/my-key
34
- VAULT_ADDR=http://127.0.0.1:8200
35
- VAULT_TOKEN=secret
36
- ```
37
-
38
- And update your model
39
-
40
- ```ruby
41
- class User < ApplicationRecord
42
- has_kms_key
43
-
44
- attr_encrypted :email, key: :kms_key
45
- end
46
- ```
47
-
48
- For each encrypted attribute, use the `kms_key` method for its key.
49
-
50
- ## Auditing
51
-
52
- Follow the [instructions here](https://www.vaultproject.io/docs/audit/) to set up data access logging. To know what data is being decrypted, you’ll need to add context.
53
-
54
- Add a `kms_encryption_context` method to your model.
55
-
56
- ```ruby
57
- class User < ApplicationRecord
58
- def kms_encryption_context
59
- # some hash
60
- end
61
- end
62
- ```
63
-
64
- 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. Read more about [encryption context here](https://docs.aws.amazon.com/kms/latest/developerguide/encryption-context.html).
65
-
66
- The primary key is a good choice, but auto-generated ids aren’t available until a record is created, and we need to encrypt before this. One solution is to preload the primary key. Here’s what it looks like with Postgres:
67
-
68
- ```ruby
69
- class User < ApplicationRecord
70
- def kms_encryption_context
71
- self.id ||= self.class.connection.execute("select nextval('#{self.class.sequence_name}')").first["nextval"]
72
- {"Record" => "#{model_name}/#{id}"}
73
- end
74
- end
75
- ```
76
-
77
- ## Alerting
78
-
79
- We recommend setting up alerts on suspicious behavior.
80
-
81
- ## Key Rotation
82
-
83
- To manually rotate keys, replace the old key id with the new key id in your model.
84
-
85
- ```sh
86
- KMS_KEY_ID=...
87
- ```
88
-
89
- and run
90
-
91
- ```ruby
92
- User.find_each do |user|
93
- user.rotate_kms_key!
94
- end
95
- ```
96
-
97
- ## Testing
98
-
99
- For testing, you can prevent network calls to KMS by setting:
100
-
101
- ```sh
102
- KMS_KEY_ID=insecure-test-key
103
- ```
104
-
105
- ## Multiple Keys Per Record
106
-
107
- You may want to protect different columns with different data keys (or even master keys).
108
-
109
- To do this, add more columns
110
-
111
- ```ruby
112
- add_column :users, :encrypted_phone, :text
113
- add_column :users, :encrypted_phone_iv, :text
114
- add_column :users, :encrypted_kms_key_phone, :text
115
- ```
116
-
117
- And update your model
118
-
119
- ```ruby
120
- class User < ApplicationRecord
121
- has_kms_key
122
- has_kms_key name: :phone, key_id: "..."
123
-
124
- attr_encrypted :email, key: :kms_key
125
- attr_encrypted :phone, key: :kms_key_phone
126
- end
127
- ```
128
-
129
- For context, use:
130
-
131
- ```ruby
132
- class User < ApplicationRecord
133
- def kms_encryption_context_phone
134
- # some hash
135
- end
136
- end
137
- ```
138
-
139
- To rotate keys, use:
140
-
141
- ```ruby
142
- user.rotate_kms_key_phone!
143
- ```