heroku-config 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +29 -2
- data/lib/heroku_config/aws_key.rb +19 -5
- data/lib/heroku_config/aws_rotate.rb +9 -2
- data/lib/heroku_config/aws_rotate_all.rb +24 -0
- data/lib/heroku_config/cli.rb +8 -2
- data/lib/heroku_config/config.rb +2 -1
- data/lib/heroku_config/help/aws_rotate.md +3 -1
- data/lib/heroku_config/help/aws_rotate_all.md +27 -0
- data/lib/heroku_config/version.rb +1 -1
- data/spec/fixtures/heroku-apps.txt +2 -0
- data/spec/lib/cli_spec.rb +5 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52a0676bf09a3f428fafa5a9c04dc2199f8b7c86712c406591ee300c7725a851
|
4
|
+
data.tar.gz: 3b4c9a26b6f26788a07a5cecd85de0c16a317f4b174aed58dfa43b02b2b5796a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5840cceab8d8bb86d4a2bc126f8e1e132cb7e4849e2b7b31a475cf37ed80b9aa25f60e94afc8b7611ec4e2c9517cd48c1a2779e3b4b4b2b0c989c48307781dee
|
7
|
+
data.tar.gz: e07acd595822a3c66c53f3b727180bf87e9d30aae5f9fc26db4374035a6786859736bb58597402349bdfee96c56219688defb6285cf78d0ca71b73c9a7c2dadd
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,10 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
|
5
5
|
|
6
|
+
## [0.3.0]
|
7
|
+
- add aws-rotate-all command
|
8
|
+
- friendly error if access key does not exist on heroku app
|
9
|
+
|
6
10
|
## [0.2.0]
|
7
11
|
- check if new key is useable before completing rotation
|
8
12
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -4,12 +4,18 @@
|
|
4
4
|
|
5
5
|
Quickly rotate [AWS credential keys](https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html) and [heroku configs](https://devcenter.heroku.com/articles/config-vars).
|
6
6
|
|
7
|
-
Do you have long-term AWS credentials like `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` deployed to your Heroku applications? When was the last time they were rotated?
|
7
|
+
Do you have long-term AWS credentials like `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` deployed to your Heroku applications? When was the last time they were rotated?
|
8
8
|
|
9
9
|
Rotating AWS keys is one of the simplest security measures to take. Usually though, we're too busy with developing features and rotating keys take a back seat. This tool automates the boring and manual process of rotating keys. Run this on your CodeBuild, jenkins server, a lambda function, or just manually when you have to.
|
10
10
|
|
11
11
|
## Usage
|
12
12
|
|
13
|
+
Switch to an AWS_PROFILE with the permissions to create and delete AWS keys, usually an admin.
|
14
|
+
|
15
|
+
export AWS_PROFILE=yourprofile
|
16
|
+
|
17
|
+
Run the `aws-rotate` command.
|
18
|
+
|
13
19
|
heroku-config aws-rotate APP
|
14
20
|
|
15
21
|
## Example with Output
|
@@ -27,9 +33,30 @@ Rotating AWS keys is one of the simplest security measures to take. Usually thou
|
|
27
33
|
Old access key deleted: AKIAXZ6ODJLQSGEXAMPLE
|
28
34
|
$
|
29
35
|
|
36
|
+
## Rotate Multiple Apps
|
37
|
+
|
38
|
+
You can use the `aws-rotate-all` command to rotate a list of heroku apps.
|
39
|
+
|
40
|
+
heroku-config aws-rotate-all FILE
|
41
|
+
|
42
|
+
The FILE should contain a list of apps separated by new lines. Example:
|
43
|
+
|
44
|
+
~/heroku-apps.txt:
|
45
|
+
|
46
|
+
radiant-fortress-40674
|
47
|
+
protected-oasis-24054
|
48
|
+
|
49
|
+
Then the command would be:
|
50
|
+
|
51
|
+
heroku-config aws-rotate-all ~/heroku-apps.txt
|
52
|
+
|
53
|
+
For more help:
|
54
|
+
|
55
|
+
heroku-config aws-rotate-all -h
|
56
|
+
|
30
57
|
## Installation
|
31
58
|
|
32
|
-
|
59
|
+
Install with:
|
33
60
|
|
34
61
|
gem install heroku-config
|
35
62
|
|
@@ -2,6 +2,7 @@ module HerokuConfig
|
|
2
2
|
class AwsKey < Base
|
3
3
|
include AwsServices
|
4
4
|
class MaxKeysError < StandardError; end
|
5
|
+
class AccessKeyNotFound < StandardError; end
|
5
6
|
|
6
7
|
def initialize(options, access_key_id)
|
7
8
|
@options, @access_key_id = options, access_key_id
|
@@ -26,13 +27,25 @@ module HerokuConfig
|
|
26
27
|
true
|
27
28
|
end
|
28
29
|
|
29
|
-
def get_user_name
|
30
|
+
def get_user_name(quiet_error: true)
|
30
31
|
return "fakeuser" if @options[:noop]
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
begin
|
34
|
+
resp = iam.get_access_key_last_used(
|
35
|
+
access_key_id: @access_key_id,
|
36
|
+
)
|
37
|
+
resp.user_name
|
38
|
+
rescue Aws::IAM::Errors::AccessDenied => e # "obscure" error if access key is not found also
|
39
|
+
puts "#{e.class} #{e.message}".color(:red)
|
40
|
+
puts <<~EOL
|
41
|
+
Are you sure the access key exists?
|
42
|
+
You can try running the following with an admin user to see if the key exists:
|
43
|
+
|
44
|
+
aws iam get-access-key-last-used --access-key-id #{@access_key_id}
|
45
|
+
|
46
|
+
EOL
|
47
|
+
@options[:cli] ? exit(1) : raise(AccessKeyNotFound)
|
48
|
+
end
|
36
49
|
end
|
37
50
|
|
38
51
|
def wait_until_usable(key, secret)
|
@@ -44,6 +57,7 @@ module HerokuConfig
|
|
44
57
|
)
|
45
58
|
begin
|
46
59
|
sts.get_caller_identity
|
60
|
+
puts "Confirmed that new AWS key is usable."
|
47
61
|
true
|
48
62
|
rescue Aws::STS::Errors::InvalidClientTokenId => e
|
49
63
|
puts "#{e.class}: #{e.message}"
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module HerokuConfig
|
2
2
|
class AwsRotate < Base
|
3
|
+
class MaxKeysError < StandardError; end
|
4
|
+
|
3
5
|
def initialize(options={})
|
4
6
|
@options = options
|
5
7
|
@app = options[:app]
|
@@ -8,8 +10,13 @@ module HerokuConfig
|
|
8
10
|
def run
|
9
11
|
key_id = config.get("AWS_ACCESS_KEY_ID")
|
10
12
|
unless key_id
|
11
|
-
puts "WARN: No AWS_ACCESS_KEY_ID found for #{@app.color(:green)} app.
|
12
|
-
|
13
|
+
puts "WARN: No AWS_ACCESS_KEY_ID found for #{@app.color(:green)} app."
|
14
|
+
if @options[:cli]
|
15
|
+
puts "Exiting"
|
16
|
+
exit 0
|
17
|
+
else
|
18
|
+
return
|
19
|
+
end
|
13
20
|
end
|
14
21
|
|
15
22
|
aws_key = AwsKey.new(@options, key_id)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module HerokuConfig
|
2
|
+
class AwsRotateAll < Base
|
3
|
+
def initialize(options={})
|
4
|
+
@options = options
|
5
|
+
@file = options[:file]
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
if ENV['HEROKU_CONFIG_TEST']
|
10
|
+
puts "NOOP"
|
11
|
+
return
|
12
|
+
end
|
13
|
+
|
14
|
+
apps.each do |app|
|
15
|
+
AwsRotate.new(@options.merge(app: app)).run
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def apps
|
20
|
+
IO.readlines(@file).map(&:strip).reject(&:empty?)
|
21
|
+
end
|
22
|
+
memoize :apps
|
23
|
+
end
|
24
|
+
end
|
data/lib/heroku_config/cli.rb
CHANGED
@@ -3,10 +3,16 @@ module HerokuConfig
|
|
3
3
|
class_option :verbose, type: :boolean
|
4
4
|
class_option :noop, type: :boolean
|
5
5
|
|
6
|
-
desc "aws-rotate APP", "
|
6
|
+
desc "aws-rotate APP", "Rotates AWS key for app"
|
7
7
|
long_desc Help.text(:aws_rotate)
|
8
8
|
def aws_rotate(app)
|
9
|
-
AwsRotate.new(options.merge(app: app)).run
|
9
|
+
AwsRotate.new(options.merge(app: app, cli: true)).run
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "aws-rotate-all FILE", "Rotates AWS key for list of apps"
|
13
|
+
long_desc Help.text(:aws_rotate_all)
|
14
|
+
def aws_rotate_all(file)
|
15
|
+
AwsRotateAll.new(options.merge(file: file)).run
|
10
16
|
end
|
11
17
|
|
12
18
|
desc "completion *PARAMS", "Prints words for auto-completion."
|
data/lib/heroku_config/config.rb
CHANGED
@@ -8,11 +8,13 @@
|
|
8
8
|
=> heroku config:get AWS_ACCESS_KEY_ID -a protected-oasis-24054
|
9
9
|
Updating access key for user: bob
|
10
10
|
Created new access key: AKIAXZ6ODJLQQEXAMPLE
|
11
|
+
Checking if new AWS key is usable yet.
|
12
|
+
Confirmed that new AWS key is usable.
|
11
13
|
=> heroku config:set AWS_ACCESS_KEY_ID=AKIAXZ6ODJLQQEXAMPLE AWS_SECRET_ACCESS_KEY=sp4gmsuif0XgYG2cPiZbkvl93kTGaeDDhEXAMPLE -a protected-oasis-24054
|
12
14
|
Setting heroku config variables
|
13
15
|
Setting AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and restarting protected-oasis-24054... done, v21
|
14
16
|
|
15
17
|
AWS_ACCESS_KEY_ID: AKIAXZ6ODJLQQEXAMPLE
|
16
18
|
AWS_SECRET_ACCESS_KEY: sp4gmsuif0XgYG2cPiZbkvl93kTGaeDDhEXAMPLE
|
17
|
-
Old access key deleted:
|
19
|
+
Old access key deleted: AKIAXZ6ODJLQSEXAMPLE
|
18
20
|
$
|
@@ -0,0 +1,27 @@
|
|
1
|
+
## Examples
|
2
|
+
|
3
|
+
heroku-config aws-rotate-all
|
4
|
+
|
5
|
+
## Example with Output
|
6
|
+
|
7
|
+
$ cat ~/heroku-apps.txt
|
8
|
+
radiant-fortress-40674
|
9
|
+
protected-oasis-24054
|
10
|
+
$ heroku-config aws-rotate-all ~/heroku-apps.txt
|
11
|
+
=> heroku config:get AWS_ACCESS_KEY_ID -a radiant-fortress-40674
|
12
|
+
WARN: No AWS_ACCESS_KEY_ID found for radiant-fortress-40674 app.
|
13
|
+
=> heroku config:get AWS_ACCESS_KEY_ID -a protected-oasis-24054
|
14
|
+
Updating access key for user: bob
|
15
|
+
Created new access key: AKIAXZ6ODJLQSEXAMPLE
|
16
|
+
Checking if new AWS key is usable yet.
|
17
|
+
Aws::STS::Errors::InvalidClientTokenId: The security token included in the request is invalid.
|
18
|
+
New IAM key not usable yet. Delaying for 5 seconds and retrying...
|
19
|
+
Confirmed that new AWS key is usable.
|
20
|
+
=> heroku config:set AWS_ACCESS_KEY_ID=AKIAXZ6ODJLQSEXAMPLE AWS_SECRET_ACCESS_KEY=SGxokj5/9PYaAtqu3C6UOqPPUi+C0yPT6EXAMPLE -a protected-oasis-24054
|
21
|
+
Setting heroku config variables
|
22
|
+
Setting AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and restarting protected-oasis-24054... done, v27
|
23
|
+
|
24
|
+
AWS_ACCESS_KEY_ID: AKIAXZ6ODJLQSEXAMPLE
|
25
|
+
AWS_SECRET_ACCESS_KEY: SGxokj5/9PYaAtqu3C6UOqPPUi+C0yPT6EXAMPLE
|
26
|
+
Old access key deleted: AKIAXZ6ODJLQZEXAMPLE
|
27
|
+
$
|
data/spec/lib/cli_spec.rb
CHANGED
@@ -6,8 +6,12 @@ describe HerokuConfig::CLI do
|
|
6
6
|
describe "heroku-config" do
|
7
7
|
it "aws-rotate" do
|
8
8
|
out = execute("exe/heroku-config aws-rotate #{@args}")
|
9
|
-
puts out
|
10
9
|
expect(out).to include("NOOP: Updating access key for user: fakeuser")
|
11
10
|
end
|
11
|
+
|
12
|
+
it "aws-rotate-all" do
|
13
|
+
out = execute("exe/heroku-config aws-rotate-all spec/fixtures/heroku-apps.txt")
|
14
|
+
expect(out).to include("NOOP")
|
15
|
+
end
|
12
16
|
end
|
13
17
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heroku-config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -202,6 +202,7 @@ files:
|
|
202
202
|
- lib/heroku_config/autoloader.rb
|
203
203
|
- lib/heroku_config/aws_key.rb
|
204
204
|
- lib/heroku_config/aws_rotate.rb
|
205
|
+
- lib/heroku_config/aws_rotate_all.rb
|
205
206
|
- lib/heroku_config/aws_services.rb
|
206
207
|
- lib/heroku_config/base.rb
|
207
208
|
- lib/heroku_config/cli.rb
|
@@ -212,9 +213,11 @@ files:
|
|
212
213
|
- lib/heroku_config/config.rb
|
213
214
|
- lib/heroku_config/help.rb
|
214
215
|
- lib/heroku_config/help/aws_rotate.md
|
216
|
+
- lib/heroku_config/help/aws_rotate_all.md
|
215
217
|
- lib/heroku_config/help/completion.md
|
216
218
|
- lib/heroku_config/help/completion_script.md
|
217
219
|
- lib/heroku_config/version.rb
|
220
|
+
- spec/fixtures/heroku-apps.txt
|
218
221
|
- spec/lib/cli_spec.rb
|
219
222
|
- spec/spec_helper.rb
|
220
223
|
homepage: https://github.com/tongueroo/heroku-config
|
@@ -241,5 +244,6 @@ signing_key:
|
|
241
244
|
specification_version: 4
|
242
245
|
summary: Heroku Config AWS Access Key Rotator
|
243
246
|
test_files:
|
247
|
+
- spec/fixtures/heroku-apps.txt
|
244
248
|
- spec/lib/cli_spec.rb
|
245
249
|
- spec/spec_helper.rb
|