chamber 2.12.2 → 2.14.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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -2
- data/README.md +101 -26
- data/lib/chamber.rb +72 -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/errors/environment_conversion.rb +8 -0
- 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 +21 -10
- 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 +48 -32
- 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 +58 -54
- data/lib/chamber/types/secured.rb +8 -10
- data/lib/chamber/version.rb +1 -1
- data/templates/settings.yml +2 -0
- metadata +52 -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
|
###
|
@@ -220,26 +228,26 @@ class Settings
|
|
220
228
|
end
|
221
229
|
|
222
230
|
def securable
|
223
|
-
Settings.new(metadata.merge(
|
224
|
-
|
225
|
-
|
226
|
-
|
231
|
+
Settings.new(**metadata.merge(
|
232
|
+
settings: raw_data,
|
233
|
+
pre_filters: [Filters::SecureFilter],
|
234
|
+
))
|
227
235
|
end
|
228
236
|
|
229
237
|
def secure
|
230
|
-
Settings.new(metadata.merge(
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
238
|
+
Settings.new(**metadata.merge(
|
239
|
+
settings: raw_data,
|
240
|
+
pre_filters: [Filters::EncryptionFilter],
|
241
|
+
post_filters: [Filters::TranslateSecureKeysFilter],
|
242
|
+
))
|
235
243
|
end
|
236
244
|
|
237
245
|
def insecure
|
238
|
-
Settings.new(metadata.merge(
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
246
|
+
Settings.new(**metadata.merge(
|
247
|
+
settings: raw_data,
|
248
|
+
pre_filters: [Filters::InsecureFilter],
|
249
|
+
post_filters: [Filters::TranslateSecureKeysFilter],
|
250
|
+
))
|
243
251
|
end
|
244
252
|
|
245
253
|
def method_missing(name, *args)
|
@@ -262,24 +270,20 @@ class Settings
|
|
262
270
|
@namespaces = NamespaceSet.new(raw_namespaces)
|
263
271
|
end
|
264
272
|
|
273
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
265
274
|
def raw_data
|
266
275
|
@filtered_raw_data ||= pre_filters.inject(@raw_data) do |filtered_data, filter|
|
267
|
-
filter.execute({ data: filtered_data }.
|
268
|
-
merge(metadata))
|
276
|
+
filter.execute(**{ data: filtered_data }.merge(metadata))
|
269
277
|
end
|
270
278
|
end
|
279
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
271
280
|
|
272
281
|
def data
|
273
282
|
@data ||= post_filters.inject(raw_data) do |filtered_data, filter|
|
274
|
-
filter.execute({ data: filtered_data }.
|
275
|
-
merge(metadata))
|
283
|
+
filter.execute(**{ data: filtered_data }.merge(metadata))
|
276
284
|
end
|
277
285
|
end
|
278
286
|
|
279
|
-
def secure_key_prefix
|
280
|
-
'_secure_'
|
281
|
-
end
|
282
|
-
|
283
287
|
def metadata
|
284
288
|
{
|
285
289
|
decryption_keys: decryption_keys,
|
@@ -3,21 +3,19 @@
|
|
3
3
|
require 'active_support/json'
|
4
4
|
require 'chamber'
|
5
5
|
|
6
|
-
# rubocop:disable Lint/HandleExceptions, Layout/EmptyLinesAroundModuleBody
|
7
6
|
module Chamber
|
8
|
-
|
9
7
|
begin
|
10
8
|
require 'active_record/type/value'
|
11
9
|
|
12
10
|
CHAMBER_TYPE_VALUE_SUPERCLASS = ActiveRecord::Type::Value
|
13
|
-
rescue LoadError
|
11
|
+
rescue LoadError # rubocop:disable Lint/SuppressedException
|
14
12
|
end
|
15
13
|
|
16
14
|
begin
|
17
15
|
require 'active_model/type/value'
|
18
16
|
|
19
17
|
CHAMBER_TYPE_VALUE_SUPERCLASS = ActiveModel::Type::Value
|
20
|
-
rescue LoadError
|
18
|
+
rescue LoadError # rubocop:disable Lint/SuppressedException
|
21
19
|
end
|
22
20
|
|
23
21
|
module Types
|
@@ -25,11 +23,12 @@ class Secured < CHAMBER_TYPE_VALUE_SUPERCLASS
|
|
25
23
|
attr_accessor :decryption_keys,
|
26
24
|
:encryption_keys
|
27
25
|
|
28
|
-
def initialize(
|
29
|
-
|
30
|
-
|
31
|
-
self.
|
32
|
-
|
26
|
+
def initialize(decryption_keys: ::Chamber.configuration.decryption_keys,
|
27
|
+
encryption_keys: ::Chamber.configuration.encryption_keys)
|
28
|
+
self.decryption_keys = decryption_keys
|
29
|
+
self.encryption_keys = encryption_keys
|
30
|
+
|
31
|
+
super()
|
33
32
|
end
|
34
33
|
|
35
34
|
def type
|
@@ -78,4 +77,3 @@ class Secured < CHAMBER_TYPE_VALUE_SUPERCLASS
|
|
78
77
|
end
|
79
78
|
end
|
80
79
|
end
|
81
|
-
# rubocop:enable Lint/HandleExceptions, Layout/EmptyLinesAroundModuleBody
|