chamber 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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