chamber 2.12.3 → 2.14.1
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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +101 -26
- data/lib/chamber.rb +82 -10
- data/lib/chamber/adapters/cloud/circle_ci.rb +85 -0
- data/lib/chamber/adapters/cloud/heroku.rb +74 -0
- data/lib/chamber/binary/circle_ci.rb +122 -0
- data/lib/chamber/binary/heroku.rb +45 -16
- data/lib/chamber/binary/runner.rb +42 -26
- data/lib/chamber/binary/travis.rb +5 -3
- data/lib/chamber/commands/base.rb +10 -16
- data/lib/chamber/commands/cloud/base.rb +35 -0
- data/lib/chamber/commands/{heroku → cloud}/clear.rb +6 -8
- data/lib/chamber/commands/cloud/compare.rb +26 -0
- data/lib/chamber/commands/cloud/pull.rb +29 -0
- data/lib/chamber/commands/cloud/push.rb +44 -0
- data/lib/chamber/commands/comparable.rb +2 -2
- data/lib/chamber/commands/compare.rb +6 -9
- data/lib/chamber/commands/initialize.rb +26 -22
- data/lib/chamber/commands/securable.rb +10 -10
- data/lib/chamber/commands/secure.rb +2 -2
- data/lib/chamber/commands/show.rb +8 -8
- data/lib/chamber/commands/sign.rb +2 -2
- data/lib/chamber/commands/verify.rb +2 -2
- data/lib/chamber/configuration.rb +8 -3
- data/lib/chamber/context_resolver.rb +16 -7
- data/lib/chamber/encryption_methods/ssl.rb +21 -12
- data/lib/chamber/file.rb +22 -20
- data/lib/chamber/file_set.rb +21 -11
- data/lib/chamber/files/signature.rb +31 -23
- data/lib/chamber/filters/decryption_filter.rb +13 -11
- data/lib/chamber/filters/encryption_filter.rb +17 -8
- data/lib/chamber/filters/environment_filter.rb +12 -14
- data/lib/chamber/filters/failed_decryption_filter.rb +6 -6
- data/lib/chamber/filters/insecure_filter.rb +12 -3
- data/lib/chamber/filters/namespace_filter.rb +5 -5
- data/lib/chamber/filters/secure_filter.rb +5 -5
- data/lib/chamber/filters/translate_secure_keys_filter.rb +5 -5
- data/lib/chamber/instance.rb +54 -30
- data/lib/chamber/integrations/rails.rb +1 -1
- data/lib/chamber/integrations/sinatra.rb +6 -6
- data/lib/chamber/key_pair.rb +8 -8
- data/lib/chamber/keys/base.rb +35 -41
- data/lib/chamber/keys/decryption.rb +8 -14
- data/lib/chamber/keys/encryption.rb +8 -14
- data/lib/chamber/namespace_set.rb +2 -4
- data/lib/chamber/settings.rb +86 -56
- data/lib/chamber/types/secured.rb +8 -10
- data/lib/chamber/version.rb +1 -1
- data/templates/settings.yml +2 -0
- metadata +51 -41
- metadata.gz.sig +0 -0
- data/lib/chamber/commands/heroku.rb +0 -31
- data/lib/chamber/commands/heroku/compare.rb +0 -33
- data/lib/chamber/commands/heroku/pull.rb +0 -30
- data/lib/chamber/commands/heroku/push.rb +0 -27
@@ -16,12 +16,12 @@ module Sinatra
|
|
16
16
|
end
|
17
17
|
|
18
18
|
Chamber.load(
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
basepath: root,
|
20
|
+
namespaces: {
|
21
|
+
environment: -> { env },
|
22
|
+
hostname: -> { Socket.gethostname },
|
23
|
+
},
|
24
|
+
)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
data/lib/chamber/key_pair.rb
CHANGED
@@ -9,10 +9,10 @@ class KeyPair
|
|
9
9
|
:namespace,
|
10
10
|
:passphrase
|
11
11
|
|
12
|
-
def initialize(
|
13
|
-
self.namespace =
|
14
|
-
self.passphrase =
|
15
|
-
self.key_file_path = Pathname.new(
|
12
|
+
def initialize(key_file_path:, namespace: nil, passphrase: ::SecureRandom.uuid)
|
13
|
+
self.namespace = namespace
|
14
|
+
self.passphrase = passphrase
|
15
|
+
self.key_file_path = Pathname.new(key_file_path)
|
16
16
|
end
|
17
17
|
|
18
18
|
def encrypted_private_key_passphrase_filepath
|
@@ -77,10 +77,10 @@ class KeyPair
|
|
77
77
|
def base_key_filename
|
78
78
|
@base_key_filename ||= [
|
79
79
|
'.chamber',
|
80
|
-
namespace,
|
81
|
-
]
|
82
|
-
compact
|
83
|
-
join('.')
|
80
|
+
namespace ? namespace.tr('-.', '') : nil,
|
81
|
+
]
|
82
|
+
.compact
|
83
|
+
.join('.')
|
84
84
|
end
|
85
85
|
end
|
86
86
|
end
|
data/lib/chamber/keys/base.rb
CHANGED
@@ -3,73 +3,67 @@
|
|
3
3
|
module Chamber
|
4
4
|
module Keys
|
5
5
|
class Base
|
6
|
-
def self.resolve(
|
7
|
-
new(
|
6
|
+
def self.resolve(**args)
|
7
|
+
new(**args).resolve
|
8
8
|
end
|
9
9
|
|
10
10
|
attr_accessor :rootpath
|
11
11
|
attr_reader :filenames,
|
12
12
|
:namespaces
|
13
13
|
|
14
|
-
def initialize(
|
15
|
-
self.rootpath = Pathname.new(
|
16
|
-
self.namespaces =
|
17
|
-
self.filenames =
|
14
|
+
def initialize(rootpath:, namespaces:, filenames: nil)
|
15
|
+
self.rootpath = Pathname.new(rootpath)
|
16
|
+
self.namespaces = namespaces
|
17
|
+
self.filenames = filenames
|
18
18
|
end
|
19
19
|
|
20
20
|
def resolve
|
21
|
-
|
22
|
-
namespace =
|
23
|
-
value =
|
24
|
-
key_from_environment_variable(filename)
|
21
|
+
key_paths.each_with_object({}) do |path, memo|
|
22
|
+
namespace = namespace_from_path(path) || '__default'
|
23
|
+
value = path.readable? ? path.read : ENV[environment_variable_from_path(path)]
|
25
24
|
|
26
25
|
memo[namespace.downcase.to_sym] = value if value
|
27
26
|
end
|
28
27
|
end
|
29
28
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
def as_environment_variables
|
30
|
+
key_paths.select(&:readable?).each_with_object({}) do |path, memo|
|
31
|
+
memo[environment_variable_from_path(path)] = path.read
|
32
|
+
end
|
33
|
+
end
|
35
34
|
|
36
|
-
|
35
|
+
private
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
).
|
42
|
-
uniq
|
43
|
-
end
|
37
|
+
def key_paths
|
38
|
+
@key_paths = (filenames.any? ? filenames : [default_key_file_path]) +
|
39
|
+
namespaces.map { |n| namespace_to_key_path(n) }
|
44
40
|
end
|
45
41
|
|
46
|
-
|
42
|
+
# rubocop:disable Performance/ChainArrayAllocation
|
43
|
+
def filenames=(other)
|
44
|
+
@filenames = Array(other)
|
45
|
+
.map { |o| Pathname.new(o) }
|
46
|
+
.compact
|
47
|
+
end
|
48
|
+
# rubocop:enable Performance/ChainArrayAllocation
|
47
49
|
|
48
50
|
def namespaces=(other)
|
49
|
-
@namespaces
|
50
|
-
keys = if other.respond_to?(:keys)
|
51
|
-
other.keys.map(&:to_s)
|
52
|
-
else
|
53
|
-
other
|
54
|
-
end
|
55
|
-
|
56
|
-
keys + %w{signature}
|
57
|
-
end
|
51
|
+
@namespaces = other + %w{signature}
|
58
52
|
end
|
59
53
|
|
60
|
-
def
|
61
|
-
|
54
|
+
def namespace_from_path(path)
|
55
|
+
path
|
56
|
+
.basename
|
57
|
+
.to_s
|
58
|
+
.match(self.class::NAMESPACE_PATTERN) { |m| m[1].upcase }
|
62
59
|
end
|
63
60
|
|
64
|
-
def
|
65
|
-
|
61
|
+
def namespace_to_key_path(namespace)
|
62
|
+
rootpath + ".chamber.#{namespace.to_s.tr('.-', '')}#{key_filename_extension}"
|
66
63
|
end
|
67
64
|
|
68
|
-
def
|
69
|
-
|
70
|
-
basename.
|
71
|
-
to_s.
|
72
|
-
match(self.class::NAMESPACE_PATTERN) { |m| m[1].upcase }
|
65
|
+
def default_key_file_path
|
66
|
+
Pathname.new(rootpath + ".chamber#{key_filename_extension}")
|
73
67
|
end
|
74
68
|
end
|
75
69
|
end
|
@@ -13,28 +13,22 @@ class Decryption < Chamber::Keys::Base
|
|
13
13
|
(\w+) # Namespace
|
14
14
|
\.pem # Extension
|
15
15
|
\z # End of Filename
|
16
|
-
/x
|
16
|
+
/x.freeze
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
-
def
|
20
|
+
def environment_variable_from_path(path)
|
21
21
|
[
|
22
22
|
'CHAMBER',
|
23
|
-
|
23
|
+
namespace_from_path(path),
|
24
24
|
'KEY',
|
25
|
-
]
|
26
|
-
compact
|
27
|
-
join('_')
|
25
|
+
]
|
26
|
+
.compact
|
27
|
+
.join('_')
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
|
32
|
-
rootpath + ".chamber.#{namespace}.pem"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def default_key_file_path
|
37
|
-
Pathname.new(rootpath + '.chamber.pem')
|
30
|
+
def key_filename_extension
|
31
|
+
'.pem'
|
38
32
|
end
|
39
33
|
end
|
40
34
|
end
|
@@ -13,28 +13,22 @@ class Encryption < Chamber::Keys::Base
|
|
13
13
|
(\w+) # Namespace
|
14
14
|
\.pub\.pem # Extension
|
15
15
|
\z # End of Filename
|
16
|
-
/x
|
16
|
+
/x.freeze
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
-
def
|
20
|
+
def environment_variable_from_path(path)
|
21
21
|
[
|
22
22
|
'CHAMBER',
|
23
|
-
|
23
|
+
namespace_from_path(path),
|
24
24
|
'PUBLIC_KEY',
|
25
|
-
]
|
26
|
-
compact
|
27
|
-
join('_')
|
25
|
+
]
|
26
|
+
.compact
|
27
|
+
.join('_')
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
|
32
|
-
rootpath + ".chamber.#{namespace}.pub.pem"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def default_key_file_path
|
37
|
-
Pathname.new(rootpath + '.chamber.pub.pem')
|
30
|
+
def key_filename_extension
|
31
|
+
'.pub.pem'
|
38
32
|
end
|
39
33
|
end
|
40
34
|
end
|
@@ -71,10 +71,8 @@ class NamespaceSet
|
|
71
71
|
# Internal: Iterates over each namespace value and allows it to be used in
|
72
72
|
# a block.
|
73
73
|
#
|
74
|
-
def each
|
75
|
-
namespaces.each
|
76
|
-
yield namespace
|
77
|
-
end
|
74
|
+
def each(&block)
|
75
|
+
namespaces.each(&block)
|
78
76
|
end
|
79
77
|
|
80
78
|
###
|
data/lib/chamber/settings.rb
CHANGED
@@ -16,29 +16,40 @@ require 'chamber/filters/failed_decryption_filter'
|
|
16
16
|
#
|
17
17
|
module Chamber
|
18
18
|
class Settings
|
19
|
-
attr_accessor :
|
20
|
-
:post_filters,
|
19
|
+
attr_accessor :decryption_keys,
|
21
20
|
:encryption_keys,
|
22
|
-
:
|
21
|
+
:post_filters,
|
22
|
+
:pre_filters,
|
23
|
+
:secure_key_prefix
|
23
24
|
attr_reader :namespaces
|
24
25
|
|
25
|
-
# rubocop:disable Metrics/
|
26
|
-
def initialize(
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
26
|
+
# rubocop:disable Metrics/ParameterLists
|
27
|
+
def initialize(
|
28
|
+
decryption_keys: {},
|
29
|
+
encryption_keys: {},
|
30
|
+
namespaces: [],
|
31
|
+
pre_filters: [
|
32
|
+
Filters::NamespaceFilter,
|
33
|
+
],
|
34
|
+
post_filters: [
|
35
|
+
Filters::DecryptionFilter,
|
36
|
+
Filters::EnvironmentFilter,
|
37
|
+
Filters::FailedDecryptionFilter,
|
38
|
+
Filters::TranslateSecureKeysFilter,
|
39
|
+
],
|
40
|
+
secure_key_prefix: '_secure_',
|
41
|
+
settings: {},
|
42
|
+
**_args
|
43
|
+
)
|
44
|
+
self.decryption_keys = decryption_keys
|
45
|
+
self.encryption_keys = encryption_keys
|
46
|
+
self.namespaces = namespaces
|
47
|
+
self.post_filters = post_filters
|
48
|
+
self.pre_filters = pre_filters
|
49
|
+
self.raw_data = settings
|
50
|
+
self.secure_key_prefix = secure_key_prefix
|
40
51
|
end
|
41
|
-
# rubocop:enable Metrics/
|
52
|
+
# rubocop:enable Metrics/ParameterLists
|
42
53
|
|
43
54
|
###
|
44
55
|
# Internal: Converts a Settings object into a hash that is compatible as an
|
@@ -79,15 +90,11 @@ class Settings
|
|
79
90
|
# } ).to_s
|
80
91
|
# # => 'MY_KEY="my value" MY_OTHER_KEY="my other value"'
|
81
92
|
#
|
82
|
-
def to_s(
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
concatenated_name_hash = to_concatenated_name_hash(hierarchical_separator)
|
89
|
-
|
90
|
-
pairs = concatenated_name_hash.to_a.map do |key, value|
|
93
|
+
def to_s(hierarchical_separator: '_',
|
94
|
+
pair_separator: ' ',
|
95
|
+
value_surrounder: '"',
|
96
|
+
name_value_separator: '=')
|
97
|
+
pairs = to_concatenated_name_hash(hierarchical_separator).to_a.map do |key, value|
|
91
98
|
"#{key.upcase}#{name_value_separator}#{value_surrounder}#{value}#{value_surrounder}"
|
92
99
|
end
|
93
100
|
|
@@ -182,20 +189,21 @@ class Settings
|
|
182
189
|
# Returns a new Settings object
|
183
190
|
#
|
184
191
|
def merge(other)
|
185
|
-
other_settings =
|
192
|
+
other_settings = case other
|
193
|
+
when Settings
|
186
194
|
other
|
187
|
-
|
195
|
+
when Hash
|
188
196
|
Settings.new(settings: other)
|
189
197
|
end
|
190
198
|
|
191
|
-
# rubocop:disable
|
199
|
+
# rubocop:disable Layout/LineLength
|
192
200
|
Settings.new(
|
193
201
|
encryption_keys: encryption_keys.any? ? encryption_keys : other_settings.encryption_keys,
|
194
202
|
decryption_keys: decryption_keys.any? ? decryption_keys : other_settings.decryption_keys,
|
195
203
|
namespaces: (namespaces + other_settings.namespaces),
|
196
204
|
settings: raw_data.merge(other_settings.raw_data),
|
197
205
|
)
|
198
|
-
# rubocop:enable
|
206
|
+
# rubocop:enable Layout/LineLength
|
199
207
|
end
|
200
208
|
|
201
209
|
###
|
@@ -219,33 +227,59 @@ class Settings
|
|
219
227
|
namespaces == other.namespaces
|
220
228
|
end
|
221
229
|
|
230
|
+
def [](key)
|
231
|
+
warn "WARNING: Bracket access will require strings instead of symbols in Chamber 3.0. You attempted to access the '#{key}' setting. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#removal-of-bracket-indifferent-access for full details." if key.is_a?(::Symbol) # rubocop:disable Layout/LineLength
|
232
|
+
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." unless data.has_key?(key) # rubocop:disable Layout/LineLength
|
233
|
+
|
234
|
+
data.[](key)
|
235
|
+
end
|
236
|
+
|
237
|
+
def dig!(*args)
|
238
|
+
args.inject(data) do |data_value, bracket_value|
|
239
|
+
key = bracket_value.is_a?(::Symbol) ? bracket_value.to_s : bracket_value
|
240
|
+
|
241
|
+
data_value.fetch(key)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def dig(*args)
|
246
|
+
dig!(*args)
|
247
|
+
rescue ::KeyError, ::IndexError # rubocop:disable Lint/ShadowedException
|
248
|
+
nil
|
249
|
+
end
|
250
|
+
|
222
251
|
def securable
|
223
|
-
Settings.new(metadata.merge(
|
224
|
-
|
225
|
-
|
226
|
-
|
252
|
+
Settings.new(**metadata.merge(
|
253
|
+
settings: raw_data,
|
254
|
+
pre_filters: [Filters::SecureFilter],
|
255
|
+
))
|
227
256
|
end
|
228
257
|
|
229
258
|
def secure
|
230
|
-
Settings.new(metadata.merge(
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
259
|
+
Settings.new(**metadata.merge(
|
260
|
+
settings: raw_data,
|
261
|
+
pre_filters: [Filters::EncryptionFilter],
|
262
|
+
post_filters: [Filters::TranslateSecureKeysFilter],
|
263
|
+
))
|
235
264
|
end
|
236
265
|
|
237
266
|
def insecure
|
238
|
-
Settings.new(metadata.merge(
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
267
|
+
Settings.new(**metadata.merge(
|
268
|
+
settings: raw_data,
|
269
|
+
pre_filters: [Filters::InsecureFilter],
|
270
|
+
post_filters: [Filters::TranslateSecureKeysFilter],
|
271
|
+
))
|
243
272
|
end
|
244
273
|
|
245
274
|
def method_missing(name, *args)
|
246
|
-
|
275
|
+
if data.respond_to?(name)
|
276
|
+
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." # rubocop:disable Layout/LineLength
|
277
|
+
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." if name.end_with?('?') # rubocop:disable Layout/LineLength
|
247
278
|
|
248
|
-
|
279
|
+
data.public_send(name, *args)
|
280
|
+
else
|
281
|
+
super
|
282
|
+
end
|
249
283
|
end
|
250
284
|
|
251
285
|
def respond_to_missing?(name, include_private = false)
|
@@ -262,24 +296,20 @@ class Settings
|
|
262
296
|
@namespaces = NamespaceSet.new(raw_namespaces)
|
263
297
|
end
|
264
298
|
|
299
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
265
300
|
def raw_data
|
266
301
|
@filtered_raw_data ||= pre_filters.inject(@raw_data) do |filtered_data, filter|
|
267
|
-
filter.execute({ data: filtered_data }.
|
268
|
-
merge(metadata))
|
302
|
+
filter.execute(**{ data: filtered_data }.merge(metadata))
|
269
303
|
end
|
270
304
|
end
|
305
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
271
306
|
|
272
307
|
def data
|
273
308
|
@data ||= post_filters.inject(raw_data) do |filtered_data, filter|
|
274
|
-
filter.execute({ data: filtered_data }.
|
275
|
-
merge(metadata))
|
309
|
+
filter.execute(**{ data: filtered_data }.merge(metadata))
|
276
310
|
end
|
277
311
|
end
|
278
312
|
|
279
|
-
def secure_key_prefix
|
280
|
-
'_secure_'
|
281
|
-
end
|
282
|
-
|
283
313
|
def metadata
|
284
314
|
{
|
285
315
|
decryption_keys: decryption_keys,
|