chamber 2.14.3 → 3.0.0rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/chamber/binary/circle_ci.rb +0 -1
- data/lib/chamber/binary/heroku.rb +0 -1
- data/lib/chamber/binary/runner.rb +0 -1
- data/lib/chamber/binary/travis.rb +0 -1
- data/lib/chamber/commands/initialize.rb +1 -1
- data/lib/chamber/encryption_methods/public_key.rb +26 -40
- data/lib/chamber/encryption_methods/ssl.rb +33 -51
- data/lib/chamber/errors/disallowed_class.rb +8 -0
- data/lib/chamber/file.rb +10 -22
- data/lib/chamber/files/signature.rb +6 -6
- data/lib/chamber/filters/decryption_filter.rb +9 -11
- data/lib/chamber/filters/encryption_filter.rb +8 -6
- data/lib/chamber/filters/environment_filter.rb +6 -7
- data/lib/chamber/filters/failed_decryption_filter.rb +4 -1
- data/lib/chamber/filters/insecure_filter.rb +1 -2
- data/lib/chamber/filters/namespace_filter.rb +11 -9
- data/lib/chamber/filters/secure_filter.rb +5 -3
- data/lib/chamber/filters/translate_secure_keys_filter.rb +5 -3
- data/lib/chamber/instance.rb +0 -10
- data/lib/chamber/refinements/deep_dup.rb +34 -0
- data/lib/chamber/refinements/enumerable.rb +1 -2
- data/lib/chamber/refinements/hash.rb +25 -0
- data/lib/chamber/settings.rb +15 -32
- data/lib/chamber/types/secured.rb +5 -5
- data/lib/chamber/version.rb +1 -1
- data/lib/chamber.rb +0 -16
- data.tar.gz.sig +0 -0
- metadata +9 -21
- metadata.gz.sig +0 -0
- data/lib/chamber/core_ext/hash.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9de7c74ea902d381006bd6b5f05bae3680d1beef940ae75e483f30c923bc310f
|
4
|
+
data.tar.gz: b6f45eb5b668a5964e898ffb4caa5b9a3e9bc227736dd0e687e257cff0c99f84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1ab7fedfaf6cb26ab3e97402966368f3e686751ca76e441a7d9db64b7fe354a289ac4ac330cac806fb7960f3b4750c1ce4f7799e548c4f0f549ee57826e8552
|
7
|
+
data.tar.gz: 64cfa0683ca78d71cd620e38e60c4d2c25683c5217d74858995b2ee65eda704f7d2aca9395451ac743424bd75b8974ee088ed3563e192be5ab057f49ad458165
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -194,7 +194,7 @@ class Initialize < Chamber::Commands::Base
|
|
194
194
|
.chamber*.enc.pass
|
195
195
|
!.chamber*.pub.pem
|
196
196
|
}.each do |pattern|
|
197
|
-
unless gitignore_contents
|
197
|
+
unless gitignore_contents&.match?(Regexp.new(Regexp.escape(pattern)))
|
198
198
|
shell.append_to_file gitignore_filepath, "#{pattern}\n"
|
199
199
|
end
|
200
200
|
end
|
@@ -2,55 +2,41 @@
|
|
2
2
|
|
3
3
|
require 'base64'
|
4
4
|
|
5
|
+
require 'chamber/errors/disallowed_class'
|
6
|
+
|
5
7
|
module Chamber
|
6
8
|
module EncryptionMethods
|
7
9
|
class PublicKey
|
8
|
-
def self.encrypt(
|
10
|
+
def self.encrypt(_settings_key, value, encryption_key)
|
9
11
|
value = YAML.dump(value)
|
10
12
|
encrypted_string = encryption_key.public_encrypt(value)
|
11
13
|
|
12
14
|
Base64.strict_encode64(encrypted_string)
|
13
15
|
end
|
14
16
|
|
15
|
-
def self.decrypt(
|
16
|
-
if decryption_key.nil?
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
#{error.message}
|
40
|
-
|
41
|
-
Called from: '#{caller.to_a[8]}'
|
42
|
-
HEREDOC
|
43
|
-
|
44
|
-
if YAML.respond_to?(:unsafe_load)
|
45
|
-
YAML.unsafe_load(unencrypted_value)
|
46
|
-
else
|
47
|
-
YAML.load(unencrypted_value)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
rescue TypeError
|
51
|
-
unencrypted_value
|
52
|
-
end
|
53
|
-
end
|
17
|
+
def self.decrypt(_settings_key, value, decryption_key)
|
18
|
+
return value if decryption_key.nil?
|
19
|
+
|
20
|
+
decoded_string = ::Base64.strict_decode64(value)
|
21
|
+
unencrypted_value = decryption_key.private_decrypt(decoded_string)
|
22
|
+
|
23
|
+
::YAML.safe_load(unencrypted_value,
|
24
|
+
aliases: true,
|
25
|
+
permitted_classes: [
|
26
|
+
::Date,
|
27
|
+
::Time,
|
28
|
+
::Regexp,
|
29
|
+
])
|
30
|
+
rescue ::Psych::DisallowedClass => error
|
31
|
+
raise ::Chamber::Errors::DisallowedClass, <<~HEREDOC
|
32
|
+
#{error.message}
|
33
|
+
|
34
|
+
You attempted to load a class instance via your Chamber settings that is not allowed.
|
35
|
+
|
36
|
+
See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#limiting-complex-classes for full details.
|
37
|
+
HEREDOC
|
38
|
+
rescue ::TypeError
|
39
|
+
unencrypted_value
|
54
40
|
end
|
55
41
|
end
|
56
42
|
end
|
@@ -16,7 +16,7 @@ class Ssl
|
|
16
16
|
\z
|
17
17
|
/x.freeze
|
18
18
|
|
19
|
-
def self.encrypt(
|
19
|
+
def self.encrypt(_settings_key, value, encryption_keys) # rubocop:disable Metrics/AbcSize
|
20
20
|
value = YAML.dump(value)
|
21
21
|
cipher = OpenSSL::Cipher.new('AES-128-CBC')
|
22
22
|
cipher.encrypt
|
@@ -35,64 +35,46 @@ class Ssl
|
|
35
35
|
Base64.strict_encode64(encrypted_data)
|
36
36
|
end
|
37
37
|
|
38
|
-
def self.decrypt(
|
39
|
-
if decryption_keys.nil?
|
40
|
-
value
|
41
|
-
else
|
42
|
-
key, iv, decoded_string = value
|
43
|
-
.match(LARGE_DATA_STRING_PATTERN)
|
44
|
-
.captures
|
45
|
-
.map do |part|
|
46
|
-
Base64.strict_decode64(part)
|
47
|
-
end
|
48
|
-
key = decryption_keys.private_decrypt(key)
|
38
|
+
def self.decrypt(_settings_key, value, decryption_keys) # rubocop:disable Metrics/AbcSize
|
39
|
+
return value if decryption_keys.nil?
|
49
40
|
|
50
|
-
|
51
|
-
|
52
|
-
|
41
|
+
key, iv, decoded_string = value
|
42
|
+
.match(LARGE_DATA_STRING_PATTERN)
|
43
|
+
.captures
|
44
|
+
.map do |part|
|
45
|
+
::Base64.strict_decode64(part)
|
46
|
+
end
|
47
|
+
key = decryption_keys.private_decrypt(key)
|
53
48
|
|
54
|
-
|
55
|
-
cipher_dec.iv = iv
|
49
|
+
cipher_dec = ::OpenSSL::Cipher.new('AES-128-CBC')
|
56
50
|
|
57
|
-
|
58
|
-
unencrypted_value = cipher_dec.update(decoded_string) + cipher_dec.final
|
59
|
-
rescue OpenSSL::Cipher::CipherError
|
60
|
-
raise Chamber::Errors::DecryptionFailure,
|
61
|
-
'A decryption error occurred. It was probably due to invalid key data.'
|
62
|
-
end
|
51
|
+
cipher_dec.decrypt
|
63
52
|
|
64
|
-
|
65
|
-
|
66
|
-
YAML.safe_load(unencrypted_value,
|
67
|
-
aliases: true,
|
68
|
-
permitted_classes: [
|
69
|
-
::Date,
|
70
|
-
::Time,
|
71
|
-
::Regexp,
|
72
|
-
])
|
73
|
-
rescue ::Psych::DisallowedClass => error
|
74
|
-
warn <<-HEREDOC
|
75
|
-
WARNING: Recursive data structures (complex classes) being loaded from Chamber
|
76
|
-
has been deprecated and will be removed in 3.0.
|
53
|
+
cipher_dec.key = key
|
54
|
+
cipher_dec.iv = iv
|
77
55
|
|
78
|
-
|
79
|
-
for full details.
|
56
|
+
unencrypted_value = cipher_dec.update(decoded_string) + cipher_dec.final
|
80
57
|
|
81
|
-
|
58
|
+
::YAML.safe_load(unencrypted_value,
|
59
|
+
aliases: true,
|
60
|
+
permitted_classes: [
|
61
|
+
::Date,
|
62
|
+
::Time,
|
63
|
+
::Regexp,
|
64
|
+
])
|
65
|
+
rescue ::OpenSSL::Cipher::CipherError
|
66
|
+
raise ::Chamber::Errors::DecryptionFailure,
|
67
|
+
'A decryption error occurred. It was probably due to invalid key data.'
|
68
|
+
rescue ::Psych::DisallowedClass => error
|
69
|
+
raise ::Chamber::Errors::DisallowedClass, <<~HEREDOC
|
70
|
+
#{error.message}
|
82
71
|
|
83
|
-
|
84
|
-
HEREDOC
|
72
|
+
You attempted to load a class instance via your Chamber settings that is not allowed.
|
85
73
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
91
|
-
end
|
92
|
-
rescue TypeError
|
93
|
-
unencrypted_value
|
94
|
-
end
|
95
|
-
end
|
74
|
+
See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#limiting-complex-classes for full details.
|
75
|
+
HEREDOC
|
76
|
+
rescue ::TypeError
|
77
|
+
unencrypted_value
|
96
78
|
end
|
97
79
|
end
|
98
80
|
end
|
data/lib/chamber/file.rb
CHANGED
@@ -139,38 +139,26 @@ class File < Pathname
|
|
139
139
|
@secure_prefix_pattern ||= Regexp.escape(secure_prefix)
|
140
140
|
end
|
141
141
|
|
142
|
-
def file_contents_hash
|
142
|
+
def file_contents_hash
|
143
143
|
file_contents = read
|
144
|
-
erb_result = ERB.new(file_contents).result
|
144
|
+
erb_result = ::ERB.new(file_contents).result
|
145
145
|
|
146
|
-
|
147
|
-
YAML.safe_load(erb_result,
|
146
|
+
::YAML.safe_load(erb_result,
|
148
147
|
aliases: true,
|
149
148
|
permitted_classes: [
|
150
149
|
::Date,
|
151
150
|
::Time,
|
152
151
|
::Regexp,
|
153
152
|
]) || {}
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
has been deprecated and will be removed in 3.0.
|
153
|
+
rescue ::Psych::DisallowedClass => error
|
154
|
+
raise ::Chamber::Errors::DisallowedClass, <<~HEREDOC
|
155
|
+
#{error.message}
|
158
156
|
|
159
|
-
|
160
|
-
for full details.
|
157
|
+
You attempted to load a class instance via your Chamber settings that is not allowed.
|
161
158
|
|
162
|
-
#
|
163
|
-
|
164
|
-
|
165
|
-
HEREDOC
|
166
|
-
|
167
|
-
if YAML.respond_to?(:unsafe_load)
|
168
|
-
YAML.unsafe_load(erb_result) || {}
|
169
|
-
else
|
170
|
-
YAML.load(erb_result) || {}
|
171
|
-
end
|
172
|
-
end
|
173
|
-
rescue Errno::ENOENT
|
159
|
+
See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#limiting-complex-classes for full details.
|
160
|
+
HEREDOC
|
161
|
+
rescue ::Errno::ENOENT
|
174
162
|
{}
|
175
163
|
end
|
176
164
|
end
|
@@ -42,13 +42,13 @@ class Signature
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def write
|
45
|
-
signature_filename.write(
|
46
|
-
Signed By: #{signature_name}
|
47
|
-
Signed At: #{Time.now.utc.iso8601}
|
45
|
+
signature_filename.write(<<~HEREDOC, 0, mode: 'w+')
|
46
|
+
Signed By: #{signature_name}
|
47
|
+
Signed At: #{Time.now.utc.iso8601}
|
48
48
|
|
49
|
-
#{SIGNATURE_HEADER}
|
50
|
-
#{encoded_signature}
|
51
|
-
#{SIGNATURE_FOOTER}
|
49
|
+
#{SIGNATURE_HEADER}
|
50
|
+
#{encoded_signature}
|
51
|
+
#{SIGNATURE_FOOTER}
|
52
52
|
HEREDOC
|
53
53
|
end
|
54
54
|
|
@@ -2,16 +2,18 @@
|
|
2
2
|
|
3
3
|
require 'openssl'
|
4
4
|
require 'base64'
|
5
|
-
require 'hashie/mash'
|
6
5
|
require 'yaml'
|
7
6
|
require 'chamber/encryption_methods/public_key'
|
8
7
|
require 'chamber/encryption_methods/ssl'
|
9
8
|
require 'chamber/encryption_methods/none'
|
10
9
|
require 'chamber/errors/decryption_failure'
|
10
|
+
require 'chamber/refinements/deep_dup'
|
11
11
|
|
12
12
|
module Chamber
|
13
13
|
module Filters
|
14
14
|
class DecryptionFilter
|
15
|
+
using ::Chamber::Refinements::DeepDup
|
16
|
+
|
15
17
|
BASE64_STRING_PATTERN = %r{\A[A-Za-z0-9+/]{342}==\z}.freeze
|
16
18
|
LARGE_DATA_STRING_PATTERN = %r{
|
17
19
|
\A # Beginning of String
|
@@ -34,8 +36,8 @@ class DecryptionFilter
|
|
34
36
|
attr_reader :decryption_keys
|
35
37
|
|
36
38
|
def initialize(data:, secure_key_prefix:, decryption_keys: {}, **_args)
|
37
|
-
self.decryption_keys = decryption_keys || {}
|
38
|
-
self.data = data.
|
39
|
+
self.decryption_keys = (decryption_keys || {}).transform_keys(&:to_s)
|
40
|
+
self.data = data.deep_dup
|
39
41
|
self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
|
40
42
|
end
|
41
43
|
|
@@ -46,7 +48,7 @@ class DecryptionFilter
|
|
46
48
|
protected
|
47
49
|
|
48
50
|
def execute(raw_data = data)
|
49
|
-
settings =
|
51
|
+
settings = {}
|
50
52
|
|
51
53
|
raw_data.each_pair do |key, value|
|
52
54
|
settings[key] = if value.respond_to? :each_pair
|
@@ -75,21 +77,17 @@ class DecryptionFilter
|
|
75
77
|
|
76
78
|
private
|
77
79
|
|
78
|
-
# rubocop:disable Style/RedundantBegin
|
79
80
|
def decrypt(key, value)
|
80
81
|
method = decryption_method(value)
|
81
82
|
|
82
83
|
decryption_keys.each do |decryption_key|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
next
|
87
|
-
end
|
84
|
+
return method.decrypt(key, value, decryption_key)
|
85
|
+
rescue OpenSSL::PKey::RSAError
|
86
|
+
next
|
88
87
|
end
|
89
88
|
|
90
89
|
value
|
91
90
|
end
|
92
|
-
# rubocop:enable Style/RedundantBegin
|
93
91
|
|
94
92
|
def decryption_method(value)
|
95
93
|
if value.is_a?(::String)
|
@@ -1,15 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'openssl'
|
4
|
-
require 'hashie/mash'
|
5
4
|
require 'yaml'
|
6
5
|
require 'chamber/encryption_methods/public_key'
|
7
6
|
require 'chamber/encryption_methods/ssl'
|
8
7
|
require 'chamber/encryption_methods/none'
|
8
|
+
require 'chamber/refinements/deep_dup'
|
9
9
|
|
10
10
|
module Chamber
|
11
11
|
module Filters
|
12
12
|
class EncryptionFilter
|
13
|
+
using ::Chamber::Refinements::DeepDup
|
14
|
+
|
13
15
|
BASE64_STRING_PATTERN = %r{\A[A-Za-z0-9+/]{342}==\z}.freeze
|
14
16
|
BASE64_SUBSTRING_PATTERN = %r{[A-Za-z0-9+/#]*={0,2}}.freeze
|
15
17
|
LARGE_DATA_STRING_PATTERN = /
|
@@ -27,8 +29,8 @@ class EncryptionFilter
|
|
27
29
|
attr_reader :encryption_keys
|
28
30
|
|
29
31
|
def initialize(data:, secure_key_prefix:, encryption_keys: {}, **_args)
|
30
|
-
self.encryption_keys = encryption_keys || {}
|
31
|
-
self.data = data.
|
32
|
+
self.encryption_keys = (encryption_keys || {}).transform_keys(&:to_s)
|
33
|
+
self.data = data.deep_dup
|
32
34
|
self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
|
33
35
|
end
|
34
36
|
|
@@ -39,7 +41,7 @@ class EncryptionFilter
|
|
39
41
|
protected
|
40
42
|
|
41
43
|
def execute(raw_data = data, namespace = nil)
|
42
|
-
raw_data.each_with_object(
|
44
|
+
raw_data.each_with_object({}) do |(key, value), settings|
|
43
45
|
settings[key] = if value.respond_to? :each_pair
|
44
46
|
execute(value, namespace || key)
|
45
47
|
elsif key.match(secure_key_token)
|
@@ -51,7 +53,7 @@ class EncryptionFilter
|
|
51
53
|
end
|
52
54
|
|
53
55
|
def encryption_keys=(other)
|
54
|
-
@encryption_keys = other.each_with_object({}) do |(namespace, keyish), memo|
|
56
|
+
@encryption_keys = other.each_with_object({}) do |(namespace, keyish), memo| # rubocop:disable Style/HashTransformValues
|
55
57
|
memo[namespace] = if keyish.is_a?(OpenSSL::PKey::RSA)
|
56
58
|
keyish
|
57
59
|
elsif ::File.readable?(::File.expand_path(keyish))
|
@@ -67,7 +69,7 @@ class EncryptionFilter
|
|
67
69
|
|
68
70
|
def encrypt(namespace, key, value)
|
69
71
|
method = encryption_method(value)
|
70
|
-
encryption_key = encryption_keys[namespace] || encryption_keys[
|
72
|
+
encryption_key = encryption_keys[namespace] || encryption_keys['__default']
|
71
73
|
|
72
74
|
return value unless encryption_key
|
73
75
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'yaml'
|
4
|
-
require 'hashie/mash'
|
5
4
|
|
6
5
|
require 'chamber/errors/environment_conversion'
|
7
6
|
|
@@ -122,7 +121,7 @@ class EnvironmentFilter
|
|
122
121
|
private
|
123
122
|
|
124
123
|
def with_environment(settings, parent_keys, hash_block, value_block)
|
125
|
-
environment_hash =
|
124
|
+
environment_hash = {}
|
126
125
|
|
127
126
|
settings.each_pair do |key, value|
|
128
127
|
environment_key = key.to_s.gsub(secure_key_token, '')
|
@@ -170,13 +169,13 @@ class EnvironmentFilter
|
|
170
169
|
environment_value
|
171
170
|
end
|
172
171
|
rescue ArgumentError
|
173
|
-
raise Chamber::Errors::EnvironmentConversion,
|
174
|
-
We attempted to convert '#{environment_key}' from '#{environment_value}' to a '#{settings_value.class.name}'.
|
172
|
+
raise Chamber::Errors::EnvironmentConversion, <<~HEREDOC
|
173
|
+
We attempted to convert '#{environment_key}' from '#{environment_value}' to a '#{settings_value.class.name}'.
|
175
174
|
|
176
|
-
Unfortunately, this did not go as planned. Please either verify that your value is convertable
|
177
|
-
or change the original YAML value to be something more generic (like a String).
|
175
|
+
Unfortunately, this did not go as planned. Please either verify that your value is convertable
|
176
|
+
or change the original YAML value to be something more generic (like a String).
|
178
177
|
|
179
|
-
For more information, see https://github.com/thekompanee/chamber/wiki/Environment-Variable-Coercions
|
178
|
+
For more information, see https://github.com/thekompanee/chamber/wiki/Environment-Variable-Coercions
|
180
179
|
HEREDOC
|
181
180
|
end
|
182
181
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'chamber/errors/decryption_failure'
|
4
|
+
require 'chamber/refinements/deep_dup'
|
4
5
|
|
5
6
|
module Chamber
|
6
7
|
module Filters
|
7
8
|
class FailedDecryptionFilter
|
9
|
+
using ::Chamber::Refinements::DeepDup
|
10
|
+
|
8
11
|
BASE64_STRING_PATTERN = %r{\A[A-Za-z0-9+/]{342}==\z}.freeze
|
9
12
|
|
10
13
|
def self.execute(**args)
|
@@ -15,7 +18,7 @@ class FailedDecryptionFilter
|
|
15
18
|
:secure_key_token
|
16
19
|
|
17
20
|
def initialize(data:, secure_key_prefix:, **_args)
|
18
|
-
self.data = data.
|
21
|
+
self.data = data.deep_dup
|
19
22
|
self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
|
20
23
|
end
|
21
24
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'hashie/mash'
|
4
3
|
require 'chamber/filters/secure_filter'
|
5
4
|
|
6
5
|
module Chamber
|
@@ -22,7 +21,7 @@ class InsecureFilter < SecureFilter
|
|
22
21
|
|
23
22
|
def execute(raw_data = data) # rubocop:disable Metrics/CyclomaticComplexity
|
24
23
|
securable_settings = super
|
25
|
-
settings =
|
24
|
+
settings = {}
|
26
25
|
|
27
26
|
securable_settings.each_pair do |key, value|
|
28
27
|
value = if value.respond_to? :each_pair
|
@@ -1,10 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'chamber/refinements/deep_dup'
|
4
|
+
require 'chamber/refinements/hash'
|
4
5
|
|
5
6
|
module Chamber
|
6
7
|
module Filters
|
7
8
|
class NamespaceFilter
|
9
|
+
using ::Chamber::Refinements::DeepDup
|
10
|
+
using ::Chamber::Refinements::Hash
|
11
|
+
|
8
12
|
def self.execute(**args)
|
9
13
|
new(**args).__send__(:execute)
|
10
14
|
end
|
@@ -13,26 +17,24 @@ class NamespaceFilter
|
|
13
17
|
:namespaces
|
14
18
|
|
15
19
|
def initialize(data:, namespaces:, **_args)
|
16
|
-
self.data =
|
20
|
+
self.data = data.deep_dup
|
17
21
|
self.namespaces = namespaces
|
18
22
|
end
|
19
23
|
|
20
24
|
protected
|
21
25
|
|
22
26
|
def execute
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
else
|
28
|
-
Hashie::Mash.new(data)
|
27
|
+
return data unless data_is_namespaced?
|
28
|
+
|
29
|
+
namespaces.each_with_object({}) do |namespace, filtered_data|
|
30
|
+
filtered_data.deep_merge!(data[namespace]) if data[namespace]
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
34
|
private
|
33
35
|
|
34
36
|
def data_is_namespaced?
|
35
|
-
@data_is_namespaced ||= data.keys.any? { |key| namespaces.include?
|
37
|
+
@data_is_namespaced ||= data.keys.any? { |key| namespaces.include?(key.to_s) }
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'chamber/refinements/deep_dup'
|
4
4
|
|
5
5
|
module Chamber
|
6
6
|
module Filters
|
7
7
|
class SecureFilter
|
8
|
+
using ::Chamber::Refinements::DeepDup
|
9
|
+
|
8
10
|
def self.execute(**args)
|
9
11
|
new(**args).__send__(:execute)
|
10
12
|
end
|
@@ -13,14 +15,14 @@ class SecureFilter
|
|
13
15
|
:secure_key_token
|
14
16
|
|
15
17
|
def initialize(data:, secure_key_prefix:, **_args)
|
16
|
-
self.data =
|
18
|
+
self.data = data.deep_dup
|
17
19
|
self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
|
18
20
|
end
|
19
21
|
|
20
22
|
protected
|
21
23
|
|
22
24
|
def execute(raw_data = data)
|
23
|
-
settings =
|
25
|
+
settings = {}
|
24
26
|
|
25
27
|
raw_data.each_pair do |key, value|
|
26
28
|
secure_value = if value.respond_to? :each_pair
|
@@ -1,10 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'chamber/refinements/deep_dup'
|
4
4
|
|
5
5
|
module Chamber
|
6
6
|
module Filters
|
7
7
|
class TranslateSecureKeysFilter
|
8
|
+
using ::Chamber::Refinements::DeepDup
|
9
|
+
|
8
10
|
def self.execute(**args)
|
9
11
|
new(**args).__send__(:execute)
|
10
12
|
end
|
@@ -13,14 +15,14 @@ class TranslateSecureKeysFilter
|
|
13
15
|
:secure_key_token
|
14
16
|
|
15
17
|
def initialize(data:, secure_key_prefix:, **_args)
|
16
|
-
self.data = data.
|
18
|
+
self.data = data.deep_dup
|
17
19
|
self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
|
18
20
|
end
|
19
21
|
|
20
22
|
protected
|
21
23
|
|
22
24
|
def execute(raw_data = data)
|
23
|
-
settings =
|
25
|
+
settings = {}
|
24
26
|
|
25
27
|
raw_data.each_pair do |key, value|
|
26
28
|
value = execute(value) if value.respond_to? :each_pair
|
data/lib/chamber/instance.rb
CHANGED
@@ -92,15 +92,5 @@ class Instance
|
|
92
92
|
)
|
93
93
|
.to_hash
|
94
94
|
end
|
95
|
-
|
96
|
-
def method_missing(name, *args)
|
97
|
-
return settings.public_send(name, *args) if settings.respond_to?(name)
|
98
|
-
|
99
|
-
super
|
100
|
-
end
|
101
|
-
|
102
|
-
def respond_to_missing?(name, include_private = false)
|
103
|
-
settings.respond_to?(name, include_private)
|
104
|
-
end
|
105
95
|
end
|
106
96
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Chamber
|
4
|
+
module Refinements
|
5
|
+
module DeepDup
|
6
|
+
refine ::Array do
|
7
|
+
def deep_dup
|
8
|
+
map { |i| i.respond_to?(:deep_dup) ? i.deep_dup : i.dup }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
refine ::Object do
|
13
|
+
def deep_dup
|
14
|
+
dup
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
refine ::Hash do
|
19
|
+
def deep_dup
|
20
|
+
dup.tap do |hash|
|
21
|
+
each_pair do |key, value|
|
22
|
+
if key.frozen? && key.is_a?(::String)
|
23
|
+
hash[key] = value.deep_dup
|
24
|
+
else
|
25
|
+
hash.delete(key)
|
26
|
+
hash[key.deep_dup] = value.deep_dup
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -9,8 +9,7 @@ class Enumerable
|
|
9
9
|
case object
|
10
10
|
when ::Hash
|
11
11
|
object.each do |(key, value)|
|
12
|
-
|
13
|
-
warn "WARNING: Non-String settings keys are deprecated and will be removed in Chamber 3.0. You attempted to access the '#{key}' setting. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#all-settings-keys-are-now-stored-as-strings for full details. Called from: '#{caller.to_a.first}'" unless key == yield(key) # rubocop:disable Layout/LineLength
|
12
|
+
fail ::Chamber::Errors::NonConformingKey unless key == yield(key)
|
14
13
|
|
15
14
|
deep_validate_keys(value, &block)
|
16
15
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Chamber
|
4
|
+
module Refinements
|
5
|
+
module Hash
|
6
|
+
refine ::Hash do
|
7
|
+
def deep_merge(other_hash, &block)
|
8
|
+
dup.deep_merge!(other_hash, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def deep_merge!(other_hash, &block)
|
12
|
+
merge!(other_hash) do |key, this_val, other_val|
|
13
|
+
if this_val.is_a?(::Hash) && other_val.is_a?(::Hash)
|
14
|
+
this_val.deep_merge(other_val, &block)
|
15
|
+
elsif block
|
16
|
+
yield(key, this_val, other_val)
|
17
|
+
else
|
18
|
+
other_val
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/chamber/settings.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'hashie/mash'
|
4
3
|
require 'chamber/namespace_set'
|
5
4
|
require 'chamber/filters/namespace_filter'
|
6
5
|
require 'chamber/filters/encryption_filter'
|
@@ -10,13 +9,18 @@ require 'chamber/filters/secure_filter'
|
|
10
9
|
require 'chamber/filters/translate_secure_keys_filter'
|
11
10
|
require 'chamber/filters/insecure_filter'
|
12
11
|
require 'chamber/filters/failed_decryption_filter'
|
12
|
+
require 'chamber/refinements/deep_dup'
|
13
13
|
require 'chamber/refinements/enumerable'
|
14
|
+
require 'chamber/refinements/hash'
|
14
15
|
|
15
16
|
###
|
16
17
|
# Internal: Represents the base settings storage needed for Chamber.
|
17
18
|
#
|
18
19
|
module Chamber
|
19
20
|
class Settings
|
21
|
+
using ::Chamber::Refinements::Hash
|
22
|
+
using ::Chamber::Refinements::DeepDup
|
23
|
+
|
20
24
|
attr_accessor :decryption_keys,
|
21
25
|
:encryption_keys,
|
22
26
|
:post_filters,
|
@@ -45,12 +49,12 @@ class Settings
|
|
45
49
|
|
46
50
|
::Chamber::Refinements::Enumerable.deep_validate_keys(settings, &:to_s)
|
47
51
|
|
48
|
-
self.decryption_keys = decryption_keys
|
49
|
-
self.encryption_keys = encryption_keys
|
50
|
-
self.namespaces = namespaces
|
52
|
+
self.decryption_keys = (decryption_keys || {}).transform_keys(&:to_s)
|
53
|
+
self.encryption_keys = (encryption_keys || {}).transform_keys(&:to_s)
|
54
|
+
self.namespaces = NamespaceSet.new(namespaces)
|
51
55
|
self.post_filters = post_filters
|
52
56
|
self.pre_filters = pre_filters
|
53
|
-
self.raw_data = settings
|
57
|
+
self.raw_data = settings.deep_dup
|
54
58
|
self.secure_key_prefix = secure_key_prefix
|
55
59
|
end
|
56
60
|
# rubocop:enable Metrics/ParameterLists
|
@@ -113,7 +117,7 @@ class Settings
|
|
113
117
|
# Returns a Hash
|
114
118
|
#
|
115
119
|
def to_hash
|
116
|
-
data.
|
120
|
+
data.deep_dup
|
117
121
|
end
|
118
122
|
|
119
123
|
###
|
@@ -205,7 +209,7 @@ class Settings
|
|
205
209
|
encryption_keys: encryption_keys.any? ? encryption_keys : other_settings.encryption_keys,
|
206
210
|
decryption_keys: decryption_keys.any? ? decryption_keys : other_settings.decryption_keys,
|
207
211
|
namespaces: (namespaces + other_settings.namespaces),
|
208
|
-
settings: raw_data.
|
212
|
+
settings: raw_data.deep_merge(other_settings.raw_data),
|
209
213
|
)
|
210
214
|
# rubocop:enable Layout/LineLength
|
211
215
|
end
|
@@ -232,10 +236,9 @@ class Settings
|
|
232
236
|
end
|
233
237
|
|
234
238
|
def [](key)
|
235
|
-
|
236
|
-
warn "WARNING: Accessing a non-existent key ('#{key}') with brackets will fail in Chamber 3.0. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#bracket-access-now-fails-on-non-existent-keys for full details. Called from: '#{caller.to_a.first}'" unless data.has_key?(key) # rubocop:disable Layout/LineLength
|
239
|
+
fail ::ArgumentError, 'Bracket access with anything other than a String is unsupported.' unless key.is_a?(::String)
|
237
240
|
|
238
|
-
data.
|
241
|
+
data.fetch(key)
|
239
242
|
end
|
240
243
|
|
241
244
|
def dig!(*args)
|
@@ -275,30 +278,10 @@ class Settings
|
|
275
278
|
))
|
276
279
|
end
|
277
280
|
|
278
|
-
def method_missing(name, *args)
|
279
|
-
if data.respond_to?(name)
|
280
|
-
warn "WARNING: Object notation access is deprecated and will be removed in Chamber 3.0. You attempted to access the '#{name}' setting. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#removal-of-object-notation-access for full details. Called from: '#{caller.to_a.first}'" # rubocop:disable Layout/LineLength
|
281
|
-
warn "WARNING: Predicate methods are deprecated and will be removed in Chamber 3.0. You attempted to access the '#{name}' setting. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#removal-of-predicate-accessors for full details. Called from: '#{caller.to_a.first}'" if name.to_s.end_with?('?') # rubocop:disable Layout/LineLength
|
282
|
-
|
283
|
-
data.public_send(name, *args)
|
284
|
-
else
|
285
|
-
super
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
def respond_to_missing?(name, include_private = false)
|
290
|
-
data.respond_to?(name, include_private)
|
291
|
-
end
|
292
|
-
|
293
281
|
protected
|
294
282
|
|
295
|
-
|
296
|
-
|
297
|
-
end
|
298
|
-
|
299
|
-
def namespaces=(raw_namespaces)
|
300
|
-
@namespaces = NamespaceSet.new(raw_namespaces)
|
301
|
-
end
|
283
|
+
attr_writer :namespaces,
|
284
|
+
:raw_data
|
302
285
|
|
303
286
|
# rubocop:disable Naming/MemoizedInstanceVariableName
|
304
287
|
def raw_data
|
@@ -40,7 +40,7 @@ class Secured < CHAMBER_TYPE_VALUE_SUPERCLASS
|
|
40
40
|
when Hash
|
41
41
|
value
|
42
42
|
when String
|
43
|
-
::
|
43
|
+
::JSON.parse(value)
|
44
44
|
when NilClass
|
45
45
|
nil
|
46
46
|
else
|
@@ -63,10 +63,10 @@ class Secured < CHAMBER_TYPE_VALUE_SUPERCLASS
|
|
63
63
|
def serialize(value)
|
64
64
|
fail ArgumentError, 'Any attributes encrypted with Chamber must be a Hash' unless value.is_a?(Hash)
|
65
65
|
|
66
|
-
::
|
67
|
-
Chamber.encrypt(value,
|
68
|
-
|
69
|
-
|
66
|
+
::JSON.dump(
|
67
|
+
::Chamber.encrypt(value,
|
68
|
+
decryption_keys: decryption_keys,
|
69
|
+
encryption_keys: encryption_keys),
|
70
70
|
)
|
71
71
|
end
|
72
72
|
alias type_cast_for_database serialize
|
data/lib/chamber/version.rb
CHANGED
data/lib/chamber.rb
CHANGED
@@ -11,10 +11,6 @@ module Chamber
|
|
11
11
|
self.instance = Instance.new(**args)
|
12
12
|
end
|
13
13
|
|
14
|
-
def env
|
15
|
-
instance.settings
|
16
|
-
end
|
17
|
-
|
18
14
|
def instance
|
19
15
|
@instance ||= Instance.new
|
20
16
|
end
|
@@ -81,29 +77,17 @@ module Chamber
|
|
81
77
|
instance.to_s(**args)
|
82
78
|
end
|
83
79
|
|
84
|
-
def method_missing(name, *args)
|
85
|
-
return instance.public_send(name, *args) if instance.respond_to?(name)
|
86
|
-
|
87
|
-
super
|
88
|
-
end
|
89
|
-
|
90
|
-
def respond_to_missing?(name, include_private = false)
|
91
|
-
instance.respond_to?(name, include_private)
|
92
|
-
end
|
93
|
-
|
94
80
|
module_function :[],
|
95
81
|
:configuration,
|
96
82
|
:decrypt,
|
97
83
|
:dig!,
|
98
84
|
:dig,
|
99
85
|
:encrypt,
|
100
|
-
:env,
|
101
86
|
:filenames,
|
102
87
|
:files,
|
103
88
|
:instance,
|
104
89
|
:instance=,
|
105
90
|
:load,
|
106
|
-
:method_missing,
|
107
91
|
:namespaces,
|
108
92
|
:respond_to_missing?,
|
109
93
|
:secure,
|
data.tar.gz.sig
CHANGED
Binary file
|
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:
|
4
|
+
version: 3.0.0rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thekompanee
|
@@ -38,7 +38,7 @@ cert_chain:
|
|
38
38
|
ZjvLRaDI6IVoq0skZju//VZLiN6slVhAYYQj0uka/T0DZieabVYDcT4BVpa9M7Gz
|
39
39
|
CDW/VDWjvEEbsCIW0oYhtUrkqE8GLIdrpLUjefOERbS5TslD7lG/MH5k
|
40
40
|
-----END CERTIFICATE-----
|
41
|
-
date: 2022-03-
|
41
|
+
date: 2022-03-06 00:00:00.000000000 Z
|
42
42
|
dependencies:
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: thor
|
@@ -60,20 +60,6 @@ dependencies:
|
|
60
60
|
- - "<"
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '2.0'
|
63
|
-
- !ruby/object:Gem::Dependency
|
64
|
-
name: hashie
|
65
|
-
requirement: !ruby/object:Gem::Requirement
|
66
|
-
requirements:
|
67
|
-
- - "~>"
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '3.3'
|
70
|
-
type: :runtime
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
requirements:
|
74
|
-
- - "~>"
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
version: '3.3'
|
77
63
|
- !ruby/object:Gem::Dependency
|
78
64
|
name: rspec
|
79
65
|
requirement: !ruby/object:Gem::Requirement
|
@@ -183,11 +169,11 @@ files:
|
|
183
169
|
- lib/chamber/commands/verify.rb
|
184
170
|
- lib/chamber/configuration.rb
|
185
171
|
- lib/chamber/context_resolver.rb
|
186
|
-
- lib/chamber/core_ext/hash.rb
|
187
172
|
- lib/chamber/encryption_methods/none.rb
|
188
173
|
- lib/chamber/encryption_methods/public_key.rb
|
189
174
|
- lib/chamber/encryption_methods/ssl.rb
|
190
175
|
- lib/chamber/errors/decryption_failure.rb
|
176
|
+
- lib/chamber/errors/disallowed_class.rb
|
191
177
|
- lib/chamber/errors/environment_conversion.rb
|
192
178
|
- lib/chamber/errors/non_conforming_key.rb
|
193
179
|
- lib/chamber/file.rb
|
@@ -210,7 +196,9 @@ files:
|
|
210
196
|
- lib/chamber/keys/encryption.rb
|
211
197
|
- lib/chamber/namespace_set.rb
|
212
198
|
- lib/chamber/rails.rb
|
199
|
+
- lib/chamber/refinements/deep_dup.rb
|
213
200
|
- lib/chamber/refinements/enumerable.rb
|
201
|
+
- lib/chamber/refinements/hash.rb
|
214
202
|
- lib/chamber/rubinius_fix.rb
|
215
203
|
- lib/chamber/settings.rb
|
216
204
|
- lib/chamber/types/secured.rb
|
@@ -235,14 +223,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
235
223
|
requirements:
|
236
224
|
- - ">="
|
237
225
|
- !ruby/object:Gem::Version
|
238
|
-
version: 2.
|
226
|
+
version: 2.7.5
|
239
227
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
240
228
|
requirements:
|
241
|
-
- - "
|
229
|
+
- - ">"
|
242
230
|
- !ruby/object:Gem::Version
|
243
|
-
version:
|
231
|
+
version: 1.3.1
|
244
232
|
requirements: []
|
245
|
-
rubygems_version: 3.1.
|
233
|
+
rubygems_version: 3.1.6
|
246
234
|
signing_key:
|
247
235
|
specification_version: 4
|
248
236
|
summary: A surprisingly configurable convention-based approach to managing your application's
|
metadata.gz.sig
CHANGED
Binary file
|