chamber 2.4.0 → 2.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -930
- data/Rakefile +6 -0
- data/lib/chamber.rb +11 -7
- data/lib/chamber/binary/heroku.rb +45 -25
- data/lib/chamber/binary/runner.rb +82 -44
- data/lib/chamber/binary/travis.rb +14 -8
- data/lib/chamber/commands/base.rb +1 -2
- data/lib/chamber/commands/comparable.rb +0 -1
- data/lib/chamber/commands/compare.rb +1 -1
- data/lib/chamber/commands/files.rb +0 -1
- data/lib/chamber/commands/heroku.rb +2 -3
- data/lib/chamber/commands/heroku/push.rb +1 -1
- data/lib/chamber/commands/initialize.rb +69 -12
- data/lib/chamber/commands/securable.rb +9 -4
- data/lib/chamber/commands/secure.rb +1 -1
- data/lib/chamber/commands/show.rb +20 -4
- data/lib/chamber/commands/travis.rb +0 -1
- data/lib/chamber/configuration.rb +5 -5
- data/lib/chamber/context_resolver.rb +12 -12
- data/lib/chamber/decryption_key.rb +51 -0
- data/lib/chamber/environmentable.rb +4 -1
- data/lib/chamber/errors/decryption_failure.rb +6 -0
- data/lib/chamber/file.rb +7 -8
- data/lib/chamber/file_set.rb +23 -22
- data/lib/chamber/filters/boolean_conversion_filter.rb +1 -2
- data/lib/chamber/filters/decryption_filter.rb +42 -25
- data/lib/chamber/filters/encryption_filter.rb +7 -5
- data/lib/chamber/filters/environment_filter.rb +7 -7
- data/lib/chamber/filters/failed_decryption_filter.rb +41 -0
- data/lib/chamber/filters/namespace_filter.rb +1 -1
- data/lib/chamber/filters/secure_filter.rb +3 -5
- data/lib/chamber/filters/translate_secure_keys_filter.rb +5 -24
- data/lib/chamber/namespace_set.rb +6 -6
- data/lib/chamber/rails.rb +1 -3
- data/lib/chamber/rails/railtie.rb +6 -3
- data/lib/chamber/settings.rb +34 -32
- data/lib/chamber/version.rb +1 -1
- data/spec/fixtures/settings.yml +1 -0
- data/spec/lib/chamber/commands/files_spec.rb +4 -2
- data/spec/lib/chamber/commands/secure_spec.rb +8 -5
- data/spec/lib/chamber/commands/show_spec.rb +18 -3
- data/spec/lib/chamber/context_resolver_spec.rb +38 -18
- data/spec/lib/chamber/file_set_spec.rb +73 -52
- data/spec/lib/chamber/file_spec.rb +37 -23
- data/spec/lib/chamber/filters/boolean_conversion_filter_spec.rb +35 -33
- data/spec/lib/chamber/filters/decryption_filter_spec.rb +142 -21
- data/spec/lib/chamber/filters/encryption_filter_spec.rb +51 -19
- data/spec/lib/chamber/filters/environment_filter_spec.rb +12 -6
- data/spec/lib/chamber/filters/failed_decryption_filter_spec.rb +53 -0
- data/spec/lib/chamber/filters/insecure_filter_spec.rb +38 -18
- data/spec/lib/chamber/filters/namespace_filter_spec.rb +38 -38
- data/spec/lib/chamber/filters/secure_filter_spec.rb +10 -10
- data/spec/lib/chamber/filters/translate_secure_keys_filter_spec.rb +9 -6
- data/spec/lib/chamber/namespace_set_spec.rb +7 -5
- data/spec/lib/chamber/settings_spec.rb +168 -79
- data/spec/lib/chamber_spec.rb +72 -71
- metadata +22 -21
- data/lib/chamber/errors/undecryptable_value_error.rb +0 -6
- data/templates/settings.yml +0 -14
@@ -5,26 +5,26 @@ module Chamber
|
|
5
5
|
module Filters
|
6
6
|
describe InsecureFilter do
|
7
7
|
it 'will return values which are marked as "secure" if they are unencrypted' do
|
8
|
-
filtered_settings = InsecureFilter.execute(
|
9
|
-
|
8
|
+
filtered_settings = InsecureFilter.execute(data: {
|
9
|
+
_secure_my_secure_setting: 'hello' })
|
10
10
|
|
11
11
|
expect(filtered_settings._secure_my_secure_setting).to match 'hello'
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'will not return values which are not marked as "secure"' do
|
15
|
-
filtered_settings = InsecureFilter.execute(
|
16
|
-
|
15
|
+
filtered_settings = InsecureFilter.execute(data: {
|
16
|
+
my_secure_setting: 'hello' })
|
17
17
|
|
18
18
|
expect(filtered_settings.my_secure_setting).to be_nil
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'will properly return values even if they are mixed and deeply nested' do
|
22
|
-
filtered_settings = InsecureFilter.execute(
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
filtered_settings = InsecureFilter.execute(data: {
|
23
|
+
_secure_setting: 'hello',
|
24
|
+
secure_setting: 'goodbye',
|
25
|
+
secure_group: {
|
26
|
+
_secure_nested_setting: 'movie',
|
27
|
+
insecure_nested_setting: 'dinner' } })
|
28
28
|
|
29
29
|
expect(filtered_settings._secure_setting).to eql 'hello'
|
30
30
|
expect(filtered_settings.secure_setting).to be_nil
|
@@ -33,14 +33,34 @@ describe InsecureFilter do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'will not return values which are encrypted' do
|
36
|
-
filtered_settings = InsecureFilter.execute(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
36
|
+
filtered_settings = InsecureFilter.execute(
|
37
|
+
data: {
|
38
|
+
_secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpss' \
|
39
|
+
'pg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzC' \
|
40
|
+
'MJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YG' \
|
41
|
+
'DJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6ag' \
|
42
|
+
'y1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMn' \
|
43
|
+
'gJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfN' \
|
44
|
+
'xMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
|
45
|
+
secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpss' \
|
46
|
+
'pg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzC' \
|
47
|
+
'MJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YG' \
|
48
|
+
'DJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6ag' \
|
49
|
+
'y1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMn' \
|
50
|
+
'gJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfN' \
|
51
|
+
'xMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
|
52
|
+
_secure_other_setting: 'hello',
|
53
|
+
secure_group: {
|
54
|
+
_secure_nested_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTh' \
|
55
|
+
'aV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4' \
|
56
|
+
'akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGy' \
|
57
|
+
'dkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9' \
|
58
|
+
'ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8' \
|
59
|
+
'QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZ' \
|
60
|
+
'gfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMn' \
|
61
|
+
'z84XzmUp2Y0H1jPgGkBKQJKArfQ==',
|
62
|
+
_secure_other_nested_setting: 'goodbye',
|
63
|
+
insecure_nested_setting: 'dinner' } })
|
44
64
|
|
45
65
|
expect(filtered_settings._secure_setting?).to eql false
|
46
66
|
expect(filtered_settings.secure_setting?).to eql false
|
@@ -6,67 +6,67 @@ module Chamber
|
|
6
6
|
module Filters
|
7
7
|
describe NamespaceFilter do
|
8
8
|
it 'can filter settings data based on the settings namespaces' do
|
9
|
-
filtered_settings = NamespaceFilter.execute(
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
'other_namespace_value' ])
|
9
|
+
filtered_settings = NamespaceFilter.execute(
|
10
|
+
data: {
|
11
|
+
namespace_value: {
|
12
|
+
namespace_setting: 'value 1' },
|
13
|
+
other_namespace_value: {
|
14
|
+
other_namespace_setting: 'value 2' } },
|
15
|
+
namespaces: %w{namespace_value other_namespace_value})
|
17
16
|
|
18
17
|
expect(filtered_settings.namespace_setting).to eql 'value 1'
|
19
18
|
expect(filtered_settings.other_namespace_setting).to eql 'value 2'
|
20
19
|
end
|
21
20
|
|
22
21
|
it 'ignores data which is not part of a namespace' do
|
23
|
-
filtered_settings = NamespaceFilter.execute(
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
filtered_settings = NamespaceFilter.execute(
|
23
|
+
data: {
|
24
|
+
namespace_value: {
|
25
|
+
namespace_setting: 'value 1' },
|
26
|
+
non_namespaced_value: {
|
27
|
+
non_namespaced_setting: 'value 2' } },
|
28
|
+
namespaces: [
|
29
|
+
'namespace_value'])
|
30
30
|
|
31
31
|
expect(filtered_settings.namespace_setting).to eql 'value 1'
|
32
32
|
expect(filtered_settings.non_namespaced_setting).to be_nil
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'ignores namespaces which do not exist in the data' do
|
36
|
-
filtered_settings = NamespaceFilter.execute(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
'other_namespace_value' ])
|
36
|
+
filtered_settings = NamespaceFilter.execute(
|
37
|
+
data: {
|
38
|
+
namespace_value: {
|
39
|
+
namespace_setting: 'value 1' } },
|
40
|
+
namespaces: %w{namespace_value other_namespace_value})
|
42
41
|
|
43
42
|
expect(filtered_settings.namespace_setting).to eql 'value 1'
|
44
43
|
end
|
45
44
|
|
46
45
|
it 'does not filter data if it does not include any namespaces' do
|
47
|
-
filtered_settings = NamespaceFilter.execute(
|
48
|
-
|
49
|
-
|
46
|
+
filtered_settings = NamespaceFilter.execute(
|
47
|
+
data: {
|
48
|
+
non_namespaced_setting: 'value 1' },
|
49
|
+
namespaces: [])
|
50
50
|
|
51
51
|
expect(filtered_settings.non_namespaced_setting).to eql 'value 1'
|
52
52
|
end
|
53
53
|
|
54
54
|
it 'can filter if it is given NamespaceSets' do
|
55
|
-
filtered_settings = NamespaceFilter.execute(
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
55
|
+
filtered_settings = NamespaceFilter.execute(
|
56
|
+
data: {
|
57
|
+
namespace_value: {
|
58
|
+
namespace_setting: 'value 1',
|
59
|
+
another_namespace_setting: 'value 2' },
|
60
|
+
other_namespace_value: {
|
61
|
+
namespace_setting_1: 'value 1',
|
62
|
+
another_namespace_setting_2: 'value 2' },
|
63
|
+
non_namespaced_value: 'value 3' },
|
64
|
+
namespaces: NamespaceSet.new(%w{namespace_value other_namespace_value}))
|
65
65
|
|
66
|
-
expect(filtered_settings.to_hash).to eql(
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
expect(filtered_settings.to_hash).to eql('namespace_setting' => 'value 1',
|
67
|
+
'another_namespace_setting' => 'value 2',
|
68
|
+
'namespace_setting_1' => 'value 1',
|
69
|
+
'another_namespace_setting_2' => 'value 2')
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -5,26 +5,26 @@ module Chamber
|
|
5
5
|
module Filters
|
6
6
|
describe SecureFilter do
|
7
7
|
it 'will return values which are marked as "secure"' do
|
8
|
-
filtered_settings = SecureFilter.execute(
|
9
|
-
|
8
|
+
filtered_settings = SecureFilter.execute(data: {
|
9
|
+
_secure_my_secure_setting: 'hello' })
|
10
10
|
|
11
11
|
expect(filtered_settings._secure_my_secure_setting).to match 'hello'
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'will not return values which are not marked as "secure"' do
|
15
|
-
filtered_settings = SecureFilter.execute(
|
16
|
-
|
15
|
+
filtered_settings = SecureFilter.execute(data: {
|
16
|
+
my_secure_setting: 'hello' })
|
17
17
|
|
18
18
|
expect(filtered_settings.my_secure_setting).to be_nil
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'will properly return values even if they are mixed and deeply nested' do
|
22
|
-
filtered_settings = SecureFilter.execute(
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
filtered_settings = SecureFilter.execute(data: {
|
23
|
+
_secure_setting: 'hello',
|
24
|
+
secure_setting: 'goodbye',
|
25
|
+
secure_group: {
|
26
|
+
_secure_nested_setting: 'movie',
|
27
|
+
insecure_nested_setting: 'dinner' } })
|
28
28
|
|
29
29
|
expect(filtered_settings._secure_setting).to eql 'hello'
|
30
30
|
expect(filtered_settings.secure_setting).to be_nil
|
@@ -5,22 +5,25 @@ module Chamber
|
|
5
5
|
module Filters
|
6
6
|
describe TranslateSecureKeysFilter do
|
7
7
|
it 'will translate keys if they start with "_secure_"' do
|
8
|
-
filtered_settings = TranslateSecureKeysFilter.execute(
|
9
|
-
|
8
|
+
filtered_settings = TranslateSecureKeysFilter.execute(
|
9
|
+
data: {
|
10
|
+
_secure_my_secure_setting: 'hello' })
|
10
11
|
|
11
12
|
expect(filtered_settings.my_secure_setting).to eql 'hello'
|
12
13
|
end
|
13
14
|
|
14
15
|
it 'will not translate keys if they do not start with "_secure_"' do
|
15
|
-
filtered_settings = TranslateSecureKeysFilter.execute(
|
16
|
-
|
16
|
+
filtered_settings = TranslateSecureKeysFilter.execute(
|
17
|
+
data: {
|
18
|
+
my_secure_setting: 'hello' })
|
17
19
|
|
18
20
|
expect(filtered_settings.my_secure_setting).to eql 'hello'
|
19
21
|
end
|
20
22
|
|
21
23
|
it 'will not translate the key if it starts with "secure"' do
|
22
|
-
filtered_settings = TranslateSecureKeysFilter.execute(
|
23
|
-
|
24
|
+
filtered_settings = TranslateSecureKeysFilter.execute(
|
25
|
+
data: {
|
26
|
+
secure_setting: 'hello' })
|
24
27
|
|
25
28
|
expect(filtered_settings.secure_setting).to eql 'hello'
|
26
29
|
end
|
@@ -4,8 +4,8 @@ require 'chamber/namespace_set'
|
|
4
4
|
module Chamber
|
5
5
|
describe NamespaceSet do
|
6
6
|
it 'can create a set from from a hash' do
|
7
|
-
namespace_set = NamespaceSet.new(
|
8
|
-
|
7
|
+
namespace_set = NamespaceSet.new(environment: :development,
|
8
|
+
hostname: 'my host')
|
9
9
|
|
10
10
|
expect(namespace_set).to eq ['development', 'my host']
|
11
11
|
end
|
@@ -50,7 +50,9 @@ describe NamespaceSet do
|
|
50
50
|
expect(namespace_set.object_id).not_to eq original_set.object_id
|
51
51
|
end
|
52
52
|
|
53
|
-
it 'when creating itself from another NamespaceSet, it does not nest the
|
53
|
+
it 'when creating itself from another NamespaceSet, it does not nest the ' \
|
54
|
+
'NamespaceSets' do
|
55
|
+
|
54
56
|
original_set = NamespaceSet[:development, 'my host']
|
55
57
|
namespace_set = NamespaceSet.new(original_set)
|
56
58
|
|
@@ -105,11 +107,11 @@ describe NamespaceSet do
|
|
105
107
|
end
|
106
108
|
|
107
109
|
it 'will process a value by executing it if it is a callable' do
|
108
|
-
namespace_set = NamespaceSet[
|
110
|
+
namespace_set = NamespaceSet[-> { 'callable' }]
|
109
111
|
|
110
112
|
expect(namespace_set).to eq ['callable']
|
111
113
|
|
112
|
-
namespace_set = NamespaceSet.new(
|
114
|
+
namespace_set = NamespaceSet.new(my_namespace: -> { 'callable' })
|
113
115
|
|
114
116
|
expect(namespace_set).to eq ['callable']
|
115
117
|
end
|
@@ -4,28 +4,28 @@ require 'chamber/settings'
|
|
4
4
|
module Chamber
|
5
5
|
describe Settings do
|
6
6
|
it 'can verify that it is equal to another Settings object' do
|
7
|
-
settings = Settings.new(
|
8
|
-
|
9
|
-
other_settings = Settings.new(
|
10
|
-
|
7
|
+
settings = Settings.new(settings: { setting: 'value' },
|
8
|
+
namespaces: ['good'])
|
9
|
+
other_settings = Settings.new(settings: { setting: 'value' },
|
10
|
+
namespaces: ['good'])
|
11
11
|
|
12
12
|
expect(settings).to eql other_settings
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'does not consider itself equal if the namespaces are not equal' do
|
16
|
-
settings = Settings.new(
|
17
|
-
|
18
|
-
other_settings = Settings.new(
|
19
|
-
|
16
|
+
settings = Settings.new(settings: { setting: 'value' },
|
17
|
+
namespaces: ['good'])
|
18
|
+
other_settings = Settings.new(settings: { setting: 'value' },
|
19
|
+
namespaces: ['bad'])
|
20
20
|
|
21
21
|
expect(settings).not_to eql other_settings
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'does not consider itself equal if the settings are not equal' do
|
25
|
-
settings = Settings.new(
|
26
|
-
|
27
|
-
other_settings = Settings.new(
|
28
|
-
|
25
|
+
settings = Settings.new(settings: { setting: 'value' },
|
26
|
+
namespaces: ['good'])
|
27
|
+
other_settings = Settings.new(settings: { setting: 'value 1' },
|
28
|
+
namespaces: ['good'])
|
29
29
|
|
30
30
|
expect(settings).not_to eql other_settings
|
31
31
|
end
|
@@ -34,11 +34,11 @@ describe Settings do
|
|
34
34
|
settings = Settings.new(settings: {
|
35
35
|
my_setting: 'value',
|
36
36
|
level_1: {
|
37
|
-
level_2:
|
37
|
+
level_2: {
|
38
38
|
some_setting: 'hello',
|
39
39
|
another: 'goodbye',
|
40
40
|
},
|
41
|
-
body:
|
41
|
+
body: 'gracias',
|
42
42
|
},
|
43
43
|
there: 'was not that easy?',
|
44
44
|
})
|
@@ -52,45 +52,53 @@ describe Settings do
|
|
52
52
|
)
|
53
53
|
end
|
54
54
|
|
55
|
-
it 'sorts environment variables by name when converted to an environment hash so
|
55
|
+
it 'sorts environment variables by name when converted to an environment hash so ' \
|
56
|
+
'that they are easier to parse for humans' do
|
57
|
+
|
56
58
|
settings = Settings.new(settings: { 'C' => 'value',
|
57
59
|
'D' => 'value',
|
58
60
|
'A' => 'value',
|
59
61
|
'E' => 'value',
|
60
62
|
'B' => 'value' })
|
61
63
|
|
62
|
-
expect(settings.to_environment.to_a).to eql([
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
expect(settings.to_environment.to_a).to eql([%w{A value},
|
65
|
+
%w{B value},
|
66
|
+
%w{C value},
|
67
|
+
%w{D value},
|
68
|
+
%w{E value}])
|
67
69
|
end
|
68
70
|
|
69
71
|
it 'can convert itself into a string' do
|
70
72
|
settings = Settings.new(settings: {
|
71
73
|
my_setting: 'value',
|
72
74
|
level_1: {
|
73
|
-
level_2:
|
75
|
+
level_2: {
|
74
76
|
some_setting: 'hello',
|
75
77
|
another: 'goodbye',
|
76
78
|
},
|
77
|
-
body:
|
79
|
+
body: 'gracias',
|
78
80
|
},
|
79
81
|
there: 'was not that easy?',
|
80
82
|
})
|
81
83
|
|
82
|
-
expect(settings.to_s).to eql %
|
84
|
+
expect(settings.to_s).to eql %w{
|
85
|
+
LEVEL_1_BODY="gracias"
|
86
|
+
LEVEL_1_LEVEL_2_ANOTHER="goodbye"
|
87
|
+
LEVEL_1_LEVEL_2_SOME_SETTING="hello"
|
88
|
+
MY_SETTING="value"
|
89
|
+
THERE="was not that easy?"
|
90
|
+
}.join(' ')
|
83
91
|
end
|
84
92
|
|
85
93
|
it 'can convert itself into a string with custom options' do
|
86
94
|
settings = Settings.new(settings: {
|
87
95
|
my_setting: 'value',
|
88
96
|
level_1: {
|
89
|
-
level_2:
|
97
|
+
level_2: {
|
90
98
|
some_setting: 'hello',
|
91
99
|
another: 'goodbye',
|
92
100
|
},
|
93
|
-
body:
|
101
|
+
body: 'gracias',
|
94
102
|
},
|
95
103
|
there: 'was not that easy?',
|
96
104
|
})
|
@@ -110,32 +118,32 @@ HEREDOC
|
|
110
118
|
end
|
111
119
|
|
112
120
|
it 'can merge itself with a hash' do
|
113
|
-
settings = Settings.new(settings: {setting: 'value'})
|
121
|
+
settings = Settings.new(settings: { setting: 'value' })
|
114
122
|
other_settings = { other_setting: 'another value' }
|
115
123
|
|
116
124
|
merged_settings = settings.merge(other_settings)
|
117
125
|
|
118
126
|
expect(merged_settings).to eq('setting' => 'value',
|
119
|
-
|
127
|
+
'other_setting' => 'another value')
|
120
128
|
end
|
121
129
|
|
122
130
|
it 'can merge itself with Settings' do
|
123
|
-
settings = Settings.new(settings: {setting: 'value'},
|
131
|
+
settings = Settings.new(settings: { setting: 'value' },
|
124
132
|
namespaces: ['good'])
|
125
|
-
other_settings = Settings.new(settings: {other_setting: 'another value'},
|
133
|
+
other_settings = Settings.new(settings: { other_setting: 'another value' },
|
126
134
|
namespaces: ['bad'])
|
127
135
|
|
128
136
|
merged_settings = settings.merge(other_settings)
|
129
137
|
|
130
138
|
expect(merged_settings).to eql Settings.new(settings: {
|
131
|
-
setting:
|
132
|
-
other_setting:
|
133
|
-
namespaces:
|
139
|
+
setting: 'value',
|
140
|
+
other_setting: 'another value' },
|
141
|
+
namespaces: %w{good bad})
|
134
142
|
end
|
135
143
|
|
136
144
|
it 'does not manipulate the existing Settings but instead returns a new one' do
|
137
|
-
settings = Settings.new(settings: {setting: 'value'})
|
138
|
-
other_settings = Settings.new(settings: {other_setting: 'another value'})
|
145
|
+
settings = Settings.new(settings: { setting: 'value' })
|
146
|
+
other_settings = Settings.new(settings: { other_setting: 'another value' })
|
139
147
|
|
140
148
|
merged_settings = settings.merge(other_settings)
|
141
149
|
|
@@ -144,7 +152,7 @@ HEREDOC
|
|
144
152
|
end
|
145
153
|
|
146
154
|
it 'can convert itself into a hash' do
|
147
|
-
settings = Settings.new(settings: {setting: 'value'})
|
155
|
+
settings = Settings.new(settings: { setting: 'value' })
|
148
156
|
|
149
157
|
expect(settings.to_hash).to eql('setting' => 'value')
|
150
158
|
expect(settings.to_hash).to be_a Hash
|
@@ -155,28 +163,30 @@ HEREDOC
|
|
155
163
|
settings = Settings.new(settings: {
|
156
164
|
my_setting: 'value',
|
157
165
|
level_1: {
|
158
|
-
level_2:
|
166
|
+
level_2: {
|
159
167
|
some_setting: 'hello',
|
160
168
|
another: 'goodbye',
|
161
169
|
},
|
162
|
-
body:
|
170
|
+
body: 'gracias',
|
163
171
|
},
|
164
172
|
there: 'was not that easy?',
|
165
173
|
})
|
166
174
|
|
167
175
|
expect(settings.to_flattened_name_hash).to eql(
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
176
|
+
%w{my_setting} => 'value',
|
177
|
+
%w{level_1 level_2 some_setting} => 'hello',
|
178
|
+
%w{level_1 level_2 another} => 'goodbye',
|
179
|
+
%w{level_1 body} => 'gracias',
|
180
|
+
%w{there} => 'was not that easy?',
|
173
181
|
)
|
174
182
|
expect(settings.to_flattened_name_hash).to be_a Hash
|
175
183
|
expect(settings.to_flattened_name_hash).not_to be_a Hashie::Mash
|
176
184
|
end
|
177
185
|
|
178
|
-
it 'does not allow manipulation of the internal setting hash when converted to
|
179
|
-
|
186
|
+
it 'does not allow manipulation of the internal setting hash when converted to ' \
|
187
|
+
'a Hash' do
|
188
|
+
|
189
|
+
settings = Settings.new(settings: { setting: 'value' })
|
180
190
|
|
181
191
|
settings_hash = settings.to_hash
|
182
192
|
settings_hash['setting'] = 'foo'
|
@@ -186,60 +196,69 @@ HEREDOC
|
|
186
196
|
end
|
187
197
|
|
188
198
|
it 'allows messages to be passed through to the underlying data' do
|
189
|
-
settings = Settings.new(settings: {setting: 'value'})
|
199
|
+
settings = Settings.new(settings: { setting: 'value' })
|
190
200
|
|
191
201
|
expect(settings.setting).to eql 'value'
|
192
202
|
end
|
193
203
|
|
194
204
|
it 'will still raise an error if the underlying data does not respond to it' do
|
195
|
-
settings = Settings.new(settings: {setting: 'value'})
|
205
|
+
settings = Settings.new(settings: { setting: 'value' })
|
196
206
|
|
197
207
|
expect { settings.unknown }.to raise_error NoMethodError
|
198
208
|
end
|
199
209
|
|
200
210
|
it 'can notify properly whether it responds to messages if the underlying data does' do
|
201
|
-
settings = Settings.new(settings: {setting: 'value'})
|
211
|
+
settings = Settings.new(settings: { setting: 'value' })
|
202
212
|
|
203
213
|
expect(settings.respond_to?(:setting)).to be_a TrueClass
|
204
214
|
end
|
205
215
|
|
206
216
|
it 'only includes namespaced data if any exists' do
|
207
217
|
settings = Settings.new(settings: {
|
208
|
-
namespace_value:
|
209
|
-
namespace_setting:
|
210
|
-
other_namespace_value:
|
211
|
-
other_namespace_setting:
|
212
|
-
non_namespace_setting:
|
218
|
+
namespace_value: {
|
219
|
+
namespace_setting: 'value' },
|
220
|
+
other_namespace_value: {
|
221
|
+
other_namespace_setting: 'value' },
|
222
|
+
non_namespace_setting: 'other value',
|
213
223
|
},
|
214
|
-
namespaces:
|
224
|
+
namespaces: %w{namespace_value other_namespace_value})
|
215
225
|
|
216
|
-
expect(settings).to eq('namespace_setting'
|
217
|
-
|
226
|
+
expect(settings).to eq('namespace_setting' => 'value',
|
227
|
+
'other_namespace_setting' => 'value')
|
218
228
|
end
|
219
229
|
|
220
230
|
it 'can decrypt a setting if it finds a secure key' do
|
221
|
-
settings = Settings.new(
|
222
|
-
|
223
|
-
|
224
|
-
|
231
|
+
settings = Settings.new(
|
232
|
+
settings: {
|
233
|
+
_secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTha' \
|
234
|
+
'V4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4ak' \
|
235
|
+
'un6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkE' \
|
236
|
+
'jY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8M' \
|
237
|
+
'v4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/' \
|
238
|
+
'1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86' \
|
239
|
+
'wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmU' \
|
240
|
+
'p2Y0H1jPgGkBKQJKArfQ==',
|
241
|
+
},
|
242
|
+
decryption_key: './spec/spec_key')
|
225
243
|
|
226
244
|
expect(settings).to eq('my_encrypted_setting' => 'hello')
|
227
245
|
end
|
228
246
|
|
229
247
|
it 'can encrypt a setting if it finds a secure key' do
|
230
|
-
settings = Settings.new(settings:
|
231
|
-
_secure_my_encrypted_setting: 'hello'
|
248
|
+
settings = Settings.new(settings: {
|
249
|
+
_secure_my_encrypted_setting: 'hello',
|
232
250
|
},
|
233
251
|
encryption_key: './spec/spec_key.pub',
|
234
252
|
pre_filters: [],
|
235
|
-
post_filters: [
|
253
|
+
post_filters: [Filters::EncryptionFilter])
|
236
254
|
|
237
|
-
expect(settings._secure_my_encrypted_setting).to match
|
255
|
+
expect(settings._secure_my_encrypted_setting).to match \
|
256
|
+
Filters::EncryptionFilter::BASE64_STRING_PATTERN
|
238
257
|
end
|
239
258
|
|
240
259
|
it 'can encrypt a settings without explicitly having to have a filter passed' do
|
241
|
-
settings = Settings.new(settings:
|
242
|
-
_secure_my_encrypted_setting: 'hello'
|
260
|
+
settings = Settings.new(settings: {
|
261
|
+
_secure_my_encrypted_setting: 'hello',
|
243
262
|
},
|
244
263
|
decryption_key: './spec/spec_key',
|
245
264
|
encryption_key: './spec/spec_key.pub')
|
@@ -248,22 +267,31 @@ HEREDOC
|
|
248
267
|
|
249
268
|
secure_settings = settings.secure
|
250
269
|
|
251
|
-
expect(secure_settings.my_encrypted_setting).to match
|
270
|
+
expect(secure_settings.my_encrypted_setting).to match \
|
271
|
+
Filters::EncryptionFilter::BASE64_STRING_PATTERN
|
252
272
|
end
|
253
273
|
|
254
274
|
it 'can check if it is equal to other items which can be converted into hashes' do
|
255
|
-
settings = Settings.new(settings: {setting: 'value'})
|
275
|
+
settings = Settings.new(settings: { setting: 'value' })
|
256
276
|
|
257
277
|
expect(settings).to eq('setting' => 'value')
|
258
278
|
end
|
259
279
|
|
260
280
|
it 'can filter securable settings' do
|
261
|
-
settings = Settings.new(
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
281
|
+
settings = Settings.new(
|
282
|
+
settings: {
|
283
|
+
_secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTha' \
|
284
|
+
'V4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4ak' \
|
285
|
+
'un6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkE' \
|
286
|
+
'jY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8M' \
|
287
|
+
'v4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/' \
|
288
|
+
'1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86' \
|
289
|
+
'wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmU' \
|
290
|
+
'p2Y0H1jPgGkBKQJKArfQ==',
|
291
|
+
_secure_my_unencrypted_setting: 'nifty',
|
292
|
+
my_insecure_setting: 'goodbye',
|
293
|
+
},
|
294
|
+
decryption_key: './spec/spec_key')
|
267
295
|
|
268
296
|
secured_settings = settings.securable
|
269
297
|
|
@@ -273,12 +301,20 @@ HEREDOC
|
|
273
301
|
end
|
274
302
|
|
275
303
|
it 'can filter unencrypted settings' do
|
276
|
-
settings = Settings.new(
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
304
|
+
settings = Settings.new(
|
305
|
+
settings: {
|
306
|
+
_secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTha' \
|
307
|
+
'V4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4ak' \
|
308
|
+
'un6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkE' \
|
309
|
+
'jY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8M' \
|
310
|
+
'v4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/' \
|
311
|
+
'1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86' \
|
312
|
+
'wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmU' \
|
313
|
+
'p2Y0H1jPgGkBKQJKArfQ==',
|
314
|
+
_secure_my_unencrypted_setting: 'nifty',
|
315
|
+
my_insecure_setting: 'goodbye',
|
316
|
+
},
|
317
|
+
decryption_key: './spec/spec_key')
|
282
318
|
|
283
319
|
secured_settings = settings.insecure
|
284
320
|
|
@@ -286,5 +322,58 @@ HEREDOC
|
|
286
322
|
expect(secured_settings.my_unencrypted_setting).to eql 'nifty'
|
287
323
|
expect(secured_settings.my_insecure_setting?).to eql false
|
288
324
|
end
|
325
|
+
|
326
|
+
it 'raises an exception when it accesses a value which cannot be decrypted' do
|
327
|
+
settings = Settings.new(
|
328
|
+
settings: {
|
329
|
+
_secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTha' \
|
330
|
+
'V4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4ak' \
|
331
|
+
'un6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkE' \
|
332
|
+
'jY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8M' \
|
333
|
+
'v4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/' \
|
334
|
+
'1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86' \
|
335
|
+
'wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmU' \
|
336
|
+
'p2Y0H1jPgGkBKQJKArfQ==',
|
337
|
+
},
|
338
|
+
)
|
339
|
+
|
340
|
+
expect { settings.my_encrypted_setting }.
|
341
|
+
to raise_error Chamber::Errors::DecryptionFailure
|
342
|
+
end
|
343
|
+
|
344
|
+
it 'prefers environment variable values over encrypted values' do
|
345
|
+
ENV['MY_ENCRYPTED_SETTING'] = 'my env setting'
|
346
|
+
ENV['ENCRYPTED_GROUP_MY_ENCRYPTED_GROUP_SETTING'] = 'my env group'
|
347
|
+
|
348
|
+
settings = Settings.new(
|
349
|
+
settings: {
|
350
|
+
_secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYTha' \
|
351
|
+
'V4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4ak' \
|
352
|
+
'un6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkE' \
|
353
|
+
'jY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8M' \
|
354
|
+
'v4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/' \
|
355
|
+
'1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86' \
|
356
|
+
'wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmU' \
|
357
|
+
'p2Y0H1jPgGkBKQJKArfQ==',
|
358
|
+
encrypted_group: {
|
359
|
+
_secure_my_encrypted_group_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdn' \
|
360
|
+
'MoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3Fx' \
|
361
|
+
'ptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEA' \
|
362
|
+
'QLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUT' \
|
363
|
+
'f34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5k' \
|
364
|
+
'LAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlz' \
|
365
|
+
'pKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgU' \
|
366
|
+
'Kc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84Xz' \
|
367
|
+
'mUp2Y0H1jPgGkBKQJKArfQ==',
|
368
|
+
},
|
369
|
+
},
|
370
|
+
)
|
371
|
+
|
372
|
+
expect(settings.my_encrypted_setting).to eql 'my env setting'
|
373
|
+
expect(settings.encrypted_group.my_encrypted_group_setting).to eql 'my env group'
|
374
|
+
|
375
|
+
ENV['MY_ENCRYPTED_SETTING'] = nil
|
376
|
+
ENV['ENCRYPTED_GROUP_MY_ENCRYPTED_GROUP_SETTING'] = nil
|
377
|
+
end
|
289
378
|
end
|
290
379
|
end
|