sidekiq-field-encryptor 0.2.0 → 0.4.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/.github/CODEOWNERS +2 -0
- data/.github/workflows/test.yml +49 -0
- data/.rspec +2 -1
- data/.rubocop-https---raw-githubusercontent-com-aptible-dryer-lint-main--rubocop-base-yml +380 -0
- data/.rubocop.yml +16 -0
- data/.rubocop_ignore.yml +11 -0
- data/Gemfile +2 -0
- data/Makefile +7 -0
- data/README.md +2 -3
- data/Rakefile +2 -3
- data/SECURITY.md +23 -0
- data/lib/sidekiq-field-encryptor/encryptor.rb +18 -6
- data/lib/sidekiq-field-encryptor/version.rb +3 -1
- data/lib/sidekiq-field-encryptor.rb +2 -0
- data/sidekiq-field-encryptor.gemspec +8 -5
- data/spec/sidekiq-field-encryptor/encryptor_spec.rb +21 -17
- data/spec/spec_helper.rb +2 -0
- metadata +51 -19
- data/.travis.yml +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 930fe1d92b017b2b44b2102082cf4775cd2285e553d1243569807212453c83ca
|
|
4
|
+
data.tar.gz: 66280ab60c4e52985dc36b29d37669d9a8576cfd66c1ba296230359eceae7d72
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ef8f4ec59c3ac5a6a99b5fc25bc9681727963c2ce29c7c1a5a06860bdb2872664e9a3fffb8930da405a34f30164162faaab4741edf717843742cdbb486daf408
|
|
7
|
+
data.tar.gz: 0bbaea48f3ea6b9ab97c4492454ee3148fb998d9f4c6f6207f87b22c47c28a6b5322c1ae70b510d60d7923117bdf53951f7c54f7393c54a4a47d5ae0e1d301ff
|
data/.github/CODEOWNERS
ADDED
|
@@ -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: make lint
|
|
33
|
+
|
|
34
|
+
- name: Run Tests
|
|
35
|
+
run: make test
|
|
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
|
@@ -0,0 +1,380 @@
|
|
|
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
|
+
Capybara/NegationMatcher:
|
|
249
|
+
Enabled: true
|
|
250
|
+
|
|
251
|
+
Capybara/SpecificActions:
|
|
252
|
+
Enabled: true
|
|
253
|
+
|
|
254
|
+
Capybara/SpecificFinders:
|
|
255
|
+
Enabled: true
|
|
256
|
+
|
|
257
|
+
Capybara/SpecificMatcher:
|
|
258
|
+
Enabled: true
|
|
259
|
+
|
|
260
|
+
FactoryBot/ConsistentParenthesesStyle:
|
|
261
|
+
Enabled: true
|
|
262
|
+
|
|
263
|
+
FactoryBot/SyntaxMethods:
|
|
264
|
+
Enabled: true
|
|
265
|
+
|
|
266
|
+
RSpecRails/AvoidSetupHook:
|
|
267
|
+
Enabled: true
|
|
268
|
+
|
|
269
|
+
RSpecRails/HaveHttpStatus:
|
|
270
|
+
Enabled: true
|
|
271
|
+
|
|
272
|
+
RSpecRails/InferredSpecType:
|
|
273
|
+
Enabled: true
|
|
274
|
+
|
|
275
|
+
###############################################################################
|
|
276
|
+
## Customizations ##
|
|
277
|
+
###############################################################################
|
|
278
|
+
|
|
279
|
+
# Try to keep a balance between the fact that some people are
|
|
280
|
+
# working from laptops and the fact that unnecessarily short
|
|
281
|
+
# lines make code hard to read.
|
|
282
|
+
Layout/LineLength:
|
|
283
|
+
Enabled: true
|
|
284
|
+
Max: 120
|
|
285
|
+
|
|
286
|
+
# TODO: We have enough places where this isn't used that it would
|
|
287
|
+
# be hard to switch, but maybe we should enable in the future?
|
|
288
|
+
RSpec/NamedSubject:
|
|
289
|
+
Enabled: false
|
|
290
|
+
|
|
291
|
+
# Sometimes our tests are only confirming that
|
|
292
|
+
# an exception isn't raised.
|
|
293
|
+
RSpec/NoExpectationExample:
|
|
294
|
+
Enabled: false
|
|
295
|
+
|
|
296
|
+
# These sometimes make tests look nicer.
|
|
297
|
+
RSpec/NestedGroups:
|
|
298
|
+
Enabled: false
|
|
299
|
+
|
|
300
|
+
RSpec/RepeatedExampleGroupBody:
|
|
301
|
+
Enabled: false
|
|
302
|
+
|
|
303
|
+
RSpec/MultipleMemoizedHelpers:
|
|
304
|
+
Max: 20
|
|
305
|
+
|
|
306
|
+
RSpec/SubjectStub:
|
|
307
|
+
Enabled: false
|
|
308
|
+
|
|
309
|
+
RSpec/MessageSpies:
|
|
310
|
+
Enabled: false
|
|
311
|
+
|
|
312
|
+
RSpec/ExpectInHook:
|
|
313
|
+
Enabled: false
|
|
314
|
+
|
|
315
|
+
RSpec/MultipleExpectations:
|
|
316
|
+
Enabled: false
|
|
317
|
+
|
|
318
|
+
RSpec/ExampleLength:
|
|
319
|
+
Enabled: false
|
|
320
|
+
|
|
321
|
+
# These aren't effective enough at calculating the right
|
|
322
|
+
# kinds of complexity.
|
|
323
|
+
Metrics/CyclomaticComplexity:
|
|
324
|
+
Enabled: false
|
|
325
|
+
|
|
326
|
+
Metrics/AbcSize:
|
|
327
|
+
Enabled: false
|
|
328
|
+
|
|
329
|
+
Metrics/PerceivedComplexity:
|
|
330
|
+
Enabled: false
|
|
331
|
+
|
|
332
|
+
# Favor explicit over implicit.
|
|
333
|
+
Metrics/ParameterLists:
|
|
334
|
+
Max: 20
|
|
335
|
+
|
|
336
|
+
Style/HashSyntax:
|
|
337
|
+
Enabled: false
|
|
338
|
+
|
|
339
|
+
Naming/BlockForwarding:
|
|
340
|
+
Enabled: true
|
|
341
|
+
EnforcedStyle: explicit
|
|
342
|
+
|
|
343
|
+
# This probably isn't right to disable, but at the same time, there
|
|
344
|
+
# are places where we're using (valid) boilerplate code that adds up.
|
|
345
|
+
Metrics/MethodLength:
|
|
346
|
+
Enabled: false
|
|
347
|
+
|
|
348
|
+
# This probably isn't best to change either, but some modules and corresponding
|
|
349
|
+
# helpers will have a fair number of lines and this seems arbitrarily limiting
|
|
350
|
+
Metrics/ModuleLength:
|
|
351
|
+
Enabled: false
|
|
352
|
+
|
|
353
|
+
# We may want to re-enable this in the future with a reasonable value,
|
|
354
|
+
# but right now this is overly prescriptive, especially in scenarios
|
|
355
|
+
# where we have a lot of boilerplate code.
|
|
356
|
+
Metrics/ClassLength:
|
|
357
|
+
Enabled: false
|
|
358
|
+
|
|
359
|
+
# This is fine being a judgement call.
|
|
360
|
+
Metrics/BlockLength:
|
|
361
|
+
Enabled: false
|
|
362
|
+
|
|
363
|
+
# This is overly prescriptive with minimal gain.
|
|
364
|
+
RSpec/ContextWording:
|
|
365
|
+
Enabled: false
|
|
366
|
+
|
|
367
|
+
# This is allowing something implicit, which isn't ideal,
|
|
368
|
+
# but it's also something we heavily leverage.
|
|
369
|
+
RSpec/LetSetup:
|
|
370
|
+
Enabled: false
|
|
371
|
+
|
|
372
|
+
# This doesn't feel great to add, but unfortunately it's making
|
|
373
|
+
# incorrect assumptions about some of our function names
|
|
374
|
+
# which causes a lot of false positives.
|
|
375
|
+
RSpec/PredicateMatcher:
|
|
376
|
+
Enabled: false
|
|
377
|
+
|
|
378
|
+
# There are valid reasons to do this.
|
|
379
|
+
RSpec/InstanceVariable:
|
|
380
|
+
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$/
|
data/.rubocop_ignore.yml
ADDED
data/Gemfile
CHANGED
data/Makefile
ADDED
data/README.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#  Sidekiq::Field::Encryptor
|
|
2
2
|
|
|
3
3
|
[](https://rubygems.org/gems/sidekiq-field-encryptor)
|
|
4
|
-
[](https://travis-ci.org/aptible/sidekiq-field-encryptor)
|
|
5
4
|
[](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 (`
|
|
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)
|
|
48
|
+
Copyright (c) 2024 [Aptible](https://www.aptible.com), Blake Pettersson, and contributors.
|
data/Rakefile
CHANGED
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,6 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'base64'
|
|
2
4
|
require 'encryptor'
|
|
3
5
|
require 'json'
|
|
6
|
+
require 'sidekiq'
|
|
4
7
|
require 'sidekiq-field-encryptor/version'
|
|
5
8
|
|
|
6
9
|
# This middleware configures encryption of any fields that can contain sensitive
|
|
@@ -22,9 +25,10 @@ require 'sidekiq-field-encryptor/version'
|
|
|
22
25
|
# Will encrypt the values {'x' => 1} and 'b' when storing the job in Redis and
|
|
23
26
|
# decrypt the values inside the client before the job is executed.
|
|
24
27
|
module SidekiqFieldEncryptor
|
|
25
|
-
SERIALIZE_JSON = 'json'
|
|
26
|
-
SERIALIZE_MARHSALL = 'marshal'
|
|
28
|
+
SERIALIZE_JSON = 'json'
|
|
29
|
+
SERIALIZE_MARHSALL = 'marshal'
|
|
27
30
|
|
|
31
|
+
# Shared methods between client and base
|
|
28
32
|
class Base
|
|
29
33
|
def initialize(options = {})
|
|
30
34
|
@encryption_key = options[:encryption_key]
|
|
@@ -60,7 +64,7 @@ module SidekiqFieldEncryptor
|
|
|
60
64
|
JSON.parse(value, quirks_mode: true)
|
|
61
65
|
when SERIALIZE_MARHSALL, nil
|
|
62
66
|
# No method used to be Marshall, so we respect this here
|
|
63
|
-
Marshal.load(value)
|
|
67
|
+
Marshal.load(value) # rubocop:disable Security/MarshalLoad
|
|
64
68
|
else
|
|
65
69
|
raise "Invalid serialization_method: #{@serialization_method}"
|
|
66
70
|
end
|
|
@@ -68,7 +72,7 @@ module SidekiqFieldEncryptor
|
|
|
68
72
|
|
|
69
73
|
def encrypt(value)
|
|
70
74
|
plaintext = serialize(value)
|
|
71
|
-
iv = OpenSSL::Cipher
|
|
75
|
+
iv = OpenSSL::Cipher.new(@encryption_algorithm).random_iv
|
|
72
76
|
args = { key: @encryption_key, iv: iv, algorithm: @encryption_algorithm }
|
|
73
77
|
ciphertext = ::Encryptor.encrypt(plaintext, **args)
|
|
74
78
|
[
|
|
@@ -85,36 +89,44 @@ module SidekiqFieldEncryptor
|
|
|
85
89
|
args = { key: @encryption_key, iv: iv, algorithm: @encryption_algorithm }
|
|
86
90
|
plaintext = ::Encryptor.decrypt(ciphertext, **args)
|
|
87
91
|
deserialize(serialization_method, plaintext)
|
|
92
|
+
rescue OpenSSL::Cipher::CipherError
|
|
93
|
+
raise 'Could not decrypt - is the encryption key correct?'
|
|
88
94
|
end
|
|
89
95
|
|
|
90
96
|
def process_message(message)
|
|
91
97
|
fields = @encrypted_fields[message['class']]
|
|
92
98
|
return unless fields
|
|
99
|
+
|
|
93
100
|
assert_key_configured
|
|
94
101
|
message['args'].size.times.each do |arg_index|
|
|
95
102
|
to_encrypt = fields[arg_index]
|
|
96
103
|
next unless to_encrypt
|
|
104
|
+
|
|
97
105
|
raw_value = message['args'][arg_index]
|
|
98
106
|
if to_encrypt == true
|
|
99
107
|
message['args'][arg_index] = yield(raw_value)
|
|
100
108
|
elsif to_encrypt.is_a?(Array) && raw_value.is_a?(Hash)
|
|
101
|
-
message['args'][arg_index] =
|
|
109
|
+
message['args'][arg_index] = raw_value.to_h do |key, value|
|
|
102
110
|
value = yield(value) if to_encrypt.member?(key.to_s)
|
|
103
111
|
[key, value]
|
|
104
|
-
end
|
|
112
|
+
end
|
|
105
113
|
end
|
|
106
114
|
end
|
|
107
115
|
end
|
|
108
116
|
end
|
|
109
117
|
|
|
118
|
+
# Used when encrypting fields
|
|
110
119
|
class Client < Base
|
|
120
|
+
include Sidekiq::ClientMiddleware
|
|
111
121
|
def call(_, message, _, _)
|
|
112
122
|
process_message(message) { |value| encrypt(value) }
|
|
113
123
|
yield
|
|
114
124
|
end
|
|
115
125
|
end
|
|
116
126
|
|
|
127
|
+
# Used when decrypting fields
|
|
117
128
|
class Server < Base
|
|
129
|
+
include Sidekiq::ServerMiddleware
|
|
118
130
|
def call(_, message, _)
|
|
119
131
|
process_message(message) { |value| decrypt(value) }
|
|
120
132
|
yield
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
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,15 @@ 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
|
+
spec.add_dependency 'sidekiq'
|
|
23
24
|
|
|
24
25
|
spec.add_development_dependency 'bundler'
|
|
25
|
-
spec.add_development_dependency 'aptible-tasks'
|
|
26
26
|
spec.add_development_dependency 'rake'
|
|
27
|
-
spec.add_development_dependency 'rspec'
|
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.12'
|
|
28
|
+
spec.add_development_dependency 'rubocop', '< 1.78'
|
|
29
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.16.0'
|
|
30
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
28
31
|
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
|
|
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 =
|
|
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
|
-
|
|
27
|
+
described_class.new(
|
|
25
28
|
encryption_key: key,
|
|
26
|
-
encrypted_fields: { 'FooJob' => { 1 => true, 2 => %w
|
|
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
|
|
41
|
-
fields = { 'FooJob' => { 1 => true, 2 => %w
|
|
43
|
+
key = OpenSSL::Cipher.new('aes-128-cbc').random_key
|
|
44
|
+
fields = { 'FooJob' => { 1 => true, 2 => %w[b d] } }
|
|
42
45
|
|
|
43
|
-
ko =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
-
|
|
87
|
+
described_class.new(
|
|
84
88
|
encryption_key: key,
|
|
85
|
-
encrypted_fields: { 'FooJob' => { 1 => true, 2 => %w
|
|
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
|
|
102
|
+
key = OpenSSL::Cipher.new('aes-128-cbc').random_key
|
|
99
103
|
fields = { 'FooJob' => { 1 => true } }
|
|
100
104
|
|
|
101
|
-
ko =
|
|
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 =
|
|
111
|
+
ok = described_class.new(
|
|
108
112
|
encryption_key: key,
|
|
109
113
|
encryption_algorithm: 'aes-128-cbc',
|
|
110
114
|
encrypted_fields: fields
|
|
@@ -119,7 +123,7 @@ describe SidekiqFieldEncryptor::Server do
|
|
|
119
123
|
end
|
|
120
124
|
|
|
121
125
|
it 'fails if the serialization methods are different' do
|
|
122
|
-
r =
|
|
126
|
+
r = described_class.new(
|
|
123
127
|
encryption_key: key,
|
|
124
128
|
encrypted_fields: { 'FooJob' => { 1 => true } },
|
|
125
129
|
serialization_method: SidekiqFieldEncryptor::SERIALIZE_JSON
|
|
@@ -137,7 +141,7 @@ describe SidekiqFieldEncryptor::Server do
|
|
|
137
141
|
end
|
|
138
142
|
|
|
139
143
|
it 'allows compat serialization' do
|
|
140
|
-
r =
|
|
144
|
+
r = described_class.new(
|
|
141
145
|
encryption_key: key,
|
|
142
146
|
encrypted_fields: { 'FooJob' => { 1 => true } },
|
|
143
147
|
serialization_method: SidekiqFieldEncryptor::SERIALIZE_JSON,
|
data/spec/spec_helper.rb
CHANGED
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.
|
|
4
|
+
version: 0.4.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:
|
|
11
|
+
date: 2025-11-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: encryptor
|
|
@@ -25,13 +25,13 @@ dependencies:
|
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: sidekiq
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: '0'
|
|
34
|
-
type: :
|
|
34
|
+
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
@@ -39,7 +39,7 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: bundler
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - ">="
|
|
@@ -70,16 +70,44 @@ dependencies:
|
|
|
70
70
|
name: rspec
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
|
-
- - "
|
|
73
|
+
- - "~>"
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '
|
|
75
|
+
version: '3.12'
|
|
76
76
|
type: :development
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
|
-
- - "
|
|
80
|
+
- - "~>"
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
82
|
+
version: '3.12'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rubocop
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "<"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '1.78'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "<"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '1.78'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: rubocop-rspec
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: 2.16.0
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 2.16.0
|
|
83
111
|
description: Selectively encrypt fields in Sidekiq
|
|
84
112
|
email:
|
|
85
113
|
- blake@aptible.com
|
|
@@ -87,13 +115,19 @@ executables: []
|
|
|
87
115
|
extensions: []
|
|
88
116
|
extra_rdoc_files: []
|
|
89
117
|
files:
|
|
118
|
+
- ".github/CODEOWNERS"
|
|
119
|
+
- ".github/workflows/test.yml"
|
|
90
120
|
- ".gitignore"
|
|
91
121
|
- ".rspec"
|
|
92
|
-
- ".
|
|
122
|
+
- ".rubocop-https---raw-githubusercontent-com-aptible-dryer-lint-main--rubocop-base-yml"
|
|
123
|
+
- ".rubocop.yml"
|
|
124
|
+
- ".rubocop_ignore.yml"
|
|
93
125
|
- Gemfile
|
|
94
126
|
- LICENSE.md
|
|
127
|
+
- Makefile
|
|
95
128
|
- README.md
|
|
96
129
|
- Rakefile
|
|
130
|
+
- SECURITY.md
|
|
97
131
|
- lib/sidekiq-field-encryptor.rb
|
|
98
132
|
- lib/sidekiq-field-encryptor/encryptor.rb
|
|
99
133
|
- lib/sidekiq-field-encryptor/version.rb
|
|
@@ -103,8 +137,9 @@ files:
|
|
|
103
137
|
homepage: https://github.com/aptible/sidekiq-field-encryptor
|
|
104
138
|
licenses:
|
|
105
139
|
- MIT
|
|
106
|
-
metadata:
|
|
107
|
-
|
|
140
|
+
metadata:
|
|
141
|
+
rubygems_mfa_required: 'true'
|
|
142
|
+
post_install_message:
|
|
108
143
|
rdoc_options: []
|
|
109
144
|
require_paths:
|
|
110
145
|
- lib
|
|
@@ -119,11 +154,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
119
154
|
- !ruby/object:Gem::Version
|
|
120
155
|
version: '0'
|
|
121
156
|
requirements: []
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
signing_key:
|
|
157
|
+
rubygems_version: 3.4.10
|
|
158
|
+
signing_key:
|
|
125
159
|
specification_version: 4
|
|
126
160
|
summary: Selectively encrypt fields sent into Sidekiq
|
|
127
|
-
test_files:
|
|
128
|
-
- spec/sidekiq-field-encryptor/encryptor_spec.rb
|
|
129
|
-
- spec/spec_helper.rb
|
|
161
|
+
test_files: []
|
data/.travis.yml
DELETED