credman 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f25d3191780d08906d8892c1f95ad775b11bebef09037be0bb93118bf3d86886
4
- data.tar.gz: b07393ac4330ee9aaa4bc9b022ab9a64f7330cbea16f130b8a00886fa76dcdcd
3
+ metadata.gz: 7091148f095fc916aa4cf688580c55738c3e5729a151b0cd13641f56f6555800
4
+ data.tar.gz: f491e43c418467b63854fe11a796e0bd53a23d32e2bfee1451584a27045b63d7
5
5
  SHA512:
6
- metadata.gz: 32b50f324c60ae1257b2838cc596d30d5c6681351885cb0f0b9f98f7ee6d6d8ee6df053ee6b0d593574567cca3008b3878e4c2e99b20ff83c2af6d04979f6644
7
- data.tar.gz: 24389f20374400c35c28813bd463f41f51af0f807cda971aa8e1c9d29f39542956596cd2bc69abedd7feb912db2f189a9531279cefa2b75dd9fc9b969153d445
6
+ metadata.gz: 5847672f5ff43eccece5a745b247348384feaf4df52d15e84d6a4b37bd50eac8793272abe2231ffe93542be4fde2c6c4db8e23d6851459c4cea63a59230d95ea
7
+ data.tar.gz: 835d72fe2686d7aa562c28bbe956d1d867833d0bfb1d1df52b7fa6127a22b3186e48dd756d8bc606a91a99da28994607d7e39a8e418e4868653e0549c3f85f34
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [0.0.6] - 2022-09-19
2
+
3
+ - Cover all commands by specs (PR #11)
4
+ - Small refactoring with extracting common methods into Credman::Base class (PR #11)
5
+ - default `default_diff_branch` changed to `origin/main` (PR #11)
6
+ - `version` command added (PR #13)
7
+
1
8
  ## [0.0.5] - 2022-09-06
2
9
 
3
10
  - Introduce config with `default_diff_branch` and `available_environments` options (PR #9)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- credman (0.0.5)
4
+ credman (0.0.6)
5
5
  activesupport (>= 6.0)
6
6
  dry-cli (~> 0.7)
7
7
  hash_diff (~> 1.0)
@@ -11,7 +11,7 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- activesupport (7.0.3.1)
14
+ activesupport (7.0.4)
15
15
  concurrent-ruby (~> 1.0, >= 1.0.2)
16
16
  i18n (>= 1.6, < 2)
17
17
  minitest (>= 5.1)
data/README.md CHANGED
@@ -1,6 +1,20 @@
1
+ [![Gem Version](https://badge.fury.io/rb/credman.svg)](https://badge.fury.io/rb/credman)
2
+
1
3
  # Credman
2
4
 
3
- Handy console command for developers to manage Rails credentials.
5
+ Handy console tool for developers to manage Rails credentials.
6
+
7
+ ## Motivation
8
+
9
+ Rails credentials is a nice tool to store encrypted credentials directly in your repo. Starting with Rails 6.0 it brings multi environment credentials feature that allows us to split credentials into separate files.
10
+
11
+ But it also brought a lot of pain for developers:
12
+ - Each enviroment credentials file must have a complete list of all keys. It's easy to forget to add a key into one of the environments (see [set](#credman-set) and [delete](#credman-delete) command)
13
+ - You have to manually open each environment file. It's ok for one file but not for 3 or more. It also brings mistakes you might miss until deploy to production. (see [set](#credman-set) and [delete](#credman-delete) command)
14
+ - Merge conflicts become a hell since files are encrypted (see [conflicts](#credman-conflicts) command)
15
+ - You can't easily see what keys were added/changed/deleted in the current branch (see [diff](#credman-diff) command)
16
+
17
+ This gem is designed to solve all these problems and make life easier for developers who use multi environment credentials.
4
18
 
5
19
  ## Installation
6
20
 
@@ -25,12 +39,51 @@ or
25
39
  bundle exec credman usage
26
40
  ```
27
41
 
42
+ <details>
43
+ <summary>Output</summary>
44
+
45
+ ```
46
+ Commands:
47
+ credman conflicts # Help to resolve merge conflicts for credentials
48
+ credman delete KEYS # Delete keys for given environments
49
+ credman diff [BRANCH] # Show credentials diff between given branch (heroku by default) and current changes
50
+ credman get KEYS # Find keys in credentials files for each environment
51
+ credman list # List of all keys for each environment
52
+ credman set KEY VALUE # Set a value to the key provided for given environments
53
+ ```
54
+
55
+ </details>
56
+
28
57
  Details of any command:
29
58
 
30
59
  ```
31
60
  bundle exec credman set -h
32
61
  ```
33
62
 
63
+ <details>
64
+ <summary>Output</summary>
65
+
66
+ ```
67
+ Command:
68
+ credman set
69
+
70
+ Usage:
71
+ credman set KEY VALUE
72
+
73
+ Description:
74
+ Set a value to the key provided for given environments
75
+
76
+ Arguments:
77
+ KEY # REQUIRED
78
+ VALUE # REQUIRED
79
+
80
+ Options:
81
+ --environments=VALUE1,VALUE2,.., -e VALUE # filter for environments, default: []
82
+ --help, -h
83
+ ```
84
+
85
+ </details>
86
+
34
87
  ### credman list
35
88
  List all your keys for all environments.
36
89
 
@@ -38,48 +91,138 @@ List all your keys for all environments.
38
91
  bundle exec credman list
39
92
  ```
40
93
 
94
+ <details>
95
+ <summary>Output</summary>
96
+
97
+ ```
98
+ development:
99
+ aws.api_key: 123
100
+ ...
101
+ test:
102
+ aws.api_key: nil
103
+ ...
104
+ production:
105
+ aws.api_key: nil
106
+ ...
107
+ ```
108
+ </details>
109
+
41
110
  ### credman get
42
111
  Getting a particular key's values.
43
112
 
44
113
  ```
45
- bundle exec credman get google.maps.api_key github.private_key
114
+ bundle exec credman get google.recaptcha.secret circle_ci.token
46
115
  ```
47
116
 
117
+ <details>
118
+ <summary>Output</summary>
119
+
120
+ ```
121
+ development:
122
+ google.recaptcha.secret: nil
123
+ circle_ci.token: <secret>
124
+ test:
125
+ google.recaptcha.secret: nil
126
+ circle_ci.token: nil
127
+ production:
128
+ google.recaptcha.secret: <secret>
129
+ circle_ci.token: <secret>
130
+ ```
131
+ </details>
132
+
48
133
  ### credman set
49
134
 
50
135
  Add/change a value for a particular key. `-e` attribute is mandatory for this command.
51
136
 
52
137
 
53
138
  ```
54
- bundle exec credman set new_service.super_key new_secret_value -e development,test,staging,production
139
+ bundle exec credman set new_service.super_key new_secret_value -e development,test,production
55
140
  ```
56
141
 
142
+ <details>
143
+ <summary>Output</summary>
144
+
145
+ ```
146
+ development:
147
+ new_service.super_key: ADDED: new_secret_value
148
+ test:
149
+ new_service.super_key: ADDED: new_secret_value
150
+ production:
151
+ new_service.super_key: ADDED: new_secret_value
152
+ ```
153
+ </details>
154
+
57
155
  ### credman delete
58
156
 
59
157
  Delete for keys. `-e` attribute is mandatory for this command.
60
158
 
61
159
  ```
62
- bundle exec credman delete new_service.super_key new_service.another_key -e development,test,staging,production
160
+ bundle exec credman delete new_service.super_key new_service.another_key -e development,test,production
161
+ ```
162
+
163
+ <details>
164
+ <summary>Output</summary>
165
+
166
+ ```
167
+ development:
168
+ new_service.super_key: ✅ deleted
169
+ new_service.another_key: ❌ key not found, can't delete
170
+ test:
171
+ new_service.super_key: ✅ deleted
172
+ new_service.another_key: ❌ key not found, can't delete
173
+ production:
174
+ new_service.super_key: ✅ deleted
175
+ new_service.another_key: ❌ key not found, can't delete
63
176
  ```
177
+ </details>
64
178
 
65
179
  ### credman diff
66
180
 
67
- Shows all keys changed compared with `heroku` branch by default. You can specify any branch from origin you want to. For example `bin/earl diff my_branch`
181
+ Shows all keys changed compared with `main` branch by default.
182
+ You can set the default branch by adding `config/credman.yml` file with `default_diff_branch: your_branch`
183
+ You can specify any branch from origin you want to. For example `credman diff my_branch`
184
+
185
+ ```
186
+ bundle exec credman diff
187
+ ```
188
+
189
+ <details>
190
+ <summary>Output</summary>
68
191
 
69
192
  ```
70
- > bundle exec credman diff
71
193
  development:
72
194
  new_service.super_key: ADDED: "new_secret_value"
73
195
  test:
74
196
  new_service.super_key: ADDED: "new_secret_value"
75
- staging:
76
- new_service.super_key: ADDED: "new_secret_value"
77
197
  production:
78
198
  new_service.super_key: ADDED: "new_secret_value"
79
199
  ```
200
+ </details>
80
201
 
81
202
  ### credman conflicts
82
- Run it if you have merge conflicts in `configs/credentials/*.yml.enc`. That interactive tool will help you resolve the conflict.
203
+
204
+ Run it if you have merge conflicts in `configs/credentials/*.yml.enc`.
205
+ That interactive tool will help you resolve the conflict.
206
+ In most of cases it will just automagically resolve the conflicts.
207
+ In case of a key was changed in both branches it will ask you to choose the correct value.
208
+
209
+ ```
210
+ bundle exec credman conflicts
211
+ ```
212
+
213
+ <details>
214
+ <summary>Output</summary>
215
+
216
+ ```
217
+ development:
218
+ ❗️ The key another_key changed in both branches, their: "another_value", our: "conflicting_value"
219
+ Which one should we use? Please type `their` or `our` to apply particular change or enter to abort.
220
+ > their
221
+ ✅ another_key set as "another_value"
222
+ ✅ Merged config for rspec has been saved
223
+ resolves conflict with user input
224
+ ```
225
+ </details>
83
226
 
84
227
  ## Development
85
228
 
File without changes
data/config/credman.yml CHANGED
@@ -1,4 +1,4 @@
1
- default_diff_branch: main
1
+ default_diff_branch: origin/main
2
2
  available_environments:
3
3
  - development
4
4
  - test
data/lib/credman/base.rb CHANGED
@@ -35,15 +35,35 @@ module Credman
35
35
  config.dig(*dig_keys)&.key?(keys_path.last)
36
36
  end
37
37
 
38
+ def rewrite_config_for(environment, new_config)
39
+ # removes "---\n" in the very beginning
40
+ config_as_string = new_config.deep_stringify_keys.to_yaml[4..]
41
+
42
+ encrypted_configuration(environment).write(config_as_string)
43
+ end
44
+
45
+ def key_for(environment)
46
+ ENV["RAILS_MASTER_KEY"] || Pathname.new("config/credentials/#{environment}.key").binread.strip
47
+ end
48
+
49
+ def decript(key, content)
50
+ ActiveSupport::MessageEncryptor.new([key].pack("H*"), cipher: "aes-128-gcm")
51
+ .decrypt_and_verify(content)
52
+ end
53
+
38
54
  private
39
55
 
40
56
  def config_for(environment)
57
+ encrypted_configuration(environment).config
58
+ end
59
+
60
+ def encrypted_configuration(environment)
41
61
  ActiveSupport::EncryptedConfiguration.new(
42
62
  config_path: "config/credentials/#{environment}.yml.enc",
43
63
  key_path: "config/credentials/#{environment}.key",
44
64
  env_key: "RAILS_MASTER_KEY",
45
65
  raise_if_missing_key: true
46
- ).config
66
+ )
47
67
  end
48
68
  end
49
69
  end
@@ -93,6 +93,14 @@ module Credman
93
93
  Credman::Conflicts.new(environments).perform
94
94
  end
95
95
  end
96
+
97
+ class Version < Dry::CLI::Command
98
+ desc "Print current version"
99
+
100
+ def call(*)
101
+ puts Credman::VERSION
102
+ end
103
+ end
96
104
  end
97
105
  end
98
106
  end
@@ -36,7 +36,7 @@ module Credman
36
36
  end
37
37
  end
38
38
 
39
- add_setting :default_diff_branch, "main"
39
+ add_setting :default_diff_branch, "origin/main"
40
40
  add_setting :available_environments, %w[development test production]
41
41
  end
42
42
  end
@@ -20,9 +20,7 @@ module Credman
20
20
  @merged_config = our_config.deep_merge(their_config)
21
21
  deep_print_diff(HashDiff.diff(their_config, our_config))
22
22
 
23
- # removes "---\n" in the very beginning
24
- merged_config_as_string = @merged_config.deep_stringify_keys.to_yaml[4..]
25
- rewrite_config_for(env, merged_config_as_string)
23
+ rewrite_config_for(env, @merged_config)
26
24
  puts "✅ Merged config for #{env} has been saved"
27
25
  end
28
26
  end
@@ -33,15 +31,6 @@ module Credman
33
31
  deserialize(decript(key_for(environment), encripted_file_content)).deep_symbolize_keys
34
32
  end
35
33
 
36
- def key_for(environment)
37
- Pathname.new("config/credentials/#{environment}.key").binread.strip
38
- end
39
-
40
- def decript(key, content)
41
- ActiveSupport::MessageEncryptor.new([key].pack("H*"), cipher: "aes-128-gcm")
42
- .decrypt_and_verify(content)
43
- end
44
-
45
34
  def deserialize(raw_config)
46
35
  YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(raw_config) : YAML.safe_load(raw_config)
47
36
  end
@@ -105,14 +94,5 @@ module Credman
105
94
  deep_set!(obj[key], keys.slice(1..-1), value)
106
95
  end
107
96
  end
108
-
109
- def rewrite_config_for(environment, new_config)
110
- ActiveSupport::EncryptedFile.new(
111
- content_path: "config/credentials/#{environment}.yml.enc",
112
- key_path: "config/credentials/#{environment}.key",
113
- env_key: "RAILS_MASTER_KEY",
114
- raise_if_missing_key: true
115
- ).write(new_config)
116
- end
117
97
  end
118
98
  end
@@ -20,23 +20,10 @@ module Credman
20
20
  end
21
21
  end
22
22
 
23
- if is_updated
24
- # removes "---\n" in the very beginning
25
- config_as_string = updated_config.deep_stringify_keys.to_yaml[4..]
26
- rewrite_config_for(env, config_as_string)
27
- end
23
+ rewrite_config_for(env, updated_config) if is_updated
28
24
  end
29
25
  end
30
26
 
31
- def rewrite_config_for(environment, new_config)
32
- ActiveSupport::EncryptedConfiguration.new(
33
- config_path: "config/credentials/#{environment}.yml.enc",
34
- key_path: "config/credentials/#{environment}.key",
35
- env_key: "RAILS_MASTER_KEY",
36
- raise_if_missing_key: true
37
- ).write(new_config)
38
- end
39
-
40
27
  def deep_delete!(obj, keys)
41
28
  key = keys.first
42
29
  if keys.length == 1
data/lib/credman/diff.rb CHANGED
@@ -8,11 +8,11 @@ module Credman
8
8
  configs.each do |env, config|
9
9
  puts pastel.green("#{env}:")
10
10
 
11
- result = cmd.run!("echo `git show origin/#{branch_to_compare}:config/credentials/#{env}.yml.enc`")
11
+ result = cmd.run!("echo `git show #{branch_to_compare}:config/credentials/#{env}.yml.enc`")
12
12
  encripted_file_content = result.out.strip
13
13
 
14
14
  if encripted_file_content.blank?
15
- puts "❗️ Can not find #{env} credentials file in origin/#{branch_to_compare} branch"
15
+ puts "❗️ Can not find #{env} credentials file in #{branch_to_compare} branch"
16
16
  next
17
17
  end
18
18
  branch_config = config_to_compare_for(env, encripted_file_content)
@@ -27,15 +27,6 @@ module Credman
27
27
  deserialize(decript(key_for(environment), encripted_file_content)).deep_symbolize_keys
28
28
  end
29
29
 
30
- def key_for(environment)
31
- Pathname.new("config/credentials/#{environment}.key").binread.strip
32
- end
33
-
34
- def decript(key, content)
35
- ActiveSupport::MessageEncryptor.new([key].pack("H*"), cipher: "aes-128-gcm")
36
- .decrypt_and_verify(content)
37
- end
38
-
39
30
  def deserialize(raw_config)
40
31
  YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(raw_config) : YAML.safe_load(raw_config)
41
32
  end
data/lib/credman/set.rb CHANGED
@@ -3,6 +3,7 @@ module Credman
3
3
  def perform(key, new_value)
4
4
  key_with_path = key.split(".").map(&:to_sym)
5
5
  new_value = normalize_new_value(new_value)
6
+ abort pastel.red("Invalid key") if key.blank?
6
7
 
7
8
  configs.each do |env, config|
8
9
  puts pastel.green("#{env}:")
@@ -25,22 +26,11 @@ module Credman
25
26
  if update_config
26
27
  updated_config = config.dup
27
28
  deep_set!(updated_config, key_with_path, new_value)
28
- # removes "---\n" in the very beginning
29
- config_as_string = updated_config.deep_stringify_keys.to_yaml[4..]
30
- rewrite_config_for(env, config_as_string)
29
+ rewrite_config_for(env, updated_config)
31
30
  end
32
31
  end
33
32
  end
34
33
 
35
- def rewrite_config_for(environment, new_config)
36
- ActiveSupport::EncryptedConfiguration.new(
37
- config_path: "config/credentials/#{environment}.yml.enc",
38
- key_path: "config/credentials/#{environment}.key",
39
- env_key: "RAILS_MASTER_KEY",
40
- raise_if_missing_key: true
41
- ).write(new_config)
42
- end
43
-
44
34
  def deep_set!(obj, keys, value)
45
35
  key = keys.first
46
36
  if keys.length == 1
@@ -1,3 +1,3 @@
1
1
  module Credman
2
- VERSION = "0.0.5".freeze
2
+ VERSION = "0.0.6".freeze
3
3
  end
data/lib/credman.rb CHANGED
@@ -35,6 +35,7 @@ module Credman
35
35
  register "delete", Delete
36
36
  register "diff", Diff
37
37
  register "conflicts", Conflicts
38
+ register "version", Version, aliases: ["v", "-v", "--version"]
38
39
  end
39
40
  end
40
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: credman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Andronov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-09 00:00:00.000000000 Z
11
+ date: 2022-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -157,6 +157,7 @@ files:
157
157
  - bin/credman
158
158
  - bin/rspec
159
159
  - bin/setup
160
+ - config/credentials/.gitkeep
160
161
  - config/credman.yml
161
162
  - credman.gemspec
162
163
  - gemfiles/.bundle/config