heroku-config 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f2111e59e572f3463941128576134d04698f17a13fd133c1213a420b8aa59dd
4
- data.tar.gz: 77deca42ebf969b897016d61895c61c9c401a0d1833e5f0a2bbbb2a65a021e51
3
+ metadata.gz: 52a0676bf09a3f428fafa5a9c04dc2199f8b7c86712c406591ee300c7725a851
4
+ data.tar.gz: 3b4c9a26b6f26788a07a5cecd85de0c16a317f4b174aed58dfa43b02b2b5796a
5
5
  SHA512:
6
- metadata.gz: 077a3d0563fb87a77786a1e714a0c1674f6efbcf0deb97df964d02cb32018ceb9d77dcb9b6234a95db9ac2f5e9c8e61f5698e8542ad0746d7025325740e8db71
7
- data.tar.gz: b2f1d704ee3de001475569491e09368c41ba22258d64d15b88e0e1a4ff92f44f8553d1007d6f1b1472e816963837320bf40f3b5e357fb280b3f0568c193f3648
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- heroku-config (0.1.0)
4
+ heroku-config (0.2.0)
5
5
  activesupport
6
6
  aws-sdk-core
7
7
  aws-sdk-iam
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
- Or install with RubyGems.
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
- resp = iam.get_access_key_last_used(
33
- access_key_id: @access_key_id,
34
- )
35
- resp.user_name
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. Exiting."
12
- exit 0
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
@@ -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", "Say aws_rotate to 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."
@@ -9,7 +9,8 @@ module HerokuConfig
9
9
 
10
10
  def get(name)
11
11
  return "fakevalue" if ENV['HEROKU_CONFIG_TEST']
12
- sh "heroku config:get #{name} -a #{@app}"
12
+ out = sh "heroku config:get #{name} -a #{@app}"
13
+ return out if !out&.empty?
13
14
  end
14
15
 
15
16
  def set(*params)
@@ -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: AKIAXZ6ODJLQSGGE27KK
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
+ $
@@ -1,3 +1,3 @@
1
1
  module HerokuConfig
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -0,0 +1,2 @@
1
+ radiant-fortress-40674
2
+ protected-oasis-24054
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.2.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-16 00:00:00.000000000 Z
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