chamber 2.2.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 94ba60754a727dae0bbfe6519cf3c0610a20b395
4
- data.tar.gz: 63fb2ae59e7083ce8ead5e83c6c74c41905b809b
3
+ metadata.gz: e00049d9950a63a991be3de4cec30e8afd9f3ed9
4
+ data.tar.gz: ef49dca6ba236376806c878ebe462170e7317259
5
5
  SHA512:
6
- metadata.gz: 4e05ce98bd1110227bb32dfce42393a82c0b78e7f055ff5245e9491af05e2484841bd49d78af79009ea9d01bc0691edb00c4eaf87e2a339700794a9fe11b95fc
7
- data.tar.gz: a9ae301824a743a9669b93f71da831e67ea17bf98a175980c2e4eba708d5805fcac64c15a5e820ae90282cf2bda8db59dd7bbe9032c5775de22610ce92b2c5bc
6
+ metadata.gz: efcee15432655ae9ac0ccf3ec639b7520506159cb237868abb8a365c56108727ec6e964140584f09b29dc65da3de302a7157d6d56dab23d92d3bd964bacb0a3d
7
+ data.tar.gz: 34148d8932aad7777144b425999ea93eee32f0615450eb50f207754b5a29b7125b4b22c27898d8b1e5970782bc972e9b99cf2ba6bc606414a72f476e581f2f52
@@ -17,8 +17,8 @@ class Compare < Chamber::Commands::Base
17
17
  secured_settings.to_s(pair_separator: "\n",
18
18
  value_surrounder: '')
19
19
  else
20
- all_settings.to_s(pair_separator: "\n",
21
- value_surrounder: '')
20
+ current_settings.to_s(pair_separator: "\n",
21
+ value_surrounder: '')
22
22
  end
23
23
  end
24
24
 
@@ -12,7 +12,7 @@ module Securable
12
12
  merge(files: ignored_settings_filepaths).
13
13
  reject { |k, v| k == 'basepath' }
14
14
  self.ignored_settings_instance = Chamber::Instance.new(ignored_settings_options)
15
- self.all_settings_instance = Chamber::Instance.new(options)
15
+ self.current_settings_instance = Chamber::Instance.new(options)
16
16
  self.only_sensitive = options[:only_sensitive]
17
17
  end
18
18
 
@@ -20,28 +20,36 @@ module Securable
20
20
 
21
21
  attr_accessor :only_sensitive,
22
22
  :ignored_settings_instance,
23
- :all_settings_instance
23
+ :current_settings_instance
24
24
 
25
25
  def securable_environment_variables
26
26
  if only_sensitive
27
- secured_settings.to_environment
27
+ securable_settings.to_environment
28
28
  else
29
- all_settings.to_environment
29
+ current_settings.to_environment
30
30
  end
31
31
  end
32
32
 
33
- def secured_settings
34
- ignored_settings_instance.settings.merge(all_settings.secured)
33
+ def insecure_environment_variables
34
+ securable_settings.insecure.to_environment
35
35
  end
36
36
 
37
- def all_settings
38
- all_settings_instance.settings
37
+ def securable_settings
38
+ ignored_settings.merge(current_settings.securable)
39
+ end
40
+
41
+ def current_settings
42
+ current_settings_instance.settings
43
+ end
44
+
45
+ def ignored_settings
46
+ ignored_settings_instance.settings
39
47
  end
40
48
 
41
49
  def ignored_settings_filepaths
42
50
  shell_escaped_chamber_filenames = chamber.filenames.map { |filename| Shellwords.escape(filename) }
43
51
 
44
- `git ls-files --other --ignored --exclude-from=.gitignore | sed -e "s|^|#{Shellwords.escape(rootpath)}/|" | grep --colour=never -E '#{shell_escaped_chamber_filenames.join('|')}'`.split("\n")
52
+ `git ls-files --other --ignored --exclude-from=.gitignore | sed -e "s|^|#{Shellwords.escape(rootpath.to_s)}/|" | grep --colour=never -E '#{shell_escaped_chamber_filenames.join('|')}'`.split("\n")
45
53
  end
46
54
  end
47
55
  end
@@ -11,9 +11,7 @@ class Secure < Chamber::Commands::Base
11
11
 
12
12
  def call
13
13
  disable_warnings do
14
- securable_environment_variables.each do |key, value|
15
- next if value.match %r{\A[A-Za-z0-9\+\/]{342}==\z}
16
-
14
+ insecure_environment_variables.each do |key, value|
17
15
  if dry_run
18
16
  shell.say_status 'encrypt', key, :blue
19
17
  else
data/lib/chamber/file.rb CHANGED
@@ -71,9 +71,20 @@ class File < Pathname
71
71
  end
72
72
 
73
73
  def secure
74
- secure_settings = to_settings.secure
74
+ insecure_settings = to_settings.insecure.to_flattened_name_hash
75
+ secure_settings = to_settings.insecure.secure.to_flattened_name_hash
76
+ file_contents = self.read
75
77
 
76
- ::File.open(self, 'w') { |file| file.write YAML.dump(secure_settings.to_hash) }
78
+ insecure_settings.each_pair do |name_pieces, value|
79
+ secure_value = secure_settings[name_pieces]
80
+
81
+ file_contents.
82
+ sub!(
83
+ /^(\s*)_secure_#{name_pieces.last}(\s*):(\s*)['"]?#{value}['"]?$/,
84
+ "\\1_secure_#{name_pieces.last}\\2:\\3#{secure_value}")
85
+ end
86
+
87
+ self.write(file_contents)
77
88
  end
78
89
 
79
90
  protected
@@ -229,7 +229,7 @@ class FileSet
229
229
  private
230
230
 
231
231
  def all_files
232
- @all_files ||= Pathname.glob(file_globs).sort
232
+ @all_files ||= file_globs.map { |fg| Pathname.glob(fg) }.flatten.uniq.sort
233
233
  end
234
234
 
235
235
  def non_namespaced_files
@@ -19,8 +19,6 @@ class BooleanConversionFilter
19
19
  if value.respond_to? :each_pair
20
20
  execute(value)
21
21
  else
22
- break if value.nil?
23
-
24
22
  settings[key] = if value.is_a? String
25
23
  case value
26
24
  when 'false', 'f', 'no'
@@ -29,24 +29,22 @@ class DecryptionFilter
29
29
  raw_data.each_pair do |key, value|
30
30
  if value.respond_to? :each_pair
31
31
  value = execute(value)
32
- elsif value.respond_to? :match
33
- if key.match(SECURE_KEY_TOKEN)
34
- key = key.to_s.sub(SECURE_KEY_TOKEN, '')
35
- value = if value.match(BASE64_STRING_PATTERN)
36
- if decryption_key.nil?
37
- value
38
- else
39
- decoded_string = Base64.strict_decode64(value)
40
- decryption_key.private_decrypt(decoded_string)
41
- end
42
- else
43
- warn "WARNING: It appears that you would like to keep your information for #{key} secure, however the value for that setting does not appear to be encrypted. Make sure you run 'chamber settings secure' before committing."
44
-
32
+ elsif key.match(SECURE_KEY_TOKEN) && value.respond_to?(:match)
33
+ value = if value.match(BASE64_STRING_PATTERN)
34
+ if decryption_key.nil?
45
35
  value
36
+ else
37
+ decoded_string = Base64.strict_decode64(value)
38
+ decryption_key.private_decrypt(decoded_string)
46
39
  end
47
- else
48
- key = key.to_s
49
- end
40
+ else
41
+ warn 'WARNING: It appears that you would like to keep your ' \
42
+ "information for #{key} secure, however the value for that " \
43
+ 'setting does not appear to be encrypted. Make sure you run ' \
44
+ "'chamber secure' before committing."
45
+
46
+ value
47
+ end
50
48
  end
51
49
 
52
50
  settings[key] = value
@@ -0,0 +1,29 @@
1
+ require 'hashie/mash'
2
+ require 'chamber/filters/secure_filter'
3
+
4
+ module Chamber
5
+ module Filters
6
+ class InsecureFilter < SecureFilter
7
+ BASE64 = %r{\A[A-Za-z0-9\+\/]{342}==\z}
8
+
9
+ protected
10
+
11
+ def execute(raw_data = data)
12
+ securable_settings = super
13
+ settings = Hashie::Mash.new
14
+
15
+ securable_settings.each_pair do |key, value|
16
+ value = if value.respond_to? :each_pair
17
+ execute(value)
18
+ elsif value.respond_to? :match
19
+ value unless value.match(BASE64)
20
+ end
21
+
22
+ settings[key] = value unless value.nil?
23
+ end
24
+
25
+ settings
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,54 @@
1
+ require 'hashie/mash'
2
+ require 'chamber/errors/undecryptable_value_error'
3
+
4
+ module Chamber
5
+ module Filters
6
+ class TranslateSecureKeysFilter
7
+ SECURE_KEY_TOKEN = %r{\A_secure_}
8
+
9
+ def initialize(options = {})
10
+ self.data = options.fetch(:data).dup
11
+ end
12
+
13
+ def self.execute(options = {})
14
+ self.new(options).send(:execute)
15
+ end
16
+
17
+ protected
18
+
19
+ attr_accessor :data
20
+
21
+ def execute(raw_data = data)
22
+ settings = Hashie::Mash.new
23
+
24
+ raw_data.each_pair do |key, value|
25
+ if value.respond_to? :each_pair
26
+ value = execute(value)
27
+ end
28
+
29
+ key = key.to_s
30
+
31
+ if key.match(SECURE_KEY_TOKEN)
32
+ key = key.sub(SECURE_KEY_TOKEN, '')
33
+ end
34
+
35
+ settings[key] = value
36
+ end
37
+
38
+ settings
39
+ end
40
+
41
+ def decryption_key=(keyish)
42
+ return @decryption_key = nil if keyish.nil?
43
+
44
+ key_content = if ::File.readable?(::File.expand_path(keyish))
45
+ ::File.read(::File.expand_path(keyish))
46
+ else
47
+ keyish
48
+ end
49
+
50
+ @decryption_key = OpenSSL::PKey::RSA.new(key_content)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,5 +1,4 @@
1
1
  require 'hashie/mash'
2
- require 'chamber/system_environment'
3
2
  require 'chamber/namespace_set'
4
3
  require 'chamber/filters/namespace_filter'
5
4
  require 'chamber/filters/encryption_filter'
@@ -7,6 +6,8 @@ require 'chamber/filters/decryption_filter'
7
6
  require 'chamber/filters/environment_filter'
8
7
  require 'chamber/filters/boolean_conversion_filter'
9
8
  require 'chamber/filters/secure_filter'
9
+ require 'chamber/filters/translate_secure_keys_filter'
10
+ require 'chamber/filters/insecure_filter'
10
11
 
11
12
  ###
12
13
  # Internal: Represents the base settings storage needed for Chamber.
@@ -26,6 +27,7 @@ class Settings
26
27
  ]
27
28
  self.post_filters = options[:post_filters] || [
28
29
  Filters::DecryptionFilter,
30
+ Filters::TranslateSecureKeysFilter,
29
31
  Filters::EnvironmentFilter,
30
32
  Filters::BooleanConversionFilter,
31
33
  ]
@@ -53,7 +55,9 @@ class Settings
53
55
  # Returns a Hash sorted alphabetically by the names of the keys
54
56
  #
55
57
  def to_environment
56
- Hash[SystemEnvironment.extract_from(data).sort]
58
+ to_concatenated_name_hash('_').each_with_object({}) do |pair, env_hash|
59
+ env_hash[pair[0].upcase] = pair[1].to_s
60
+ end
57
61
  end
58
62
 
59
63
  ###
@@ -69,17 +73,85 @@ class Settings
69
73
  # # => 'MY_KEY="my value" MY_OTHER_KEY="my other value"'
70
74
  #
71
75
  def to_s(options = {})
72
- pair_separator = options[:pair_separator] || ' '
73
- value_surrounder = options[:value_surrounder] || '"'
74
- name_value_separator = options[:name_value_separator] || '='
76
+ hierarchical_separator = options[:hierarchical_separator] || '_'
77
+ pair_separator = options[:pair_separator] || ' '
78
+ value_surrounder = options[:value_surrounder] || '"'
79
+ name_value_separator = options[:name_value_separator] || '='
80
+
81
+ concatenated_name_hash = to_concatenated_name_hash(hierarchical_separator)
75
82
 
76
- pairs = to_environment.to_a.map do |pair|
77
- %Q{#{pair[0]}#{name_value_separator}#{value_surrounder}#{pair[1]}#{value_surrounder}}
83
+ pairs = concatenated_name_hash.to_a.map do |key, value|
84
+ %Q{#{key.upcase}#{name_value_separator}#{value_surrounder}#{value}#{value_surrounder}}
78
85
  end
79
86
 
80
87
  pairs.join(pair_separator)
81
88
  end
82
89
 
90
+ ###
91
+ # Internal: Returns the Settings data as a Hash for easy manipulation.
92
+ # Changes made to the hash will *not* be reflected in the original Settings
93
+ # object.
94
+ #
95
+ # Returns a Hash
96
+ #
97
+ def to_hash
98
+ data.to_hash
99
+ end
100
+
101
+ ###
102
+ # Internal: Returns a hash which contains the flattened name hierarchy of the
103
+ # setting as the keys and the values of each setting as the value.
104
+ #
105
+ # Examples:
106
+ # Settings.new(settings: {
107
+ # my_setting: 'value',
108
+ # there: 'was not that easy?',
109
+ # level_1: {
110
+ # level_2: {
111
+ # some_setting: 'hello',
112
+ # another: 'goodbye',
113
+ # },
114
+ # body: 'gracias',
115
+ # },
116
+ # }).to_flattened_name_hash
117
+ # # => {
118
+ # ['my_setting'] => 'value',
119
+ # ['there'] => 'was not that easy?',
120
+ # ['level_1', 'level_2', 'some_setting'] => 'hello',
121
+ # ['level_1', 'level_2', 'another'] => 'goodbye',
122
+ # ['level_1', 'body'] => 'gracias',
123
+ # }
124
+ #
125
+ # Returns a Hash
126
+ #
127
+ def to_flattened_name_hash(hash = data, parent_keys = [])
128
+ flattened_name_hash = {}
129
+
130
+ hash.each_pair do |key, value|
131
+ flattened_name_components = parent_keys.dup.push(key)
132
+
133
+ if value.respond_to?(:each_pair)
134
+ flattened_name_hash.merge! to_flattened_name_hash(value, flattened_name_components)
135
+ else
136
+ flattened_name_hash[flattened_name_components] = value
137
+ end
138
+ end
139
+
140
+ flattened_name_hash
141
+ end
142
+
143
+ def to_concatenated_name_hash(hierarchical_separator = '_')
144
+ concatenated_name_hash = {}
145
+
146
+ to_flattened_name_hash.each_pair do |flattened_name, value|
147
+ concatenated_name = flattened_name.join(hierarchical_separator)
148
+
149
+ concatenated_name_hash[concatenated_name] = value
150
+ end
151
+
152
+ concatenated_name_hash.sort
153
+ end
154
+
83
155
  ###
84
156
  # Internal: Merges a Settings object with another Settings object or
85
157
  # a hash-like object.
@@ -115,17 +187,6 @@ class Settings
115
187
  settings: raw_data.merge(other_settings.raw_data))
116
188
  end
117
189
 
118
- ###
119
- # Internal: Returns the Settings data as a Hash for easy manipulation.
120
- # Changes made to the hash will *not* be reflected in the original Settings
121
- # object.
122
- #
123
- # Returns a Hash
124
- #
125
- def to_hash
126
- data.to_hash
127
- end
128
-
129
190
  ###
130
191
  # Internal: Determines whether a Settings is equal to another hash-like
131
192
  # object.
@@ -147,7 +208,7 @@ class Settings
147
208
  self.namespaces == other.namespaces
148
209
  end
149
210
 
150
- def secured
211
+ def securable
151
212
  Settings.new( metadata.merge(
152
213
  settings: raw_data,
153
214
  pre_filters: [Filters::SecureFilter]))
@@ -155,9 +216,16 @@ class Settings
155
216
 
156
217
  def secure
157
218
  Settings.new( metadata.merge(
158
- settings: @raw_data,
219
+ settings: raw_data,
159
220
  pre_filters: [Filters::EncryptionFilter],
160
- post_filters: [] ))
221
+ post_filters: [Filters::TranslateSecureKeysFilter] ))
222
+ end
223
+
224
+ def insecure
225
+ Settings.new( metadata.merge(
226
+ settings: raw_data,
227
+ pre_filters: [Filters::InsecureFilter],
228
+ post_filters: [Filters::TranslateSecureKeysFilter] ))
161
229
  end
162
230
 
163
231
  protected
@@ -1,3 +1,3 @@
1
1
  module Chamber
2
- VERSION = '2.2.1'
2
+ VERSION = '2.3.0'
3
3
  end
@@ -5,27 +5,31 @@ require 'fileutils'
5
5
  module Chamber
6
6
  module Commands
7
7
  describe Secure do
8
- let(:rootpath) { Pathname.new(::File.expand_path('./spec/fixtures')) }
9
- let(:settings_filename) { rootpath + 'settings' + 'unencrypted.yml' }
10
- let(:options) { { basepath: rootpath,
8
+ let(:rootpath) { Pathname.new(::File.expand_path('./spec/fixtures')) }
9
+ let(:settings_directory) { rootpath + 'settings' }
10
+ let(:settings_filename) { settings_directory + 'unencrypted.yml' }
11
+ let(:options) { { basepath: rootpath,
11
12
  rootpath: rootpath,
12
13
  encryption_key: rootpath + '../spec_key',
13
14
  shell: double.as_null_object } }
14
15
 
16
+ before(:each) do
17
+ ::FileUtils.mkdir_p settings_directory unless ::File.exist? settings_directory
18
+ end
19
+
20
+ after(:each) do
21
+ ::FileUtils.rm_rf(settings_directory) if ::File.exist? settings_directory
22
+ end
23
+
15
24
  it 'can return values formatted as environment variables' do
16
- ::FileUtils.mkdir_p rootpath + 'settings' unless ::File.exist? rootpath + 'settings'
17
- ::File.open(settings_filename, 'w') do |file|
18
- file.write <<-HEREDOC
25
+ settings_filename.write <<-HEREDOC
19
26
  test:
20
27
  _secure_my_unencrpyted_setting: hello
21
28
  HEREDOC
22
- end
23
29
 
24
30
  Secure.call(options)
25
31
 
26
- expect(::File.read(settings_filename)).to match %r{_secure_my_unencrpyted_setting: [A-Za-z0-9\+\/]{342}==}
27
-
28
- ::File.delete(settings_filename)
32
+ expect(settings_filename.read).to match %r{_secure_my_unencrpyted_setting: [A-Za-z0-9\+\/]{342}==}
29
33
  end
30
34
  end
31
35
  end
@@ -12,8 +12,8 @@ describe Show do
12
12
  it 'can return values formatted as environment variables' do
13
13
  expect(Show.call(options.merge(as_env: true))).to eql(
14
14
  <<-HEREDOC.chomp
15
- ANOTHER_LEVEL_LEVEL_THREE_AN_ARRAY="["item 1", "item 2", "item 3"]"
16
15
  ANOTHER_LEVEL_LEVEL_THREE_A_SCALAR="hello"
16
+ ANOTHER_LEVEL_LEVEL_THREE_AN_ARRAY="["item 1", "item 2", "item 3"]"
17
17
  ANOTHER_LEVEL_SETTING_ONE="1"
18
18
  ANOTHER_LEVEL_SETTING_TWO="2"
19
19
  MY_BOOLEAN="false"
@@ -103,7 +103,9 @@ describe File do
103
103
  end
104
104
 
105
105
  it 'can securely encrypt the settings contained in a file' do
106
- tempfile = create_tempfile_with_content %Q({ _secure_setting: hello })
106
+ tempfile = create_tempfile_with_content <<-HEREDOC
107
+ _secure_setting: hello
108
+ HEREDOC
107
109
  settings_file = File.new path: tempfile.path,
108
110
  encryption_key: './spec/spec_key.pub'
109
111
 
@@ -113,5 +115,59 @@ describe File do
113
115
 
114
116
  expect(settings_file.to_settings.send(:raw_data)['_secure_setting']).to match Filters::EncryptionFilter::BASE64_STRING_PATTERN
115
117
  end
118
+
119
+ it 'does not encrypt the settings contained in a file which are already secure' do
120
+ tempfile = create_tempfile_with_content <<-HEREDOC
121
+ _secure_setting: hello
122
+ _secure_other_setting: g4ryOaWniDPht0x1pW10XWgtC7Bax2yQAM3+p9ZDMmBUKlVXgvCn8MvdvciX0126P7uuLylY7Pdbm8AnpjeaTvPOaDnDjPATkH1xpQG/HKBy+7zd67SMb3tJ3sxJNkYm6RrmydFHkDCghG37lvCnuZs1Jvd/mhpr/+thqKvtI+c/vzY+eFxM52lnoWWOgqwGCtUjb+PMbq+HjId6X8uRbpL1SpINA6WYJwvxTVK9XD/HYn67Fcqdova4dEHoqwzFfE+XVXM8uesE1DG3PFNhAzkT+mWXtBmo17i+K4wrOO06I13uDS3x+7LqoZz/Ez17SPXRJze4M/wyWfm43pnuVw==
123
+ HEREDOC
124
+
125
+ settings_file = File.new path: tempfile.path,
126
+ encryption_key: './spec/spec_key.pub'
127
+
128
+ settings_file.secure
129
+
130
+ settings_file = File.new path: tempfile.path
131
+
132
+ expect(settings_file.to_settings.send(:raw_data)['_secure_setting']).to match Filters::EncryptionFilter::BASE64_STRING_PATTERN
133
+ expect(settings_file.to_settings.send(:raw_data)['_secure_other_setting']).to eql "g4ryOaWniDPht0x1pW10XWgtC7Bax2yQAM3+p9ZDMmBUKlVXgvCn8MvdvciX0126P7uuLylY7Pdbm8AnpjeaTvPOaDnDjPATkH1xpQG/HKBy+7zd67SMb3tJ3sxJNkYm6RrmydFHkDCghG37lvCnuZs1Jvd/mhpr/+thqKvtI+c/vzY+eFxM52lnoWWOgqwGCtUjb+PMbq+HjId6X8uRbpL1SpINA6WYJwvxTVK9XD/HYn67Fcqdova4dEHoqwzFfE+XVXM8uesE1DG3PFNhAzkT+mWXtBmo17i+K4wrOO06I13uDS3x+7LqoZz/Ez17SPXRJze4M/wyWfm43pnuVw=="
134
+ end
135
+
136
+ it 'does not rewrite the entire file but only the encrypted settings' do
137
+ tempfile = create_tempfile_with_content <<-HEREDOC
138
+ default:
139
+ stuff: &default
140
+ _secure_setting: hello
141
+ _secure_other_setting: g4ryOaWniDPht0x1pW10XWgtC7Bax2yQAM3+p9ZDMmBUKlVXgvCn8MvdvciX0126P7uuLylY7Pdbm8AnpjeaTvPOaDnDjPATkH1xpQG/HKBy+7zd67SMb3tJ3sxJNkYm6RrmydFHkDCghG37lvCnuZs1Jvd/mhpr/+thqKvtI+c/vzY+eFxM52lnoWWOgqwGCtUjb+PMbq+HjId6X8uRbpL1SpINA6WYJwvxTVK9XD/HYn67Fcqdova4dEHoqwzFfE+XVXM8uesE1DG3PFNhAzkT+mWXtBmo17i+K4wrOO06I13uDS3x+7LqoZz/Ez17SPXRJze4M/wyWfm43pnuVw==
142
+
143
+ other:
144
+ stuff:
145
+ <<: *default
146
+ _secure_another_setting: "Thanks for all the fish"
147
+ regular_setting: <%= 1 + 1 %>
148
+ HEREDOC
149
+
150
+ settings_file = File.new path: tempfile.path,
151
+ encryption_key: './spec/spec_key.pub'
152
+
153
+ settings_file.secure
154
+
155
+ file_contents = ::File.read(tempfile.path)
156
+ secure_setting_encoded = file_contents[/ _secure_setting: ([A-Za-z0-9\+\/]{342}==)$/, 1]
157
+ secure_another_setting_encoded = file_contents[/ _secure_another_setting: ([A-Za-z0-9\+\/]{342}==)$/, 1]
158
+
159
+ expect(::File.read(tempfile.path)).to eql <<-HEREDOC
160
+ default:
161
+ stuff: &default
162
+ _secure_setting: #{secure_setting_encoded}
163
+ _secure_other_setting: g4ryOaWniDPht0x1pW10XWgtC7Bax2yQAM3+p9ZDMmBUKlVXgvCn8MvdvciX0126P7uuLylY7Pdbm8AnpjeaTvPOaDnDjPATkH1xpQG/HKBy+7zd67SMb3tJ3sxJNkYm6RrmydFHkDCghG37lvCnuZs1Jvd/mhpr/+thqKvtI+c/vzY+eFxM52lnoWWOgqwGCtUjb+PMbq+HjId6X8uRbpL1SpINA6WYJwvxTVK9XD/HYn67Fcqdova4dEHoqwzFfE+XVXM8uesE1DG3PFNhAzkT+mWXtBmo17i+K4wrOO06I13uDS3x+7LqoZz/Ez17SPXRJze4M/wyWfm43pnuVw==
164
+
165
+ other:
166
+ stuff:
167
+ <<: *default
168
+ _secure_another_setting: #{secure_another_setting_encoded}
169
+ regular_setting: <%= 1 + 1 %>
170
+ HEREDOC
171
+ end
116
172
  end
117
173
  end
@@ -21,6 +21,7 @@ describe BooleanConversionFilter do
21
21
  non_boolean: Time.utc(2012, 8, 1),
22
22
  nilly: nil, },
23
23
  false_boolean: 'false',
24
+ nilly: nil,
24
25
  non_boolean: [1, 2, 3] })
25
26
 
26
27
  expect(filtered_data).to eql( true_boolean: true,
@@ -37,6 +38,7 @@ describe BooleanConversionFilter do
37
38
  non_boolean: Time.utc(2012, 8, 1),
38
39
  nilly: nil, },
39
40
  false_boolean: false,
41
+ nilly: nil,
40
42
  non_boolean: [1, 2, 3] )
41
43
  end
42
44
  end
@@ -9,7 +9,7 @@ describe DecryptionFilter do
9
9
  _secure_my_secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' },
10
10
  decryption_key: './spec/spec_key' )
11
11
 
12
- expect(filtered_settings.my_secure_setting).to eql 'hello'
12
+ expect(filtered_settings._secure_my_secure_setting).to eql 'hello'
13
13
  end
14
14
 
15
15
  it 'will not attempt to decrypt values which are not marked as "secure"' do
@@ -33,7 +33,7 @@ describe DecryptionFilter do
33
33
  _secure_my_secure_setting: 'cJbFe0NI5\wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' },
34
34
  decryption_key: './spec/spec_key' )
35
35
 
36
- expect(filtered_settings.my_secure_setting).to eql 'cJbFe0NI5\wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
36
+ expect(filtered_settings._secure_my_secure_setting).to eql 'cJbFe0NI5\wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
37
37
  end
38
38
 
39
39
  it 'will not attempt to decrypt values if it guesses that they are not encrpyted' do
@@ -41,14 +41,14 @@ describe DecryptionFilter do
41
41
  _secure_my_secure_setting: 'hello' },
42
42
  decryption_key: './spec/spec_key' )
43
43
 
44
- expect(filtered_settings.my_secure_setting).to eql 'hello'
44
+ expect(filtered_settings._secure_my_secure_setting).to eql 'hello'
45
45
  end
46
46
 
47
47
  it 'simply returns the encrypted string if there is no decryption key' do
48
48
  filtered_settings = DecryptionFilter.execute( data: {
49
49
  _secure_my_secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' })
50
50
 
51
- expect(filtered_settings.my_secure_setting).to eql 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
51
+ expect(filtered_settings._secure_my_secure_setting).to eql 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
52
52
  end
53
53
  end
54
54
  end
@@ -0,0 +1,54 @@
1
+ require 'rspectacular'
2
+ require 'chamber/filters/insecure_filter'
3
+
4
+ module Chamber
5
+ module Filters
6
+ describe InsecureFilter do
7
+ it 'will return values which are marked as "secure" if they are unencrypted' do
8
+ filtered_settings = InsecureFilter.execute( data: {
9
+ _secure_my_secure_setting: 'hello' })
10
+
11
+ expect(filtered_settings._secure_my_secure_setting).to match 'hello'
12
+ end
13
+
14
+ it 'will not return values which are not marked as "secure"' do
15
+ filtered_settings = InsecureFilter.execute( data: {
16
+ my_secure_setting: 'hello' })
17
+
18
+ expect(filtered_settings.my_secure_setting).to be_nil
19
+ end
20
+
21
+ it 'will properly return values even if they are mixed and deeply nested' do
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
+
29
+ expect(filtered_settings._secure_setting).to eql 'hello'
30
+ expect(filtered_settings.secure_setting).to be_nil
31
+ expect(filtered_settings.secure_group._secure_nested_setting).to eql 'movie'
32
+ expect(filtered_settings.secure_group.insecure_nested_setting).to be_nil
33
+ end
34
+
35
+ it 'will not return values which are encrypted' do
36
+ filtered_settings = InsecureFilter.execute( data: {
37
+ _secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
38
+ secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
39
+ _secure_other_setting: 'hello',
40
+ secure_group: {
41
+ _secure_nested_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
42
+ _secure_other_nested_setting: 'goodbye',
43
+ insecure_nested_setting: 'dinner' }})
44
+
45
+ expect(filtered_settings._secure_setting?).to eql false
46
+ expect(filtered_settings.secure_setting?).to eql false
47
+ expect(filtered_settings._secure_other_setting).to eql 'hello'
48
+ expect(filtered_settings.secure_group._secure_nested_setting?).to eql false
49
+ expect(filtered_settings.secure_group._secure_other_nested_setting).to eql 'goodbye'
50
+ expect(filtered_settings.secure_group.insecure_nested_setting?).to eql false
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,29 @@
1
+ require 'rspectacular'
2
+ require 'chamber/filters/translate_secure_keys_filter'
3
+
4
+ module Chamber
5
+ module Filters
6
+ describe TranslateSecureKeysFilter do
7
+ it 'will translate keys if they start with "_secure_"' do
8
+ filtered_settings = TranslateSecureKeysFilter.execute( data: {
9
+ _secure_my_secure_setting: 'hello' })
10
+
11
+ expect(filtered_settings.my_secure_setting).to eql 'hello'
12
+ end
13
+
14
+ it 'will not translate keys if they do not start with "_secure_"' do
15
+ filtered_settings = TranslateSecureKeysFilter.execute( data: {
16
+ my_secure_setting: 'hello' })
17
+
18
+ expect(filtered_settings.my_secure_setting).to eql 'hello'
19
+ end
20
+
21
+ it 'will not translate the key if it starts with "secure"' do
22
+ filtered_settings = TranslateSecureKeysFilter.execute( data: {
23
+ secure_setting: 'hello' })
24
+
25
+ expect(filtered_settings.secure_setting).to eql 'hello'
26
+ end
27
+ end
28
+ end
29
+ end
@@ -31,25 +31,33 @@ describe Settings do
31
31
  end
32
32
 
33
33
  it 'knows how to convert itself into an environment hash' do
34
- allow(SystemEnvironment).to receive(:extract_from).
35
- and_return(:environment => :development)
36
-
37
- settings = Settings.new(settings: {setting: 'value'})
38
-
39
- expect(settings.to_environment).to eql(:environment => :development)
40
- expect(SystemEnvironment).to have_received(:extract_from).
41
- with(Hashie::Mash.new setting: 'value')
34
+ settings = Settings.new(settings: {
35
+ my_setting: 'value',
36
+ level_1: {
37
+ level_2: {
38
+ some_setting: 'hello',
39
+ another: 'goodbye',
40
+ },
41
+ body: 'gracias',
42
+ },
43
+ there: 'was not that easy?',
44
+ })
45
+
46
+ expect(settings.to_environment).to eql(
47
+ 'MY_SETTING' => 'value',
48
+ 'LEVEL_1_LEVEL_2_SOME_SETTING' => 'hello',
49
+ 'LEVEL_1_LEVEL_2_ANOTHER' => 'goodbye',
50
+ 'LEVEL_1_BODY' => 'gracias',
51
+ 'THERE' => 'was not that easy?',
52
+ )
42
53
  end
43
54
 
44
55
  it 'sorts environment variables by name when converted to an environment hash so that they are easier to parse for humans' do
45
- allow(SystemEnvironment).to receive(:extract_from).
46
- and_return('C' => 'value',
47
- 'D' => 'value',
48
- 'A' => 'value',
49
- 'E' => 'value',
50
- 'B' => 'value',)
51
-
52
- settings = Settings.new(settings: { setting: 'value' })
56
+ settings = Settings.new(settings: { 'C' => 'value',
57
+ 'D' => 'value',
58
+ 'A' => 'value',
59
+ 'E' => 'value',
60
+ 'B' => 'value' })
53
61
 
54
62
  expect(settings.to_environment.to_a).to eql([['A', 'value'],
55
63
  ['B', 'value'],
@@ -59,16 +67,46 @@ describe Settings do
59
67
  end
60
68
 
61
69
  it 'can convert itself into a string' do
62
- allow(SystemEnvironment).to receive(:extract_from).
63
- and_return('C' => 'cv',
64
- 'D' => 'dv',
65
- 'A' => 'av',
66
- 'E' => 'ev',
67
- 'B' => 'bv',)
68
-
69
- settings = Settings.new(settings: { setting: 'value' })
70
+ settings = Settings.new(settings: {
71
+ my_setting: 'value',
72
+ level_1: {
73
+ level_2: {
74
+ some_setting: 'hello',
75
+ another: 'goodbye',
76
+ },
77
+ body: 'gracias',
78
+ },
79
+ there: 'was not that easy?',
80
+ })
81
+
82
+ expect(settings.to_s).to eql %Q{LEVEL_1_BODY="gracias" LEVEL_1_LEVEL_2_ANOTHER="goodbye" LEVEL_1_LEVEL_2_SOME_SETTING="hello" MY_SETTING="value" THERE="was not that easy?"}
83
+ end
70
84
 
71
- expect(settings.to_s).to eql %Q{A="av" B="bv" C="cv" D="dv" E="ev"}
85
+ it 'can convert itself into a string with custom options' do
86
+ settings = Settings.new(settings: {
87
+ my_setting: 'value',
88
+ level_1: {
89
+ level_2: {
90
+ some_setting: 'hello',
91
+ another: 'goodbye',
92
+ },
93
+ body: 'gracias',
94
+ },
95
+ there: 'was not that easy?',
96
+ })
97
+
98
+ settings_string = settings.to_s hierarchical_separator: '/',
99
+ pair_separator: "\n",
100
+ value_surrounder: "'",
101
+ name_value_separator: ': '
102
+
103
+ expect(settings_string).to eql <<-HEREDOC.chomp
104
+ LEVEL_1/BODY: 'gracias'
105
+ LEVEL_1/LEVEL_2/ANOTHER: 'goodbye'
106
+ LEVEL_1/LEVEL_2/SOME_SETTING: 'hello'
107
+ MY_SETTING: 'value'
108
+ THERE: 'was not that easy?'
109
+ HEREDOC
72
110
  end
73
111
 
74
112
  it 'can merge itself with a hash' do
@@ -113,6 +151,30 @@ describe Settings do
113
151
  expect(settings.to_hash).not_to be_a Hashie::Mash
114
152
  end
115
153
 
154
+ it 'can convert itself into a hash with flattened names' do
155
+ settings = Settings.new(settings: {
156
+ my_setting: 'value',
157
+ level_1: {
158
+ level_2: {
159
+ some_setting: 'hello',
160
+ another: 'goodbye',
161
+ },
162
+ body: 'gracias',
163
+ },
164
+ there: 'was not that easy?',
165
+ })
166
+
167
+ expect(settings.to_flattened_name_hash).to eql(
168
+ ['my_setting'] => 'value',
169
+ ['level_1', 'level_2', 'some_setting'] => 'hello',
170
+ ['level_1', 'level_2', 'another'] => 'goodbye',
171
+ ['level_1', 'body'] => 'gracias',
172
+ ['there'] => 'was not that easy?',
173
+ )
174
+ expect(settings.to_flattened_name_hash).to be_a Hash
175
+ expect(settings.to_flattened_name_hash).not_to be_a Hashie::Mash
176
+ end
177
+
116
178
  it 'does not allow manipulation of the internal setting hash when converted to a Hash' do
117
179
  settings = Settings.new(settings: {setting: 'value'})
118
180
 
@@ -186,7 +248,7 @@ describe Settings do
186
248
 
187
249
  secure_settings = settings.secure
188
250
 
189
- expect(secure_settings._secure_my_encrypted_setting).to match Filters::EncryptionFilter::BASE64_STRING_PATTERN
251
+ expect(secure_settings.my_encrypted_setting).to match Filters::EncryptionFilter::BASE64_STRING_PATTERN
190
252
  end
191
253
 
192
254
  it 'can check if it is equal to other items which can be converted into hashes' do
@@ -195,17 +257,34 @@ describe Settings do
195
257
  expect(settings).to eq('setting' => 'value')
196
258
  end
197
259
 
198
- it 'can filter secured settings' do
199
- settings = Settings.new(settings: {
200
- _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
201
- my_insecure_setting: 'goodbye',
260
+ it 'can filter securable settings' do
261
+ settings = Settings.new(settings: {
262
+ _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
263
+ _secure_my_unencrypted_setting: 'nifty',
264
+ my_insecure_setting: 'goodbye',
265
+ },
266
+ decryption_key: './spec/spec_key')
267
+
268
+ secured_settings = settings.securable
269
+
270
+ expect(secured_settings.my_encrypted_setting).to eql 'hello'
271
+ expect(secured_settings.my_unencrypted_setting).to eql 'nifty'
272
+ expect(secured_settings.my_insecure_setting?).to eql false
273
+ end
274
+
275
+ it 'can filter unencrypted settings' do
276
+ settings = Settings.new(settings: {
277
+ _secure_my_encrypted_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==',
278
+ _secure_my_unencrypted_setting: 'nifty',
279
+ my_insecure_setting: 'goodbye',
202
280
  },
203
281
  decryption_key: './spec/spec_key')
204
282
 
205
- secured_settings = settings.secured
283
+ secured_settings = settings.insecure
206
284
 
207
- expect(secured_settings.my_encrypted_setting).to eql 'hello'
208
- expect(secured_settings.my_insecure_setting?).to eql false
285
+ expect(secured_settings.my_encrypted_setting?).to eql false
286
+ expect(secured_settings.my_unencrypted_setting).to eql 'nifty'
287
+ expect(secured_settings.my_insecure_setting?).to eql false
209
288
  end
210
289
  end
211
290
  end
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: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - stevenhallen
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-04-06 00:00:00.000000000 Z
14
+ date: 2014-06-29 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: thor
@@ -19,56 +19,56 @@ dependencies:
19
19
  requirements:
20
20
  - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: 0.18.1
22
+ version: 0.19.1
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: 0.18.1
29
+ version: 0.19.1
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: hashie
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  requirements:
34
34
  - - "~>"
35
35
  - !ruby/object:Gem::Version
36
- version: '2.0'
36
+ version: 2.0.5
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
41
  - - "~>"
42
42
  - !ruby/object:Gem::Version
43
- version: '2.0'
43
+ version: 2.0.5
44
44
  - !ruby/object:Gem::Dependency
45
45
  name: rspec
46
46
  requirement: !ruby/object:Gem::Requirement
47
47
  requirements:
48
48
  - - "~>"
49
49
  - !ruby/object:Gem::Version
50
- version: 3.0.0.beta
50
+ version: '3.0'
51
51
  type: :development
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
55
  - - "~>"
56
56
  - !ruby/object:Gem::Version
57
- version: 3.0.0.beta
57
+ version: '3.0'
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspectacular
60
60
  requirement: !ruby/object:Gem::Requirement
61
61
  requirements:
62
62
  - - "~>"
63
63
  - !ruby/object:Gem::Version
64
- version: 0.23.0
64
+ version: '0.46'
65
65
  type: :development
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
68
68
  requirements:
69
69
  - - "~>"
70
70
  - !ruby/object:Gem::Version
71
- version: 0.23.0
71
+ version: '0.46'
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: codeclimate-test-reporter
74
74
  requirement: !ruby/object:Gem::Requirement
@@ -127,14 +127,15 @@ files:
127
127
  - lib/chamber/filters/decryption_filter.rb
128
128
  - lib/chamber/filters/encryption_filter.rb
129
129
  - lib/chamber/filters/environment_filter.rb
130
+ - lib/chamber/filters/insecure_filter.rb
130
131
  - lib/chamber/filters/namespace_filter.rb
131
132
  - lib/chamber/filters/secure_filter.rb
133
+ - lib/chamber/filters/translate_secure_keys_filter.rb
132
134
  - lib/chamber/instance.rb
133
135
  - lib/chamber/namespace_set.rb
134
136
  - lib/chamber/rails.rb
135
137
  - lib/chamber/rails/railtie.rb
136
138
  - lib/chamber/settings.rb
137
- - lib/chamber/system_environment.rb
138
139
  - lib/chamber/version.rb
139
140
  - spec/fixtures/settings.yml
140
141
  - spec/lib/chamber/commands/files_spec.rb
@@ -151,11 +152,12 @@ files:
151
152
  - spec/lib/chamber/filters/decryption_filter_spec.rb
152
153
  - spec/lib/chamber/filters/encryption_filter_spec.rb
153
154
  - spec/lib/chamber/filters/environment_filter_spec.rb
155
+ - spec/lib/chamber/filters/insecure_filter_spec.rb
154
156
  - spec/lib/chamber/filters/namespace_filter_spec.rb
155
157
  - spec/lib/chamber/filters/secure_filter_spec.rb
158
+ - spec/lib/chamber/filters/translate_secure_keys_filter_spec.rb
156
159
  - spec/lib/chamber/namespace_set_spec.rb
157
160
  - spec/lib/chamber/settings_spec.rb
158
- - spec/lib/chamber/system_environment_spec.rb
159
161
  - spec/lib/chamber_spec.rb
160
162
  - spec/rails-2-test/config.ru
161
163
  - spec/rails-2-test/config/application.rb
@@ -190,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
192
  version: '0'
191
193
  requirements: []
192
194
  rubyforge_project: chamber
193
- rubygems_version: 2.2.2
195
+ rubygems_version: 2.3.0
194
196
  signing_key:
195
197
  specification_version: 4
196
198
  summary: A surprisingly configurable convention-based approach to managing your application's
@@ -211,11 +213,12 @@ test_files:
211
213
  - spec/lib/chamber/filters/decryption_filter_spec.rb
212
214
  - spec/lib/chamber/filters/encryption_filter_spec.rb
213
215
  - spec/lib/chamber/filters/environment_filter_spec.rb
216
+ - spec/lib/chamber/filters/insecure_filter_spec.rb
214
217
  - spec/lib/chamber/filters/namespace_filter_spec.rb
215
218
  - spec/lib/chamber/filters/secure_filter_spec.rb
219
+ - spec/lib/chamber/filters/translate_secure_keys_filter_spec.rb
216
220
  - spec/lib/chamber/namespace_set_spec.rb
217
221
  - spec/lib/chamber/settings_spec.rb
218
- - spec/lib/chamber/system_environment_spec.rb
219
222
  - spec/lib/chamber_spec.rb
220
223
  - spec/rails-2-test/config/application.rb
221
224
  - spec/rails-2-test/config.ru
@@ -1,55 +0,0 @@
1
- require 'chamber/environmentable'
2
-
3
- ###
4
- # Internal: Gives access to the existing environment for importing/exporting
5
- # values.
6
- #
7
- module Chamber
8
- module SystemEnvironment
9
- extend Environmentable
10
-
11
- ###
12
- # Internal: Allows the environment variable-compatible variables to be
13
- # extracted from a passed in hash.
14
- #
15
- # Examples:
16
- #
17
- # ###
18
- # # Extracts the environment variables based on the hash keys
19
- # #
20
- # SystemEnvironment.extract_from(
21
- # level_one_1: {
22
- # level_two_1: 'value 1',
23
- # level_two_2: {
24
- # level_three_1: 'value 2' } } )
25
- #
26
- # # => {
27
- # 'LEVEL_ONE_1_LEVEL_TWO_1' => 'env value 1',
28
- # 'LEVEL_ONE_1_LEVEL_TWO_2_LEVEL_THREE_1' => 'env value 2',
29
- # }
30
- #
31
- # ###
32
- # # Can extract environment variables if said variables are prefixed
33
- # #
34
- # SystemEnvironment.extract_from({
35
- # level_two_1: 'value 1',
36
- # level_two_2: 'value 2'
37
- # },
38
- # ['prefix'])
39
- #
40
- # # => {
41
- # 'PREFIX_LEVEL_TWO_1' => 'value 1',
42
- # 'PREFIX_LEVEL_TWO_2' => 'value 2',
43
- # }
44
- #
45
- def self.extract_from(settings, parent_keys = [])
46
- with_environment(settings, parent_keys,
47
- ->(key, value, environment_keys) do
48
- extract_from(value, environment_keys)
49
- end,
50
- ->(key, value, environment_key) do
51
- { environment_key => value.to_s }
52
- end)
53
- end
54
- end
55
- end
@@ -1,51 +0,0 @@
1
- require 'rspectacular'
2
- require 'chamber/system_environment'
3
-
4
- module Chamber
5
- describe SystemEnvironment do
6
- it 'can extract environment variables based on a hash that is passed in' do
7
- source_hash = {
8
- level_one_1: {
9
- level_two_1: 'value 1',
10
- level_two_2: {
11
- level_three_1: 'value 2',
12
- level_three_2: 'value 3',
13
- },
14
- level_two_3: 'value 4',
15
- level_one_2: 'value 5' }
16
- }
17
-
18
- expect(SystemEnvironment.extract_from(source_hash)).to eql({
19
- 'LEVEL_ONE_1_LEVEL_TWO_1' => 'value 1',
20
- 'LEVEL_ONE_1_LEVEL_TWO_2_LEVEL_THREE_1' => 'value 2',
21
- 'LEVEL_ONE_1_LEVEL_TWO_2_LEVEL_THREE_2' => 'value 3',
22
- 'LEVEL_ONE_1_LEVEL_TWO_3' => 'value 4',
23
- 'LEVEL_ONE_1_LEVEL_ONE_2' => 'value 5',
24
- })
25
- end
26
-
27
- it 'converts all items to strings so that they are usable as an environment variable' do
28
- source_hash = {
29
- value_one: Time.utc(2013, 10, 8, 18, 0, 1),
30
- value_two: 3,
31
- }
32
-
33
- expect(SystemEnvironment.extract_from(source_hash)).to eql({
34
- 'VALUE_ONE' => '2013-10-08 18:00:01 UTC',
35
- 'VALUE_TWO' => '3',
36
- })
37
- end
38
-
39
- it 'allows extracted environment variables to be prefixed for compatibility' do
40
- source_hash = {
41
- value_one: 'value',
42
- }
43
-
44
- environment_hash = SystemEnvironment.extract_from(source_hash, [:prefix])
45
-
46
- expect(environment_hash).to eql({
47
- 'PREFIX_VALUE_ONE' => 'value',
48
- })
49
- end
50
- end
51
- end