chamber 1.0.3 → 2.0.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
- data/README.md +288 -173
- data/bin/chamber +2 -288
- data/lib/chamber.rb +19 -67
- data/lib/chamber/binary/heroku.rb +59 -0
- data/lib/chamber/binary/runner.rb +94 -0
- data/lib/chamber/binary/travis.rb +23 -0
- data/lib/chamber/commands/base.rb +33 -0
- data/lib/chamber/commands/comparable.rb +37 -0
- data/lib/chamber/commands/compare.rb +46 -0
- data/lib/chamber/commands/context_resolver.rb +72 -0
- data/lib/chamber/commands/files.rb +12 -0
- data/lib/chamber/commands/heroku.rb +30 -0
- data/lib/chamber/commands/heroku/clear.rb +25 -0
- data/lib/chamber/commands/heroku/compare.rb +31 -0
- data/lib/chamber/commands/heroku/pull.rb +30 -0
- data/lib/chamber/commands/heroku/push.rb +25 -0
- data/lib/chamber/commands/initialize.rb +73 -0
- data/lib/chamber/commands/securable.rb +48 -0
- data/lib/chamber/commands/secure.rb +16 -0
- data/lib/chamber/commands/show.rb +23 -0
- data/lib/chamber/commands/travis.rb +14 -0
- data/lib/chamber/commands/travis/secure.rb +35 -0
- data/lib/chamber/configuration.rb +34 -0
- data/lib/chamber/environmentable.rb +23 -0
- data/lib/chamber/errors/undecryptable_value_error.rb +6 -0
- data/lib/chamber/file.rb +17 -5
- data/lib/chamber/file_set.rb +18 -12
- data/lib/chamber/filters/boolean_conversion_filter.rb +41 -0
- data/lib/chamber/filters/decryption_filter.rb +69 -0
- data/lib/chamber/filters/encryption_filter.rb +57 -0
- data/lib/chamber/filters/environment_filter.rb +75 -0
- data/lib/chamber/filters/namespace_filter.rb +37 -0
- data/lib/chamber/filters/secure_filter.rb +39 -0
- data/lib/chamber/instance.rb +40 -0
- data/lib/chamber/namespace_set.rb +55 -16
- data/lib/chamber/rails/railtie.rb +1 -1
- data/lib/chamber/settings.rb +103 -42
- data/lib/chamber/system_environment.rb +3 -93
- data/lib/chamber/version.rb +2 -2
- data/spec/fixtures/settings.yml +27 -0
- data/spec/lib/chamber/commands/context_resolver_spec.rb +106 -0
- data/spec/lib/chamber/commands/files_spec.rb +19 -0
- data/spec/lib/chamber/commands/heroku/clear_spec.rb +11 -0
- data/spec/lib/chamber/commands/heroku/compare_spec.rb +11 -0
- data/spec/lib/chamber/commands/heroku/pull_spec.rb +11 -0
- data/spec/lib/chamber/commands/heroku/push_spec.rb +11 -0
- data/spec/lib/chamber/commands/secure_spec.rb +29 -0
- data/spec/lib/chamber/commands/show_spec.rb +43 -0
- data/spec/lib/chamber/file_set_spec.rb +1 -1
- data/spec/lib/chamber/file_spec.rb +32 -9
- data/spec/lib/chamber/filters/boolean_conversion_filter_spec.rb +44 -0
- data/spec/lib/chamber/filters/decryption_filter_spec.rb +55 -0
- data/spec/lib/chamber/filters/encryption_filter_spec.rb +48 -0
- data/spec/lib/chamber/filters/environment_filter_spec.rb +35 -0
- data/spec/lib/chamber/filters/namespace_filter_spec.rb +73 -0
- data/spec/lib/chamber/filters/secure_filter_spec.rb +36 -0
- data/spec/lib/chamber/namespace_set_spec.rb +61 -18
- data/spec/lib/chamber/settings_spec.rb +99 -23
- data/spec/lib/chamber/system_environment_spec.rb +1 -71
- data/spec/lib/chamber_spec.rb +40 -26
- data/spec/rails-2-test/config.ru +0 -0
- data/spec/rails-2-test/config/application.rb +5 -0
- data/spec/rails-2-test/script/console +0 -0
- data/spec/rails-3-test/config.ru +0 -0
- data/spec/rails-3-test/config/application.rb +5 -0
- data/spec/rails-3-test/script/rails +0 -0
- data/spec/rails-4-test/bin/rails +0 -0
- data/spec/rails-4-test/config.ru +0 -0
- data/spec/rails-4-test/config/application.rb +5 -0
- data/spec/spec_key +27 -0
- data/spec/spec_key.pub +9 -0
- metadata +85 -4
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'chamber/binary/travis'
|
3
|
+
require 'chamber/binary/heroku'
|
4
|
+
require 'chamber/commands/show'
|
5
|
+
require 'chamber/commands/files'
|
6
|
+
require 'chamber/commands/secure'
|
7
|
+
require 'chamber/commands/compare'
|
8
|
+
require 'chamber/commands/initialize'
|
9
|
+
|
10
|
+
module Chamber
|
11
|
+
module Binary
|
12
|
+
class Runner < Thor
|
13
|
+
include Thor::Actions
|
14
|
+
|
15
|
+
class_option :rootpath,
|
16
|
+
type: :string,
|
17
|
+
aliases: '-r',
|
18
|
+
default: ENV['PWD'],
|
19
|
+
desc: 'The root filepath of the application'
|
20
|
+
class_option :basepath,
|
21
|
+
type: :string,
|
22
|
+
aliases: '-b',
|
23
|
+
desc: 'The base filepath where Chamber will look for the conventional settings files'
|
24
|
+
class_option :files,
|
25
|
+
type: :array,
|
26
|
+
aliases: '-f',
|
27
|
+
desc: 'The set of file globs that Chamber will use for processing'
|
28
|
+
class_option :namespaces,
|
29
|
+
type: :array,
|
30
|
+
aliases: '-n',
|
31
|
+
default: [],
|
32
|
+
desc: 'The set of namespaces that Chamber will use for processing'
|
33
|
+
class_option :preset,
|
34
|
+
type: :string,
|
35
|
+
aliases: '-p',
|
36
|
+
enum: ['rails'],
|
37
|
+
desc: 'Used to quickly assign a given scenario to the chamber command (eg Rails apps)'
|
38
|
+
class_option :decryption_key,
|
39
|
+
type: :string,
|
40
|
+
desc: 'The path to or contents of the private key associated with the project (typically .chamber.pem)'
|
41
|
+
class_option :encryption_key,
|
42
|
+
type: :string,
|
43
|
+
desc: 'The path to or contents of the public key associated with the project (typically .chamber.pub.pem)'
|
44
|
+
class_option :shell,
|
45
|
+
default: self.new,
|
46
|
+
desc: 'The command runner. Can be overridden for specific logging capabilities.'
|
47
|
+
|
48
|
+
desc 'travis SUBCOMMAND ...ARGS', 'For manipulating Travis CI environment variables'
|
49
|
+
subcommand 'travis', Chamber::Binary::Travis
|
50
|
+
|
51
|
+
desc 'heroku SUBCOMMAND ...ARGS', 'For manipulating Heroku environment variables'
|
52
|
+
subcommand 'heroku', Chamber::Binary::Heroku
|
53
|
+
|
54
|
+
desc 'show', 'Displays the list of settings and their values'
|
55
|
+
method_option :as_env,
|
56
|
+
type: :boolean,
|
57
|
+
aliases: '-e',
|
58
|
+
desc: 'Whether the displayed settings should be environment variable compatible'
|
59
|
+
def show
|
60
|
+
puts Commands::Show.call(options)
|
61
|
+
end
|
62
|
+
|
63
|
+
desc 'files', 'Lists the settings files which are parsed with the given options'
|
64
|
+
def files
|
65
|
+
puts Commands::Files.call(options)
|
66
|
+
end
|
67
|
+
|
68
|
+
desc 'compare', 'Displays the difference between what is currently stored in the Heroku application\'s config and what Chamber knows about locally'
|
69
|
+
method_option :keys_only,
|
70
|
+
type: :boolean,
|
71
|
+
default: true,
|
72
|
+
desc: 'Whether or not to only compare the keys but not the values of the two sets of settings'
|
73
|
+
method_option :first,
|
74
|
+
type: :array,
|
75
|
+
desc: 'The list of namespaces which will be used as the source of the comparison'
|
76
|
+
method_option :second,
|
77
|
+
type: :array,
|
78
|
+
desc: 'The list of namespaces which will be used as the destination of the comparison'
|
79
|
+
def compare
|
80
|
+
Commands::Compare.call(options)
|
81
|
+
end
|
82
|
+
|
83
|
+
desc 'secure', 'Secures any values which appear to need to be encrypted in any of the settings files which match irrespective of namespaces'
|
84
|
+
def secure
|
85
|
+
Commands::Secure.call(options)
|
86
|
+
end
|
87
|
+
|
88
|
+
desc 'init', 'Sets Chamber up matching best practices for secure configuration management'
|
89
|
+
def init
|
90
|
+
Commands::Initialize.call(options)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'chamber/commands/travis/secure'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Binary
|
6
|
+
class Travis < Thor
|
7
|
+
|
8
|
+
desc 'secure', 'Uses your Travis CI public key to encrypt the settings you have chosen not to commit to the repo'
|
9
|
+
method_option :dry_run,
|
10
|
+
type: :boolean,
|
11
|
+
aliases: '-d',
|
12
|
+
desc: 'Does not actually encrypt anything to .travis.yml, but instead displays what values would be encrypted'
|
13
|
+
method_option :only_sensitive,
|
14
|
+
type: :boolean,
|
15
|
+
aliases: '-o',
|
16
|
+
default: true,
|
17
|
+
desc: 'Does not encrypt settings into .travis.yml unless they are contained in files which have been gitignored or settings which are marked as "_secure"'
|
18
|
+
def secure
|
19
|
+
Commands::Travis::Secure.call(options)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'chamber/commands/context_resolver'
|
2
|
+
require 'chamber/instance'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Commands
|
6
|
+
class Base
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
options = ContextResolver.resolve(options)
|
10
|
+
|
11
|
+
self.chamber = Chamber::Instance.new options
|
12
|
+
self.shell = options[:shell]
|
13
|
+
self.rootpath = options[:rootpath]
|
14
|
+
self.dry_run = options[:dry_run]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.call(options = {})
|
18
|
+
self.new(options).call
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
attr_accessor :chamber,
|
24
|
+
:shell,
|
25
|
+
:dry_run
|
26
|
+
attr_reader :rootpath
|
27
|
+
|
28
|
+
def rootpath=(other)
|
29
|
+
@rootpath ||= Pathname.new(other)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module Chamber
|
4
|
+
module Commands
|
5
|
+
module Comparable
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
super
|
9
|
+
|
10
|
+
self.keys_only = options[:keys_only]
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
system("git diff --no-index #{first_settings_file} #{second_settings_file}")
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
attr_accessor :keys_only
|
20
|
+
|
21
|
+
def first_settings_file
|
22
|
+
create_comparable_settings_file 'first', first_settings_data
|
23
|
+
end
|
24
|
+
|
25
|
+
def second_settings_file
|
26
|
+
create_comparable_settings_file 'second', second_settings_data
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_comparable_settings_file(name, config)
|
30
|
+
Tempfile.open(name) do |file|
|
31
|
+
file.write config
|
32
|
+
file.to_path
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'chamber/instance'
|
2
|
+
require 'chamber/commands/base'
|
3
|
+
require 'chamber/commands/comparable'
|
4
|
+
|
5
|
+
module Chamber
|
6
|
+
module Commands
|
7
|
+
class Compare < Chamber::Commands::Base
|
8
|
+
include Chamber::Commands::Comparable
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
super
|
12
|
+
|
13
|
+
first_settings_options = options.merge(namespaces: options[:first])
|
14
|
+
self.first_settings_instance = Chamber::Instance.new(first_settings_options)
|
15
|
+
|
16
|
+
second_settings_options = options.merge(namespaces: options[:second])
|
17
|
+
self.second_settings_instance = Chamber::Instance.new(second_settings_options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.call(options = {})
|
21
|
+
self.new(options).call
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
attr_accessor :first_settings_instance,
|
27
|
+
:second_settings_instance
|
28
|
+
|
29
|
+
def first_settings_data
|
30
|
+
settings_data(first_settings_instance)
|
31
|
+
end
|
32
|
+
|
33
|
+
def second_settings_data
|
34
|
+
settings_data(second_settings_instance)
|
35
|
+
end
|
36
|
+
|
37
|
+
def settings_data(instance)
|
38
|
+
if keys_only
|
39
|
+
instance.to_environment.keys.join("\n")
|
40
|
+
else
|
41
|
+
instance.to_s(pair_separator: "\n")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Chamber
|
2
|
+
module Commands
|
3
|
+
class ContextResolver
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
self.options = options.dup
|
7
|
+
end
|
8
|
+
|
9
|
+
def resolve
|
10
|
+
options[:rootpath] ||= Pathname.pwd
|
11
|
+
options[:rootpath] = Pathname.new(options[:rootpath])
|
12
|
+
options[:encryption_key] = resolve_encryption_key(options[:encryption_key])
|
13
|
+
options[:decryption_key] = resolve_decryption_key(options[:decryption_key])
|
14
|
+
options[:namespaces] ||= []
|
15
|
+
options[:preset] ||= resolve_preset
|
16
|
+
|
17
|
+
if options[:preset] == 'rails'
|
18
|
+
options[:basepath] ||= options[:rootpath] + 'config'
|
19
|
+
|
20
|
+
if options[:namespaces] == []
|
21
|
+
require options[:rootpath].join('config', 'application')
|
22
|
+
|
23
|
+
options[:namespaces] = [::Rails.env]
|
24
|
+
end
|
25
|
+
else
|
26
|
+
options[:basepath] ||= options[:rootpath]
|
27
|
+
end
|
28
|
+
|
29
|
+
options
|
30
|
+
rescue LoadError
|
31
|
+
options
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.resolve(options = {})
|
35
|
+
self.new(options).resolve
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
attr_accessor :options
|
41
|
+
|
42
|
+
def resolve_preset
|
43
|
+
if in_a_rails_project?
|
44
|
+
'rails'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def resolve_encryption_key(key)
|
49
|
+
key ||= options[:rootpath] + '.chamber.pub.pem'
|
50
|
+
|
51
|
+
key if Pathname.new(key).readable?
|
52
|
+
end
|
53
|
+
|
54
|
+
def resolve_decryption_key(key)
|
55
|
+
key ||= options[:rootpath] + '.chamber.pem'
|
56
|
+
|
57
|
+
key if Pathname.new(key).readable?
|
58
|
+
end
|
59
|
+
|
60
|
+
def in_a_rails_project?
|
61
|
+
(options[:rootpath] + 'config.ru').exist? &&
|
62
|
+
rails_executable_exists?
|
63
|
+
end
|
64
|
+
|
65
|
+
def rails_executable_exists?
|
66
|
+
options[:rootpath].join('bin', 'rails').exist? ||
|
67
|
+
options[:rootpath].join('script', 'rails').exist? ||
|
68
|
+
options[:rootpath].join('script', 'console').exist?
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
|
3
|
+
module Chamber
|
4
|
+
module Commands
|
5
|
+
module Heroku
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
super
|
9
|
+
|
10
|
+
self.app = options[:app]
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
attr_accessor :app
|
16
|
+
|
17
|
+
def configuration
|
18
|
+
@configuration ||= heroku("config --shell").chomp
|
19
|
+
end
|
20
|
+
|
21
|
+
def heroku(command)
|
22
|
+
Bundler.with_clean_env { `heroku #{command}#{app_option}` }
|
23
|
+
end
|
24
|
+
|
25
|
+
def app_option
|
26
|
+
app ? " --app #{app}" : ""
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'chamber/commands/base'
|
2
|
+
require 'chamber/commands/heroku'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Commands
|
6
|
+
module Heroku
|
7
|
+
class Clear < Chamber::Commands::Base
|
8
|
+
include Chamber::Commands::Heroku
|
9
|
+
|
10
|
+
def call
|
11
|
+
chamber.to_environment.keys.each do |key|
|
12
|
+
next unless configuration.match(key)
|
13
|
+
|
14
|
+
if dry_run
|
15
|
+
shell.say_status 'remove', key, :blue
|
16
|
+
else
|
17
|
+
shell.say_status 'remove', key, :green
|
18
|
+
shell.say heroku("config:unset #{key}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'chamber/commands/securable'
|
2
|
+
require 'chamber/commands/heroku'
|
3
|
+
require 'chamber/commands/comparable'
|
4
|
+
|
5
|
+
module Chamber
|
6
|
+
module Commands
|
7
|
+
module Heroku
|
8
|
+
class Compare < Chamber::Commands::Base
|
9
|
+
include Chamber::Commands::Securable
|
10
|
+
include Chamber::Commands::Heroku
|
11
|
+
include Chamber::Commands::Comparable
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def first_settings_data
|
16
|
+
if only_sensitive
|
17
|
+
secured_settings.to_s(pair_separator: "\n",
|
18
|
+
value_surrounder: '')
|
19
|
+
else
|
20
|
+
all_settings.to_s(pair_separator: "\n",
|
21
|
+
value_surrounder: '')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def second_settings_data
|
26
|
+
configuration
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'chamber/commands/base'
|
2
|
+
require 'chamber/commands/heroku'
|
3
|
+
|
4
|
+
module Chamber
|
5
|
+
module Commands
|
6
|
+
module Heroku
|
7
|
+
class Pull < Chamber::Commands::Base
|
8
|
+
include Chamber::Commands::Heroku
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
super
|
12
|
+
|
13
|
+
self.target_file = options[:into]
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
if target_file
|
18
|
+
shell.create_file target_file, configuration
|
19
|
+
else
|
20
|
+
configuration
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
attr_accessor :target_file
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|