chamber 2.13.1 → 2.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +101 -26
  5. data/lib/chamber.rb +72 -10
  6. data/lib/chamber/adapters/cloud/circle_ci.rb +16 -13
  7. data/lib/chamber/adapters/cloud/heroku.rb +40 -13
  8. data/lib/chamber/binary/circle_ci.rb +25 -12
  9. data/lib/chamber/binary/heroku.rb +31 -12
  10. data/lib/chamber/binary/runner.rb +37 -27
  11. data/lib/chamber/binary/travis.rb +5 -3
  12. data/lib/chamber/commands/base.rb +10 -16
  13. data/lib/chamber/commands/cloud/base.rb +3 -3
  14. data/lib/chamber/commands/cloud/pull.rb +2 -2
  15. data/lib/chamber/commands/cloud/push.rb +7 -7
  16. data/lib/chamber/commands/comparable.rb +2 -2
  17. data/lib/chamber/commands/compare.rb +6 -9
  18. data/lib/chamber/commands/initialize.rb +26 -22
  19. data/lib/chamber/commands/securable.rb +9 -9
  20. data/lib/chamber/commands/secure.rb +2 -2
  21. data/lib/chamber/commands/show.rb +8 -8
  22. data/lib/chamber/commands/sign.rb +2 -2
  23. data/lib/chamber/commands/verify.rb +2 -2
  24. data/lib/chamber/configuration.rb +6 -3
  25. data/lib/chamber/context_resolver.rb +8 -7
  26. data/lib/chamber/encryption_methods/ssl.rb +12 -12
  27. data/lib/chamber/file.rb +16 -14
  28. data/lib/chamber/file_set.rb +18 -8
  29. data/lib/chamber/files/signature.rb +16 -14
  30. data/lib/chamber/filters/decryption_filter.rb +12 -10
  31. data/lib/chamber/filters/encryption_filter.rb +8 -8
  32. data/lib/chamber/filters/environment_filter.rb +12 -14
  33. data/lib/chamber/filters/failed_decryption_filter.rb +6 -6
  34. data/lib/chamber/filters/insecure_filter.rb +3 -3
  35. data/lib/chamber/filters/namespace_filter.rb +5 -5
  36. data/lib/chamber/filters/secure_filter.rb +5 -5
  37. data/lib/chamber/filters/translate_secure_keys_filter.rb +5 -5
  38. data/lib/chamber/instance.rb +37 -21
  39. data/lib/chamber/key_pair.rb +7 -7
  40. data/lib/chamber/keys/base.rb +13 -13
  41. data/lib/chamber/keys/decryption.rb +3 -3
  42. data/lib/chamber/keys/encryption.rb +3 -3
  43. data/lib/chamber/namespace_set.rb +2 -4
  44. data/lib/chamber/settings.rb +45 -43
  45. data/lib/chamber/types/secured.rb +8 -10
  46. data/lib/chamber/version.rb +1 -1
  47. data/templates/settings.yml +2 -0
  48. metadata +24 -26
  49. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f29fb224fb009c2d3cda5c3429024a2246fb9ab1893def95a984b087fe77849
4
- data.tar.gz: 281ad1fe8607f1b0c887cfcbd2bb736a82d6d51fd075bbef1e9204bd2d0bb00e
3
+ metadata.gz: 5bf2d68260ae1fa27b7a2befdc5ff274c34477ff3bf584027d39747fbcd5a489
4
+ data.tar.gz: 63f97b11849eb6e800b5f4e4f0ae49ad57d1e92cd942f114d417dc8c980a40a4
5
5
  SHA512:
6
- metadata.gz: 4ac5037eb08def3e9bb7304ebd485917246f83ce9d1db7a605425f4f015f70cb908ac8b3544c1b28cbff2445478be1764a34b05e76a2a33f93cadfcedffd6398
7
- data.tar.gz: 8be1ebdd092c55a5c8a40e7de6320db810728c13411b842f2a060b38c770835e34c763b3220ddc1dd5e614d53b4cd52f7d26725a805861756783dbfe7f780b23
6
+ metadata.gz: 8a8f5f026bee9a0380410ee6ed8c4e563f0c465b56a0d111d10f8ef35eb986f4e3cfeb7acfaa283cfcc7380135026d63f4edbfd3649ea4bfc543b91410f1b155
7
+ data.tar.gz: 9d012efb86e89a1a78cd39f0bd54200d0508394b46a7b66b2144b645bcd86f17d25f1f2ad3d2df8c3cab355f1669903b17d8dc8de024d520b854022a6e32d892
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -1,5 +1,33 @@
1
- # Chamber
2
- [![Gem Version](https://img.shields.io/gem/v/chamber.svg)](https://rubygems.org/gems/chamber) ![Rubygems Rank Overall](https://img.shields.io/gem/rt/chamber.svg) ![Rubygems Rank Daily](https://img.shields.io/gem/rd/chamber.svg) ![Rubygems Downloads](https://img.shields.io/gem/dv/chamber/stable.svg) [![Build Status](https://img.shields.io/travis/thekompanee/chamber/master.svg)](http://travis-ci.org/thekompanee/chamber) [![Code Climate](https://codeclimate.com/github/thekompanee/chamber.svg)](https://codeclimate.com/github/thekompanee/chamber) [![Code Climate](https://codeclimate.com/github/thekompanee/chamber/coverage.svg)](https://codeclimate.com/github/thekompanee/chamber)
1
+ Chamber
2
+ ================================================================================
3
+
4
+ <div align="center">
5
+ <a href="https://rubygems.org/gems/chamber" alt="RubyGems Version">
6
+ <img src="https://img.shields.io/gem/v/chamber.svg?style=flat-square&label=current-version" alt="RubyGems Version" />
7
+ </a>
8
+
9
+ <a href="https://rubygems.org/gems/chamber" alt="RubyGems Rank Overall">
10
+ <img src="https://img.shields.io/gem/rt/chamber.svg?style=flat-square&label=total-rank" alt="RubyGems Rank Overall" />
11
+ </a>
12
+
13
+ <a href="https://rubygems.org/gems/chamber" alt="RubyGems Rank Daily">
14
+ <img src="https://img.shields.io/gem/rd/chamber.svg?style=flat-square&label=daily-rank" alt="RubyGems Rank Daily" />
15
+ </a>
16
+
17
+ <a href="https://rubygems.org/gems/chamber" alt="RubyGems Downloads">
18
+ <img src="https://img.shields.io/gem/dt/chamber.svg?style=flat-square&label=total-downloads" alt="RubyGems Downloads" />
19
+ </a>
20
+
21
+ <a href="https://github.com/thekompanee/chamber/actions?query=workflow%3ABuild" alt="Build Status">
22
+ <img src="https://img.shields.io/github/workflow/status/thekompanee/chamber/Build?label=CI&style=flat-square&logo=github" alt="Build Status" />
23
+ </a>
24
+
25
+ <a href="#" alt="Maintainability">
26
+ <img src="https://img.shields.io/codeclimate/maintainability/thekompanee/chamber?style=flat-square&label=grade" alt="Maintainability" />
27
+ </a>
28
+ </div>
29
+
30
+ <br>
3
31
 
4
32
  Chamber is the auto-encrypting, extremely organizable, Heroku-loving,
5
33
  CLI-having, non-extra-repo-needing, non-Rails-specific-ing, CI-serving
@@ -9,17 +37,73 @@ We looked at all of the options out there and thought something was still
9
37
  missing, so we wrote Chamber. We made it with lots of ❤ and we hope you like it
10
38
  as much as we do.
11
39
 
12
- ## What Sets Chamber Apart?
40
+ What Sets Chamber Apart
41
+ --------------------------------------------------------------------------------
13
42
 
14
43
  For an idea of how Chamber compares to other popular libraries, check out our
15
44
  [Gem Comparison][comparison].
16
45
 
17
- ## Basic Usage
46
+ Basic Usage
47
+ --------------------------------------------------------------------------------
48
+
49
+ Before starting this guide, make sure you [install chamber][installation].
50
+
51
+ Once your app is initialized, you should have a `settings.yml` file somewhere.
52
+ A lot of times it's the root of your project and sometimes it's in a framework
53
+ specific location.
54
+
55
+ Inside of here you can define any settings you'd like like so:
56
+
57
+ ```yaml
58
+ # settings.yml
59
+
60
+ smtp_username: 'my_username'
61
+ smtp_password: 'my_password'
62
+ ```
63
+
64
+ From there you can access your settings by using the special `Chamber.env`
65
+ constant.
66
+
67
+ ```ruby
68
+ Chamber.env.smtp_password
69
+ # => 'my_password'
70
+ ```
71
+
72
+ If you want to encrypt a setting, prefix the setting name with `_secure_` like
73
+ so:
74
+
75
+ ```ruby
76
+ # settings.yml
77
+
78
+ smtp_username: 'my_username'
79
+ _secure_smtp_password: 'my_password'
80
+ ```
81
+
82
+ And then run `chamber secure`. Your settings file will have an encrypted value:
83
+
84
+ ```ruby
85
+ # settings.yml
86
+
87
+ smtp_username: 'my_username'
88
+ _secure_smtp_password: JL5hAVux4tERpv49QPWxy9H0VC2Rnk7V8/e8+1XOwPcXcoH/a7Lh253UY/v9m8nI/Onb+ZG9nZ082J4M/BmLa+f7jwMEwufIqbUhUah9eKIW8xcxlppBYpl7JVGf2HJF5TfCN44gMQNgGNzboCQXKqRyeGFm4u772Sg9V2gEx/q7qJ6F4jg7v/cltCFLmJfXA2SHA5Dai4p9L4IvMVVJGm34k5j7KOegNqpVWs2RY99cagjPuzc9VM2XSUsXgqcUJdmH8YtPW8Kqkyg0oYlRh6VQWABlWXwTZz74QjTTjqtqfoELIoFTMBDh+cCvuUTAE5m06LhlqauVrB4UnBsd5g==
89
+ ```
90
+
91
+ which you still access the same way because Chamber handles the decryption for
92
+ you:
93
+
94
+ ```ruby
95
+ Chamber.env.smtp_password
96
+ # => 'my_password'
97
+ ```
98
+
99
+ Full Reference
100
+ --------------------------------------------------------------------------------
18
101
 
19
- You can view our Basic Usage Guide [here][basic-usage]. Otherwise, for the full
102
+ There's so much to Chamber, we couldn't put it all in the README. For the full
20
103
  Chamber guide, visit the [wiki][wiki].
21
104
 
22
- ## Credits
105
+ Credits
106
+ --------------------------------------------------------------------------------
23
107
 
24
108
  Chamber was written by [Jeff Felchner][jeff-profile] and
25
109
  [Mark McEahern][mark-profile]
@@ -30,27 +114,18 @@ Chamber is maintained and funded by [The Kompanee, Ltd.][kompanee-site]
30
114
 
31
115
  The names and logos for The Kompanee are trademarks of The Kompanee, Ltd.
32
116
 
33
- ## License
117
+ License
118
+ --------------------------------------------------------------------------------
34
119
 
35
- Chamber is Copyright © 2014-2019 Jeff Felchner and Mark McEahern. It is free
120
+ Chamber is Copyright © 2014-2021 Jeff Felchner and Mark McEahern. It is free
36
121
  software, and may be redistributed under the terms specified in the
37
122
  [LICENSE][license] file.
38
123
 
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
124
+ [comparison]: https://github.com/thekompanee/chamber/wiki/Gem-Comparison
125
+ [jeff-profile]: https://github.com/jfelchner
126
+ [kompanee-logo]: https://kompanee-public-assets.s3.amazonaws.com/readmes/kompanee-horizontal-black.png
127
+ [kompanee-site]: http://www.thekompanee.com
128
+ [license]: https://github.com/thekompanee/chamber/blob/master/LICENSE.txt
129
+ [mark-profile]: https://github.com/m5rk
130
+ [wiki]: https://github.com/thekompanee/chamber/wiki
131
+ [installation]: https://github.com/thekompanee/chamber/wiki/Installation
@@ -7,12 +7,8 @@ require 'chamber/rails'
7
7
  module Chamber
8
8
  attr_writer :instance
9
9
 
10
- def load(options = {})
11
- self.instance = Instance.new(options)
12
- end
13
-
14
- def to_s(options = {})
15
- instance.to_s(options)
10
+ def load(**args)
11
+ self.instance = Instance.new(**args)
16
12
  end
17
13
 
18
14
  def env
@@ -20,7 +16,61 @@ module Chamber
20
16
  end
21
17
 
22
18
  def instance
23
- @instance ||= Instance.new({})
19
+ @instance ||= Instance.new
20
+ end
21
+
22
+ def [](key)
23
+ instance.[](key)
24
+ end
25
+
26
+ def configuration
27
+ instance.configuration
28
+ end
29
+
30
+ def decrypt(value, **args)
31
+ instance.decrypt(value, **args)
32
+ end
33
+
34
+ def encrypt(value, **args)
35
+ instance.encrypt(value, **args)
36
+ end
37
+
38
+ def files
39
+ instance.files
40
+ end
41
+
42
+ def filenames
43
+ instance.filenames
44
+ end
45
+
46
+ def namespaces
47
+ instance.namespaces
48
+ end
49
+
50
+ def secure
51
+ instance.secure
52
+ end
53
+
54
+ def sign
55
+ instance.sign
56
+ end
57
+
58
+ def verify
59
+ instance.verify
60
+ end
61
+
62
+ def to_environment
63
+ instance.to_environment
64
+ end
65
+
66
+ def to_hash
67
+ instance.to_hash
68
+ end
69
+
70
+ def to_s(**args)
71
+ return '' unless @instance
72
+
73
+ instance.to_s(**args)
24
74
  end
25
75
 
26
76
  def method_missing(name, *args)
@@ -33,11 +83,23 @@ module Chamber
33
83
  instance.respond_to?(name, include_private)
34
84
  end
35
85
 
36
- module_function :load,
37
- :to_s,
86
+ module_function :[],
87
+ :configuration,
88
+ :decrypt,
89
+ :encrypt,
38
90
  :env,
91
+ :filenames,
92
+ :files,
39
93
  :instance,
40
94
  :instance=,
95
+ :load,
41
96
  :method_missing,
42
- :respond_to_missing?
97
+ :namespaces,
98
+ :respond_to_missing?,
99
+ :secure,
100
+ :sign,
101
+ :to_environment,
102
+ :to_hash,
103
+ :to_s,
104
+ :verify
43
105
  end
@@ -17,11 +17,11 @@ class CircleCi
17
17
  :username,
18
18
  :vcs_type
19
19
 
20
- def initialize(options = {})
21
- self.api_token = options.fetch(:api_token)
22
- self.project = options.fetch(:project)
23
- self.username = options.fetch(:username)
24
- self.vcs_type = options.fetch(:vcs_type)
20
+ def initialize(api_token:, project:, username:, vcs_type:)
21
+ self.api_token = api_token
22
+ self.project = project
23
+ self.username = username
24
+ self.vcs_type = vcs_type
25
25
  end
26
26
 
27
27
  def add_environment_variable(name, value)
@@ -39,18 +39,21 @@ class CircleCi
39
39
  response['name']
40
40
  end
41
41
 
42
+ # rubocop:disable Layout/MultilineAssignmentLayout
42
43
  def environment_variables
43
- @environment_variables ||= begin
44
- request = ::Net::HTTP::Get.new(request_uri(resource: 'envvar'))
44
+ @environment_variables ||= \
45
+ begin
46
+ request = ::Net::HTTP::Get.new(request_uri(resource: 'envvar'))
45
47
 
46
- request.basic_auth api_token, ''
47
- request['Content-Type'] = 'application/json'
48
+ request.basic_auth api_token, ''
49
+ request['Content-Type'] = 'application/json'
48
50
 
49
- ::JSON
50
- .parse(response(request).body)
51
- .each_with_object({}) { |e, m| m[e['name']] = e['value'] }
52
- end
51
+ ::JSON
52
+ .parse(response(request).body)
53
+ .each_with_object({}) { |e, m| m[e['name']] = e['value'] }
54
+ end
53
55
  end
56
+ # rubocop:enable Layout/MultilineAssignmentLayout
54
57
 
55
58
  def remove_environment_variable(name)
56
59
  request = ::Net::HTTP::Delete.new(request_uri(resource: "envvar/#{name}"))
@@ -8,38 +8,65 @@ module Chamber
8
8
  module Adapters
9
9
  module Cloud
10
10
  class Heroku
11
- attr_accessor :app
11
+ API_HOST = 'api.heroku.com'
12
+ API_PORT = 443
13
+ API_BASE_URI = ''
12
14
 
13
- def initialize(options = {})
14
- self.app = options.fetch(:app)
15
+ attr_accessor :api_token,
16
+ :app
17
+
18
+ def initialize(api_token:, app:)
19
+ self.api_token = api_token
20
+ self.app = app
15
21
  end
16
22
 
17
- def add_environment_variable(name, value)
18
- value = value.shellescape unless value =~ /\n/
23
+ def add_environment_variable(name, value) # rubocop:disable Metrics/AbcSize
24
+ value = value.gsub(/\n/, '\n') if value
25
+ request = ::Net::HTTP::Patch.new(config_vars_uri)
26
+
27
+ request['Authorization'] = "Bearer #{api_token}"
28
+ request['Accept'] = 'application/vnd.heroku+json; version=3'
29
+ request['Content-Type'] = 'application/json'
30
+ request.body = ::JSON.dump(Hash[name, value])
19
31
 
20
- response = heroku(%Q{config:set #{name}="#{value}"})
32
+ response = ::JSON.parse(response(request).body)
21
33
 
22
- fail NameError, "The variable name '#{name}' is invalid" if response.match?(/invalid/)
34
+ fail NameError, response['message'] if response['message']
23
35
 
24
36
  response
25
37
  end
26
38
 
27
39
  def environment_variables
28
- @environment_variables ||= ::JSON.parse(heroku('config --json'))
40
+ request = ::Net::HTTP::Get.new(config_vars_uri)
41
+
42
+ request['Authorization'] = "Bearer #{api_token}"
43
+ request['Accept'] = 'application/vnd.heroku+json; version=3'
44
+
45
+ response = ::JSON.parse(response(request).body)
46
+
47
+ fail NameError, response['message'] if response['message']
48
+
49
+ response
29
50
  end
30
51
 
31
52
  def remove_environment_variable(name)
32
- heroku("config:unset #{name}")
53
+ add_environment_variable(name, nil)
33
54
  end
34
55
 
35
56
  private
36
57
 
37
- def heroku(command)
38
- Bundler.with_clean_env { `heroku #{command}#{app_option} 2>&1` }
58
+ def config_vars_uri
59
+ "#{API_BASE_URI}/apps/#{app}/config-vars"
60
+ end
61
+
62
+ def response(request)
63
+ connection.request(request)
39
64
  end
40
65
 
41
- def app_option
42
- app ? " --app='#{app}'" : ''
66
+ def connection
67
+ @connection ||= ::Net::HTTP.new(API_HOST, API_PORT).tap do |conn|
68
+ conn.use_ssl = true
69
+ end
43
70
  end
44
71
  end
45
72
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'thor'
4
+ require 'chamber/core_ext/hash'
4
5
  require 'chamber/commands/cloud/clear'
5
6
  require 'chamber/commands/cloud/push'
6
7
  require 'chamber/commands/cloud/pull'
@@ -36,8 +37,9 @@ class CircleCi < Thor
36
37
  desc: 'The type of VCS your project is using.',
37
38
  enum: %w{github bitbucket}
38
39
 
39
- desc 'clear', 'Removes all CircleCi environment variables which match settings that ' \
40
- 'Chamber knows about'
40
+ desc 'clear',
41
+ 'Removes all CircleCi environment variables which match settings that Chamber ' \
42
+ 'knows about'
41
43
 
42
44
  method_option :dry_run,
43
45
  type: :boolean,
@@ -46,11 +48,14 @@ class CircleCi < Thor
46
48
  'would change if cleared'
47
49
 
48
50
  def clear
49
- Commands::Cloud::Clear.call(options.merge(shell: self, adapter: 'circle_ci'))
51
+ Commands::Cloud::Clear.call(**options
52
+ .transform_keys(&:to_sym)
53
+ .merge(shell: self, adapter: 'circle_ci'))
50
54
  end
51
55
 
52
- desc 'push', 'Sends settings to CircleCi so that they may be used in the application ' \
53
- 'once it is deployed'
56
+ desc 'push',
57
+ 'Sends settings to CircleCi so that they may be used in the application ' \
58
+ 'once it is deployed'
54
59
 
55
60
  method_option :dry_run,
56
61
  type: :boolean,
@@ -75,11 +80,14 @@ class CircleCi < Thor
75
80
  'will be pushed'
76
81
 
77
82
  def push
78
- Commands::Cloud::Push.call(options.merge(shell: self, adapter: 'circle_ci'))
83
+ Commands::Cloud::Push.call(**options
84
+ .transform_keys(&:to_sym)
85
+ .merge(shell: self, adapter: 'circle_ci'))
79
86
  end
80
87
 
81
- desc 'pull', 'Retrieves the environment variables for the application and stores ' \
82
- 'them in a temporary file'
88
+ desc 'pull',
89
+ 'Retrieves the environment variables for the application and stores them in a ' \
90
+ 'temporary file'
83
91
 
84
92
  method_option :into,
85
93
  type: :string,
@@ -87,11 +95,14 @@ class CircleCi < Thor
87
95
  'stored. This file WILL BE OVERRIDDEN.'
88
96
 
89
97
  def pull
90
- Commands::Cloud::Pull.call(options.merge(shell: self, adapter: 'circle_ci'))
98
+ Commands::Cloud::Pull.call(**options
99
+ .transform_keys(&:to_sym)
100
+ .merge(shell: self, adapter: 'circle_ci'))
91
101
  end
92
102
 
93
- desc 'compare', 'Displays the difference between what is currently stored in the ' \
94
- 'CircleCi application\'s config and what Chamber knows about locally'
103
+ desc 'compare',
104
+ 'Displays the difference between what is currently stored in the ' \
105
+ 'CircleCi application\'s config and what Chamber knows about locally'
95
106
 
96
107
  method_option :only_sensitive,
97
108
  type: :boolean,
@@ -102,7 +113,9 @@ class CircleCi < Thor
102
113
  'which are marked as "_secure"'
103
114
 
104
115
  def compare
105
- Commands::Cloud::Compare.call(options.merge(shell: self, adapter: 'circle_ci'))
116
+ Commands::Cloud::Compare.call(**options
117
+ .transform_keys(&:to_sym)
118
+ .merge(shell: self, adapter: 'circle_ci'))
106
119
  end
107
120
  end
108
121
  end