aws-mfa-secure 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 373259274cc623e8bb6b7ca2e044be59ea2abaa6c09f268bdf5376518b04baff
4
+ data.tar.gz: 8a59132aa173779f10f17d7e5d9ce4eedcb50ae304b6c8624f8db3e37dd79bbe
5
+ SHA512:
6
+ metadata.gz: 890158626d55398170a6904f1c2e19ce863a52caee43dd458f7d17967c9e73d0039676fcc3c0f36cd05658aee6ac6152fd568c80edb0b65e048812b98e379104
7
+ data.tar.gz: 9e09d81ad7ec37a89e4e4e5c0305c0e9f4367286ccc7d5664c90aa7aa6a3e38921b2f3b850442dfa4dd023920ff0d8dd77f516f6231b63b9029de31c8914684c
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ _yardoc
7
+ coverage
8
+ doc/
9
+ InstalledFiles
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --color
3
+ --format documentation
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
+
6
+ ## [0.1.0]
7
+ - Initial release.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem dependencies in aws-mfa-secure.gemspec
4
+ gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/Gemfile.lock ADDED
@@ -0,0 +1,82 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ aws-mfa-secure (0.1.0)
5
+ activesupport
6
+ aws-sdk-core
7
+ memoist
8
+ rainbow
9
+ thor
10
+ zeitwerk
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ activesupport (6.0.1)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 0.7, < 2)
18
+ minitest (~> 5.1)
19
+ tzinfo (~> 1.1)
20
+ zeitwerk (~> 2.2)
21
+ aws-eventstream (1.0.3)
22
+ aws-partitions (1.237.0)
23
+ aws-sdk-core (3.76.0)
24
+ aws-eventstream (~> 1.0, >= 1.0.2)
25
+ aws-partitions (~> 1, >= 1.228.0)
26
+ aws-sigv4 (~> 1.1)
27
+ jmespath (~> 1.0)
28
+ aws-sigv4 (1.1.0)
29
+ aws-eventstream (~> 1.0, >= 1.0.2)
30
+ byebug (11.0.1)
31
+ cli_markdown (0.1.0)
32
+ codeclimate-test-reporter (1.0.9)
33
+ simplecov (<= 0.13)
34
+ concurrent-ruby (1.1.5)
35
+ diff-lcs (1.3)
36
+ docile (1.1.5)
37
+ i18n (1.7.0)
38
+ concurrent-ruby (~> 1.0)
39
+ jmespath (1.4.0)
40
+ json (2.2.0)
41
+ memoist (0.16.1)
42
+ minitest (5.13.0)
43
+ rainbow (3.0.0)
44
+ rake (13.0.0)
45
+ rspec (3.9.0)
46
+ rspec-core (~> 3.9.0)
47
+ rspec-expectations (~> 3.9.0)
48
+ rspec-mocks (~> 3.9.0)
49
+ rspec-core (3.9.0)
50
+ rspec-support (~> 3.9.0)
51
+ rspec-expectations (3.9.0)
52
+ diff-lcs (>= 1.2.0, < 2.0)
53
+ rspec-support (~> 3.9.0)
54
+ rspec-mocks (3.9.0)
55
+ diff-lcs (>= 1.2.0, < 2.0)
56
+ rspec-support (~> 3.9.0)
57
+ rspec-support (3.9.0)
58
+ simplecov (0.13.0)
59
+ docile (~> 1.1.0)
60
+ json (>= 1.8, < 3)
61
+ simplecov-html (~> 0.10.0)
62
+ simplecov-html (0.10.2)
63
+ thor (0.20.3)
64
+ thread_safe (0.3.6)
65
+ tzinfo (1.2.5)
66
+ thread_safe (~> 0.1)
67
+ zeitwerk (2.2.1)
68
+
69
+ PLATFORMS
70
+ ruby
71
+
72
+ DEPENDENCIES
73
+ aws-mfa-secure!
74
+ bundler
75
+ byebug
76
+ cli_markdown
77
+ codeclimate-test-reporter
78
+ rake
79
+ rspec
80
+
81
+ BUNDLED WITH
82
+ 2.0.2
data/Guardfile ADDED
@@ -0,0 +1,19 @@
1
+ guard "bundler", cmd: "bundle" do
2
+ watch("Gemfile")
3
+ watch(/^.+\.gemspec/)
4
+ end
5
+
6
+ guard :rspec, cmd: "bundle exec rspec" do
7
+ require "guard/rspec/dsl"
8
+ dsl = Guard::RSpec::Dsl.new(self)
9
+
10
+ # RSpec files
11
+ rspec = dsl.rspec
12
+ watch(rspec.spec_helper) { rspec.spec_dir }
13
+ watch(rspec.spec_support) { rspec.spec_dir }
14
+ watch(rspec.spec_files)
15
+
16
+ # Ruby files
17
+ ruby = dsl.ruby
18
+ dsl.watch_spec_files_for(ruby.lib_files)
19
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2019 Tung Nguyen
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # AWS MFA Secure
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/aws-mfa-secure.png)](http://badge.fury.io/rb/aws-mfa-secure)
4
+
5
+ Surprisingly, the [aws cli](https://docs.aws.amazon.com/cli/latest/reference/) does not yet support MFA for normal IAM users. See: https://github.com/boto/botocore/pull/1399 The aws-mfa-secure tool decorates the AWS CLI or API to handle MFA authentication. The MFA prompt only activates if `mfa_serial` is configured.
6
+
7
+ ## Installation
8
+
9
+ gem install aws-mfa-secure
10
+
11
+ Prerequisite: The [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/) is required. You can install the AWS CLI via pip.
12
+
13
+ pip install awscli --upgrade --user
14
+
15
+ ## Usage
16
+
17
+ **Summary**:
18
+
19
+ 1. Configure `~/.aws/credentials` with `mfa_serial`
20
+ 2. Set up bash alias
21
+ 3. Use aws cli like normal
22
+
23
+ ### Configure ~/.aws/credentials with mfa_serial
24
+
25
+ Set up `mfa_serial` in credentials file for the profile section that requires it. Example:
26
+
27
+ ~/.aws/credentials:
28
+
29
+ [mfa]
30
+ aws_access_key_id = BKCAXZ6ODJLQ1EXAMPLE
31
+ aws_secret_access_key = ABCDl4hXikfOHTvNqFAnb2Ea62bUuu/eUEXAMPLE
32
+ mfa_serial = arn:aws:iam::112233445566:mfa/MFAUser
33
+
34
+ Note: AWS already supports `mfa_serial` assumed roles: [AWS Configuration and Credential File Settings](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). The aws-mfa-secure tool does not decorate for assumed roles and lets the AWS CLI or SDK handle it.
35
+
36
+ ### Set up bash alias
37
+
38
+ alias aws="aws-mfa-secure session"
39
+
40
+ You may want to add the alias to your `~/.bash_profile`
41
+
42
+ Autocompletion still works with the alias.
43
+
44
+ ### Use aws cli like normal
45
+
46
+ Call `aws` command like you usually would:
47
+
48
+ aws s3 ls
49
+
50
+ ### Example with Output
51
+
52
+ $ export AWS_PROFILE=mfa
53
+ $ aws s3 ls
54
+ Please provide your MFA code: 751888
55
+ 2019-09-21 15:53:34 my-example-test-bucket
56
+ $ aws s3 ls
57
+ 2019-09-21 15:53:34 my-example-test-bucket
58
+ $
59
+
60
+ Expiration: You get prompted for the MFA token once, and the MFA secure session lasts for 12 hours. You can override the default expiration time with `AWS_MFA_TTL`. For example, `AWS_MFA_TTL=3600` means the session expires in 1 hour instead.
61
+
62
+ ## Calling Directly
63
+
64
+ You can also call `aws-mfa-secure session` directly.
65
+
66
+ aws-mfa-secure session --version
67
+ aws-mfa-secure session s3 ls
68
+
69
+ The arguments of `aws-mfa-secure session` are delegated to the `aws` command. So:
70
+
71
+ aws-mfa-secure session s3 ls
72
+
73
+ Is the same as:
74
+
75
+ aws s3 ls
76
+
77
+ Except `aws-mfa-secure session` will use the temporary session environment `AWS_*` variables values.
78
+
79
+ ## Exports
80
+
81
+ You can also generate the exports script.
82
+
83
+ $ aws-mfa-secure exports
84
+ Please provide your MFA code: 147280
85
+ export AWS_ACCESS_KEY_ID=ASIAXZ6ODJLBCEXAMPLE
86
+ export AWS_SECRET_ACCESS_KEY=HgYHvNxacSsFSwls1FO9RoF5+tvYCFIABEXAMPLE
87
+ export AWS_SESSION_TOKEN=IQoJb3JpZ2luX2VjEJ3//////////wEaCXVzLWVhc3QtMSJGMEQCIGnuGzUr8aszNWMFlFXQvFVhIA6aGdx3DskqY1JaIZWVAiANfE3xA79vIMVTqLnds4F2LpDy/qUeNRr7e9g9VQoS9SqyAQi2//////////8BEAEaDDUzNjc2NjI3MDE3NyIMgDgauwgJ4FIOMRV+KoYBRKR/MnKFB9/Q0Isc6D8gpG404xGJWqStNfGS0sHNsB5vVP/ccaAj4MG54p0Pl+V0LuIMXy345ua/bxxQFDWqhG0ORsXFEOo3iD1IQ+YA/yougAUl/0hbyvK3Jnf3NEHDejdL95iFCluJhoR0zFlDv7GwwBSXLUxS9K96/vgA0MmgK9a7kaAwoYiZ7gU63wHVDNYa1myqIP16Mi6KZ2zm9inMofixNN1ea3JMyRW+chWW8kdjjW4R3MFecpwoIayE7g3QLanmjE3jzrlxjIJWnl8tiipV+jassiSdlxLL2j1IIFH2pNEqrn4hkHG5t7OG+qZCTl8AnQ4W5wusmBoSIavr5w0dOdyx2mdsBMFtO82ZXvHSryY1gbIM9JyUd7dJ9h/mkfGL2p0n0R/lya8s9j8P8/8if+2uQcF+/BGDxojJ67kYXgstgfLjM5j8pZgyYj6YUFyTpyiOkllbPk/AjyxJY1svxW25wbNO+c13
88
+ $
89
+
90
+ You can eval it to set the environment variables in one go. Note, the MFA code prompt is written to standard error so it won't affect the eval.
91
+
92
+ $ eval `aws-mfa-secure exports`
93
+
94
+ If you're using the `aws-mfa-secure exports` command, the `aws-mfa-secure unsets` command is useful to unset the `AWS_*` env variables quickly. For more info: `aws-mfa-secure unsets -h`.
95
+
96
+ ## AWS Extension
97
+
98
+ You can also use `aws-mfa-secure` to add MFA support to Ruby libraries. Do so by requiring the `aws_mfa_secure/ext/aws`.
99
+
100
+ ```ruby
101
+ require "aws_mfa_secure/ext/aws" # add MFA support
102
+ ```
103
+
104
+ This patches the aws-sdk-ruby library and adds MFA support.
105
+
106
+ ## Setting MFA Info with Env Variables
107
+
108
+ You can also set the MFA info with env variables. They take the highest precedence and override what's in `~/.aws/credentials`. Example:
109
+
110
+ AWS_MFA_TOKEN=112233 arn:aws:iam::112233445566:mfa/MFAUser aws s3 ls
111
+
112
+ ## How It Works
113
+
114
+ docs: [How It Works](docs/how-it-works.md)
115
+
116
+ ## Related
117
+
118
+ You may also be interested in [tongueroo/aws-rotate](https://github.com/tongueroo/aws-rotate). It's an easy way to rotate all your AWS keys in your `~/.aws/credentials`.
119
+
120
+ ## Contributing
121
+
122
+ 1. Fork it
123
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
124
+ 3. Commit your changes (`git commit -am "Add some feature"`)
125
+ 4. Push to the branch (`git push origin my-new-feature`)
126
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ task default: :spec
5
+
6
+ RSpec::Core::RakeTask.new
7
+
8
+ require_relative "lib/aws-mfa-secure"
9
+ require "cli_markdown"
10
+ desc "Generates cli reference docs as markdown"
11
+ task :docs do
12
+ mkdir_p "docs/_includes"
13
+ CliMarkdown::Creator.create_all(cli_class: AwsMfaSecure::CLI, cli_name: "aws-mfa-secure")
14
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "aws_mfa_secure/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "aws-mfa-secure"
8
+ spec.version = AwsMfaSecure::VERSION
9
+ spec.authors = ["Tung Nguyen"]
10
+ spec.email = ["tongueroo@gmail.com"]
11
+ spec.summary = "Adds MFA Support to AWS CLI and Ruby SDKs for normal IAM user"
12
+ spec.homepage = "https://github.com/tongueroo/aws-mfa-secure"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.bindir = "exe"
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport"
22
+ spec.add_dependency "aws-sdk-core"
23
+ spec.add_dependency "memoist"
24
+ spec.add_dependency "rainbow"
25
+ spec.add_dependency "thor"
26
+ spec.add_dependency "zeitwerk"
27
+
28
+ spec.add_development_dependency "bundler"
29
+ spec.add_development_dependency "byebug"
30
+ spec.add_development_dependency "cli_markdown"
31
+ spec.add_development_dependency "rake"
32
+ spec.add_development_dependency "rspec"
33
+ end
@@ -0,0 +1,19 @@
1
+ ## How It Works
2
+
3
+ The wrapper `aws-mfa-secure session` command uses [sts.get_session_token](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/STS/Client.html#get_session_token-instance_method) to fetch temporary session AWS access tokens.
4
+
5
+ The tokens get saved to `~/.aws/aws-mfa-secure-sessions/AWS_PROFILE` and are then used to set the environment variables, which take the [higher precedence](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html#config-settings-and-precedence).
6
+
7
+ * AWS_ACCESS_KEY_ID
8
+ * AWS_SECRET_ACCESS_KEY
9
+ * AWS_SESSION_TOKEN
10
+
11
+ The arguments are delegate the to the `aws` command. So:
12
+
13
+ aws-mfa-secure session s3 ls
14
+
15
+ Is the same as:
16
+
17
+ aws s3 ls
18
+
19
+ Except using the session environment `AWS_*` variables values.
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Trap ^C
4
+ Signal.trap("INT") {
5
+ puts "\nCtrl-C detected. Exiting..."
6
+ sleep 0.1
7
+ exit
8
+ }
9
+
10
+ $:.unshift(File.expand_path("../../lib", __FILE__))
11
+ require "aws-mfa-secure"
12
+ require "aws_mfa_secure/cli"
13
+
14
+ AwsMfaSecure::CLI.start(ARGV)
@@ -0,0 +1 @@
1
+ require_relative "aws_mfa_secure"
@@ -0,0 +1,12 @@
1
+ $:.unshift(File.expand_path("../", __FILE__))
2
+ require "aws_mfa_secure/version"
3
+ require "rainbow/ext/string"
4
+
5
+ require "aws_mfa_secure/autoloader"
6
+ AwsMfaSecure::Autoloader.setup
7
+
8
+ module AwsMfaSecure
9
+ class Error < StandardError; end
10
+ end
11
+
12
+ require "#{Dir.pwd}/spec/monkey_patches" if ENV['AWS_MFA_SECURE_TEST']
@@ -0,0 +1,22 @@
1
+ require "zeitwerk"
2
+
3
+ module AwsMfaSecure
4
+ class Autoloader
5
+ class Inflector < Zeitwerk::Inflector
6
+ def camelize(basename, _abspath)
7
+ map = { cli: "CLI", version: "VERSION" }
8
+ map[basename.to_sym] || super
9
+ end
10
+ end
11
+
12
+ class << self
13
+ def setup
14
+ loader = Zeitwerk::Loader.new
15
+ loader.inflector = Inflector.new
16
+ loader.push_dir(File.dirname(__dir__)) # lib
17
+ loader.ignore("#{File.dirname(__dir__)}/aws-mfa-secure.rb")
18
+ loader.setup
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,128 @@
1
+ require "aws-sdk-core"
2
+ require "fileutils"
3
+ require "json"
4
+ require "memoist"
5
+ require "time"
6
+ require "active_support/core_ext/string"
7
+ require "active_support/core_ext/hash"
8
+
9
+ module AwsMfaSecure
10
+ class MfaError < StandardError; end
11
+
12
+ class Base
13
+ extend Memoist
14
+
15
+ def iam_mfa?
16
+ return false unless mfa_serial
17
+
18
+ # The iam_mfa? check will only return true for the case when mfa_serial is set and access keys are used.
19
+ # This is because for assume role cases, the current aws cli tool supports mfa_serial already.
20
+ # Sending session AWS based access keys intefere with the current aws cli assume role mfa_serial support
21
+ aws_access_key_id = aws_configure_get(:aws_access_key_id)
22
+ aws_secret_access_key = aws_configure_get(:aws_secret_access_key)
23
+ source_profile = aws_configure_get(:source_profile)
24
+
25
+ aws_access_key_id && aws_secret_access_key && !source_profile
26
+ end
27
+
28
+ def fetch_creds?
29
+ !good_session_creds?
30
+ end
31
+
32
+ def good_session_creds?
33
+ return false unless File.exist?(session_creds_path)
34
+
35
+ expiration = Time.parse(credentials["expiration"])
36
+ Time.now.utc < expiration # not expired
37
+ end
38
+
39
+ def credentials
40
+ JSON.load(IO.read(session_creds_path))
41
+ end
42
+ memoize :credentials
43
+
44
+ def save_creds(credentials)
45
+ FileUtils.mkdir_p(File.dirname(session_creds_path))
46
+ IO.write(session_creds_path, JSON.pretty_generate(credentials))
47
+ end
48
+
49
+ def session_creds_path
50
+ "#{ENV['HOME']}/.aws/aws-mfa-secure-sessions/#{@aws_profile}"
51
+ end
52
+
53
+ def get_session_token(shell: false)
54
+ retries = 0
55
+ begin
56
+ token_code = mfa_prompt
57
+ options = {
58
+ serial_number: mfa_serial,
59
+ token_code: token_code,
60
+ }
61
+ options[:duration_seconds] = ENV['AWS_MFA_TTL'] if ENV['AWS_MFA_TTL']
62
+
63
+ if shell
64
+ shell_get_session_token(options, token_code) # mimic ruby sdk
65
+ else # ruby sdk
66
+ sts.get_session_token(options)
67
+ end
68
+ rescue Aws::STS::Errors::ValidationError, Aws::STS::Errors::AccessDenied, MfaError => e
69
+ $stderr.puts "#{e.class}: #{e.message}"
70
+ $stderr.puts "Incorrect MFA code. Please try again."
71
+ retries += 1
72
+ if retries >= 3
73
+ $stderr.puts "Giving up after #{retries} retries."
74
+ exit 1
75
+ end
76
+ retry
77
+ end
78
+ end
79
+
80
+ def mfa_prompt
81
+ if ENV['AWS_MFA_TOKEN']
82
+ token_code = ENV.delete('AWS_MFA_TOKEN') # only use once, prompt afterwards if incorrect
83
+ return token_code
84
+ end
85
+
86
+ $stderr.print "Please provide your MFA code: "
87
+ $stdin.gets.strip
88
+ end
89
+
90
+ def shell_get_session_token(options, token_code)
91
+ args = options.map { |k,v| "--#{k.to_s.gsub('_','-')} #{v}" }.join(' ')
92
+ command = "aws sts get-session-token #{args} 2>&1"
93
+ # puts "=> #{command}" # uncomment for debugging
94
+ out = `#{command}`
95
+
96
+ unless out.include?("Credentials")
97
+ raise(MfaError, out.strip) # custom error
98
+ end
99
+
100
+ data = JSON.load(out)
101
+ resp = data.deep_transform_keys { |k| k.underscore }
102
+ # mimic ruby sdk resp
103
+ credentials = Aws::STS::Types::Credentials.new(resp["credentials"])
104
+ Aws::STS::Types::GetSessionTokenResponse.new(credentials: credentials)
105
+ end
106
+
107
+ def mfa_serial
108
+ ENV['AWS_MFA_SERIAL'] || aws_configure_get(:mfa_serial)
109
+ end
110
+
111
+ def sts
112
+ Aws::STS::Client.new
113
+ end
114
+ memoize :sts
115
+
116
+ # Note the strip
117
+ # Each aws configure get call has about a 300-400ms overhead so we memoize it.
118
+ def aws_configure_get(prop)
119
+ v = `aws configure get #{prop}`.strip
120
+ v unless v.empty?
121
+ end
122
+ memoize :aws_configure_get
123
+
124
+ def aws_profile
125
+ ENV['AWS_PROFILE'] || 'default'
126
+ end
127
+ end
128
+ end