chamber 1.0.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +288 -173
- data/bin/chamber +2 -288
- data/lib/chamber.rb +19 -67
- data/lib/chamber/binary/heroku.rb +59 -0
- data/lib/chamber/binary/runner.rb +94 -0
- data/lib/chamber/binary/travis.rb +23 -0
- data/lib/chamber/commands/base.rb +33 -0
- data/lib/chamber/commands/comparable.rb +37 -0
- data/lib/chamber/commands/compare.rb +46 -0
- data/lib/chamber/commands/context_resolver.rb +72 -0
- data/lib/chamber/commands/files.rb +12 -0
- data/lib/chamber/commands/heroku.rb +30 -0
- data/lib/chamber/commands/heroku/clear.rb +25 -0
- data/lib/chamber/commands/heroku/compare.rb +31 -0
- data/lib/chamber/commands/heroku/pull.rb +30 -0
- data/lib/chamber/commands/heroku/push.rb +25 -0
- data/lib/chamber/commands/initialize.rb +73 -0
- data/lib/chamber/commands/securable.rb +48 -0
- data/lib/chamber/commands/secure.rb +16 -0
- data/lib/chamber/commands/show.rb +23 -0
- data/lib/chamber/commands/travis.rb +14 -0
- data/lib/chamber/commands/travis/secure.rb +35 -0
- data/lib/chamber/configuration.rb +34 -0
- data/lib/chamber/environmentable.rb +23 -0
- data/lib/chamber/errors/undecryptable_value_error.rb +6 -0
- data/lib/chamber/file.rb +17 -5
- data/lib/chamber/file_set.rb +18 -12
- data/lib/chamber/filters/boolean_conversion_filter.rb +41 -0
- data/lib/chamber/filters/decryption_filter.rb +69 -0
- data/lib/chamber/filters/encryption_filter.rb +57 -0
- data/lib/chamber/filters/environment_filter.rb +75 -0
- data/lib/chamber/filters/namespace_filter.rb +37 -0
- data/lib/chamber/filters/secure_filter.rb +39 -0
- data/lib/chamber/instance.rb +40 -0
- data/lib/chamber/namespace_set.rb +55 -16
- data/lib/chamber/rails/railtie.rb +1 -1
- data/lib/chamber/settings.rb +103 -42
- data/lib/chamber/system_environment.rb +3 -93
- data/lib/chamber/version.rb +2 -2
- data/spec/fixtures/settings.yml +27 -0
- data/spec/lib/chamber/commands/context_resolver_spec.rb +106 -0
- data/spec/lib/chamber/commands/files_spec.rb +19 -0
- data/spec/lib/chamber/commands/heroku/clear_spec.rb +11 -0
- data/spec/lib/chamber/commands/heroku/compare_spec.rb +11 -0
- data/spec/lib/chamber/commands/heroku/pull_spec.rb +11 -0
- data/spec/lib/chamber/commands/heroku/push_spec.rb +11 -0
- data/spec/lib/chamber/commands/secure_spec.rb +29 -0
- data/spec/lib/chamber/commands/show_spec.rb +43 -0
- data/spec/lib/chamber/file_set_spec.rb +1 -1
- data/spec/lib/chamber/file_spec.rb +32 -9
- data/spec/lib/chamber/filters/boolean_conversion_filter_spec.rb +44 -0
- data/spec/lib/chamber/filters/decryption_filter_spec.rb +55 -0
- data/spec/lib/chamber/filters/encryption_filter_spec.rb +48 -0
- data/spec/lib/chamber/filters/environment_filter_spec.rb +35 -0
- data/spec/lib/chamber/filters/namespace_filter_spec.rb +73 -0
- data/spec/lib/chamber/filters/secure_filter_spec.rb +36 -0
- data/spec/lib/chamber/namespace_set_spec.rb +61 -18
- data/spec/lib/chamber/settings_spec.rb +99 -23
- data/spec/lib/chamber/system_environment_spec.rb +1 -71
- data/spec/lib/chamber_spec.rb +40 -26
- data/spec/rails-2-test/config.ru +0 -0
- data/spec/rails-2-test/config/application.rb +5 -0
- data/spec/rails-2-test/script/console +0 -0
- data/spec/rails-3-test/config.ru +0 -0
- data/spec/rails-3-test/config/application.rb +5 -0
- data/spec/rails-3-test/script/rails +0 -0
- data/spec/rails-4-test/bin/rails +0 -0
- data/spec/rails-4-test/config.ru +0 -0
- data/spec/rails-4-test/config/application.rb +5 -0
- data/spec/spec_key +27 -0
- data/spec/spec_key.pub +9 -0
- metadata +85 -4
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'chamber/commands/files'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Commands
|
6
|
+
describe Files do
|
7
|
+
let(:rootpath) { ::File.expand_path('./spec/fixtures') }
|
8
|
+
let(:options) { { basepath: rootpath,
|
9
|
+
rootpath: rootpath } }
|
10
|
+
|
11
|
+
it 'can return values formatted as environment variables' do
|
12
|
+
files = Files.call(options)
|
13
|
+
|
14
|
+
expect(files.size).to eql 1
|
15
|
+
expect(files.first).to include 'spec/fixtures/settings.yml'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'chamber/commands/secure'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Commands
|
6
|
+
describe Secure do
|
7
|
+
let(:rootpath) { Pathname.new(::File.expand_path('./spec/fixtures')) }
|
8
|
+
let(:settings_filename) { rootpath + 'settings' + 'unencrypted.yml' }
|
9
|
+
let(:options) { { basepath: rootpath,
|
10
|
+
rootpath: rootpath,
|
11
|
+
encryption_key: rootpath + '../spec_key'} }
|
12
|
+
|
13
|
+
it 'can return values formatted as environment variables' do
|
14
|
+
::File.open(settings_filename, 'w') do |file|
|
15
|
+
file.write <<-HEREDOC
|
16
|
+
test:
|
17
|
+
_secure_my_unencrpyted_setting: hello
|
18
|
+
HEREDOC
|
19
|
+
end
|
20
|
+
|
21
|
+
files = Secure.call(options)
|
22
|
+
|
23
|
+
expect(::File.read(settings_filename)).to match %r{_secure_my_unencrpyted_setting: [A-Za-z0-9\+\/]{342}==}
|
24
|
+
|
25
|
+
::File.delete(settings_filename)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'chamber/commands/show'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Commands
|
6
|
+
describe Show do
|
7
|
+
let(:rootpath) { ::File.expand_path('./spec/fixtures') }
|
8
|
+
let(:options) { { basepath: rootpath,
|
9
|
+
rootpath: rootpath,
|
10
|
+
namespaces: 'test' } }
|
11
|
+
|
12
|
+
it 'can return values formatted as environment variables' do
|
13
|
+
expect(Show.call(options.merge(as_env: true))).to eql(
|
14
|
+
<<-HEREDOC.chomp
|
15
|
+
ANOTHER_LEVEL_LEVEL_THREE_AN_ARRAY="["item 1", "item 2", "item 3"]"
|
16
|
+
ANOTHER_LEVEL_LEVEL_THREE_A_SCALAR="hello"
|
17
|
+
ANOTHER_LEVEL_SETTING_ONE="1"
|
18
|
+
ANOTHER_LEVEL_SETTING_TWO="2"
|
19
|
+
MY_BOOLEAN="false"
|
20
|
+
MY_DYNAMIC_SETTING="2"
|
21
|
+
MY_SETTING="my_value"
|
22
|
+
HEREDOC
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'can return values formatted as a hash' do
|
27
|
+
expect(Show.call(options)).to eql(
|
28
|
+
<<-HEREDOC.chomp
|
29
|
+
{"my_setting"=>"my_value",
|
30
|
+
"my_boolean"=>false,
|
31
|
+
"my_dynamic_setting"=>2,
|
32
|
+
"another_level"=>
|
33
|
+
{"setting_one"=>1,
|
34
|
+
"setting_two"=>2,
|
35
|
+
"level_three"=>
|
36
|
+
{"an_array"=>["item 1", "item 2", "item 3"],
|
37
|
+
"a_scalar"=>"hello"}}}
|
38
|
+
HEREDOC
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -3,7 +3,7 @@ require 'chamber/file_set'
|
|
3
3
|
require 'fileutils'
|
4
4
|
|
5
5
|
|
6
|
-
|
6
|
+
module Chamber
|
7
7
|
describe FileSet do
|
8
8
|
before(:each) { FileUtils.mkdir '/tmp/settings' unless ::File.exist? '/tmp/settings' }
|
9
9
|
after(:each) { FileUtils.rm_rf '/tmp/settings' if ::File.exist? '/tmp/settings' }
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rspectacular'
|
2
2
|
require 'chamber/file'
|
3
3
|
require 'chamber/settings'
|
4
|
+
require 'chamber/filters/encryption_filter'
|
4
5
|
require 'tempfile'
|
5
6
|
|
6
7
|
def create_tempfile_with_content(content)
|
@@ -10,7 +11,7 @@ def create_tempfile_with_content(content)
|
|
10
11
|
tempfile
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
|
+
module Chamber
|
14
15
|
describe File do
|
15
16
|
it 'can convert file contents to settings' do
|
16
17
|
tempfile = create_tempfile_with_content %Q({ test: settings })
|
@@ -23,8 +24,10 @@ describe File do
|
|
23
24
|
|
24
25
|
expect(file_settings).to eql :settings
|
25
26
|
expect(Settings).to have_received(:new).
|
26
|
-
with(settings:
|
27
|
-
namespaces:
|
27
|
+
with(settings: {'test' => 'settings'},
|
28
|
+
namespaces: {},
|
29
|
+
decryption_key: nil,
|
30
|
+
encryption_key: nil)
|
28
31
|
end
|
29
32
|
|
30
33
|
it 'can convert a file whose contents are empty' do
|
@@ -38,8 +41,10 @@ describe File do
|
|
38
41
|
|
39
42
|
expect(file_settings).to eql :settings
|
40
43
|
expect(Settings).to have_received(:new).
|
41
|
-
with(settings:
|
42
|
-
namespaces:
|
44
|
+
with(settings: {},
|
45
|
+
namespaces: {},
|
46
|
+
decryption_key: nil,
|
47
|
+
encryption_key: nil)
|
43
48
|
end
|
44
49
|
|
45
50
|
it 'throws an error when the file contents are malformed' do
|
@@ -62,7 +67,9 @@ describe File do
|
|
62
67
|
expect(Settings).to have_received(:new).
|
63
68
|
with( settings: {'test' => 'settings'},
|
64
69
|
namespaces: {
|
65
|
-
environment: :development }
|
70
|
+
environment: :development },
|
71
|
+
decryption_key: nil,
|
72
|
+
encryption_key: nil)
|
66
73
|
end
|
67
74
|
|
68
75
|
it 'can handle files which contain ERB markup' do
|
@@ -74,7 +81,9 @@ describe File do
|
|
74
81
|
settings_file.to_settings
|
75
82
|
expect(Settings).to have_received(:new).
|
76
83
|
with( settings: {'test' => 2},
|
77
|
-
namespaces: {}
|
84
|
+
namespaces: {},
|
85
|
+
decryption_key: nil,
|
86
|
+
encryption_key: nil)
|
78
87
|
end
|
79
88
|
|
80
89
|
it 'does not throw an error when attempting to convert a file which does not exist' do
|
@@ -87,8 +96,22 @@ describe File do
|
|
87
96
|
|
88
97
|
expect(file_settings).to eql :settings
|
89
98
|
expect(Settings).to have_received(:new).
|
90
|
-
with(settings:
|
91
|
-
namespaces:
|
99
|
+
with(settings: {},
|
100
|
+
namespaces: {},
|
101
|
+
decryption_key: nil,
|
102
|
+
encryption_key: nil)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'can securely encrypt the settings contained in a file' do
|
106
|
+
tempfile = create_tempfile_with_content %Q({ _secure_setting: hello })
|
107
|
+
settings_file = File.new path: tempfile.path,
|
108
|
+
encryption_key: './spec/spec_key.pub'
|
109
|
+
|
110
|
+
settings_file.secure
|
111
|
+
|
112
|
+
settings_file = File.new path: tempfile.path
|
113
|
+
|
114
|
+
expect(settings_file.to_settings.send(:raw_data)['_secure_setting']).to match Filters::EncryptionFilter::BASE64_STRING_PATTERN
|
92
115
|
end
|
93
116
|
end
|
94
117
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'chamber/filters/boolean_conversion_filter'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Filters
|
6
|
+
describe BooleanConversionFilter do
|
7
|
+
it 'can convert string boolean values into TrueClass and FalseClass even if they are deeply nested' do
|
8
|
+
filtered_data = BooleanConversionFilter.execute(
|
9
|
+
data: {
|
10
|
+
true_boolean: 'true',
|
11
|
+
boolean_group: {
|
12
|
+
yes_boolean: 'yes',
|
13
|
+
t_boolean: 't',
|
14
|
+
non_boolean: 'hello',
|
15
|
+
sub_boolean_group: {
|
16
|
+
false_boolean: 'false',
|
17
|
+
no_boolean: 'no',
|
18
|
+
nilly: nil,
|
19
|
+
non_boolean: 3, },
|
20
|
+
f_boolean: 'f',
|
21
|
+
non_boolean: Time.utc(2012, 8, 1),
|
22
|
+
nilly: nil, },
|
23
|
+
false_boolean: 'false',
|
24
|
+
non_boolean: [1, 2, 3] })
|
25
|
+
|
26
|
+
expect(filtered_data).to eql( true_boolean: true,
|
27
|
+
boolean_group: {
|
28
|
+
yes_boolean: true,
|
29
|
+
t_boolean: true,
|
30
|
+
non_boolean: 'hello',
|
31
|
+
sub_boolean_group: {
|
32
|
+
false_boolean: false,
|
33
|
+
no_boolean: false,
|
34
|
+
nilly: nil,
|
35
|
+
non_boolean: 3, },
|
36
|
+
f_boolean: false,
|
37
|
+
non_boolean: Time.utc(2012, 8, 1),
|
38
|
+
nilly: nil, },
|
39
|
+
false_boolean: false,
|
40
|
+
non_boolean: [1, 2, 3] )
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'chamber/filters/decryption_filter'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Filters
|
6
|
+
describe DecryptionFilter do
|
7
|
+
it 'will attempt to decrypt values which are marked as "secure"' do
|
8
|
+
filtered_settings = DecryptionFilter.execute( data: {
|
9
|
+
_secure_my_secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' },
|
10
|
+
decryption_key: './spec/spec_key' )
|
11
|
+
|
12
|
+
expect(filtered_settings.my_secure_setting).to eql 'hello'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'will not attempt to decrypt values which are not marked as "secure"' do
|
16
|
+
filtered_settings = DecryptionFilter.execute( data: {
|
17
|
+
my_secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' },
|
18
|
+
decryption_key: './spec/spec_key' )
|
19
|
+
|
20
|
+
expect(filtered_settings.my_secure_setting).to eql 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'will not attempt to decrypt values even if they are prefixed with "secure"' do
|
24
|
+
filtered_settings = DecryptionFilter.execute( data: {
|
25
|
+
secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' },
|
26
|
+
decryption_key: './spec/spec_key' )
|
27
|
+
|
28
|
+
expect(filtered_settings.secure_setting).to eql 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'will not attempt to decrypt values even if they are not properly encoded' do
|
32
|
+
filtered_settings = DecryptionFilter.execute( data: {
|
33
|
+
_secure_my_secure_setting: 'cJbFe0NI5\wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' },
|
34
|
+
decryption_key: './spec/spec_key' )
|
35
|
+
|
36
|
+
expect(filtered_settings.my_secure_setting).to eql 'cJbFe0NI5\wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'will not attempt to decrypt values if it guesses that they are not encrpyted' do
|
40
|
+
filtered_settings = DecryptionFilter.execute( data: {
|
41
|
+
_secure_my_secure_setting: 'hello' },
|
42
|
+
decryption_key: './spec/spec_key' )
|
43
|
+
|
44
|
+
expect(filtered_settings.my_secure_setting).to eql 'hello'
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'will raise an exception if there is an encrypted value that it cannot decrypt' do
|
48
|
+
expect { DecryptionFilter.execute(data: {
|
49
|
+
_secure_my_secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
|
50
|
+
}) }.to \
|
51
|
+
raise_error(Chamber::Errors::UndecryptableValueError, 'my_secure_setting appears to need decrypting but the decryption key is not available.')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'chamber/filters/encryption_filter'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Filters
|
6
|
+
describe EncryptionFilter do
|
7
|
+
it 'will attempt to encrypt values which are marked as "secure"' do
|
8
|
+
filtered_settings = EncryptionFilter.execute( data: {
|
9
|
+
_secure_my_secure_setting: 'hello' },
|
10
|
+
encryption_key: './spec/spec_key.pub' )
|
11
|
+
|
12
|
+
expect(filtered_settings._secure_my_secure_setting).to match EncryptionFilter::BASE64_STRING_PATTERN
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'will not attempt to encrypt values which are not marked as "secure"' do
|
16
|
+
filtered_settings = EncryptionFilter.execute( data: {
|
17
|
+
my_secure_setting: 'hello' },
|
18
|
+
encryption_key: './spec/spec_key.pub' )
|
19
|
+
|
20
|
+
expect(filtered_settings.my_secure_setting).to eql 'hello'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'will not attempt to encrypt values even if they are prefixed with "secure"' do
|
24
|
+
filtered_settings = EncryptionFilter.execute( data: {
|
25
|
+
secure_setting: 'hello' },
|
26
|
+
encryption_key: './spec/spec_key.pub' )
|
27
|
+
|
28
|
+
expect(filtered_settings.secure_setting).to eql 'hello'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'will attempt to encrypt values if they are not properly encoded' do
|
32
|
+
filtered_settings = EncryptionFilter.execute( data: {
|
33
|
+
_secure_my_secure_setting: 'fNI5\jwlBn' },
|
34
|
+
encryption_key: './spec/spec_key.pub' )
|
35
|
+
|
36
|
+
expect(filtered_settings._secure_my_secure_setting).to match EncryptionFilter::BASE64_STRING_PATTERN
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'will not attempt to encrypt values if it guesses that they are already encrpyted' do
|
40
|
+
filtered_settings = EncryptionFilter.execute( data: {
|
41
|
+
_secure_my_secure_setting: 'fNI5wlBniNhEU4396pmhWwx+A09bRAMJOUASuP7PzprewBX8CXYqL+v/uXOJpIRCLDjwe8quuC+j9iLcPU7HBRMr054gGxeqZexbLevXcPk7SrMis3qeEKmnAuarQGXe7ZAntidMY9Lx4pqSkhYXwQnI48d2Dh44qfaS9w2OrehSkpdFRnuxQeOpCKO/bleB0J88WGkytCohyHCRIpbaEjEC3UD52pnqMeu/ClNm+PBgE6Ci94pu5UUnZuIE/y+P4A3wgD6G/u8hgvAW51JwVryg/im1rayGAwWYNgupQ/5LDmjffwx7Q3fyMH2uF3CDIKRIC6U+mnM5SRMO4Dzysw==' },
|
42
|
+
encryption_key: './spec/spec_key.pub' )
|
43
|
+
|
44
|
+
expect(filtered_settings._secure_my_secure_setting).to eql 'fNI5wlBniNhEU4396pmhWwx+A09bRAMJOUASuP7PzprewBX8CXYqL+v/uXOJpIRCLDjwe8quuC+j9iLcPU7HBRMr054gGxeqZexbLevXcPk7SrMis3qeEKmnAuarQGXe7ZAntidMY9Lx4pqSkhYXwQnI48d2Dh44qfaS9w2OrehSkpdFRnuxQeOpCKO/bleB0J88WGkytCohyHCRIpbaEjEC3UD52pnqMeu/ClNm+PBgE6Ci94pu5UUnZuIE/y+P4A3wgD6G/u8hgvAW51JwVryg/im1rayGAwWYNgupQ/5LDmjffwx7Q3fyMH2uF3CDIKRIC6U+mnM5SRMO4Dzysw=='
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'chamber/filters/environment_filter'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Filters
|
6
|
+
describe EnvironmentFilter do
|
7
|
+
it 'can extract data from the environment if an existing variable matches the composite key' do
|
8
|
+
ENV['TEST_SETTING_GROUP_TEST_SETTING_LEVEL_TEST_SETTING'] = 'value 2'
|
9
|
+
|
10
|
+
filtered_data = EnvironmentFilter.execute(data: {
|
11
|
+
test_setting_group: {
|
12
|
+
test_setting_level: {
|
13
|
+
test_setting: 'value 1' }}})
|
14
|
+
|
15
|
+
expect(filtered_data.test_setting_group.test_setting_level.test_setting).to eql 'value 2'
|
16
|
+
|
17
|
+
ENV.delete('TEST_SETTING_GROUP_TEST_SETTING_LEVEL_TEST_SETTING')
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'does not affect items which are not stored in the environment' do
|
21
|
+
ENV['TEST_SETTING_GROUP_TEST_SETTING_LEVEL_TEST_SETTING'] = 'value 2'
|
22
|
+
|
23
|
+
filtered_data = EnvironmentFilter.execute(data: {
|
24
|
+
test_setting_group: {
|
25
|
+
test_setting_level: {
|
26
|
+
test_setting: 'value 1',
|
27
|
+
another_setting: 'value 3', }}})
|
28
|
+
|
29
|
+
expect(filtered_data.test_setting_group.test_setting_level.another_setting).to eql 'value 3'
|
30
|
+
|
31
|
+
ENV.delete('TEST_SETTING_GROUP_TEST_SETTING_LEVEL_TEST_SETTING')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'chamber/filters/namespace_filter'
|
3
|
+
require 'chamber/namespace_set'
|
4
|
+
|
5
|
+
module Chamber
|
6
|
+
module Filters
|
7
|
+
describe NamespaceFilter do
|
8
|
+
it 'can filter settings data based on the settings namespaces' do
|
9
|
+
filtered_settings = NamespaceFilter.execute(data: {
|
10
|
+
namespace_value: {
|
11
|
+
namespace_setting: 'value 1' },
|
12
|
+
other_namespace_value: {
|
13
|
+
other_namespace_setting: 'value 2' }},
|
14
|
+
namespaces: [
|
15
|
+
'namespace_value',
|
16
|
+
'other_namespace_value' ])
|
17
|
+
|
18
|
+
expect(filtered_settings.namespace_setting).to eql 'value 1'
|
19
|
+
expect(filtered_settings.other_namespace_setting).to eql 'value 2'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'ignores data which is not part of a namespace' do
|
23
|
+
filtered_settings = NamespaceFilter.execute(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
|
+
|
31
|
+
expect(filtered_settings.namespace_setting).to eql 'value 1'
|
32
|
+
expect(filtered_settings.non_namespaced_setting).to be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'ignores namespaces which do not exist in the data' do
|
36
|
+
filtered_settings = NamespaceFilter.execute(data: {
|
37
|
+
namespace_value: {
|
38
|
+
namespace_setting: 'value 1' }},
|
39
|
+
namespaces: [
|
40
|
+
'namespace_value',
|
41
|
+
'other_namespace_value' ])
|
42
|
+
|
43
|
+
expect(filtered_settings.namespace_setting).to eql 'value 1'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'does not filter data if it does not include any namespaces' do
|
47
|
+
filtered_settings = NamespaceFilter.execute(data: {
|
48
|
+
non_namespaced_setting: 'value 1' },
|
49
|
+
namespaces: [])
|
50
|
+
|
51
|
+
expect(filtered_settings.non_namespaced_setting).to eql 'value 1'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'can filter if it is given NamespaceSets' do
|
55
|
+
filtered_settings = NamespaceFilter.execute(data: {
|
56
|
+
namespace_value: {
|
57
|
+
namespace_setting: 'value 1',
|
58
|
+
another_namespace_setting: 'value 2' },
|
59
|
+
other_namespace_value: {
|
60
|
+
namespace_setting_1: 'value 1',
|
61
|
+
another_namespace_setting_2: 'value 2' },
|
62
|
+
non_namespaced_value: 'value 3' },
|
63
|
+
namespaces:
|
64
|
+
NamespaceSet.new(['namespace_value', 'other_namespace_value']) )
|
65
|
+
|
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
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|