sidekiq-field-encryptor 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d7b580f10f55bd99cc1b08a0d41157746562b155
4
- data.tar.gz: d93bb7059b52325809a24f161c98ec4b705f9323
2
+ SHA256:
3
+ metadata.gz: 17ebe672dfa0a9ce9941c411ae902205222c07606a74cb4515fcd69bea950a00
4
+ data.tar.gz: 6e5a0a1942a16b0a59a04ff8b6f31d4a60637bf7036634286ed7892c726ec705
5
5
  SHA512:
6
- metadata.gz: 73208766812240af540b2fac93f98f4d585ffb0065dda731dbd47be7b01ee4d4b8eab048925c2254c465ce46ecaf0a775ffb6a6e010c1b52d429f04119992f02
7
- data.tar.gz: 04f77a80f08b85d429c804a38b2244a4f5f564cd6a4a5e7704fb9727796261d7280a0fc47f80a4d3f593d9a6940be13f9b397c6d4f930a38eb294440012aa048
6
+ metadata.gz: 223e413322218a774fad26818770f62a3604e2461e8a3941f52f4670a211c1a0ccacdb57642a7abd8d79d34a25a0d49dd44d6dacd044808f6ff3b69580ced6b2
7
+ data.tar.gz: 0bccf7635de692edb8c21bf39dc86f15c7fb96015df2df2623f3636922b72ab7a7c822f99f2357eaae9245ffd6f525229594029cf8053eeb193779f3187a7a8e
@@ -0,0 +1,2 @@
1
+ * @aguilinger
2
+ * @mdelaossa
@@ -0,0 +1,49 @@
1
+ name: Tests
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - main
7
+ - master
8
+ push:
9
+ branches:
10
+ - main
11
+ - master
12
+
13
+ jobs:
14
+ test:
15
+ name: Test Ruby ${{ matrix.RUBY_VERSION }}
16
+ runs-on: ubuntu-24.04
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ RUBY_VERSION: ["2.6", "3.3"]
21
+ steps:
22
+ - name: Check out code
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Install Ruby
26
+ uses: ruby/setup-ruby@v1
27
+ with:
28
+ ruby-version: ${{ matrix.RUBY_VERSION }}
29
+ bundler-cache: true
30
+
31
+ - name: Run Lint
32
+ run: bundle exec rubocop
33
+
34
+ - name: Run Tests
35
+ run: bundle exec rspec
36
+
37
+ results:
38
+ if: ${{ always() }}
39
+ runs-on: ubuntu-latest
40
+ name: Final Results
41
+ needs: [test]
42
+ steps:
43
+ - run: exit 1
44
+ # see https://stackoverflow.com/a/67532120/4907315
45
+ if: >-
46
+ ${{
47
+ contains(needs.*.result, 'failure')
48
+ || contains(needs.*.result, 'cancelled')
49
+ }}
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --color
2
- --format documentation
2
+ --format documentation
3
+ --require spec_helper
@@ -0,0 +1,353 @@
1
+ require:
2
+ - rubocop-rspec
3
+
4
+ Gemspec/DeprecatedAttributeAssignment:
5
+ Enabled: true
6
+
7
+ Gemspec/RequireMFA:
8
+ Enabled: true
9
+
10
+ Layout/LineContinuationLeadingSpace:
11
+ Enabled: true
12
+
13
+ Layout/LineContinuationSpacing:
14
+ Enabled: true
15
+
16
+ Layout/LineEndStringConcatenationIndentation:
17
+ Enabled: true
18
+
19
+ Layout/SpaceBeforeBrackets:
20
+ Enabled: true
21
+
22
+ Lint/AmbiguousAssignment:
23
+ Enabled: true
24
+
25
+ Lint/AmbiguousOperatorPrecedence:
26
+ Enabled: true
27
+
28
+ Lint/AmbiguousRange:
29
+ Enabled: true
30
+
31
+ Lint/ConstantOverwrittenInRescue:
32
+ Enabled: true
33
+
34
+ Lint/DeprecatedConstants:
35
+ Enabled: true
36
+
37
+ Lint/DuplicateBranch:
38
+ Enabled: true
39
+
40
+ Lint/DuplicateMagicComment:
41
+ Enabled: true
42
+
43
+ Lint/DuplicateRegexpCharacterClassElement:
44
+ Enabled: true
45
+
46
+ Lint/EmptyBlock:
47
+ Enabled: false
48
+
49
+ Lint/EmptyClass:
50
+ Enabled: true
51
+
52
+ Lint/EmptyInPattern:
53
+ Enabled: true
54
+
55
+ Lint/IncompatibleIoSelectWithFiberScheduler:
56
+ Enabled: true
57
+
58
+ Lint/LambdaWithoutLiteralBlock:
59
+ Enabled: true
60
+
61
+ Lint/NoReturnInBeginEndBlocks:
62
+ Enabled: true
63
+
64
+ Lint/NonAtomicFileOperation:
65
+ Enabled: true
66
+
67
+ Lint/NumberedParameterAssignment:
68
+ Enabled: true
69
+
70
+ Lint/OrAssignmentToConstant:
71
+ Enabled: true
72
+
73
+ Lint/RedundantDirGlobSort:
74
+ Enabled: true
75
+
76
+ Lint/RefinementImportMethods:
77
+ Enabled: true
78
+
79
+ Lint/RequireRangeParentheses:
80
+ Enabled: true
81
+
82
+ Lint/RequireRelativeSelfPath:
83
+ Enabled: true
84
+
85
+ Lint/SymbolConversion:
86
+ Enabled: true
87
+
88
+ Lint/ToEnumArguments:
89
+ Enabled: true
90
+
91
+ Lint/TripleQuotes:
92
+ Enabled: true
93
+
94
+ Lint/UnexpectedBlockArity:
95
+ Enabled: true
96
+
97
+ Lint/UnmodifiedReduceAccumulator:
98
+ Enabled: true
99
+
100
+ Lint/UselessRuby2Keywords:
101
+ Enabled: true
102
+
103
+ Security/CompoundHash:
104
+ Enabled: true
105
+
106
+ Security/IoMethods:
107
+ Enabled: true
108
+
109
+ Style/ArgumentsForwarding:
110
+ Enabled: true
111
+
112
+ Style/CollectionCompact:
113
+ Enabled: true
114
+
115
+ Style/DocumentDynamicEvalDefinition:
116
+ Enabled: true
117
+
118
+ Style/EmptyHeredoc:
119
+ Enabled: true
120
+
121
+ Style/EndlessMethod:
122
+ Enabled: true
123
+
124
+ Style/EnvHome:
125
+ Enabled: true
126
+
127
+ Style/FetchEnvVar:
128
+ Enabled: true
129
+
130
+ Style/FileRead:
131
+ Enabled: true
132
+
133
+ Style/FileWrite:
134
+ Enabled: true
135
+
136
+ # TODO - remove this when this has been released on rubocop
137
+ Style/GuardClause:
138
+ Enabled: false
139
+
140
+ Style/HashConversion:
141
+ Enabled: true
142
+
143
+ Style/HashExcept:
144
+ Enabled: true
145
+
146
+ Style/IfWithBooleanLiteralBranches:
147
+ Enabled: true
148
+
149
+ Style/InPatternThen:
150
+ Enabled: true
151
+
152
+ Style/MagicCommentFormat:
153
+ Enabled: true
154
+
155
+ Style/MapCompactWithConditionalBlock:
156
+ Enabled: true
157
+
158
+ Style/MapToHash:
159
+ Enabled: true
160
+
161
+ Style/MultilineInPatternThen:
162
+ Enabled: true
163
+
164
+ Style/NegatedIfElseCondition:
165
+ Enabled: true
166
+
167
+ Style/NestedFileDirname:
168
+ Enabled: true
169
+
170
+ Style/NilLambda:
171
+ Enabled: true
172
+
173
+ Style/NumberedParameters:
174
+ Enabled: true
175
+
176
+ Style/NumberedParametersLimit:
177
+ Enabled: true
178
+
179
+ Style/NumericLiterals:
180
+ Enabled: false
181
+
182
+ Style/ObjectThen:
183
+ Enabled: true
184
+
185
+ Style/OpenStructUse:
186
+ Enabled: true
187
+
188
+ Style/OperatorMethodCall:
189
+ Enabled: true
190
+
191
+ Style/QuotedSymbols:
192
+ Enabled: true
193
+
194
+ Style/RedundantArgument:
195
+ Enabled: true
196
+
197
+ Style/RedundantEach:
198
+ Enabled: true
199
+
200
+ Style/RedundantInitialize:
201
+ Enabled: true
202
+
203
+ Style/RedundantSelfAssignmentBranch:
204
+ Enabled: true
205
+
206
+ Style/RedundantStringEscape:
207
+ Enabled: true
208
+
209
+ Style/SelectByRegexp:
210
+ Enabled: true
211
+
212
+ Style/StringChars:
213
+ Enabled: true
214
+
215
+ Style/SwapValues:
216
+ Enabled: true
217
+
218
+ RSpec/BeEq:
219
+ Enabled: true
220
+
221
+ RSpec/BeNil:
222
+ Enabled: true
223
+
224
+ RSpec/ChangeByZero:
225
+ Enabled: true
226
+
227
+ RSpec/ClassCheck:
228
+ Enabled: true
229
+
230
+ RSpec/ExcessiveDocstringSpacing:
231
+ Enabled: true
232
+
233
+ RSpec/IdenticalEqualityAssertion:
234
+ Enabled: true
235
+
236
+ RSpec/SortMetadata:
237
+ Enabled: true
238
+
239
+ RSpec/SubjectDeclaration:
240
+ Enabled: true
241
+
242
+ RSpec/StubbedMock:
243
+ Enabled: false
244
+
245
+ RSpec/VerifiedDoubleReference:
246
+ Enabled: true
247
+
248
+ ###############################################################################
249
+ ## Customizations ##
250
+ ###############################################################################
251
+
252
+ # Try to keep a balance between the fact that some people are
253
+ # working from laptops and the fact that unnecessarily short
254
+ # lines make code hard to read.
255
+ Layout/LineLength:
256
+ Enabled: true
257
+ Max: 120
258
+
259
+ # TODO: We have enough places where this isn't used that it would
260
+ # be hard to switch, but maybe we should enable in the future?
261
+ RSpec/NamedSubject:
262
+ Enabled: false
263
+
264
+ # Sometimes our tests are only confirming that
265
+ # an exception isn't raised.
266
+ RSpec/NoExpectationExample:
267
+ Enabled: false
268
+
269
+ # These sometimes make tests look nicer.
270
+ RSpec/NestedGroups:
271
+ Enabled: false
272
+
273
+ RSpec/RepeatedExampleGroupBody:
274
+ Enabled: false
275
+
276
+ RSpec/MultipleMemoizedHelpers:
277
+ Max: 20
278
+
279
+ RSpec/SubjectStub:
280
+ Enabled: false
281
+
282
+ RSpec/MessageSpies:
283
+ Enabled: false
284
+
285
+ RSpec/ExpectInHook:
286
+ Enabled: false
287
+
288
+ RSpec/MultipleExpectations:
289
+ Enabled: false
290
+
291
+ RSpec/ExampleLength:
292
+ Enabled: false
293
+
294
+ # These aren't effective enough at calculating the right
295
+ # kinds of complexity.
296
+ Metrics/CyclomaticComplexity:
297
+ Enabled: false
298
+
299
+ Metrics/AbcSize:
300
+ Enabled: false
301
+
302
+ Metrics/PerceivedComplexity:
303
+ Enabled: false
304
+
305
+ # Favor explicit over implicit.
306
+ Metrics/ParameterLists:
307
+ Max: 20
308
+
309
+ Style/HashSyntax:
310
+ Enabled: false
311
+
312
+ Naming/BlockForwarding:
313
+ Enabled: true
314
+ EnforcedStyle: explicit
315
+
316
+ # This probably isn't right to disable, but at the same time, there
317
+ # are places where we're using (valid) boilerplate code that adds up.
318
+ Metrics/MethodLength:
319
+ Enabled: false
320
+
321
+ # This probably isn't best to change either, but some modules and corresponding
322
+ # helpers will have a fair number of lines and this seems arbitrarily limiting
323
+ Metrics/ModuleLength:
324
+ Enabled: false
325
+
326
+ # We may want to re-enable this in the future with a reasonable value,
327
+ # but right now this is overly prescriptive, especially in scenarios
328
+ # where we have a lot of boilerplate code.
329
+ Metrics/ClassLength:
330
+ Enabled: false
331
+
332
+ # This is fine being a judgement call.
333
+ Metrics/BlockLength:
334
+ Enabled: false
335
+
336
+ # This is overly prescriptive with minimal gain.
337
+ RSpec/ContextWording:
338
+ Enabled: false
339
+
340
+ # This is allowing something implicit, which isn't ideal,
341
+ # but it's also something we heavily leverage.
342
+ RSpec/LetSetup:
343
+ Enabled: false
344
+
345
+ # This doesn't feel great to add, but unfortunately it's making
346
+ # incorrect assumptions about some of our function names
347
+ # which causes a lot of false positives.
348
+ RSpec/PredicateMatcher:
349
+ Enabled: false
350
+
351
+ # There are valid reasons to do this.
352
+ RSpec/InstanceVariable:
353
+ Enabled: false
data/.rubocop.yml ADDED
@@ -0,0 +1,16 @@
1
+ inherit_from:
2
+ - https://raw.githubusercontent.com/aptible/dryer-lint/main/.rubocop.base.yml
3
+ - .rubocop_ignore.yml
4
+
5
+ Style/GuardClause:
6
+ Enabled: false
7
+
8
+ AllCops:
9
+ TargetRubyVersion: 3.1
10
+ NewCops: disable
11
+ Include:
12
+ - !ruby/regexp /\.rb$/
13
+ - !ruby/regexp /Gemfile$/
14
+ - !ruby/regexp /\.gemspec$/
15
+ - !ruby/regexp /\.rake$/
16
+ - !ruby/regexp /Rakefile$/
@@ -0,0 +1,11 @@
1
+ Naming/FileName:
2
+ Exclude:
3
+ - 'lib/sidekiq-field-encryptor.rb'
4
+
5
+ RSpec/MultipleDescribes:
6
+ Exclude:
7
+ - 'spec/sidekiq-field-encryptor/encryptor_spec.rb'
8
+
9
+ Gemspec/RequiredRubyVersion:
10
+ Exclude:
11
+ - 'sidekiq-field-encryptor.gemspec'
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in sidekiq-field-encryptor.gemspec
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # ![](https://raw.github.com/aptible/straptible/master/lib/straptible/rails/templates/public.api/icon-60px.png) Sidekiq::Field::Encryptor
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/sidekiq-field-encryptor.png)](https://rubygems.org/gems/sidekiq-field-encryptor)
4
- [![Build Status](https://travis-ci.org/aptible/sidekiq-field-encryptor.png?branch=master)](https://travis-ci.org/aptible/sidekiq-field-encryptor)
5
4
  [![Dependency Status](https://gemnasium.com/aptible/sidekiq-field-encryptor.png)](https://gemnasium.com/aptible/sidekiq-field-encryptor)
6
5
 
7
6
  This is a utility which is intended to be used for encrypting sensitive data in Sidekiq jobs. The data is encrypted before sending it to Redis, and decrypted right before the Sidekiq job is executed.
@@ -39,11 +38,11 @@ decrypt the values inside the client before the job is executed.
39
38
 
40
39
  1. Fork the project.
41
40
  1. Commit your changes, with specs.
42
- 1. Ensure that your code passes specs (`rake spec`) and meets Aptible's Ruby style guide (`rake rubocop`).
41
+ 1. Ensure that your code passes specs (`bundle exec rspec`) and meets Aptible's Ruby style guide (`bundle exec rubocop`).
43
42
  1. Create a new pull request on GitHub.
44
43
 
45
44
  ## Copyright and License
46
45
 
47
46
  MIT License, see [LICENSE](LICENSE.md) for details.
48
47
 
49
- Copyright (c) 2015 [Aptible](https://www.aptible.com), Blake Pettersson, and contributors.
48
+ Copyright (c) 2024 [Aptible](https://www.aptible.com), Blake Pettersson, and contributors.
data/Rakefile CHANGED
@@ -1,4 +1,3 @@
1
- require 'bundler/gem_tasks'
1
+ # frozen_string_literal: true
2
2
 
3
- require 'aptible/tasks'
4
- Aptible::Tasks.load_tasks
3
+ require 'bundler/gem_tasks'
data/SECURITY.md ADDED
@@ -0,0 +1,23 @@
1
+ # Aptible Open Source Security Policies and Procedures
2
+
3
+ This document outlines security procedures and general policies for the Aptible open source projects as found on https://github.com/aptible.
4
+
5
+ * [Reporting a Vulnerability](#reporting-a-vulnerability)
6
+ * [Responsible Disclosure Policy](#responsible-disclosure-policy)
7
+
8
+ ## Reporting a Vulnerability
9
+
10
+ The Aptible team and community take all security vulnerabilities
11
+ seriously. Thank you for improving the security of our open source software. We appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions.
12
+
13
+ Report security vulnerabilities by emailing the Aptible security team at:
14
+
15
+ security@aptible.com
16
+
17
+ Security researchers can also privately report security vulnerabilities to repository maintainers using the GitHub "Report a Vulnerability" feature. [See how-to here](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability).
18
+
19
+ The Aptible team will acknowledge your email within 24 business hours and send a detailed response within 48 business hours indicating the next steps in handling your report. The Aptible security team will keep you informed of the progress and may ask for additional information or guidance.
20
+
21
+ ## Responsible Disclosure Policy
22
+
23
+ Please see Aptible's Responsible Disclosure Policy here: https://www.aptible.com/legal/responsible-disclosure/
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
  require 'encryptor'
5
+ require 'json'
3
6
  require 'sidekiq-field-encryptor/version'
4
7
 
5
8
  # This middleware configures encryption of any fields that can contain sensitive
@@ -21,52 +24,95 @@ require 'sidekiq-field-encryptor/version'
21
24
  # Will encrypt the values {'x' => 1} and 'b' when storing the job in Redis and
22
25
  # decrypt the values inside the client before the job is executed.
23
26
  module SidekiqFieldEncryptor
27
+ SERIALIZE_JSON = 'json'
28
+ SERIALIZE_MARHSALL = 'marshal'
29
+
30
+ # Shared methods between client and base
24
31
  class Base
25
32
  def initialize(options = {})
26
33
  @encryption_key = options[:encryption_key]
27
34
  @encrypted_fields = options[:encrypted_fields] || {}
28
35
  @encryption_algorithm = options[:encryption_algorithm] || 'aes-256-gcm'
36
+
37
+ @serialization_method = options[:serialization_method] || SERIALIZE_JSON
38
+ @serialization_compat = options[:serialization_compat]
29
39
  end
30
40
 
31
41
  def assert_key_configured
32
42
  raise 'Encryption key not configured' if @encryption_key.nil?
33
43
  end
34
44
 
45
+ def serialize(value)
46
+ case @serialization_method
47
+ when SERIALIZE_JSON
48
+ JSON.generate(value, quirks_mode: true)
49
+ when SERIALIZE_MARHSALL
50
+ Marshal.dump(value)
51
+ else
52
+ raise "Invalid serialization_method: #{@serialization_method}"
53
+ end
54
+ end
55
+
56
+ def deserialize(method, value)
57
+ if !@serialization_compat && method != @serialization_method
58
+ raise "Invalid serialization_method received: #{method}"
59
+ end
60
+
61
+ case method
62
+ when SERIALIZE_JSON
63
+ JSON.parse(value, quirks_mode: true)
64
+ when SERIALIZE_MARHSALL, nil
65
+ # No method used to be Marshall, so we respect this here
66
+ Marshal.load(value) # rubocop:disable Security/MarshalLoad
67
+ else
68
+ raise "Invalid serialization_method: #{@serialization_method}"
69
+ end
70
+ end
71
+
35
72
  def encrypt(value)
36
- plaintext = Marshal.dump(value)
37
- iv = OpenSSL::Cipher::Cipher.new(@encryption_algorithm).random_iv
73
+ plaintext = serialize(value)
74
+ iv = OpenSSL::Cipher.new(@encryption_algorithm).random_iv
38
75
  args = { key: @encryption_key, iv: iv, algorithm: @encryption_algorithm }
39
76
  ciphertext = ::Encryptor.encrypt(plaintext, **args)
40
- [::Base64.encode64(ciphertext), ::Base64.encode64(iv)]
77
+ [
78
+ ::Base64.encode64(ciphertext),
79
+ ::Base64.encode64(iv),
80
+ @serialization_method
81
+ ]
41
82
  end
42
83
 
43
84
  def decrypt(encrypted)
44
- ciphertext, iv = encrypted.map { |value| ::Base64.decode64(value) }
85
+ base64_ciphertext, base64_iv, serialization_method = encrypted
86
+ ciphertext = ::Base64.decode64(base64_ciphertext)
87
+ iv = ::Base64.decode64(base64_iv)
45
88
  args = { key: @encryption_key, iv: iv, algorithm: @encryption_algorithm }
46
89
  plaintext = ::Encryptor.decrypt(ciphertext, **args)
47
- Marshal.load(plaintext)
90
+ deserialize(serialization_method, plaintext)
48
91
  end
49
92
 
50
93
  def process_message(message)
51
94
  fields = @encrypted_fields[message['class']]
52
95
  return unless fields
96
+
53
97
  assert_key_configured
54
98
  message['args'].size.times.each do |arg_index|
55
99
  to_encrypt = fields[arg_index]
56
100
  next unless to_encrypt
101
+
57
102
  raw_value = message['args'][arg_index]
58
103
  if to_encrypt == true
59
104
  message['args'][arg_index] = yield(raw_value)
60
105
  elsif to_encrypt.is_a?(Array) && raw_value.is_a?(Hash)
61
- message['args'][arg_index] = Hash[raw_value.map do |key, value|
106
+ message['args'][arg_index] = raw_value.to_h do |key, value|
62
107
  value = yield(value) if to_encrypt.member?(key.to_s)
63
108
  [key, value]
64
- end]
109
+ end
65
110
  end
66
111
  end
67
112
  end
68
113
  end
69
114
 
115
+ # Used when encrypting fields
70
116
  class Client < Base
71
117
  def call(_, message, _, _)
72
118
  process_message(message) { |value| encrypt(value) }
@@ -74,6 +120,7 @@ module SidekiqFieldEncryptor
74
120
  end
75
121
  end
76
122
 
123
+ # Used when decrypting fields
77
124
  class Server < Base
78
125
  def call(_, message, _)
79
126
  process_message(message) { |value| decrypt(value) }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SidekiqFieldEncryptor
2
- VERSION = '0.1.1'.freeze
4
+ VERSION = '0.3.0'
3
5
  end
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'sidekiq-field-encryptor/version'
2
4
  require 'sidekiq-field-encryptor/encryptor'
@@ -1,5 +1,6 @@
1
- # encoding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
 
5
6
  require 'English'
@@ -16,13 +17,13 @@ Gem::Specification.new do |spec|
16
17
  spec.license = 'MIT'
17
18
 
18
19
  spec.files = `git ls-files`.split($RS)
19
- spec.test_files = spec.files.grep(%r{^spec/})
20
20
  spec.require_paths = ['lib']
21
21
 
22
22
  spec.add_dependency 'encryptor'
23
23
 
24
24
  spec.add_development_dependency 'bundler'
25
- spec.add_development_dependency 'aptible-tasks'
26
25
  spec.add_development_dependency 'rake'
27
- spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'rspec', '~> 3.12'
27
+ spec.add_development_dependency 'rubocop-rspec'
28
+ spec.metadata['rubygems_mfa_required'] = 'true'
28
29
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe SidekiqFieldEncryptor::Client do
4
- let(:key) { OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_key }
6
+ let(:key) { OpenSSL::Cipher.new('aes-256-cbc').random_key }
5
7
  let(:message) do
6
8
  { 'class' => 'FooJob', 'args' => [1, 2, { 'a' => 'A', 'b' => 'B' }] }
7
9
  end
@@ -10,8 +12,9 @@ describe SidekiqFieldEncryptor::Client do
10
12
  it "doesn't fail when encryption isn't attempted" do
11
13
  subject.call('FooJob', message, nil, nil) {}
12
14
  end
15
+
13
16
  it 'fails when encryption is attempted' do
14
- client = SidekiqFieldEncryptor::Client.new(
17
+ client = described_class.new(
15
18
  encrypted_fields: { 'FooJob' => { 1 => true } }
16
19
  )
17
20
  expect { client.call('FooJob', message, nil, nil) {} }
@@ -21,9 +24,9 @@ describe SidekiqFieldEncryptor::Client do
21
24
 
22
25
  describe 'with an encryption key' do
23
26
  subject do
24
- SidekiqFieldEncryptor::Client.new(
27
+ described_class.new(
25
28
  encryption_key: key,
26
- encrypted_fields: { 'FooJob' => { 1 => true, 2 => %w(b d) } }
29
+ encrypted_fields: { 'FooJob' => { 1 => true, 2 => %w[b d] } }
27
30
  )
28
31
  end
29
32
 
@@ -37,16 +40,16 @@ describe SidekiqFieldEncryptor::Client do
37
40
  end
38
41
 
39
42
  it 'supports setting the encryption algorithm' do
40
- key = OpenSSL::Cipher::Cipher.new('aes-128-cbc').random_key
41
- fields = { 'FooJob' => { 1 => true, 2 => %w(b d) } }
43
+ key = OpenSSL::Cipher.new('aes-128-cbc').random_key
44
+ fields = { 'FooJob' => { 1 => true, 2 => %w[b d] } }
42
45
 
43
- ko = SidekiqFieldEncryptor::Client.new(
46
+ ko = described_class.new(
44
47
  encryption_key: key,
45
48
  encryption_algorithm: 'aes-256-cbc',
46
49
  encrypted_fields: fields
47
50
  )
48
51
 
49
- ok = SidekiqFieldEncryptor::Client.new(
52
+ ok = described_class.new(
50
53
  encryption_key: key,
51
54
  encryption_algorithm: 'aes-128-cbc',
52
55
  encrypted_fields: fields
@@ -60,7 +63,7 @@ describe SidekiqFieldEncryptor::Client do
60
63
  end
61
64
 
62
65
  describe SidekiqFieldEncryptor::Server do
63
- let(:key) { OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_key }
66
+ let(:key) { OpenSSL::Cipher.new('aes-256-cbc').random_key }
64
67
  let(:message) do
65
68
  { 'class' => 'FooJob', 'args' => [1, 2, { 'a' => 'A', 'b' => 'B' }] }
66
69
  end
@@ -69,8 +72,9 @@ describe SidekiqFieldEncryptor::Server do
69
72
  it "doesn't fail when decryption isn't attempted" do
70
73
  subject.call('FooJob', message, nil) {}
71
74
  end
75
+
72
76
  it 'fails when decryption is attempted' do
73
- server = SidekiqFieldEncryptor::Server.new(
77
+ server = described_class.new(
74
78
  encrypted_fields: { 'FooJob' => { 1 => true } }
75
79
  )
76
80
  expect { server.call('FooJob', message, nil) {} }
@@ -80,9 +84,9 @@ describe SidekiqFieldEncryptor::Server do
80
84
 
81
85
  describe 'with an encryption key' do
82
86
  subject do
83
- SidekiqFieldEncryptor::Server.new(
87
+ described_class.new(
84
88
  encryption_key: key,
85
- encrypted_fields: { 'FooJob' => { 1 => true, 2 => %w(b d) } }
89
+ encrypted_fields: { 'FooJob' => { 1 => true, 2 => %w[b d] } }
86
90
  )
87
91
  end
88
92
 
@@ -95,16 +99,16 @@ describe SidekiqFieldEncryptor::Server do
95
99
  end
96
100
 
97
101
  it 'supports setting the encryption algorithm' do
98
- key = OpenSSL::Cipher::Cipher.new('aes-128-cbc').random_key
102
+ key = OpenSSL::Cipher.new('aes-128-cbc').random_key
99
103
  fields = { 'FooJob' => { 1 => true } }
100
104
 
101
- ko = SidekiqFieldEncryptor::Server.new(
105
+ ko = described_class.new(
102
106
  encryption_key: key,
103
107
  encryption_algorithm: 'aes-256-cbc',
104
108
  encrypted_fields: fields
105
109
  )
106
110
 
107
- ok = SidekiqFieldEncryptor::Server.new(
111
+ ok = described_class.new(
108
112
  encryption_key: key,
109
113
  encryption_algorithm: 'aes-128-cbc',
110
114
  encrypted_fields: fields
@@ -117,5 +121,41 @@ describe SidekiqFieldEncryptor::Server do
117
121
 
118
122
  ok.call('FooJob', message, nil) {}
119
123
  end
124
+
125
+ it 'fails if the serialization methods are different' do
126
+ r = described_class.new(
127
+ encryption_key: key,
128
+ encrypted_fields: { 'FooJob' => { 1 => true } },
129
+ serialization_method: SidekiqFieldEncryptor::SERIALIZE_JSON
130
+ )
131
+
132
+ e = SidekiqFieldEncryptor::Client.new(
133
+ encryption_key: key,
134
+ encrypted_fields: { 'FooJob' => { 1 => true } },
135
+ serialization_method: SidekiqFieldEncryptor::SERIALIZE_MARHSALL
136
+ )
137
+
138
+ message['args'][1] = e.encrypt(message['args'][1])
139
+ expect { r.call('FooJob', message, nil) {} }
140
+ .to raise_error(/invalid serialization_method/i)
141
+ end
142
+
143
+ it 'allows compat serialization' do
144
+ r = described_class.new(
145
+ encryption_key: key,
146
+ encrypted_fields: { 'FooJob' => { 1 => true } },
147
+ serialization_method: SidekiqFieldEncryptor::SERIALIZE_JSON,
148
+ serialization_compat: true
149
+ )
150
+
151
+ e = SidekiqFieldEncryptor::Client.new(
152
+ encryption_key: key,
153
+ encrypted_fields: { 'FooJob' => { 1 => true } },
154
+ serialization_method: SidekiqFieldEncryptor::SERIALIZE_MARHSALL
155
+ )
156
+
157
+ message['args'][1] = e.encrypt(message['args'][1])
158
+ r.call('FooJob', message, nil) {}
159
+ end
120
160
  end
121
161
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
4
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
5
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-field-encryptor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Pettersson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-02 00:00:00.000000000 Z
11
+ date: 2024-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: encryptor
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: aptible-tasks
42
+ name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,21 +53,21 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rake
56
+ name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '3.12'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '3.12'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rspec
70
+ name: rubocop-rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -87,13 +87,18 @@ executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
+ - ".github/CODEOWNERS"
91
+ - ".github/workflows/test.yml"
90
92
  - ".gitignore"
91
93
  - ".rspec"
92
- - ".travis.yml"
94
+ - ".rubocop-https---raw-githubusercontent-com-aptible-dryer-lint-main--rubocop-base-yml"
95
+ - ".rubocop.yml"
96
+ - ".rubocop_ignore.yml"
93
97
  - Gemfile
94
98
  - LICENSE.md
95
99
  - README.md
96
100
  - Rakefile
101
+ - SECURITY.md
97
102
  - lib/sidekiq-field-encryptor.rb
98
103
  - lib/sidekiq-field-encryptor/encryptor.rb
99
104
  - lib/sidekiq-field-encryptor/version.rb
@@ -103,8 +108,9 @@ files:
103
108
  homepage: https://github.com/aptible/sidekiq-field-encryptor
104
109
  licenses:
105
110
  - MIT
106
- metadata: {}
107
- post_install_message:
111
+ metadata:
112
+ rubygems_mfa_required: 'true'
113
+ post_install_message:
108
114
  rdoc_options: []
109
115
  require_paths:
110
116
  - lib
@@ -119,11 +125,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
125
  - !ruby/object:Gem::Version
120
126
  version: '0'
121
127
  requirements: []
122
- rubyforge_project:
123
- rubygems_version: 2.4.5.1
124
- signing_key:
128
+ rubygems_version: 3.5.3
129
+ signing_key:
125
130
  specification_version: 4
126
131
  summary: Selectively encrypt fields sent into Sidekiq
127
- test_files:
128
- - spec/sidekiq-field-encryptor/encryptor_spec.rb
129
- - spec/spec_helper.rb
132
+ test_files: []
data/.travis.yml DELETED
@@ -1,3 +0,0 @@
1
- rvm:
2
- - "2.1"
3
- - 2.0.0