chamber 2.11.0 → 2.12.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 +0 -0
- data/README.md +40 -29
- data/lib/chamber/binary/runner.rb +23 -0
- data/lib/chamber/commands/initialize.rb +103 -31
- data/lib/chamber/commands/secure.rb +3 -5
- data/lib/chamber/commands/sign.rb +17 -0
- data/lib/chamber/commands/verify.rb +25 -0
- data/lib/chamber/encryption_methods/public_key.rb +5 -3
- data/lib/chamber/encryption_methods/ssl.rb +2 -0
- data/lib/chamber/file.rb +23 -0
- data/lib/chamber/file_set.rb +15 -1
- data/lib/chamber/files/signature.rb +85 -0
- data/lib/chamber/filters/encryption_filter.rb +0 -1
- data/lib/chamber/filters/environment_filter.rb +2 -0
- data/lib/chamber/instance.rb +8 -0
- data/lib/chamber/{rails/railtie.rb → integrations/rails.rb} +2 -2
- data/lib/chamber/integrations/sinatra.rb +29 -0
- data/lib/chamber/key_pair.rb +4 -0
- data/lib/chamber/keys/base.rb +15 -3
- data/lib/chamber/rails.rb +1 -1
- data/lib/chamber/version.rb +1 -1
- metadata +21 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2244ac836ff26be17476fae140643427bd61ec3
|
4
|
+
data.tar.gz: 3acbda9e98904305001f0aad0cd45f92909afbfa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca89abd49137ef3cae8a54b5a4a38029a55ef4e9498473dab173094704be265f0801e8698c34281dc624cbedb1b3f9f5d68ff6a3466b97b6c328575a6ab5c829
|
7
|
+
data.tar.gz: 5205ce62e2c54e5d5348a50e7bffa7fe2e196516b9d667f2b903c086f646e885c7d6459aba57fb9620edd96930f1480aa8655baa10f658fd312ad294a5e2c44a
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -1,45 +1,56 @@
|
|
1
|
-
# Chamber
|
1
|
+
# Chamber
|
2
|
+
[](https://rubygems.org/gems/chamber)    [](http://travis-ci.org/thekompanee/chamber) [](https://codeclimate.com/github/thekompanee/chamber) [](https://codeclimate.com/github/thekompanee/chamber)
|
2
3
|
|
3
|
-
Chamber is the auto-encrypting, extremely organizable, Heroku-loving,
|
4
|
-
non-extra-repo-needing, non-Rails-specific-ing, CI-serving
|
5
|
-
management library.
|
4
|
+
Chamber is the auto-encrypting, extremely organizable, Heroku-loving,
|
5
|
+
CLI-having, non-extra-repo-needing, non-Rails-specific-ing, CI-serving
|
6
|
+
configuration management library.
|
6
7
|
|
7
|
-
|
8
|
+
We looked at all of the options out there and thought something was still
|
9
|
+
missing, so we wrote Chamber. We made it with lots of ❤ and we hope you like it
|
10
|
+
as much as we do.
|
8
11
|
|
9
|
-
|
12
|
+
## What Sets Chamber Apart?
|
10
13
|
|
11
|
-
|
14
|
+
For an idea of how Chamber compares to other popular libraries, check out our
|
15
|
+
[Gem Comparison][comparison].
|
12
16
|
|
13
|
-
|
14
|
-
necessary](https://github.com/thekompanee/chamber/wiki/Basic-Usage#convention-over-configuration)
|
15
|
-
1. Thou shalt [seamlessly work with Heroku](https://github.com/thekompanee/chamber/wiki/Heroku) or other deployment platforms, where custom
|
16
|
-
settings must be stored in [environment variables](https://github.com/thekompanee/chamber/wiki/Environment-Variable-Compatibility)
|
17
|
-
1. Thou shalt seamlessly work with [Travis CI](https://github.com/thekompanee/chamber/wiki/TravisCI) and other cloud CI platforms
|
18
|
-
1. Thou shalt not force users to use arcane
|
19
|
-
[long_variables_to_keep_their_settings_organized](https://github.com/thekompanee/chamber/wiki/Accessing-Settings)
|
20
|
-
1. Thou shalt not require users keep a separate repo or cloud share sync [just to
|
21
|
-
keep their secure settings updated](https://github.com/thekompanee/chamber/wiki/Encrypting-Your-Settings)
|
22
|
-
1. Thou shalt not be bound to a single framework like Rails (it should be usable [in
|
23
|
-
plain Ruby projects](https://github.com/thekompanee/chamber/wiki/Basic-Usage#in-a-plain-old-ruby-project))
|
24
|
-
1. Thou shalt have an [easy-to-use CLI](https://github.com/thekompanee/chamber/wiki/Command-Line-Reference) for scripting
|
25
|
-
1. Thou shalt easily integrate with Capistrano for deployments
|
26
|
-
1. Thou shalt be [well documented](https://github.com/thekompanee/chamber/wiki/) with full test coverage
|
27
|
-
1. Thou shalt not have to worry about [accidentally committing secure settings](https://github.com/thekompanee/chamber/wiki/Git-Commit-Hook)
|
17
|
+
## Basic Usage
|
28
18
|
|
29
|
-
|
30
|
-
|
31
|
-
Visit the [wiki](https://github.com/thekompanee/chamber/wiki)
|
19
|
+
You can view our Basic Usage Guide [here][basic-usage]. Otherwise, for the full
|
20
|
+
Chamber guide, visit the [wiki][wiki].
|
32
21
|
|
33
22
|
## Credits
|
34
23
|
|
35
|
-
Chamber was written by Jeff Felchner and
|
24
|
+
Chamber was written by [Jeff Felchner][jeff-profile] and
|
25
|
+
[Mark McEahern][mark-profile]
|
36
26
|
|
37
|
-
![The Kompanee]
|
27
|
+
![The Kompanee][kompanee-logo]
|
38
28
|
|
39
|
-
Chamber is maintained and funded by [The Kompanee, Ltd.]
|
29
|
+
Chamber is maintained and funded by [The Kompanee, Ltd.][kompanee-site]
|
40
30
|
|
41
31
|
The names and logos for The Kompanee are trademarks of The Kompanee, Ltd.
|
42
32
|
|
43
33
|
## License
|
44
34
|
|
45
|
-
Chamber is Copyright © 2014 Jeff Felchner and Mark McEahern. It is free
|
35
|
+
Chamber is Copyright © 2014-2018 Jeff Felchner and Mark McEahern. It is free
|
36
|
+
software, and may be redistributed under the terms specified in the
|
37
|
+
[LICENSE][license] file.
|
38
|
+
|
39
|
+
[accessing]: https://github.com/thekompanee/chamber/wiki/Accessing-Settings
|
40
|
+
[basic-usage]: https://github.com/thekompanee/chamber/wiki/Basic-Usage
|
41
|
+
[cli]: https://github.com/thekompanee/chamber/wiki/CLI-Overview
|
42
|
+
[commit-hook]: https://github.com/thekompanee/chamber/wiki/Git-Commit-Hooks
|
43
|
+
[comparison]: https://github.com/thekompanee/chamber/wiki/Gem-Comparison
|
44
|
+
[encryption]: https://github.com/thekompanee/chamber/wiki/Encryption-Basics
|
45
|
+
[env-vars]: https://github.com/thekompanee/chamber/wiki/Environment-Variables
|
46
|
+
[heroku]: https://github.com/thekompanee/chamber/wiki/Heroku
|
47
|
+
[inch]: https://inch-ci.org/github/thekompanee/chamber
|
48
|
+
[jeff-profile]: https://github.com/jfelchner
|
49
|
+
[kompanee-logo]: https://kompanee-public-assets.s3.amazonaws.com/readmes/kompanee-horizontal-black.png
|
50
|
+
[kompanee-site]: http://www.thekompanee.com
|
51
|
+
[license]: https://github.com/thekompanee/chamber/blob/master/LICENSE.txt
|
52
|
+
[mark-profile]: https://github.com/m5rk
|
53
|
+
[namespace-keys]: https://github.com/thekompanee/chamber/wiki/Namespaced-Key-Pairs
|
54
|
+
[plain-ruby]: https://github.com/thekompanee/chamber/wiki/Installation#in-a-ruby-project-or-ruby-gem
|
55
|
+
[travis]: https://github.com/thekompanee/chamber/wiki/TravisCI
|
56
|
+
[wiki]: https://github.com/thekompanee/chamber/wiki
|
@@ -7,6 +7,8 @@ require 'chamber/binary/heroku'
|
|
7
7
|
require 'chamber/commands/show'
|
8
8
|
require 'chamber/commands/files'
|
9
9
|
require 'chamber/commands/secure'
|
10
|
+
require 'chamber/commands/sign'
|
11
|
+
require 'chamber/commands/verify'
|
10
12
|
require 'chamber/commands/compare'
|
11
13
|
require 'chamber/commands/initialize'
|
12
14
|
|
@@ -143,9 +145,30 @@ class Runner < Thor
|
|
143
145
|
|
144
146
|
################################################################################
|
145
147
|
|
148
|
+
desc 'sign', 'Creates or verifies signatures for all current settings files using ' \
|
149
|
+
'the signature private key.'
|
150
|
+
|
151
|
+
method_option :verify,
|
152
|
+
type: :boolean,
|
153
|
+
default: false
|
154
|
+
|
155
|
+
def sign
|
156
|
+
if options[:verify]
|
157
|
+
Commands::Verify.call(options.merge(shell: self))
|
158
|
+
else
|
159
|
+
Commands::Sign.call(options.merge(shell: self))
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
################################################################################
|
164
|
+
|
146
165
|
desc 'init', 'Sets Chamber up using best practices for secure configuration ' \
|
147
166
|
'management'
|
148
167
|
|
168
|
+
method_option :signature,
|
169
|
+
type: :boolean,
|
170
|
+
default: false
|
171
|
+
|
149
172
|
def init
|
150
173
|
Commands::Initialize.call(options.merge(shell: self))
|
151
174
|
end
|
@@ -16,13 +16,15 @@ class Initialize < Chamber::Commands::Base
|
|
16
16
|
end
|
17
17
|
|
18
18
|
attr_accessor :basepath,
|
19
|
-
:namespaces
|
19
|
+
:namespaces,
|
20
|
+
:signature
|
20
21
|
|
21
22
|
def initialize(options = {})
|
22
23
|
super
|
23
24
|
|
24
25
|
self.basepath = Chamber.configuration.basepath
|
25
26
|
self.namespaces = options.fetch(:namespaces, [])
|
27
|
+
self.signature = options.fetch(:signature)
|
26
28
|
end
|
27
29
|
|
28
30
|
# rubocop:disable Metrics/LineLength, Metrics/MethodLength, Metrics/AbcSize
|
@@ -36,9 +38,16 @@ class Initialize < Chamber::Commands::Base
|
|
36
38
|
|
37
39
|
key_pairs.each { |key_pair| generate_key_pair(key_pair) }
|
38
40
|
|
41
|
+
if signature
|
42
|
+
signature_key_pair = Chamber::KeyPair.new(namespace: 'signature',
|
43
|
+
key_file_path: rootpath)
|
44
|
+
|
45
|
+
generate_key_pair(signature_key_pair)
|
46
|
+
end
|
47
|
+
|
39
48
|
append_to_gitignore
|
40
49
|
|
41
|
-
shell.copy_file settings_template_filepath, settings_filepath
|
50
|
+
shell.copy_file settings_template_filepath, settings_filepath, skip: true
|
42
51
|
|
43
52
|
shell.say ''
|
44
53
|
shell.say '********************************************************************************', :green
|
@@ -46,47 +55,103 @@ class Initialize < Chamber::Commands::Base
|
|
46
55
|
shell.say '********************************************************************************', :green
|
47
56
|
shell.say ''
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
58
|
+
if namespaces.empty?
|
59
|
+
shell.say '.chamber.pem is your DEFAULT Chamber key.', :yellow
|
60
|
+
shell.say ''
|
61
|
+
shell.say 'If you would like a key which is used only for a certain environment (such as'
|
62
|
+
shell.say 'production), or your local machine, you can rerun the command like so:'
|
63
|
+
shell.say ''
|
64
|
+
shell.say '$ chamber init --namespaces="production my_machines_hostname"', :yellow
|
65
|
+
shell.say ''
|
66
|
+
shell.say 'You can find more information about namespace keys here:'
|
67
|
+
shell.say ''
|
68
|
+
shell.say ' * '
|
69
|
+
shell.say 'https://github.com/thekompanee/chamber/wiki/Namespaced-Key-Pairs', :blue
|
70
|
+
shell.say ''
|
71
|
+
shell.say '--------------------------------------------------------------------------------'
|
72
|
+
shell.say ''
|
73
|
+
end
|
74
|
+
|
75
|
+
if signature
|
76
|
+
shell.say ' Your Signature Keys'
|
77
|
+
shell.say ''
|
78
|
+
shell.say 'Your signature keys, which will be used for verification, are located at:'
|
79
|
+
shell.say ''
|
80
|
+
shell.say ' * Public Key: '
|
81
|
+
shell.say signature_key_pair.
|
82
|
+
public_key_filepath.
|
83
|
+
relative_path_from(Pathname.pwd), :yellow
|
84
|
+
shell.say ' * Private Key: '
|
85
|
+
shell.say signature_key_pair.
|
86
|
+
unencrypted_private_key_filepath.
|
87
|
+
relative_path_from(Pathname.pwd), :yellow
|
88
|
+
shell.say ' * Encrypted Private Key: '
|
89
|
+
shell.say signature_key_pair.
|
90
|
+
encrypted_private_key_filepath.
|
91
|
+
relative_path_from(Pathname.pwd), :yellow
|
92
|
+
shell.say ' * Encrypted Passphrase: '
|
93
|
+
shell.say signature_key_pair.
|
94
|
+
encrypted_private_key_passphrase_filepath.
|
95
|
+
relative_path_from(Pathname.pwd), :yellow
|
96
|
+
|
97
|
+
shell.say ''
|
98
|
+
shell.say 'The signature private keys should be thought of separately from the other'
|
99
|
+
shell.say 'project private keys you generate. They are not required to run the app'
|
100
|
+
shell.say 'and should only be given out to *very select* people.'
|
101
|
+
shell.say ''
|
102
|
+
shell.say 'You can find more information about settings verification here:'
|
103
|
+
shell.say ''
|
104
|
+
shell.say ' * '
|
105
|
+
shell.say 'https://github.com/thekompanee/chamber/wiki/Verifying-Settings', :blue
|
106
|
+
shell.say ''
|
107
|
+
shell.say '--------------------------------------------------------------------------------'
|
108
|
+
shell.say ''
|
109
|
+
end
|
57
110
|
|
58
|
-
shell.say '
|
111
|
+
shell.say ' Your Encrypted Keys'
|
112
|
+
shell.say ''
|
113
|
+
shell.say 'You can send your team members any of the file(s) located at:'
|
59
114
|
shell.say ''
|
60
115
|
|
61
116
|
key_pairs.each do |key_pair|
|
62
|
-
shell.say
|
63
|
-
shell.say key_pair.
|
117
|
+
shell.say ' * '
|
118
|
+
shell.say key_pair.encrypted_private_key_filepath.relative_path_from(Pathname.pwd), :yellow
|
64
119
|
end
|
65
120
|
|
66
121
|
shell.say ''
|
67
|
-
shell.say '
|
122
|
+
shell.say 'and not have to worry about sending them via a secure medium, however do'
|
123
|
+
shell.say 'not send the passphrase along with it. Give it to your team members in'
|
124
|
+
shell.say 'person.'
|
68
125
|
shell.say ''
|
69
|
-
shell.say 'You can
|
126
|
+
shell.say 'You can learn more about encrypted keys here:'
|
127
|
+
shell.say ''
|
128
|
+
shell.say ' * '
|
129
|
+
shell.say 'https://github.com/thekompanee/chamber/wiki/Keypair-Encryption#the-encrypted-private-key', :blue
|
130
|
+
shell.say ''
|
131
|
+
shell.say '--------------------------------------------------------------------------------'
|
132
|
+
shell.say ''
|
133
|
+
shell.say ' Your Key Passphrases'
|
134
|
+
shell.say ''
|
135
|
+
shell.say 'The passphrases for your encrypted private key(s) are stored in the'
|
136
|
+
shell.say 'following locations:'
|
70
137
|
shell.say ''
|
71
138
|
|
72
139
|
key_pairs.each do |key_pair|
|
73
|
-
shell.say '* '
|
74
|
-
shell.say key_pair.
|
140
|
+
shell.say ' * '
|
141
|
+
shell.say key_pair.encrypted_private_key_passphrase_filepath.relative_path_from(Pathname.pwd), :yellow
|
75
142
|
end
|
76
143
|
|
77
|
-
shell.say ''
|
78
|
-
shell.say 'and not have to worry about sending it via a secure medium (such as'
|
79
|
-
shell.say 'email), however do not send the passphrase along with it. Give it to'
|
80
|
-
shell.say 'your team members in person.'
|
81
144
|
shell.say ''
|
82
145
|
shell.say 'In order for them to decrypt it (for use with Chamber), they can use something'
|
83
146
|
shell.say 'like the following (swapping out the actual key filenames if necessary):'
|
84
147
|
shell.say ''
|
85
|
-
shell.say "$ cp #{key_pairs[0].encrypted_private_key_filepath} #{key_pairs[0].unencrypted_private_key_filepath}", :yellow
|
86
|
-
shell.say "$ ssh-keygen -p -f #{key_pairs[0].unencrypted_private_key_filepath}", :yellow
|
148
|
+
shell.say "$ cp #{key_pairs[0].encrypted_private_key_filepath.relative_path_from(Pathname.pwd)} #{key_pairs[0].unencrypted_private_key_filepath.relative_path_from(Pathname.pwd)}", :yellow
|
149
|
+
shell.say "$ ssh-keygen -p -f #{key_pairs[0].unencrypted_private_key_filepath.relative_path_from(Pathname.pwd)}", :yellow
|
87
150
|
shell.say ''
|
88
151
|
shell.say 'Enter the passphrase when prompted and leave the new passphrase blank.'
|
89
152
|
shell.say ''
|
153
|
+
shell.say '--------------------------------------------------------------------------------'
|
154
|
+
shell.say ''
|
90
155
|
end
|
91
156
|
# rubocop:enable Metrics/LineLength, Metrics/MethodLength, Metrics/AbcSize
|
92
157
|
|
@@ -102,27 +167,34 @@ class Initialize < Chamber::Commands::Base
|
|
102
167
|
shell.create_file key_pair.public_key_filepath,
|
103
168
|
key_pair.public_key_pem,
|
104
169
|
skip: true
|
170
|
+
shell.create_file key_pair.encrypted_private_key_passphrase_filepath,
|
171
|
+
key_pair.passphrase,
|
172
|
+
skip: true
|
105
173
|
|
106
174
|
`chmod 600 #{key_pair.unencrypted_private_key_filepath}`
|
107
175
|
`chmod 600 #{key_pair.encrypted_private_key_filepath}`
|
176
|
+
`chmod 600 #{key_pair.encrypted_private_key_passphrase_filepath}`
|
108
177
|
`chmod 644 #{key_pair.public_key_filepath}`
|
109
178
|
end
|
110
179
|
|
111
|
-
# rubocop:disable Style/GuardClause
|
112
180
|
def append_to_gitignore
|
113
181
|
::FileUtils.touch gitignore_filepath
|
114
182
|
|
115
183
|
gitignore_contents = ::File.read(gitignore_filepath)
|
116
184
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
185
|
+
%w{
|
186
|
+
**/settings/*-local.yml
|
187
|
+
**/settings-local.yml
|
188
|
+
.chamber*.enc
|
189
|
+
.chamber*.pem
|
190
|
+
.chamber*.enc.pass
|
191
|
+
!.chamber*.pub.pem
|
192
|
+
}.each do |pattern|
|
193
|
+
unless gitignore_contents =~ Regexp.new(Regexp.escape(pattern))
|
194
|
+
shell.append_to_file gitignore_filepath, "#{pattern}\n"
|
195
|
+
end
|
123
196
|
end
|
124
197
|
end
|
125
|
-
# rubocop:enable Style/GuardClause
|
126
198
|
|
127
199
|
def settings_template_filepath
|
128
200
|
@settings_template_filepath ||= templates_path + 'settings.yml'
|
@@ -15,11 +15,9 @@ class Secure < Chamber::Commands::Base
|
|
15
15
|
def call
|
16
16
|
disable_warnings do
|
17
17
|
insecure_environment_variables.each_key do |key|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
shell.say_status 'encrypt', key, :green
|
22
|
-
end
|
18
|
+
color = dry_run ? :blue : :green
|
19
|
+
|
20
|
+
shell.say_status 'encrypt', key, color
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'chamber/commands/base'
|
4
|
+
|
5
|
+
module Chamber
|
6
|
+
module Commands
|
7
|
+
class Sign < Chamber::Commands::Base
|
8
|
+
def initialize(options = {})
|
9
|
+
super(options.merge(namespaces: ['*']))
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
chamber.sign
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'chamber/commands/base'
|
4
|
+
|
5
|
+
module Chamber
|
6
|
+
module Commands
|
7
|
+
class Verify < Chamber::Commands::Base
|
8
|
+
def initialize(options = {})
|
9
|
+
super(options.merge(namespaces: ['*']))
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
verification_results = chamber.verify
|
14
|
+
|
15
|
+
verification_results.each_pair do |filename, result|
|
16
|
+
unless result
|
17
|
+
shell.say("The signature for '#{filename}' failed verification.", :yellow)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
verification_results
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'base64'
|
4
|
+
|
3
5
|
module Chamber
|
4
6
|
module EncryptionMethods
|
5
7
|
class PublicKey
|
6
|
-
def self.encrypt(_key, value,
|
7
|
-
value
|
8
|
-
encrypted_string =
|
8
|
+
def self.encrypt(_key, value, encryption_key)
|
9
|
+
value = YAML.dump(value)
|
10
|
+
encrypted_string = encryption_key.public_encrypt(value)
|
9
11
|
|
10
12
|
Base64.strict_encode64(encrypted_string)
|
11
13
|
end
|
data/lib/chamber/file.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'yaml'
|
5
5
|
require 'erb'
|
6
|
+
require 'chamber/files/signature'
|
6
7
|
|
7
8
|
###
|
8
9
|
# Internal: Represents a single file containing settings information in a given
|
@@ -104,6 +105,28 @@ class File < Pathname
|
|
104
105
|
end
|
105
106
|
# rubocop:enable Metrics/LineLength
|
106
107
|
|
108
|
+
def sign
|
109
|
+
signature_key_contents = decryption_keys[:signature]
|
110
|
+
|
111
|
+
fail ArgumentError, 'You asked to sign your settings files but no signature key was found. Run `chamber init --signature` to generate one.' \
|
112
|
+
unless signature_key_contents
|
113
|
+
|
114
|
+
signature = Files::Signature.new(to_s, read, signature_key_contents)
|
115
|
+
|
116
|
+
signature.write
|
117
|
+
end
|
118
|
+
|
119
|
+
def verify
|
120
|
+
signature_key_contents = encryption_keys[:signature]
|
121
|
+
|
122
|
+
fail ArgumentError, 'You asked to verify your settings files but no signature key was found. Run `chamber init --signature` to generate one.' \
|
123
|
+
unless signature_key_contents
|
124
|
+
|
125
|
+
signature = Files::Signature.new(to_s, read, signature_key_contents)
|
126
|
+
|
127
|
+
signature.verify
|
128
|
+
end
|
129
|
+
|
107
130
|
private
|
108
131
|
|
109
132
|
def secure_prefix
|
data/lib/chamber/file_set.rb
CHANGED
@@ -115,13 +115,15 @@ class FileSet
|
|
115
115
|
attr_reader :namespaces,
|
116
116
|
:paths
|
117
117
|
attr_accessor :decryption_keys,
|
118
|
-
:encryption_keys
|
118
|
+
:encryption_keys,
|
119
|
+
:basepath
|
119
120
|
|
120
121
|
def initialize(options = {})
|
121
122
|
self.namespaces = options[:namespaces] || {}
|
122
123
|
self.decryption_keys = options[:decryption_keys]
|
123
124
|
self.encryption_keys = options[:encryption_keys]
|
124
125
|
self.paths = options.fetch(:files)
|
126
|
+
self.basepath = options[:basepath]
|
125
127
|
end
|
126
128
|
|
127
129
|
###
|
@@ -181,6 +183,18 @@ class FileSet
|
|
181
183
|
files.each(&:secure)
|
182
184
|
end
|
183
185
|
|
186
|
+
def sign
|
187
|
+
files.each(&:sign)
|
188
|
+
end
|
189
|
+
|
190
|
+
def verify
|
191
|
+
files.each_with_object({}) do |file, memo|
|
192
|
+
relative_filepath = Pathname.new(file.to_s).relative_path_from(basepath).to_s
|
193
|
+
|
194
|
+
memo[relative_filepath] = file.verify
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
184
198
|
protected
|
185
199
|
|
186
200
|
###
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
require 'pathname'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
module Chamber
|
8
|
+
module Files
|
9
|
+
class Signature
|
10
|
+
SIGNATURE_HEADER = '-----BEGIN CHAMBER SIGNATURE-----'
|
11
|
+
SIGNATURE_FOOTER = '-----END CHAMBER SIGNATURE-----'
|
12
|
+
SIGNATURE_IN_SIGNATURE_FILE_PATTERN = /#{SIGNATURE_HEADER}\n(.*)\n#{SIGNATURE_FOOTER}/
|
13
|
+
|
14
|
+
attr_accessor :settings_content,
|
15
|
+
:settings_filename
|
16
|
+
|
17
|
+
attr_reader :signature_key
|
18
|
+
|
19
|
+
def initialize(settings_filename, settings_content, signature_key)
|
20
|
+
self.signature_key = signature_key
|
21
|
+
self.settings_content = settings_content
|
22
|
+
self.settings_filename = Pathname.new(settings_filename)
|
23
|
+
end
|
24
|
+
|
25
|
+
def signature_key=(keyish)
|
26
|
+
@signature_key ||= if keyish.is_a?(OpenSSL::PKey::RSA)
|
27
|
+
keyish
|
28
|
+
elsif ::File.readable?(::File.expand_path(keyish))
|
29
|
+
file_contents = ::File.read(::File.expand_path(keyish))
|
30
|
+
OpenSSL::PKey::RSA.new(file_contents)
|
31
|
+
else
|
32
|
+
OpenSSL::PKey::RSA.new(keyish)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def write
|
37
|
+
signature_filename.write(<<-HEREDOC, 0, mode: 'w+')
|
38
|
+
Signed By: #{`git config --get 'user.name'`.chomp}
|
39
|
+
Signed At: #{Time.now.utc.iso8601}
|
40
|
+
|
41
|
+
#{SIGNATURE_HEADER}
|
42
|
+
#{encoded_signature}
|
43
|
+
#{SIGNATURE_FOOTER}
|
44
|
+
HEREDOC
|
45
|
+
end
|
46
|
+
|
47
|
+
def verify
|
48
|
+
signature_key.verify(digest, signature_content, settings_content)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def encoded_signature
|
54
|
+
@encoded_signature ||= Base64.strict_encode64(raw_signature)
|
55
|
+
end
|
56
|
+
|
57
|
+
def raw_signature
|
58
|
+
@raw_signature ||= signature_key.
|
59
|
+
sign(digest, settings_content)
|
60
|
+
end
|
61
|
+
|
62
|
+
def signature_filename
|
63
|
+
@signature_filename ||= settings_filename.
|
64
|
+
sub('.yml', '.sig').
|
65
|
+
sub('.erb', '')
|
66
|
+
end
|
67
|
+
|
68
|
+
def encoded_signature_content
|
69
|
+
@encoded_signature_content ||= signature_filename.
|
70
|
+
read.
|
71
|
+
match(SIGNATURE_IN_SIGNATURE_FILE_PATTERN) do |match|
|
72
|
+
match[1]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def signature_content
|
77
|
+
@signature_content ||= Base64.strict_decode64(encoded_signature_content)
|
78
|
+
end
|
79
|
+
|
80
|
+
def digest
|
81
|
+
@digest ||= OpenSSL::Digest::SHA512.new
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/chamber/instance.rb
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
require 'socket'
|
4
4
|
|
5
5
|
module Chamber
|
6
|
-
module
|
7
|
-
class
|
6
|
+
module Integrations
|
7
|
+
class Rails < ::Rails::Railtie
|
8
8
|
initializer 'chamber.load', before: :load_environment_config do
|
9
9
|
Chamber.load(basepath: ::Rails.root.join('config'),
|
10
10
|
namespaces: {
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
module Chamber
|
6
|
+
module Integrations
|
7
|
+
module Sinatra
|
8
|
+
def self.registered(app)
|
9
|
+
app.configure do |inner_app|
|
10
|
+
env = inner_app.environment || ENV['RACK_ENV']
|
11
|
+
root = inner_app.root
|
12
|
+
|
13
|
+
if defined?(Padrino)
|
14
|
+
env = Padrino.env if Padrino.respond_to?(:env)
|
15
|
+
root = Padrino.root if Padrino.respond_to?(:root)
|
16
|
+
end
|
17
|
+
|
18
|
+
Chamber.load(
|
19
|
+
basepath: root,
|
20
|
+
namespaces: {
|
21
|
+
environment: -> { env },
|
22
|
+
hostname: -> { Socket.gethostname },
|
23
|
+
},
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/chamber/key_pair.rb
CHANGED
@@ -15,6 +15,10 @@ class KeyPair
|
|
15
15
|
self.key_file_path = Pathname.new(options.fetch(:key_file_path))
|
16
16
|
end
|
17
17
|
|
18
|
+
def encrypted_private_key_passphrase_filepath
|
19
|
+
key_file_path + "#{encrypted_private_key_filename}.pass"
|
20
|
+
end
|
21
|
+
|
18
22
|
def encrypted_private_key_filepath
|
19
23
|
key_file_path + encrypted_private_key_filename
|
20
24
|
end
|
data/lib/chamber/keys/base.rb
CHANGED
@@ -7,9 +7,9 @@ class Base
|
|
7
7
|
new(*args).resolve
|
8
8
|
end
|
9
9
|
|
10
|
-
attr_accessor :
|
11
|
-
|
12
|
-
|
10
|
+
attr_accessor :rootpath
|
11
|
+
attr_reader :filenames,
|
12
|
+
:namespaces
|
13
13
|
|
14
14
|
def initialize(options = {})
|
15
15
|
self.rootpath = Pathname.new(options.fetch(:rootpath))
|
@@ -45,6 +45,18 @@ class Base
|
|
45
45
|
|
46
46
|
private
|
47
47
|
|
48
|
+
def namespaces=(other)
|
49
|
+
@namespaces ||= begin
|
50
|
+
keys = if other.respond_to?(:keys)
|
51
|
+
other.keys.map(&:to_s)
|
52
|
+
else
|
53
|
+
other
|
54
|
+
end
|
55
|
+
|
56
|
+
keys + %w{signature}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
48
60
|
def key_from_file_contents(filename)
|
49
61
|
filename.readable? && filename.read
|
50
62
|
end
|
data/lib/chamber/rails.rb
CHANGED
data/lib/chamber/version.rb
CHANGED
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.
|
4
|
+
version: 2.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thekompanee
|
@@ -34,7 +34,7 @@ cert_chain:
|
|
34
34
|
etYUO0DlNY/qYfSfExrgt0W5dZeT09V++WPlYauHw/EZtAB0AsJwVdtIscq0HSvX
|
35
35
|
yH9AFp3KIe0v70EXzao/94n+XoDULrHEhqGMo34iS+37ZA==
|
36
36
|
-----END CERTIFICATE-----
|
37
|
-
date: 2018-01-
|
37
|
+
date: 2018-01-16 00:00:00.000000000 Z
|
38
38
|
dependencies:
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: thor
|
@@ -120,6 +120,20 @@ dependencies:
|
|
120
120
|
- - "~>"
|
121
121
|
- !ruby/object:Gem::Version
|
122
122
|
version: '4.0'
|
123
|
+
- !ruby/object:Gem::Dependency
|
124
|
+
name: timecop
|
125
|
+
requirement: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0.0'
|
130
|
+
type: :development
|
131
|
+
prerelease: false
|
132
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - "~>"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0.0'
|
123
137
|
description: Chamber lets you source your Settings from an arbitrary number of YAML
|
124
138
|
files and provides a simple mechanism for overriding settings from the ENV, which
|
125
139
|
is friendly to how Heroku addons work.
|
@@ -149,8 +163,10 @@ files:
|
|
149
163
|
- lib/chamber/commands/securable.rb
|
150
164
|
- lib/chamber/commands/secure.rb
|
151
165
|
- lib/chamber/commands/show.rb
|
166
|
+
- lib/chamber/commands/sign.rb
|
152
167
|
- lib/chamber/commands/travis.rb
|
153
168
|
- lib/chamber/commands/travis/secure.rb
|
169
|
+
- lib/chamber/commands/verify.rb
|
154
170
|
- lib/chamber/configuration.rb
|
155
171
|
- lib/chamber/context_resolver.rb
|
156
172
|
- lib/chamber/encryption_methods/none.rb
|
@@ -159,6 +175,7 @@ files:
|
|
159
175
|
- lib/chamber/errors/decryption_failure.rb
|
160
176
|
- lib/chamber/file.rb
|
161
177
|
- lib/chamber/file_set.rb
|
178
|
+
- lib/chamber/files/signature.rb
|
162
179
|
- lib/chamber/filters/decryption_filter.rb
|
163
180
|
- lib/chamber/filters/encryption_filter.rb
|
164
181
|
- lib/chamber/filters/environment_filter.rb
|
@@ -168,13 +185,14 @@ files:
|
|
168
185
|
- lib/chamber/filters/secure_filter.rb
|
169
186
|
- lib/chamber/filters/translate_secure_keys_filter.rb
|
170
187
|
- lib/chamber/instance.rb
|
188
|
+
- lib/chamber/integrations/rails.rb
|
189
|
+
- lib/chamber/integrations/sinatra.rb
|
171
190
|
- lib/chamber/key_pair.rb
|
172
191
|
- lib/chamber/keys/base.rb
|
173
192
|
- lib/chamber/keys/decryption.rb
|
174
193
|
- lib/chamber/keys/encryption.rb
|
175
194
|
- lib/chamber/namespace_set.rb
|
176
195
|
- lib/chamber/rails.rb
|
177
|
-
- lib/chamber/rails/railtie.rb
|
178
196
|
- lib/chamber/rubinius_fix.rb
|
179
197
|
- lib/chamber/settings.rb
|
180
198
|
- lib/chamber/types/secured.rb
|
metadata.gz.sig
CHANGED
Binary file
|