chamber 2.8.0 → 2.9.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -0
- data/LICENSE.txt +19 -0
- data/Rakefile +1 -0
- data/bin/chamber +1 -0
- data/lib/chamber.rb +1 -0
- data/lib/chamber/binary/heroku.rb +1 -0
- data/lib/chamber/binary/runner.rb +1 -0
- data/lib/chamber/binary/travis.rb +1 -0
- data/lib/chamber/commands/base.rb +1 -0
- data/lib/chamber/commands/comparable.rb +1 -0
- data/lib/chamber/commands/compare.rb +1 -0
- data/lib/chamber/commands/files.rb +1 -0
- data/lib/chamber/commands/heroku.rb +1 -0
- data/lib/chamber/commands/heroku/clear.rb +1 -0
- data/lib/chamber/commands/heroku/compare.rb +1 -0
- data/lib/chamber/commands/heroku/pull.rb +1 -0
- data/lib/chamber/commands/heroku/push.rb +1 -0
- data/lib/chamber/commands/initialize.rb +5 -3
- data/lib/chamber/commands/securable.rb +1 -0
- data/lib/chamber/commands/secure.rb +1 -0
- data/lib/chamber/commands/show.rb +1 -0
- data/lib/chamber/commands/travis.rb +1 -0
- data/lib/chamber/commands/travis/secure.rb +1 -0
- data/lib/chamber/configuration.rb +1 -0
- data/lib/chamber/context_resolver.rb +10 -7
- data/lib/chamber/decryption_key.rb +1 -0
- data/lib/chamber/encryption_methods/none.rb +17 -0
- data/lib/chamber/encryption_methods/public_key.rb +27 -0
- data/lib/chamber/encryption_methods/ssl.rb +60 -0
- data/lib/chamber/environmentable.rb +1 -0
- data/lib/chamber/errors/decryption_failure.rb +1 -0
- data/lib/chamber/file.rb +9 -1
- data/lib/chamber/file_set.rb +4 -3
- data/lib/chamber/filters/boolean_conversion_filter.rb +2 -1
- data/lib/chamber/filters/decryption_filter.rb +20 -29
- data/lib/chamber/filters/encryption_filter.rb +29 -14
- data/lib/chamber/filters/environment_filter.rb +2 -1
- data/lib/chamber/filters/failed_decryption_filter.rb +3 -2
- data/lib/chamber/filters/insecure_filter.rb +1 -0
- data/lib/chamber/filters/namespace_filter.rb +2 -1
- data/lib/chamber/filters/secure_filter.rb +2 -1
- data/lib/chamber/filters/translate_secure_keys_filter.rb +2 -1
- data/lib/chamber/instance.rb +1 -0
- data/lib/chamber/namespace_set.rb +4 -3
- data/lib/chamber/rails.rb +1 -0
- data/lib/chamber/rails/railtie.rb +3 -1
- data/lib/chamber/rubinius_fix.rb +1 -0
- data/lib/chamber/settings.rb +23 -18
- data/lib/chamber/version.rb +2 -1
- data/spec/lib/chamber/commands/files_spec.rb +5 -2
- data/spec/lib/chamber/commands/heroku/clear_spec.rb +1 -0
- data/spec/lib/chamber/commands/heroku/compare_spec.rb +1 -0
- data/spec/lib/chamber/commands/heroku/pull_spec.rb +1 -0
- data/spec/lib/chamber/commands/heroku/push_spec.rb +1 -0
- data/spec/lib/chamber/commands/secure_spec.rb +5 -2
- data/spec/lib/chamber/commands/show_spec.rb +1 -0
- data/spec/lib/chamber/context_resolver_spec.rb +8 -5
- data/spec/lib/chamber/file_set_spec.rb +55 -52
- data/spec/lib/chamber/file_spec.rb +43 -9
- data/spec/lib/chamber/filters/boolean_conversion_filter_spec.rb +14 -5
- data/spec/lib/chamber/filters/decryption_filter_spec.rb +85 -9
- data/spec/lib/chamber/filters/encryption_filter_spec.rb +76 -10
- data/spec/lib/chamber/filters/environment_filter_spec.rb +9 -2
- data/spec/lib/chamber/filters/failed_decryption_filter_spec.rb +7 -6
- data/spec/lib/chamber/filters/insecure_filter_spec.rb +12 -4
- data/spec/lib/chamber/filters/namespace_filter_spec.rb +33 -14
- data/spec/lib/chamber/filters/secure_filter_spec.rb +8 -3
- data/spec/lib/chamber/filters/translate_secure_keys_filter_spec.rb +10 -3
- data/spec/lib/chamber/namespace_set_spec.rb +6 -3
- data/spec/lib/chamber/settings_spec.rb +36 -25
- data/spec/lib/chamber_spec.rb +25 -10
- data/spec/rails-2-test/config/application.rb +1 -0
- data/spec/rails-3-test/config/application.rb +1 -0
- data/spec/rails-4-test/config/application.rb +1 -0
- metadata +35 -9
- metadata.gz.sig +0 -0
- data/LICENSE +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70d5a99fb72440e64e3ef88a6ab33a3304466b19
|
4
|
+
data.tar.gz: a9e604aa036a20152fa0be993ccfcd69e47406de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6bafc0df4003a0f5dc2ef004bbb874b4489166e8000f8be0caa92e2edb09197b7716a0080d7941fe482721e996110f51baff07ca167af5f4907349b9b8e80d8
|
7
|
+
data.tar.gz: 50985ca6d2a0716b1256a0e09df31d9501df5e26119be403b99ebaa7b67b327832236fc47616272579bce02abb3d9b703af8af68b24cbf8463216c87f0a98a2f
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
UM���K]����@��jb}��TχN)�)�l�X�����]�Ժ�ha�����V�u�0h�J�&��$� ���]I~{cU��±��-�9rA��l�J�r_kV%|��KH��}oM�?�H0a�v%CC!�
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010-2016 The Kompanee, Ltd
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/Rakefile
CHANGED
data/bin/chamber
CHANGED
data/lib/chamber.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'pathname'
|
2
3
|
require 'fileutils'
|
3
4
|
require 'openssl'
|
@@ -25,7 +26,7 @@ class Initialize < Chamber::Commands::Base
|
|
25
26
|
|
26
27
|
::FileUtils.touch gitignore_filepath
|
27
28
|
|
28
|
-
unless ::File.read(gitignore_filepath)
|
29
|
+
unless ::File.read(gitignore_filepath) =~ /^.chamber.pem$/
|
29
30
|
shell.append_to_file gitignore_filepath, "\n# Private and protected key files for Chamber\n"
|
30
31
|
shell.append_to_file gitignore_filepath, "#{private_key_filename}\n"
|
31
32
|
shell.append_to_file gitignore_filepath, "#{protected_key_filename}\n"
|
@@ -76,7 +77,8 @@ class Initialize < Chamber::Commands::Base
|
|
76
77
|
|
77
78
|
def gem_path
|
78
79
|
@gem_path ||= Pathname.new(
|
79
|
-
::File.expand_path('../../../..', __FILE__)
|
80
|
+
::File.expand_path('../../../..', __FILE__),
|
81
|
+
)
|
80
82
|
end
|
81
83
|
|
82
84
|
def settings_filepath
|
@@ -129,7 +131,7 @@ class Initialize < Chamber::Commands::Base
|
|
129
131
|
end
|
130
132
|
|
131
133
|
def rsa_key_passphrase
|
132
|
-
@rsa_key_passphrase
|
134
|
+
@rsa_key_passphrase ||= SecureRandom.uuid
|
133
135
|
end
|
134
136
|
end
|
135
137
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'pathname'
|
2
3
|
require 'socket'
|
3
4
|
require 'hashie/mash'
|
@@ -36,19 +37,21 @@ class ContextResolver
|
|
36
37
|
if options[:namespaces] == []
|
37
38
|
require options[:rootpath].join('config', 'application').to_s
|
38
39
|
|
39
|
-
options[:namespaces]
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
options[:namespaces] = [
|
41
|
+
::Rails.env,
|
42
|
+
Socket.gethostname,
|
43
|
+
]
|
43
44
|
end
|
44
45
|
else
|
45
|
-
options[:basepath]
|
46
|
+
options[:basepath] ||= options[:rootpath]
|
46
47
|
end
|
47
48
|
|
48
49
|
options[:basepath] = Pathname.new(options[:basepath])
|
49
50
|
|
50
|
-
options[:files] ||= [
|
51
|
-
|
51
|
+
options[:files] ||= [
|
52
|
+
options[:basepath] + 'settings*.yml',
|
53
|
+
options[:basepath] + 'settings',
|
54
|
+
]
|
52
55
|
|
53
56
|
options
|
54
57
|
rescue LoadError
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Chamber
|
2
|
+
module EncryptionMethods
|
3
|
+
class None
|
4
|
+
def self.encrypt(_key, value, _encryption_key)
|
5
|
+
value
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.decrypt(key, value, _decryption_key)
|
9
|
+
warn "WARNING: It appears that you would like to keep your information for #{key} " \
|
10
|
+
"secure, however the value for that setting does not appear to be encrypted. " \
|
11
|
+
"Make sure you run 'chamber secure' before committing."
|
12
|
+
|
13
|
+
value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Chamber
|
2
|
+
module EncryptionMethods
|
3
|
+
class PublicKey
|
4
|
+
def self.encrypt(_key, value, encryption_key)
|
5
|
+
value = YAML.dump(value)
|
6
|
+
encrypted_string = encryption_key.public_encrypt(value)
|
7
|
+
|
8
|
+
Base64.strict_encode64(encrypted_string)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.decrypt(_key, value, decryption_key)
|
12
|
+
if decryption_key.nil?
|
13
|
+
value
|
14
|
+
else
|
15
|
+
decoded_string = Base64.strict_decode64(value)
|
16
|
+
unencrypted_value = decryption_key.private_decrypt(decoded_string)
|
17
|
+
|
18
|
+
begin
|
19
|
+
_unserialized_value = YAML.load(unencrypted_value)
|
20
|
+
rescue TypeError
|
21
|
+
unencrypted_value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Chamber
|
2
|
+
module EncryptionMethods
|
3
|
+
class Ssl
|
4
|
+
LARGE_DATA_STRING_PATTERN = %r{\A([A-Za-z0-9\+\/#]*\={0,2})#([A-Za-z0-9\+\/#]*\={0,2})#([A-Za-z0-9\+\/#]*\={0,2})\z} # rubocop:disable Metrics/LineLength
|
5
|
+
|
6
|
+
def self.encrypt(_key, value, encryption_key)
|
7
|
+
value = YAML.dump(value)
|
8
|
+
cipher = OpenSSL::Cipher::Cipher.new('AES-128-CBC')
|
9
|
+
cipher.encrypt
|
10
|
+
symmetric_key = cipher.random_key
|
11
|
+
iv = cipher.random_iv
|
12
|
+
|
13
|
+
# encrypt all data with this key and iv
|
14
|
+
encrypted_data = cipher.update(value) + cipher.final
|
15
|
+
|
16
|
+
# encrypt the key with the public key
|
17
|
+
encrypted_key = encryption_key.public_encrypt(symmetric_key)
|
18
|
+
|
19
|
+
# assemble the resulting Base64 encoded data, the key
|
20
|
+
Base64.strict_encode64(encrypted_key) + '#' +
|
21
|
+
Base64.strict_encode64(iv) + '#' +
|
22
|
+
Base64.strict_encode64(encrypted_data)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.decrypt(key, value, decryption_key)
|
26
|
+
if decryption_key.nil?
|
27
|
+
value
|
28
|
+
else
|
29
|
+
key, iv, decoded_string = value.
|
30
|
+
match(LARGE_DATA_STRING_PATTERN).
|
31
|
+
captures.
|
32
|
+
map do |part|
|
33
|
+
Base64.strict_decode64(part)
|
34
|
+
end
|
35
|
+
key = decryption_key.private_decrypt(key)
|
36
|
+
|
37
|
+
cipher_dec = OpenSSL::Cipher::Cipher.new('AES-128-CBC')
|
38
|
+
|
39
|
+
cipher_dec.decrypt
|
40
|
+
|
41
|
+
cipher_dec.key = key
|
42
|
+
cipher_dec.iv = iv
|
43
|
+
|
44
|
+
begin
|
45
|
+
unencrypted_value = cipher_dec.update(decoded_string) + cipher_dec.final
|
46
|
+
rescue OpenSSL::Cipher::CipherError
|
47
|
+
raise Chamber::Errors::DecryptionFailure,
|
48
|
+
'A decryption error occurred. It was probably due to invalid key data.'
|
49
|
+
end
|
50
|
+
|
51
|
+
begin
|
52
|
+
_unserialized_value = YAML.load(unencrypted_value)
|
53
|
+
rescue TypeError
|
54
|
+
unencrypted_value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/chamber/file.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'pathname'
|
2
3
|
require 'yaml'
|
3
4
|
require 'erb'
|
@@ -83,7 +84,14 @@ class File < Pathname
|
|
83
84
|
file_contents.
|
84
85
|
sub!(
|
85
86
|
/^(\s*)_secure_#{escaped_name}(\s*):(\s*)['"]?#{escaped_value}['"]?$/,
|
86
|
-
"\\1_secure_#{name_pieces.last}\\2:\\3#{secure_value}"
|
87
|
+
"\\1_secure_#{name_pieces.last}\\2:\\3#{secure_value}",
|
88
|
+
)
|
89
|
+
|
90
|
+
file_contents.
|
91
|
+
sub!(
|
92
|
+
/^(\s*)_secure_#{escaped_name}(\s*):(\s*)\|((?:\n\1\s{2}.*)+)/,
|
93
|
+
"\\1_secure_#{name_pieces.last}\\2:\\3#{secure_value}",
|
94
|
+
)
|
87
95
|
end
|
88
96
|
|
89
97
|
write(file_contents)
|
data/lib/chamber/file_set.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'pathname'
|
2
3
|
require 'chamber/namespace_set'
|
3
4
|
require 'chamber/file'
|
@@ -163,7 +164,7 @@ class FileSet
|
|
163
164
|
# # => <Chamber::Settings>
|
164
165
|
#
|
165
166
|
def to_settings
|
166
|
-
files.
|
167
|
+
files.inject(Settings.new) do |settings, file|
|
167
168
|
settings.merge(file.to_settings).tap do |merged|
|
168
169
|
yield merged if block_given?
|
169
170
|
end
|
@@ -207,7 +208,7 @@ class FileSet
|
|
207
208
|
# duplicates removed.
|
208
209
|
#
|
209
210
|
def files
|
210
|
-
@files ||= lambda
|
211
|
+
@files ||= lambda {
|
211
212
|
sorted_relevant_files = []
|
212
213
|
|
213
214
|
file_globs.each do |glob|
|
@@ -225,7 +226,7 @@ class FileSet
|
|
225
226
|
end
|
226
227
|
|
227
228
|
sorted_relevant_files.uniq
|
228
|
-
|
229
|
+
}.call
|
229
230
|
end
|
230
231
|
|
231
232
|
private
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Chamber
|
2
3
|
module Filters
|
3
4
|
class BooleanConversionFilter
|
@@ -6,7 +7,7 @@ class BooleanConversionFilter
|
|
6
7
|
end
|
7
8
|
|
8
9
|
def self.execute(options = {})
|
9
|
-
new(options).
|
10
|
+
new(options).__send__(:execute)
|
10
11
|
end
|
11
12
|
|
12
13
|
protected
|
@@ -1,14 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'openssl'
|
2
3
|
require 'base64'
|
3
4
|
require 'hashie/mash'
|
4
5
|
require 'yaml'
|
6
|
+
require 'chamber/encryption_methods/public_key'
|
7
|
+
require 'chamber/encryption_methods/ssl'
|
8
|
+
require 'chamber/encryption_methods/none'
|
5
9
|
require 'chamber/errors/decryption_failure'
|
6
10
|
|
7
11
|
module Chamber
|
8
12
|
module Filters
|
9
13
|
class DecryptionFilter
|
10
|
-
SECURE_KEY_TOKEN
|
11
|
-
BASE64_STRING_PATTERN
|
14
|
+
SECURE_KEY_TOKEN = /\A_secure_/
|
15
|
+
BASE64_STRING_PATTERN = %r{\A[A-Za-z0-9\+/]{342}==\z}
|
16
|
+
LARGE_DATA_STRING_PATTERN = %r{\A([A-Za-z0-9\+\/#]*\={0,2})#([A-Za-z0-9\+\/#]*\={0,2})#([A-Za-z0-9\+\/#]*\={0,2})\z} # rubocop:disable Metrics/LineLength
|
12
17
|
|
13
18
|
def initialize(options = {})
|
14
19
|
self.decryption_key = options.fetch(:decryption_key, nil)
|
@@ -16,7 +21,7 @@ class DecryptionFilter
|
|
16
21
|
end
|
17
22
|
|
18
23
|
def self.execute(options = {})
|
19
|
-
new(options).
|
24
|
+
new(options).__send__(:execute)
|
20
25
|
end
|
21
26
|
|
22
27
|
protected
|
@@ -30,8 +35,8 @@ class DecryptionFilter
|
|
30
35
|
raw_data.each_pair do |key, value|
|
31
36
|
settings[key] = if value.respond_to? :each_pair
|
32
37
|
execute(value)
|
33
|
-
elsif key.match(SECURE_KEY_TOKEN)
|
34
|
-
|
38
|
+
elsif key.match(SECURE_KEY_TOKEN)
|
39
|
+
decryption_method(value).decrypt(key, value, decryption_key)
|
35
40
|
else
|
36
41
|
value
|
37
42
|
end
|
@@ -54,31 +59,17 @@ class DecryptionFilter
|
|
54
59
|
|
55
60
|
private
|
56
61
|
|
57
|
-
def
|
58
|
-
if value.match
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
value
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def decrypt(value)
|
71
|
-
if decryption_key.nil?
|
72
|
-
value
|
73
|
-
else
|
74
|
-
decoded_string = Base64.strict_decode64(value)
|
75
|
-
unencrypted_value = decryption_key.private_decrypt(decoded_string)
|
76
|
-
|
77
|
-
begin
|
78
|
-
_unserialized_value = YAML.load(unencrypted_value)
|
79
|
-
rescue TypeError
|
80
|
-
unencrypted_value
|
62
|
+
def decryption_method(value)
|
63
|
+
if value.respond_to?(:match)
|
64
|
+
if value.match(BASE64_STRING_PATTERN)
|
65
|
+
EncryptionMethods::PublicKey
|
66
|
+
elsif value.match(LARGE_DATA_STRING_PATTERN)
|
67
|
+
EncryptionMethods::Ssl
|
68
|
+
else
|
69
|
+
EncryptionMethods::None
|
81
70
|
end
|
71
|
+
else
|
72
|
+
EncryptionMethods::None
|
82
73
|
end
|
83
74
|
end
|
84
75
|
end
|