porky_lib 0.9.2 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +1 -3
- data/.rubocop.yml +58 -3
- data/Gemfile +1 -1
- data/Gemfile.lock +50 -43
- data/README.md +117 -9
- data/Rakefile +1 -0
- data/lib/porky_lib/aws/kms/client.rb +1 -1
- data/lib/porky_lib/file_service.rb +35 -9
- data/lib/porky_lib/file_service_helper.rb +39 -13
- data/lib/porky_lib/unencrypted/file_service.rb +28 -5
- data/lib/porky_lib/version.rb +1 -1
- data/lib/tasks/file.rake +85 -0
- data/porky_lib.gemspec +1 -0
- metadata +18 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 70a7962acaef46a1b1e4cd9e1decaccbe5bb35867de03bbc8c4d24329f0ef4be
|
|
4
|
+
data.tar.gz: 81cbd165551dcafd6fb595e24a74af691143858bb3d8c9f70c4d8d1cb3d0a580
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f5fbc041473d83b4f4ad03321d3f30ba40990c139f215dc98a388c99999cb747415287a2c822bedb6f3dc2f71d37f1ceb72017ada14b65aba88584555ff448fb
|
|
7
|
+
data.tar.gz: 292725e636df669d3022edb4cd7f566b1b472b60dca17c1e8db1351c107ad06799e4b4b805425a5b58282b9c50bab57519033cf37e39286a3d71098474a5d0f3
|
data/.circleci/config.yml
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -9,7 +9,8 @@ AllCops:
|
|
|
9
9
|
- node_modules/**/*
|
|
10
10
|
- output/**/*
|
|
11
11
|
- vendor/**/*
|
|
12
|
-
|
|
12
|
+
- spec/porky_lib/data/*
|
|
13
|
+
TargetRubyVersion: 2.7.1
|
|
13
14
|
RSpec:
|
|
14
15
|
Patterns:
|
|
15
16
|
- _spec.rb
|
|
@@ -17,10 +18,22 @@ AllCops:
|
|
|
17
18
|
SpecTypes:
|
|
18
19
|
Feature: 'spec/features/**/*'
|
|
19
20
|
|
|
20
|
-
Documentation:
|
|
21
|
+
Style/Documentation:
|
|
21
22
|
Enabled: false
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
Security/MarshalLoad:
|
|
25
|
+
Enabled: true
|
|
26
|
+
|
|
27
|
+
Security/Eval:
|
|
28
|
+
Enabled: true
|
|
29
|
+
|
|
30
|
+
Security/YAMLLoad:
|
|
31
|
+
Enabled: true
|
|
32
|
+
|
|
33
|
+
Security/JSONLoad:
|
|
34
|
+
Enabled: true
|
|
35
|
+
|
|
36
|
+
Layout/LineLength:
|
|
24
37
|
Max: 160
|
|
25
38
|
|
|
26
39
|
Metrics/ClassLength:
|
|
@@ -46,3 +59,45 @@ RSpec/MultipleExpectations:
|
|
|
46
59
|
|
|
47
60
|
RSpec/ExampleLength:
|
|
48
61
|
Max: 10
|
|
62
|
+
|
|
63
|
+
Style/HashEachMethods:
|
|
64
|
+
Enabled: true
|
|
65
|
+
|
|
66
|
+
Style/HashTransformKeys:
|
|
67
|
+
Enabled: true
|
|
68
|
+
|
|
69
|
+
Style/HashTransformValues:
|
|
70
|
+
Enabled: true
|
|
71
|
+
|
|
72
|
+
Lint/RaiseException:
|
|
73
|
+
Enabled: true
|
|
74
|
+
|
|
75
|
+
Lint/StructNewOverride:
|
|
76
|
+
Enabled: true
|
|
77
|
+
|
|
78
|
+
Layout/SpaceAroundMethodCallOperator:
|
|
79
|
+
Enabled: true
|
|
80
|
+
|
|
81
|
+
Style/ExponentialNotation:
|
|
82
|
+
Enabled: true
|
|
83
|
+
|
|
84
|
+
Layout/EmptyLinesAroundAttributeAccessor:
|
|
85
|
+
Enabled: true
|
|
86
|
+
|
|
87
|
+
Lint/DeprecatedOpenSSLConstant:
|
|
88
|
+
Enabled: true
|
|
89
|
+
|
|
90
|
+
Style/SlicingWithRange:
|
|
91
|
+
Enabled: true
|
|
92
|
+
|
|
93
|
+
Lint/MixedRegexpCaptureTypes:
|
|
94
|
+
Enabled: true
|
|
95
|
+
|
|
96
|
+
Style/RedundantRegexpCharacterClass:
|
|
97
|
+
Enabled: true
|
|
98
|
+
|
|
99
|
+
Style/RedundantRegexpEscape:
|
|
100
|
+
Enabled: true
|
|
101
|
+
|
|
102
|
+
Style/RedundantFetchBlock:
|
|
103
|
+
Enabled: true
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
porky_lib (0.
|
|
4
|
+
porky_lib (0.11.0)
|
|
5
5
|
aws-sdk-kms
|
|
6
6
|
aws-sdk-s3
|
|
7
7
|
msgpack
|
|
@@ -11,85 +11,91 @@ PATH
|
|
|
11
11
|
GEM
|
|
12
12
|
remote: https://rubygems.org/
|
|
13
13
|
specs:
|
|
14
|
-
ast (2.4.
|
|
15
|
-
aws-eventstream (1.0
|
|
16
|
-
aws-partitions (1.
|
|
17
|
-
aws-sdk-core (3.
|
|
18
|
-
aws-eventstream (~> 1
|
|
19
|
-
aws-partitions (~> 1, >= 1.
|
|
14
|
+
ast (2.4.1)
|
|
15
|
+
aws-eventstream (1.1.0)
|
|
16
|
+
aws-partitions (1.338.0)
|
|
17
|
+
aws-sdk-core (3.103.0)
|
|
18
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
|
19
|
+
aws-partitions (~> 1, >= 1.239.0)
|
|
20
20
|
aws-sigv4 (~> 1.1)
|
|
21
21
|
jmespath (~> 1.0)
|
|
22
|
-
aws-sdk-kms (1.
|
|
23
|
-
aws-sdk-core (~> 3, >= 3.
|
|
22
|
+
aws-sdk-kms (1.36.0)
|
|
23
|
+
aws-sdk-core (~> 3, >= 3.99.0)
|
|
24
24
|
aws-sigv4 (~> 1.1)
|
|
25
|
-
aws-sdk-s3 (1.
|
|
26
|
-
aws-sdk-core (~> 3, >= 3.
|
|
25
|
+
aws-sdk-s3 (1.73.0)
|
|
26
|
+
aws-sdk-core (~> 3, >= 3.102.1)
|
|
27
27
|
aws-sdk-kms (~> 1)
|
|
28
28
|
aws-sigv4 (~> 1.1)
|
|
29
|
-
aws-sigv4 (1.1
|
|
30
|
-
aws-eventstream (~> 1
|
|
31
|
-
bundler-audit (0.
|
|
29
|
+
aws-sigv4 (1.2.1)
|
|
30
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
|
31
|
+
bundler-audit (0.7.0.1)
|
|
32
32
|
bundler (>= 1.2.0, < 3)
|
|
33
|
-
thor (
|
|
34
|
-
byebug (11.
|
|
35
|
-
|
|
33
|
+
thor (>= 0.18, < 2)
|
|
34
|
+
byebug (11.1.3)
|
|
35
|
+
codacy-coverage (2.2.1)
|
|
36
|
+
simplecov
|
|
37
|
+
codecov (0.1.17)
|
|
36
38
|
json
|
|
37
39
|
simplecov
|
|
38
40
|
url
|
|
39
41
|
diff-lcs (1.3)
|
|
40
42
|
docile (1.3.2)
|
|
41
|
-
ffi (1.
|
|
42
|
-
jaro_winkler (1.5.3)
|
|
43
|
+
ffi (1.12.2)
|
|
43
44
|
jmespath (1.4.0)
|
|
44
|
-
json (2.
|
|
45
|
-
msgpack (1.3.
|
|
46
|
-
parallel (1.
|
|
47
|
-
parser (2.
|
|
48
|
-
ast (~> 2.4.
|
|
45
|
+
json (2.3.0)
|
|
46
|
+
msgpack (1.3.3)
|
|
47
|
+
parallel (1.19.2)
|
|
48
|
+
parser (2.7.1.4)
|
|
49
|
+
ast (~> 2.4.1)
|
|
49
50
|
rainbow (3.0.0)
|
|
50
|
-
rake (13.0.
|
|
51
|
+
rake (13.0.1)
|
|
51
52
|
rbnacl (5.0.0)
|
|
52
53
|
ffi
|
|
53
54
|
rbnacl-libsodium (1.0.16)
|
|
54
55
|
rbnacl (>= 3.0.1)
|
|
56
|
+
regexp_parser (1.7.1)
|
|
57
|
+
rexml (3.2.4)
|
|
55
58
|
rspec (3.9.0)
|
|
56
59
|
rspec-core (~> 3.9.0)
|
|
57
60
|
rspec-expectations (~> 3.9.0)
|
|
58
61
|
rspec-mocks (~> 3.9.0)
|
|
59
62
|
rspec-collection_matchers (1.2.0)
|
|
60
63
|
rspec-expectations (>= 2.99.0.beta1)
|
|
61
|
-
rspec-core (3.9.
|
|
62
|
-
rspec-support (~> 3.9.
|
|
64
|
+
rspec-core (3.9.2)
|
|
65
|
+
rspec-support (~> 3.9.3)
|
|
63
66
|
rspec-expectations (3.9.0)
|
|
64
67
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
65
68
|
rspec-support (~> 3.9.0)
|
|
66
|
-
rspec-mocks (3.9.
|
|
69
|
+
rspec-mocks (3.9.1)
|
|
67
70
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
68
71
|
rspec-support (~> 3.9.0)
|
|
69
|
-
rspec-support (3.9.
|
|
72
|
+
rspec-support (3.9.3)
|
|
70
73
|
rspec_junit_formatter (0.4.1)
|
|
71
74
|
rspec-core (>= 2, < 4, != 2.12.0)
|
|
72
|
-
rubocop (0.
|
|
73
|
-
jaro_winkler (~> 1.5.1)
|
|
75
|
+
rubocop (0.86.0)
|
|
74
76
|
parallel (~> 1.10)
|
|
75
|
-
parser (>= 2.
|
|
77
|
+
parser (>= 2.7.0.1)
|
|
76
78
|
rainbow (>= 2.2.2, < 4.0)
|
|
79
|
+
regexp_parser (>= 1.7)
|
|
80
|
+
rexml
|
|
81
|
+
rubocop-ast (>= 0.0.3, < 1.0)
|
|
77
82
|
ruby-progressbar (~> 1.7)
|
|
78
|
-
unicode-display_width (>= 1.4.0, <
|
|
79
|
-
rubocop-
|
|
83
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
|
84
|
+
rubocop-ast (0.0.3)
|
|
85
|
+
parser (>= 2.7.0.1)
|
|
86
|
+
rubocop-performance (1.6.1)
|
|
80
87
|
rubocop (>= 0.71.0)
|
|
81
|
-
rubocop-rspec (1.
|
|
88
|
+
rubocop-rspec (1.40.0)
|
|
82
89
|
rubocop (>= 0.68.1)
|
|
83
90
|
rubocop_runner (2.2.0)
|
|
84
91
|
ruby-progressbar (1.10.1)
|
|
85
|
-
simplecov (0.
|
|
92
|
+
simplecov (0.18.5)
|
|
86
93
|
docile (~> 1.1)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
thor (0.20.3)
|
|
94
|
+
simplecov-html (~> 0.11)
|
|
95
|
+
simplecov-html (0.12.2)
|
|
96
|
+
thor (1.0.1)
|
|
91
97
|
timecop (0.9.1)
|
|
92
|
-
unicode-display_width (1.
|
|
98
|
+
unicode-display_width (1.7.0)
|
|
93
99
|
url (0.3.2)
|
|
94
100
|
|
|
95
101
|
PLATFORMS
|
|
@@ -101,6 +107,7 @@ DEPENDENCIES
|
|
|
101
107
|
bundler
|
|
102
108
|
bundler-audit
|
|
103
109
|
byebug
|
|
110
|
+
codacy-coverage
|
|
104
111
|
codecov
|
|
105
112
|
msgpack
|
|
106
113
|
porky_lib!
|
|
@@ -119,7 +126,7 @@ DEPENDENCIES
|
|
|
119
126
|
timecop
|
|
120
127
|
|
|
121
128
|
RUBY VERSION
|
|
122
|
-
ruby 2.
|
|
129
|
+
ruby 2.7.1p83
|
|
123
130
|
|
|
124
131
|
BUNDLED WITH
|
|
125
|
-
2.
|
|
132
|
+
2.1.4
|
data/README.md
CHANGED
|
@@ -20,7 +20,7 @@ And then execute:
|
|
|
20
20
|
Or install it yourself as:
|
|
21
21
|
|
|
22
22
|
$ gem install porky_lib
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
Inside of your Ruby program do:
|
|
25
25
|
|
|
26
26
|
```ruby
|
|
@@ -86,7 +86,7 @@ To encrypt data with a known plaintext key:
|
|
|
86
86
|
# plaintext_key is the encryption key to use
|
|
87
87
|
# encryption_info is the structure returned that contains:
|
|
88
88
|
# ciphertext: plaintext encrypted under plaintext_key
|
|
89
|
-
# nonce: The generated nonce
|
|
89
|
+
# nonce: The generated nonce
|
|
90
90
|
encryption_info = PorkyLib::Symmetric.instance.encrypt_with_key(plaintext, plaintext_key)
|
|
91
91
|
```
|
|
92
92
|
|
|
@@ -104,7 +104,7 @@ To decrypt data with a known plaintext key:
|
|
|
104
104
|
```ruby
|
|
105
105
|
# Where ciphertext is the encrypted data to be decrypted
|
|
106
106
|
# plaintext_key is the decryption key to use
|
|
107
|
-
# nonce is the nonce to use
|
|
107
|
+
# nonce is the nonce to use
|
|
108
108
|
# decryption_info is the structured returned that contains:
|
|
109
109
|
# plaintext: ciphertext decrypted under plaintext_key
|
|
110
110
|
decryption_info = PorkyLib::Symmetric.instance.decrypt_with_key(ciphertext, plaintext_key, nonce)
|
|
@@ -137,7 +137,7 @@ plaintext_key.replace(PorkyLib::Symmetric.instance.secure_delete_plaintext_key(p
|
|
|
137
137
|
To verify whether an alias exists or not:
|
|
138
138
|
```ruby
|
|
139
139
|
# Where key_alias is the alias name to verify
|
|
140
|
-
alias_exists = PorkyLib::Symmetric.instance.cmk_alias_exists?(key_alias)
|
|
140
|
+
alias_exists = PorkyLib::Symmetric.instance.cmk_alias_exists?(key_alias)
|
|
141
141
|
```
|
|
142
142
|
|
|
143
143
|
### To Read From AWS S3
|
|
@@ -156,21 +156,57 @@ file_data = PorkyLib::Unencrypted::FileService.read(bucket_name, file_key)
|
|
|
156
156
|
|
|
157
157
|
### To Write To AWS S3
|
|
158
158
|
```ruby
|
|
159
|
-
#
|
|
159
|
+
# --- DEPRECATED --- Please use write_data or write_file instead of write
|
|
160
|
+
# Where file is the data to encrypt and upload to S3 (can be a path or raw data or ruby file object)
|
|
160
161
|
# bucket_name is the name of the S3 bucket to write to
|
|
161
162
|
# key_id is the ID of the CMK to use to generate a data encryption key to encrypt the file data
|
|
162
|
-
# options is an optional parameter for specifying optional metadata about the file
|
|
163
|
+
# options is an optional parameter for specifying optional metadata about the file and the storage_class of the object
|
|
163
164
|
file_key = PorkyLib::FileService.write(file, bucket_name, key_id, options)
|
|
164
165
|
```
|
|
165
166
|
|
|
166
|
-
### To Write
|
|
167
|
+
### To Write Files To AWS S3
|
|
167
168
|
```ruby
|
|
168
|
-
# Where file is the data to upload to S3 (can be
|
|
169
|
+
# Where file is the data to encrypt and upload to S3 (can be a path or ruby file object)
|
|
169
170
|
# bucket_name is the name of the S3 bucket to write to
|
|
170
|
-
#
|
|
171
|
+
# key_id is the ID of the CMK to use to generate a data encryption key to encrypt the file data
|
|
172
|
+
# options is an optional parameter for specifying optional metadata about the file and the storage_class of the object
|
|
173
|
+
file_key = PorkyLib::FileService.write_file(file, bucket_name, key_id, options)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### To Write Data To AWS S3
|
|
177
|
+
```ruby
|
|
178
|
+
# Where data is the raw data to encrypt and upload to S3
|
|
179
|
+
# bucket_name is the name of the S3 bucket to write to
|
|
180
|
+
# key_id is the ID of the CMK to use to generate a data encryption key to encrypt the file data
|
|
181
|
+
# options is an optional parameter for specifying optional metadata about the file and the storage_class of the object
|
|
182
|
+
file_key = PorkyLib::FileService.write_data(data, bucket_name, key_id, options)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### To Write Unencrypted To AWS S3
|
|
186
|
+
```ruby
|
|
187
|
+
# --- DEPRECATED --- Please use write_data or write_file instead of write
|
|
188
|
+
# Where file is the data to upload to S3 (can be a path or raw data or ruby file object)
|
|
189
|
+
# bucket_name is the name of the S3 bucket to write to
|
|
190
|
+
# options is an optional parameter for specifying optional metadata about the file and the storage_class of the object
|
|
171
191
|
file_key = PorkyLib::Unencrypted::FileService.write(file, bucket_name, options)
|
|
172
192
|
```
|
|
173
193
|
|
|
194
|
+
### To Write Unencrypted Files To AWS S3
|
|
195
|
+
```ruby
|
|
196
|
+
# Where file is the data to encrypt and upload to S3 (can be a path or ruby file object)
|
|
197
|
+
# bucket_name is the name of the S3 bucket to write to
|
|
198
|
+
# options is an optional parameter for specifying optional metadata about the file and the storage_class of the object
|
|
199
|
+
file_key = PorkyLib::Unencrypted::FileService.write_file(file, bucket_name, options)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### To Write Unencrypted Data To AWS S3
|
|
203
|
+
```ruby
|
|
204
|
+
# Where data is the raw data to encrypt and upload to S3
|
|
205
|
+
# bucket_name is the name of the S3 bucket to write to
|
|
206
|
+
# options is an optional parameter for specifying optional metadata about the file and the storage_class of the object
|
|
207
|
+
file_key = PorkyLib::Unencrypted::FileService.write_data(data, bucket_name, options)
|
|
208
|
+
```
|
|
209
|
+
|
|
174
210
|
### Generate S3 Presigned POST URL
|
|
175
211
|
To generate a new presigned POST url (used to upload files directly to AWS S3):
|
|
176
212
|
```ruby
|
|
@@ -188,12 +224,84 @@ To generate a new presigned GET url (used to download files directly from AWS S3
|
|
|
188
224
|
url = PorkyLib::Symmetric.instance.presigned_get_url(bucket_name, file_key)
|
|
189
225
|
```
|
|
190
226
|
|
|
227
|
+
## Rake task
|
|
228
|
+
If you want to write or read an encrypted file from the command line, there is a Rake write and read task.
|
|
229
|
+
|
|
230
|
+
> Note: the environment variables can be set globally or by prepending them to the rake task command
|
|
231
|
+
|
|
232
|
+
### Write file
|
|
233
|
+
|
|
234
|
+
Rake task name: `file:write`
|
|
235
|
+
|
|
236
|
+
Environment variables:
|
|
237
|
+
* Required
|
|
238
|
+
* `FILE_PATH` - Absolute or relative file path
|
|
239
|
+
* `CMK_KEY_ID` - Alias of the CMK key
|
|
240
|
+
* `AWS_S3_BUCKET` - AWS S3 bucket name
|
|
241
|
+
* `AWS_REGION` - AWS region name
|
|
242
|
+
* `AWS_ACCESS_KEY_ID` - AWS access key ID (credentials)
|
|
243
|
+
* `AWS_ACCESS_KEY` - AWS secret access key (credentials)
|
|
244
|
+
* Optional
|
|
245
|
+
* `AWS_S3_MOCK_CLIENT` - PorkyLib's AWS KMS mock client (defaults to `true`)
|
|
246
|
+
* `AWS_S3_MAX_FILE_SIZE` - Max file size (defaults to `1MB`)
|
|
247
|
+
* `AWS_S3_STORAGE_CLASS` - One of STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE (defaults to `STANDARD`)
|
|
248
|
+
* `AWS_S3_KEEP_FILE_NAME` - Saves the file in AWS S3 with the original file name (defaults to `true`)
|
|
249
|
+
|
|
250
|
+
### Read file
|
|
251
|
+
|
|
252
|
+
Rake task name: `file:read`
|
|
253
|
+
|
|
254
|
+
Environment variables:
|
|
255
|
+
* Required
|
|
256
|
+
* `FILE_KEY` - AWS S3 object file key
|
|
257
|
+
* `AWS_S3_BUCKET` - AWS S3 bucket name
|
|
258
|
+
* `AWS_REGION` - AWS region name
|
|
259
|
+
* `AWS_ACCESS_KEY_ID` - AWS access key ID (credentials)
|
|
260
|
+
* `AWS_ACCESS_KEY` - AWS secret access key (credentials)
|
|
261
|
+
* Optional
|
|
262
|
+
* `AWS_S3_MOCK_CLIENT` - PorkyLib's AWS KMS mock client (defaults to `true`)
|
|
263
|
+
* `AWS_S3_MAX_FILE_SIZE` - Max file size (defaults to `1MB`)
|
|
264
|
+
* `DESTINATION` - Location to save the file (defaults to `FILE_KEY`)
|
|
265
|
+
|
|
191
266
|
## Development
|
|
192
267
|
|
|
193
268
|
Development on this project should occur on separate feature branches and pull requests should be submitted. When submitting a
|
|
194
269
|
pull request, the pull request comment template should be filled out as much as possible to ensure a quick review and increase
|
|
195
270
|
the likelihood of the pull request being accepted.
|
|
196
271
|
|
|
272
|
+
### Ruby
|
|
273
|
+
|
|
274
|
+
This application requires:
|
|
275
|
+
|
|
276
|
+
* Ruby version: 2.7.1
|
|
277
|
+
|
|
278
|
+
Ruby 2.7.1 and greater requires OpenSSL 1.1+. To link to Homebrew's upgraded version of OpenSSL, add the following to your bash profile
|
|
279
|
+
|
|
280
|
+
```shell script
|
|
281
|
+
export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)"
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
If you do not have Ruby installed, it is recommended you use ruby-install and chruby to manage Ruby versions.
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
brew install ruby-install chruby
|
|
288
|
+
ruby-install ruby 2.7.1
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Add the following lines to ~/.bash_profile:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
source /usr/local/opt/chruby/share/chruby/chruby.sh
|
|
295
|
+
source /usr/local/opt/chruby/share/chruby/auto.sh
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Set Ruby version to 2.7.1:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
source ~/.bash_profile
|
|
302
|
+
chruby 2.7.1
|
|
303
|
+
```
|
|
304
|
+
|
|
197
305
|
### Running Tests
|
|
198
306
|
|
|
199
307
|
```ruby
|
data/Rakefile
CHANGED
|
@@ -72,7 +72,7 @@ class Aws::KMS::Client
|
|
|
72
72
|
|
|
73
73
|
def decrypt(ciphertext_blob:, encryption_context: nil)
|
|
74
74
|
key_id, decoded_context, plaintext = MessagePack.unpack(ciphertext_blob.reverse)
|
|
75
|
-
decoded_context =
|
|
75
|
+
decoded_context = decoded_context.transform_keys(&:to_sym) if decoded_context
|
|
76
76
|
raise Aws::KMS::Errors::InvalidCiphertextException.new(nil, nil) unless decoded_context == encryption_context
|
|
77
77
|
|
|
78
78
|
Aws::KMS::Types::DecryptResponse.new(
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require 'singleton'
|
|
4
4
|
|
|
5
5
|
class PorkyLib::FileService
|
|
6
|
+
extend Gem::Deprecate
|
|
7
|
+
|
|
6
8
|
include Singleton
|
|
7
9
|
include PorkyLib::FileServiceHelper
|
|
8
10
|
|
|
@@ -56,10 +58,30 @@ class PorkyLib::FileService
|
|
|
56
58
|
|
|
57
59
|
def write(file, bucket_name, key_id, options = {})
|
|
58
60
|
raise FileServiceError, 'Invalid input. One or more input values is nil' if input_invalid?(file, bucket_name, key_id)
|
|
59
|
-
raise FileSizeTooLargeError, "File size is larger than maximum allowed size of #{max_file_size}" if file_size_invalid?(file)
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
if file?(file)
|
|
63
|
+
write_file(file, bucket_name, key_id, options)
|
|
64
|
+
else
|
|
65
|
+
write_data(file, bucket_name, key_id, options)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
deprecate :write, 'write_file or write_data', 2020, 1
|
|
69
|
+
|
|
70
|
+
def write_file(file, bucket_name, key_id, options = {})
|
|
71
|
+
raise FileServiceError, 'Invalid input. One or more input values is nil' if input_invalid?(file, bucket_name, key_id)
|
|
72
|
+
|
|
73
|
+
write_data(read_file(file), bucket_name, key_id, options)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def write_data(data, bucket_name, key_id, options = {})
|
|
77
|
+
raise FileServiceError, 'Invalid input. One or more input values is nil' if input_invalid?(data, bucket_name, key_id)
|
|
78
|
+
raise FileSizeTooLargeError, "Data size is larger than maximum allowed size of #{max_file_size}" if data_size_invalid?(data)
|
|
79
|
+
|
|
80
|
+
file_key = if options.key?(:file_name)
|
|
81
|
+
options[:file_name]
|
|
82
|
+
else
|
|
83
|
+
generate_file_key(options)
|
|
84
|
+
end
|
|
63
85
|
tempfile = encrypt_file_contents(data, key_id, file_key, options)
|
|
64
86
|
|
|
65
87
|
begin
|
|
@@ -73,12 +95,12 @@ class PorkyLib::FileService
|
|
|
73
95
|
file_key
|
|
74
96
|
end
|
|
75
97
|
|
|
76
|
-
def overwrite_file(
|
|
77
|
-
raise FileServiceError, 'Invalid input. One or more input values is nil' if
|
|
98
|
+
def overwrite_file(data, file_key, bucket_name, key_id, options = {})
|
|
99
|
+
raise FileServiceError, 'Invalid input. One or more input values is nil' if overwrite_input_invalid?(data, file_key, bucket_name, key_id)
|
|
78
100
|
raise FileServiceError, 'Invalid input. file_key cannot be nil if overwriting an existing file' if file_key.nil?
|
|
79
|
-
raise FileSizeTooLargeError, "File size is larger than maximum allowed size of #{max_file_size}" if file_size_invalid?(file)
|
|
80
101
|
|
|
81
|
-
|
|
102
|
+
raise FileSizeTooLargeError, "File size is larger than maximum allowed size of #{max_file_size}" if data_size_invalid?(data)
|
|
103
|
+
|
|
82
104
|
tempfile = encrypt_file_contents(data, key_id, file_key, options)
|
|
83
105
|
|
|
84
106
|
begin
|
|
@@ -158,7 +180,11 @@ class PorkyLib::FileService
|
|
|
158
180
|
@s3_client ||= Aws::S3::Client.new
|
|
159
181
|
end
|
|
160
182
|
|
|
161
|
-
def input_invalid?(
|
|
162
|
-
|
|
183
|
+
def input_invalid?(file_or_data, bucket_name, key_id)
|
|
184
|
+
file_or_data.nil? || bucket_name.nil? || key_id.nil?
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def overwrite_input_invalid?(file_or_data, file_key, bucket_name, key_id)
|
|
188
|
+
file_or_data.nil? || file_key.nil? || bucket_name.nil? || key_id.nil?
|
|
163
189
|
end
|
|
164
190
|
end
|
|
@@ -3,17 +3,18 @@
|
|
|
3
3
|
require 'aws-sdk-s3'
|
|
4
4
|
|
|
5
5
|
module PorkyLib::FileServiceHelper
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
extend Gem::Deprecate
|
|
7
|
+
|
|
8
|
+
class FileServiceError < StandardError; end
|
|
9
|
+
|
|
10
|
+
def data_size_invalid?(data)
|
|
11
|
+
data.bytesize > max_size
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def
|
|
15
|
-
a_file?(file_or_content) ?
|
|
14
|
+
def file?(file_or_content)
|
|
15
|
+
a_file?(file_or_content) || a_path?(file_or_content)
|
|
16
16
|
end
|
|
17
|
+
deprecate :file?, :none, 2020, 1
|
|
17
18
|
|
|
18
19
|
def write_tempfile(file_contents, file_key)
|
|
19
20
|
tempfile = Tempfile.new(file_key)
|
|
@@ -23,13 +24,25 @@ module PorkyLib::FileServiceHelper
|
|
|
23
24
|
tempfile
|
|
24
25
|
end
|
|
25
26
|
|
|
27
|
+
def read_file(file)
|
|
28
|
+
raise FileServiceError, 'file cannot be nil' if file.nil?
|
|
29
|
+
return file if !a_file?(file) && contain_null_byte?(file)
|
|
30
|
+
raise FileServiceError, 'The specified file does not exist' unless File.file?(file)
|
|
31
|
+
|
|
32
|
+
File.read(file)
|
|
33
|
+
rescue Errno::EACCES
|
|
34
|
+
raise FileServiceError, 'The specified file cannot be read, no permissions'
|
|
35
|
+
end
|
|
36
|
+
|
|
26
37
|
def perform_upload(bucket_name, file_key, tempfile, options)
|
|
27
38
|
obj = s3.bucket(bucket_name).object(file_key)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
|
|
40
|
+
upload_options = {
|
|
41
|
+
metadata: (options[:metadata] if options.key?(:metadata)),
|
|
42
|
+
storage_class: (options[:storage_class] if options.key?(:storage_class))
|
|
43
|
+
}.compact
|
|
44
|
+
|
|
45
|
+
obj.upload_file(tempfile.path, upload_options)
|
|
33
46
|
end
|
|
34
47
|
|
|
35
48
|
def s3
|
|
@@ -58,4 +71,17 @@ module PorkyLib::FileServiceHelper
|
|
|
58
71
|
def a_file?(file_or_content)
|
|
59
72
|
!file_or_content.is_a?(String)
|
|
60
73
|
end
|
|
74
|
+
|
|
75
|
+
def a_path?(content_or_path)
|
|
76
|
+
return false if contain_null_byte?(content_or_path)
|
|
77
|
+
|
|
78
|
+
File.file?(content_or_path)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def contain_null_byte?(data)
|
|
82
|
+
null_byte = (+"\u0000").force_encoding("ASCII-8BIT")
|
|
83
|
+
data = (+data).force_encoding("ASCII-8BIT")
|
|
84
|
+
|
|
85
|
+
data.include?(null_byte)
|
|
86
|
+
end
|
|
61
87
|
end
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require 'singleton'
|
|
4
4
|
|
|
5
5
|
class PorkyLib::Unencrypted::FileService
|
|
6
|
+
extend Gem::Deprecate
|
|
7
|
+
|
|
6
8
|
include Singleton
|
|
7
9
|
include PorkyLib::FileServiceHelper
|
|
8
10
|
|
|
@@ -26,10 +28,31 @@ class PorkyLib::Unencrypted::FileService
|
|
|
26
28
|
|
|
27
29
|
def write(file, bucket_name, options = {})
|
|
28
30
|
raise FileServiceError, 'Invalid input. One or more input values is nil' if input_invalid?(file, bucket_name)
|
|
29
|
-
raise FileSizeTooLargeError, "File size is larger than maximum allowed size of #{max_file_size}" if file_size_invalid?(file)
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
if file?(file)
|
|
33
|
+
write_file(file, bucket_name, options)
|
|
34
|
+
else
|
|
35
|
+
write_data(file, bucket_name, options)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
deprecate :write, 'write_file or write_data', 2020, 1
|
|
39
|
+
|
|
40
|
+
def write_file(file, bucket_name, options = {})
|
|
41
|
+
raise FileServiceError, 'Invalid input. One or more input values is nil' if input_invalid?(file, bucket_name)
|
|
42
|
+
|
|
43
|
+
write_data(read_file(file), bucket_name, options)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def write_data(data, bucket_name, options = {})
|
|
47
|
+
raise FileServiceError, 'Invalid input. One or more input values is nil' if input_invalid?(data, bucket_name)
|
|
48
|
+
raise FileSizeTooLargeError, "Data size is larger than maximum allowed size of #{max_file_size}" if data_size_invalid?(data)
|
|
49
|
+
|
|
50
|
+
file_key = if options.key?(:file_name)
|
|
51
|
+
options[:file_name]
|
|
52
|
+
else
|
|
53
|
+
generate_file_key(options)
|
|
54
|
+
end
|
|
55
|
+
tempfile = write_tempfile(data, file_key)
|
|
33
56
|
|
|
34
57
|
begin
|
|
35
58
|
perform_upload(bucket_name, file_key, tempfile, options)
|
|
@@ -42,7 +65,7 @@ class PorkyLib::Unencrypted::FileService
|
|
|
42
65
|
|
|
43
66
|
private
|
|
44
67
|
|
|
45
|
-
def input_invalid?(
|
|
46
|
-
|
|
68
|
+
def input_invalid?(file_or_data, bucket_name)
|
|
69
|
+
file_or_data.nil? || bucket_name.nil?
|
|
47
70
|
end
|
|
48
71
|
end
|
data/lib/porky_lib/version.rb
CHANGED
data/lib/tasks/file.rake
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'porky_lib'
|
|
4
|
+
|
|
5
|
+
namespace :file do
|
|
6
|
+
desc "Read a file from AWS S3"
|
|
7
|
+
task :read do
|
|
8
|
+
# Optional arguments
|
|
9
|
+
use_mock_client = ENV.fetch('AWS_S3_MOCK_CLIENT', 'true') == 'true'
|
|
10
|
+
max_file_size = ENV.fetch('AWS_S3_MAX_FILE_SIZE', 1_048_576).to_i
|
|
11
|
+
destination = ENV.fetch('DESTINATION', ENV['FILE_KEY'])
|
|
12
|
+
|
|
13
|
+
# Required arguments
|
|
14
|
+
arguments = {
|
|
15
|
+
file_key: ENV['FILE_KEY'],
|
|
16
|
+
aws_s3_bucket: ENV['AWS_S3_BUCKET'],
|
|
17
|
+
aws_region: ENV['AWS_REGION'],
|
|
18
|
+
aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
|
|
19
|
+
aws_access_key: ENV['AWS_ACCESS_KEY']
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# Checks presence of required arguments and configures porky_lib
|
|
23
|
+
check_arguments(arguments)
|
|
24
|
+
setup_porky_lib(arguments, use_mock_client, max_file_size)
|
|
25
|
+
|
|
26
|
+
# Reads and writes the file
|
|
27
|
+
message, = PorkyLib::FileService.instance.read(arguments[:aws_s3_bucket], arguments[:file_key])
|
|
28
|
+
file = File.open(destination, 'w')
|
|
29
|
+
file.puts(message)
|
|
30
|
+
file.close
|
|
31
|
+
|
|
32
|
+
puts "SUCCESS - Saved file: '#{destination}' with content of the bucket: '#{arguments[:aws_s3_bucket]}' with file_key: '#{arguments[:file_key]}'"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
desc "Write a file to AWS S3"
|
|
36
|
+
task :write do
|
|
37
|
+
# Optional arguments
|
|
38
|
+
use_mock_client = ENV.fetch('AWS_S3_MOCK_CLIENT', 'true') == 'true'
|
|
39
|
+
max_file_size = ENV.fetch('AWS_S3_MAX_FILE_SIZE', 1_048_576).to_i
|
|
40
|
+
storage_class = ENV.fetch('AWS_S3_STORAGE_CLASS', 'STANDARD')
|
|
41
|
+
keep_file_name = ENV.fetch('AWS_S3_KEEP_FILE_NAME', 'true') == 'true'
|
|
42
|
+
|
|
43
|
+
# Required arguments
|
|
44
|
+
arguments = {
|
|
45
|
+
file_path: ENV['FILE_PATH'],
|
|
46
|
+
cmk_key_id: ENV['CMK_KEY_ID'],
|
|
47
|
+
aws_s3_bucket: ENV['AWS_S3_BUCKET'],
|
|
48
|
+
aws_region: ENV['AWS_REGION'],
|
|
49
|
+
aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
|
|
50
|
+
aws_access_key: ENV['AWS_ACCESS_KEY']
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Checks presence of required arguments and configures porky_lib
|
|
54
|
+
check_arguments(arguments)
|
|
55
|
+
setup_porky_lib(arguments, use_mock_client, max_file_size)
|
|
56
|
+
|
|
57
|
+
write_options = {
|
|
58
|
+
storage_class: storage_class,
|
|
59
|
+
file_name: (File.basename(arguments[:file_path]) if keep_file_name)
|
|
60
|
+
}.compact
|
|
61
|
+
|
|
62
|
+
# Creates CMK key with empty tags and stores file
|
|
63
|
+
PorkyLib::Symmetric.instance.create_key([{}], arguments[:cmk_key_id]) unless PorkyLib::Symmetric.instance.cmk_alias_exists?(arguments[:cmk_key_id])
|
|
64
|
+
file_key = PorkyLib::FileService.instance.write_file(arguments[:file_path], arguments[:aws_s3_bucket], arguments[:cmk_key_id], write_options)
|
|
65
|
+
|
|
66
|
+
puts "SUCCESS - Created file: '#{arguments[:file_path]}' bucket: '#{arguments[:aws_s3_bucket]}' file_key: '#{file_key}'"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def check_arguments(arguments)
|
|
73
|
+
nil_arguments = []
|
|
74
|
+
arguments.map { |key, value| nil_arguments.push(key.to_s.upcase) if value.nil? && !key.nil? }
|
|
75
|
+
abort "ERROR - Need to provide as environment variables: #{nil_arguments.join(', ')}" unless nil_arguments.empty?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def setup_porky_lib(arguments, use_mock_client, max_file_size)
|
|
79
|
+
PorkyLib::Config.configure(aws_region: arguments[:aws_region],
|
|
80
|
+
aws_key_id: arguments[:aws_access_key_id],
|
|
81
|
+
aws_key_secret: arguments[:aws_access_key],
|
|
82
|
+
aws_client_mock: use_mock_client,
|
|
83
|
+
max_file_size: max_file_size)
|
|
84
|
+
PorkyLib::Config.initialize_aws
|
|
85
|
+
end
|
data/porky_lib.gemspec
CHANGED
|
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
|
25
25
|
spec.add_development_dependency 'bundler'
|
|
26
26
|
spec.add_development_dependency 'bundler-audit'
|
|
27
27
|
spec.add_development_dependency 'byebug'
|
|
28
|
+
spec.add_development_dependency 'codacy-coverage'
|
|
28
29
|
spec.add_development_dependency 'codecov'
|
|
29
30
|
spec.add_development_dependency 'msgpack'
|
|
30
31
|
spec.add_development_dependency 'rake'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: porky_lib
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Greg Fletcher
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-07-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: aws-sdk-kms
|
|
@@ -80,6 +80,20 @@ dependencies:
|
|
|
80
80
|
- - ">="
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: codacy-coverage
|
|
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'
|
|
83
97
|
- !ruby/object:Gem::Dependency
|
|
84
98
|
name: codecov
|
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -390,6 +404,7 @@ files:
|
|
|
390
404
|
- lib/porky_lib/unencrypted.rb
|
|
391
405
|
- lib/porky_lib/unencrypted/file_service.rb
|
|
392
406
|
- lib/porky_lib/version.rb
|
|
407
|
+
- lib/tasks/file.rake
|
|
393
408
|
- porky_lib.gemspec
|
|
394
409
|
homepage: https://github.com/Zetatango/porky_lib
|
|
395
410
|
licenses: []
|
|
@@ -409,7 +424,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
409
424
|
- !ruby/object:Gem::Version
|
|
410
425
|
version: '0'
|
|
411
426
|
requirements: []
|
|
412
|
-
rubygems_version: 3.
|
|
427
|
+
rubygems_version: 3.1.2
|
|
413
428
|
signing_key:
|
|
414
429
|
specification_version: 4
|
|
415
430
|
summary: A library for cryptographic services using AWS KMS and RbNaCl
|