chamber 2.9.1 → 2.10.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
2
  SHA1:
3
- metadata.gz: 1ecd2c070d7f7877b3b727f904c140acc8974712
4
- data.tar.gz: 79b12b587b92be9f7b177c4ad4349b93a4425610
3
+ metadata.gz: f64e70d25c37ca329a62d1fb9154e8c20afcb672
4
+ data.tar.gz: fcd7a592e5200ff1d9cefe0b893eb38a9ee588d1
5
5
  SHA512:
6
- metadata.gz: 0b6038491608666d4b67b1d4eed6d7c87b8e623d27c09878da29affb9d7b78b4a39a8433584e839926beec8b615dbcadc5c07f7b917a2794c3dbe1d5be2153ea
7
- data.tar.gz: 7924650c9d08ecd452b9e89f5b9b592e065678f2b681d040e2ec48b5640727c471f76d442f5a7c60c7c662e1aca4c89e36ca63cabc4fdcdd956b3f27a08d4c5f
6
+ metadata.gz: 88901e1606334bea29432cc4942029e75f9348481c94583c915244ad5fccdca1fe27560aa74fede87a95d6c95902d238eb5ca11559b004b414f89af8a9dd0e25
7
+ data.tar.gz: eb9cb535f93b01b1bde53d55e345914a9586aef32ee76d199eb0df9b1dd0810b035cf862854cf22cfa51b928cf8bbbf7c1643632faeea957809bf6a64ebb1831
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -5,7 +5,7 @@ class Ssl
5
5
 
6
6
  def self.encrypt(_key, value, encryption_key)
7
7
  value = YAML.dump(value)
8
- cipher = OpenSSL::Cipher::Cipher.new('AES-128-CBC')
8
+ cipher = OpenSSL::Cipher.new('AES-128-CBC')
9
9
  cipher.encrypt
10
10
  symmetric_key = cipher.random_key
11
11
  iv = cipher.random_iv
@@ -34,7 +34,7 @@ class Ssl
34
34
  end
35
35
  key = decryption_key.private_decrypt(key)
36
36
 
37
- cipher_dec = OpenSSL::Cipher::Cipher.new('AES-128-CBC')
37
+ cipher_dec = OpenSSL::Cipher.new('AES-128-CBC')
38
38
 
39
39
  cipher_dec.decrypt
40
40
 
@@ -14,6 +14,7 @@ class BooleanConversionFilter
14
14
 
15
15
  attr_accessor :data
16
16
 
17
+ # rubocop:disable Metrics/BlockNesting
17
18
  def execute(settings = data)
18
19
  settings.each_pair do |key, value|
19
20
  if value.respond_to? :each_pair
@@ -34,6 +35,7 @@ class BooleanConversionFilter
34
35
  end
35
36
  end
36
37
  end
38
+ # rubocop:enable Metrics/BlockNesting
37
39
  end
38
40
  end
39
41
  end
@@ -57,7 +57,11 @@ class EncryptionFilter
57
57
  end
58
58
 
59
59
  def encryption_method(value)
60
- if value.respond_to?(:match) && value.match(BASE64_STRING_PATTERN)
60
+ value_is_encrypted = value.respond_to?(:match) &&
61
+ (value.match(BASE64_STRING_PATTERN) ||
62
+ value.match(LARGE_DATA_STRING_PATTERN))
63
+
64
+ if value_is_encrypted
61
65
  EncryptionMethods::None
62
66
  else
63
67
  serialized_value = YAML.dump(value)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require 'chamber/configuration'
3
3
  require 'chamber/file_set'
4
+ require 'chamber/settings'
4
5
 
5
6
  module Chamber
6
7
  class Instance
@@ -24,6 +25,37 @@ class Instance
24
25
  files.secure
25
26
  end
26
27
 
28
+ def encrypt(data, options = {})
29
+ config = configuration.to_hash.merge(options)
30
+
31
+ Settings.
32
+ new(
33
+ config.merge(
34
+ settings: data,
35
+ pre_filters: [Filters::EncryptionFilter],
36
+ post_filters: [],
37
+ ),
38
+ ).
39
+ to_hash
40
+ end
41
+
42
+ def decrypt(data, options = {})
43
+ config = configuration.to_hash.merge(options)
44
+
45
+ Settings.
46
+ new(
47
+ config.merge(
48
+ settings: data,
49
+ pre_filters: [Filters::NamespaceFilter],
50
+ post_filters: [
51
+ Filters::DecryptionFilter,
52
+ Filters::FailedDecryptionFilter,
53
+ ],
54
+ ),
55
+ ).
56
+ to_hash
57
+ end
58
+
27
59
  def to_s(options = {})
28
60
  settings.to_s(options)
29
61
  end
@@ -0,0 +1,79 @@
1
+ require 'active_support/json'
2
+ require 'chamber'
3
+
4
+ # rubocop:disable Lint/HandleExceptions, Style/EmptyLinesAroundModuleBody
5
+ module Chamber
6
+
7
+ begin
8
+ require 'active_record/type/value'
9
+
10
+ CHAMBER_TYPE_VALUE_SUPERCLASS = ActiveRecord::Type::Value
11
+ rescue LoadError
12
+ end
13
+
14
+ begin
15
+ require 'active_model/type/value'
16
+
17
+ CHAMBER_TYPE_VALUE_SUPERCLASS = ActiveModel::Type::Value
18
+ rescue LoadError
19
+ end
20
+
21
+ module Types
22
+ class Secured < CHAMBER_TYPE_VALUE_SUPERCLASS
23
+ attr_accessor :decryption_key,
24
+ :encryption_key
25
+
26
+ def initialize(options = {})
27
+ self.encryption_key = options.fetch(:encryption_key,
28
+ Chamber.configuration.encryption_key)
29
+ self.decryption_key = options.fetch(:decryption_key,
30
+ Chamber.configuration.decryption_key)
31
+ end
32
+
33
+ def type
34
+ :jsonb
35
+ end
36
+
37
+ def cast(value)
38
+ case value
39
+ when Hash
40
+ value
41
+ when String
42
+ ::ActiveSupport::JSON.decode(value)
43
+ when NilClass
44
+ nil
45
+ else
46
+ fail ArgumentError, 'Any attributes encrypted with Chamber must be either a Hash or a valid JSON string'
47
+ end
48
+ end
49
+ alias type_cast_from_user cast
50
+
51
+ def deserialize(value)
52
+ value = cast(value)
53
+
54
+ return if value.nil?
55
+
56
+ Chamber.decrypt(value,
57
+ decryption_key: decryption_key,
58
+ encryption_key: encryption_key)
59
+ end
60
+ alias type_cast_from_database deserialize
61
+
62
+ def serialize(value)
63
+ fail ArgumentError, 'Any attributes encrypted with Chamber must be a Hash' unless value.is_a?(Hash)
64
+
65
+ ::ActiveSupport::JSON.encode(
66
+ Chamber.encrypt(value,
67
+ decryption_key: decryption_key,
68
+ encryption_key: encryption_key),
69
+ )
70
+ end
71
+ alias type_cast_for_database serialize
72
+
73
+ def changed_in_place?(raw_old_value, new_value)
74
+ deserialize(raw_old_value) == new_value
75
+ end
76
+ end
77
+ end
78
+ end
79
+ # rubocop:enable Lint/HandleExceptions, Style/EmptyLinesAroundModuleBody
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Chamber
3
- VERSION = '2.9.1'.freeze
3
+ VERSION = '2.10.0'.freeze
4
4
  end
@@ -61,7 +61,7 @@ describe EncryptionFilter do
61
61
  EncryptionFilter::BASE64_STRING_PATTERN
62
62
  end
63
63
 
64
- it 'will not attempt to encrypt values if it guesses that they are already encrypted' do
64
+ it 'will not attempt to encrypt normal values if it guesses that they are already encrypted' do
65
65
  filtered_settings = EncryptionFilter.execute(
66
66
  data: {
67
67
  _secure_my_secure_setting: 'fNI5wlBniNhEU4396pmhWwx+A09bRAMJOUASuP7PzprewBX8C' \
@@ -87,6 +87,55 @@ describe EncryptionFilter do
87
87
  'uF3CDIKRIC6U+mnM5SRMO4Dzysw=='
88
88
  end
89
89
 
90
+ it 'will not attempt to encrypt large values if it guesses that they are already encrypted' do
91
+ filtered_settings = EncryptionFilter.execute(
92
+ data: {
93
+ _secure_my_secure_setting: 'AcMY7ALLoGZRakL3ibyo2WB438ipdMDIjsa4SCDBP2saOY63A' \
94
+ 'D3C/SZanexlYDQoYoYC0V5J5EvKHgGMDAU8qnp9LjzU5VCwJ3' \
95
+ 'SVRGz3J0c7LXgTlC585Lgy8LX+/yjYFm4D13hlMvvsoI35Bo8' \
96
+ 'EVkTSU2+0gRSjRpQJeK1o7az5+fBuNmFipevA4YfLnarnpwo2' \
97
+ 'd2oO+BqStI2QQI1UWwN2R04rvOdHoEzA6DLsdvYX+QTKDk4K5' \
98
+ 'oSKXfuMBvzOCaCGT75cmt85ZY7XZnwbKi6c4mtL1ajrCr8sQF' \
99
+ 'TA/GyG1EiYLFp1uQco0m2/S9yFf26REjax4ZE6O/ilXgT6xg=' \
100
+ '=#YAm25swWRQx4ip1RjVzpGQ==#vRGvgjErI+dATM4UOtFkkg' \
101
+ 'efFpFTvxGpHN0gRbf1VCO4K07eqAQPb46BDI67a8iNum9cBph' \
102
+ 'es7oGmuNnUvBg4JiZhKsXnolcRWdITDVh/XYNioXRmesvj4x+' \
103
+ 'tY0FVhkLV2zubRVfC7CDJgin6wRHP+bcZhICDD2YqB+XRS4ou' \
104
+ '66UeaiGA4eV4G6sPIo+DPjDM3m8JFnuRFMvGk73wthbN4MdAp' \
105
+ '9xONt5wfobJUiUR11k2iAqwhx7Wyj0imz/afI8goDTdMfQt3V' \
106
+ 'DOYqYG3y2AcYOfsOL6m0GtQRlKvtsvw+m8/ICwSGiL2Loup0j' \
107
+ '/jDGhFi1lwf4ded8aSwyS+2/Ks9C008dsJwpR1SxJ59z1KSzd' \
108
+ 'QcTcrJTnxd+2qpOVVIoaRGud2tSV+5wKXy9dWRflLsjEtBRFR' \
109
+ 'eFurTVQPodjDy+Lhs452/O/+KAJOXMKeYegCGOe8z9tLD3tel' \
110
+ 'jjTyJPeW/1FE3+tP3G3HJAV4sgoO0YwhNY1Nji56igCl3UvEP' \
111
+ 'nEQcJgu0w/+dqSreqwp6TqaqXY3lzr8vi733lti4nss=',
112
+ },
113
+ encryption_key: './spec/spec_key.pub',
114
+ )
115
+
116
+ my_secure_setting = filtered_settings._secure_my_secure_setting
117
+
118
+ expect(my_secure_setting).to eql 'AcMY7ALLoGZRakL3ibyo2WB438ipdMDIjsa4SCDBP2saOY63A' \
119
+ 'D3C/SZanexlYDQoYoYC0V5J5EvKHgGMDAU8qnp9LjzU5VCwJ3' \
120
+ 'SVRGz3J0c7LXgTlC585Lgy8LX+/yjYFm4D13hlMvvsoI35Bo8' \
121
+ 'EVkTSU2+0gRSjRpQJeK1o7az5+fBuNmFipevA4YfLnarnpwo2' \
122
+ 'd2oO+BqStI2QQI1UWwN2R04rvOdHoEzA6DLsdvYX+QTKDk4K5' \
123
+ 'oSKXfuMBvzOCaCGT75cmt85ZY7XZnwbKi6c4mtL1ajrCr8sQF' \
124
+ 'TA/GyG1EiYLFp1uQco0m2/S9yFf26REjax4ZE6O/ilXgT6xg=' \
125
+ '=#YAm25swWRQx4ip1RjVzpGQ==#vRGvgjErI+dATM4UOtFkkg' \
126
+ 'efFpFTvxGpHN0gRbf1VCO4K07eqAQPb46BDI67a8iNum9cBph' \
127
+ 'es7oGmuNnUvBg4JiZhKsXnolcRWdITDVh/XYNioXRmesvj4x+' \
128
+ 'tY0FVhkLV2zubRVfC7CDJgin6wRHP+bcZhICDD2YqB+XRS4ou' \
129
+ '66UeaiGA4eV4G6sPIo+DPjDM3m8JFnuRFMvGk73wthbN4MdAp' \
130
+ '9xONt5wfobJUiUR11k2iAqwhx7Wyj0imz/afI8goDTdMfQt3V' \
131
+ 'DOYqYG3y2AcYOfsOL6m0GtQRlKvtsvw+m8/ICwSGiL2Loup0j' \
132
+ '/jDGhFi1lwf4ded8aSwyS+2/Ks9C008dsJwpR1SxJ59z1KSzd' \
133
+ 'QcTcrJTnxd+2qpOVVIoaRGud2tSV+5wKXy9dWRflLsjEtBRFR' \
134
+ 'eFurTVQPodjDy+Lhs452/O/+KAJOXMKeYegCGOe8z9tLD3tel' \
135
+ 'jjTyJPeW/1FE3+tP3G3HJAV4sgoO0YwhNY1Nji56igCl3UvEP' \
136
+ 'nEQcJgu0w/+dqSreqwp6TqaqXY3lzr8vi733lti4nss='
137
+ end
138
+
90
139
  it 'can encrypt long multiline strings' do
91
140
  filtered_settings = EncryptionFilter.execute(
92
141
  data: {
@@ -0,0 +1,70 @@
1
+ require 'rspectacular'
2
+ require 'active_support/hash_with_indifferent_access'
3
+ require 'chamber/types/secured'
4
+
5
+ module Chamber
6
+ module Types
7
+ describe Secured do
8
+ BASE64_STRING_PATTERN = %r{[A-Za-z0-9\+/]{342}==}
9
+
10
+ subject do
11
+ Secured.new(decryption_key: './spec/spec_key',
12
+ encryption_key: './spec/spec_key.pub')
13
+ end
14
+
15
+ it 'allows strings to be cast from the user' do
16
+ json_string = '{ "hello": "there", "whatever": 3 }'
17
+ secured = subject.cast(json_string)
18
+
19
+ expect(secured).to eql('hello' => 'there', 'whatever' => 3)
20
+ end
21
+
22
+ it 'allows hashes to be cast from a user' do
23
+ json_hash = { 'hello' => 'there', 'whatever' => 3 }
24
+ secured = subject.cast(json_hash)
25
+
26
+ expect(secured).to eql('hello' => 'there', 'whatever' => 3)
27
+ end
28
+
29
+ it 'allows nils to be cast from a user' do
30
+ secured = subject.cast(nil)
31
+
32
+ expect(secured).to be_nil
33
+ end
34
+
35
+ it 'fails if passed something that it cannot be cast' do
36
+ expect { subject.cast(3) }.to \
37
+ raise_error(ArgumentError).
38
+ with_message('Any attributes encrypted with Chamber must ' \
39
+ 'be either a Hash or a valid JSON string')
40
+ end
41
+
42
+ it 'can deserialize a hash' do
43
+ json_string = '{' \
44
+ '"_secure_hello":"cpsTajQ/28E0YLQBpJ2tORnLSc6wliCqrmMzU0QfQZJlUWf' \
45
+ 'Q1yuev2xLsX56o5QkuJiqaspH9W68qXDC17UqcV0pB0y75d' \
46
+ '6ttQZbk3p9QbYgWGZOVlHEA8eJIqDUzisShrrOo+nSin6QK' \
47
+ 'UqizSjqhQC3Ii7CjTpMOK5RVc2y34vsVvYoJaqz5IYUEatA' \
48
+ 'XxzHsQ5tkcqy++a9LTJVFOt+ug+mTCstNJHW2sUK9L1XrbD' \
49
+ '2+KwUNkImCbhl6qeA+4CeVXMFgcpxjaawg5cQCgfSPj8gSy' \
50
+ 'pisbID59P0QVXRDQTdncrRv7q16RLmTqKI0xhNGevreFkNG' \
51
+ 'LAtSQjFRYfAQA==",' \
52
+ '"whatever":3' \
53
+ '}'
54
+ secured = subject.deserialize(json_string)
55
+
56
+ expect(secured).to eql('_secure_hello' => 'there', 'whatever' => 3)
57
+ end
58
+
59
+ # rubocop:disable Metrics/LineLength
60
+ it 'can serialize a hash' do
61
+ json_hash = { '_secure_hello' => 'there', 'whatever' => 3 }
62
+ secured = subject.serialize(json_hash)
63
+
64
+ expect(secured).to be_a String
65
+ expect(secured).to match(/{\"_secure_hello\":\"#{BASE64_STRING_PATTERN}\",\"whatever\":3}/)
66
+ end
67
+ # rubocop:enable Metrics/LineLength
68
+ end
69
+ end
70
+ end
@@ -3,7 +3,6 @@ require 'rspectacular'
3
3
  require 'chamber'
4
4
  require 'fileutils'
5
5
 
6
- # rubocop:disable Metrics/LineLength
7
6
  FileUtils.mkdir_p '/tmp/chamber/settings' unless File.exist? '/tmp/chamber/settings'
8
7
 
9
8
  File.open('/tmp/chamber/settings.yml', 'w+') do |file|
@@ -313,4 +312,3 @@ describe 'Chamber' do
313
312
  expect(Chamber.test.my_encrpyted_setting).to eql 'hello'
314
313
  end
315
314
  end
316
- # rubocop:enable Metrics/LineLength
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chamber
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.1
4
+ version: 2.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thekompanee
@@ -34,7 +34,7 @@ cert_chain:
34
34
  QwSfDGz6+zsImi5N3UT71+mk7YcviQSgvMRl3VkAv8MZ6wcJ5SQRpf9w0OeFH6Ln
35
35
  nNbCoHiYeXX/lz/M6AIbxDIZZTwxcyvF7bdrQ2fbH5MsfQ==
36
36
  -----END CERTIFICATE-----
37
- date: 2016-08-23 00:00:00.000000000 Z
37
+ date: 2017-02-04 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: thor
@@ -92,6 +92,34 @@ dependencies:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
94
  version: '0.46'
95
+ - !ruby/object:Gem::Dependency
96
+ name: activemodel
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '5.0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '5.0'
109
+ - !ruby/object:Gem::Dependency
110
+ name: activesupport
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '5.0'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '5.0'
95
123
  description: "\n Chamber lets you source your Settings from
96
124
  an arbitrary number of YAML files and\n provides a simple
97
125
  mechanism for overriding settings from the ENV, which is\n friendly
@@ -149,6 +177,7 @@ files:
149
177
  - lib/chamber/rails/railtie.rb
150
178
  - lib/chamber/rubinius_fix.rb
151
179
  - lib/chamber/settings.rb
180
+ - lib/chamber/types/secured.rb
152
181
  - lib/chamber/version.rb
153
182
  - spec/fixtures/settings.yml
154
183
  - spec/lib/chamber/commands/files_spec.rb
@@ -172,6 +201,7 @@ files:
172
201
  - spec/lib/chamber/filters/translate_secure_keys_filter_spec.rb
173
202
  - spec/lib/chamber/namespace_set_spec.rb
174
203
  - spec/lib/chamber/settings_spec.rb
204
+ - spec/lib/chamber/types/secured_spec.rb
175
205
  - spec/lib/chamber_spec.rb
176
206
  - spec/rails-2-test/config.ru
177
207
  - spec/rails-2-test/config/application.rb
@@ -209,7 +239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
209
239
  version: '0'
210
240
  requirements: []
211
241
  rubyforge_project:
212
- rubygems_version: 2.5.1
242
+ rubygems_version: 2.6.8
213
243
  signing_key:
214
244
  specification_version: 4
215
245
  summary: A surprisingly configurable convention-based approach to managing your application's
@@ -237,6 +267,7 @@ test_files:
237
267
  - spec/lib/chamber/filters/translate_secure_keys_filter_spec.rb
238
268
  - spec/lib/chamber/namespace_set_spec.rb
239
269
  - spec/lib/chamber/settings_spec.rb
270
+ - spec/lib/chamber/types/secured_spec.rb
240
271
  - spec/lib/chamber_spec.rb
241
272
  - spec/rails-2-test/config/application.rb
242
273
  - spec/rails-2-test/config.ru
@@ -252,4 +283,3 @@ test_files:
252
283
  - spec/rails-engine-test/spec/dummy/script/rails
253
284
  - spec/spec_key
254
285
  - spec/spec_key.pub
255
- has_rdoc:
metadata.gz.sig CHANGED
Binary file