credman 0.0.5 → 0.0.6
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/CHANGELOG.md +7 -0
- data/Gemfile.lock +2 -2
- data/README.md +152 -9
- data/config/credentials/.gitkeep +0 -0
- data/config/credman.yml +1 -1
- data/lib/credman/base.rb +21 -1
- data/lib/credman/commands.rb +8 -0
- data/lib/credman/configuration.rb +1 -1
- data/lib/credman/conflicts.rb +1 -21
- data/lib/credman/delete.rb +1 -14
- data/lib/credman/diff.rb +2 -11
- data/lib/credman/set.rb +2 -12
- data/lib/credman/version.rb +1 -1
- data/lib/credman.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7091148f095fc916aa4cf688580c55738c3e5729a151b0cd13641f56f6555800
|
4
|
+
data.tar.gz: f491e43c418467b63854fe11a796e0bd53a23d32e2bfee1451584a27045b63d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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
|
+
[](https://badge.fury.io/rb/credman)
|
2
|
+
|
1
3
|
# Credman
|
2
4
|
|
3
|
-
Handy console
|
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.
|
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,
|
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,
|
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 `
|
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
|
-
|
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
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
|
-
)
|
66
|
+
)
|
47
67
|
end
|
48
68
|
end
|
49
69
|
end
|
data/lib/credman/commands.rb
CHANGED
data/lib/credman/conflicts.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/credman/delete.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
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
|
data/lib/credman/version.rb
CHANGED
data/lib/credman.rb
CHANGED
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.
|
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-
|
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
|