aws_assume_role 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +0 -4
- data/.ruby-version +1 -0
- data/.simplecov +22 -0
- data/.travis.yml +10 -1
- data/Gemfile +1 -0
- data/README.md +9 -4
- data/Rakefile +16 -1
- data/aws_assume_role.gemspec +4 -2
- data/lib/aws_assume_role/cli/actions/abstract_action.rb +7 -3
- data/lib/aws_assume_role/cli/actions/includes.rb +1 -9
- data/lib/aws_assume_role/cli/actions/run.rb +1 -1
- data/lib/aws_assume_role/cli/actions/test.rb +3 -1
- data/lib/aws_assume_role/cli/includes.rb +1 -0
- data/lib/aws_assume_role/core_ext/aws-sdk/includes.rb +1 -1
- data/lib/aws_assume_role/credentials/factories/abstract_factory.rb +1 -1
- data/lib/aws_assume_role/credentials/factories/assume_role.rb +13 -14
- data/lib/aws_assume_role/credentials/factories/default_chain_provider.rb +56 -47
- data/lib/aws_assume_role/credentials/factories/includes.rb +7 -11
- data/lib/aws_assume_role/credentials/factories/instance_profile.rb +1 -1
- data/lib/aws_assume_role/credentials/factories/repository.rb +2 -2
- data/lib/aws_assume_role/credentials/factories/shared.rb +7 -5
- data/lib/aws_assume_role/credentials/includes.rb +4 -0
- data/lib/aws_assume_role/credentials/providers/includes.rb +3 -5
- data/lib/aws_assume_role/credentials/providers/mfa_session_credentials.rb +20 -23
- data/lib/aws_assume_role/credentials/providers/shared_keyring_credentials.rb +27 -10
- data/lib/aws_assume_role/includes.rb +9 -3
- data/lib/aws_assume_role/profile_configuration.rb +24 -25
- data/lib/aws_assume_role/runner.rb +9 -10
- data/lib/aws_assume_role/store/includes.rb +1 -11
- data/lib/aws_assume_role/store/keyring.rb +1 -2
- data/lib/aws_assume_role/store/shared_config_with_keyring.rb +86 -28
- data/lib/aws_assume_role/types.rb +1 -2
- data/lib/aws_assume_role/vendored/aws/assume_role_credentials.rb +0 -1
- data/lib/aws_assume_role/vendored/aws/includes.rb +1 -1
- data/lib/aws_assume_role/vendored/aws/refreshing_credentials.rb +0 -2
- data/lib/aws_assume_role/vendored/aws/shared_config.rb +4 -1
- data/lib/aws_assume_role/version.rb +1 -1
- metadata +40 -9
- data/lib/aws_assume_role/credentials/factories/shared_keyring.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 740d4539f3f7bf68b7acedc131890496b67eaef4
|
4
|
+
data.tar.gz: a5f739bbb05c1cd1edfc59e156ee2a348c88c9ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0898326d54de021a939f2375466c7376a3e42cca8b7c597d4b03a9b11b4a407b078b4560ec3790418c462a84bbde0836a2f9ea30acf5e1b3cebfab25e2567a55
|
7
|
+
data.tar.gz: f161cc86abf84c2e893cc9426bea9861b02b30bd31fccbf2ed8f7ac526252d51f236e530b5a178fffde1db94ef910a7cf87fc22c9645f8685f0eaa49eeb58c24
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
---
|
2
|
-
#require: rubocop-rspec
|
3
2
|
AllCops:
|
4
3
|
DisplayCopNames: true
|
5
4
|
Exclude:
|
@@ -26,9 +25,6 @@ Metrics/PerceivedComplexity:
|
|
26
25
|
Style/IndentationWidth:
|
27
26
|
Width: 4
|
28
27
|
|
29
|
-
RSpec/ExampleLength:
|
30
|
-
Enabled: false
|
31
|
-
|
32
28
|
Style/TrailingCommaInArguments:
|
33
29
|
EnforcedStyleForMultiline: comma
|
34
30
|
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.10
|
data/.simplecov
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'coveralls'
|
2
|
+
Coveralls.wear_merged!
|
3
|
+
|
4
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
5
|
+
SimpleCov::Formatter::HTMLFormatter,
|
6
|
+
Coveralls::SimpleCov::Formatter
|
7
|
+
])
|
8
|
+
|
9
|
+
SimpleCov.start do
|
10
|
+
|
11
|
+
project_name 'AWS Assume Role'
|
12
|
+
|
13
|
+
add_filter '/spec/'
|
14
|
+
add_filter 'lib/aws_assume_role/vendored'
|
15
|
+
|
16
|
+
%w(aws_assume_role).each do |group_name|
|
17
|
+
add_group(group_name, "/#{group_name}/lib")
|
18
|
+
end
|
19
|
+
|
20
|
+
merge_timeout 60 * 15 # 15 minutes
|
21
|
+
|
22
|
+
end
|
data/.travis.yml
CHANGED
@@ -1,11 +1,20 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
+
- 2.1
|
3
4
|
- 2.2
|
5
|
+
- 2.3.0
|
6
|
+
sudo: false
|
7
|
+
script: bundle exec rake
|
4
8
|
deploy:
|
5
9
|
provider: rubygems
|
6
10
|
api_key:
|
7
|
-
secure:
|
11
|
+
secure: H6MYP5cWFC0BtqrxW6ahc1RFxywtyKRFjGlSpyoBM+AH2y8U194toWQdGyO/QMRQVr7vAZf+MdxYTutDvnBEkwQbof6QBJ1+4GFWSqFgYAVEV5Ddva0ea5dVE8xC3rMRvd+i5KTzwuVNX/+Cux49v2wGRWZLKOmBSWbujsL8SbpdKaPi+qsClkdz3YTrHpGEEWTPNBNTwDMlg+qAX3UkqoAxD5ebrUaFPdJR83yMSGUPfTm/urlKvkx85MONuj7lPL1CyoYJCvy31bE6CWGq2L/+2Fnk8RvNMCaDffY+8YjKhWduBLrGuUYWf+ZcERxW6AxDy6BFIkekpFwpeaDmrdfSTK0aELSZogGqs9VHs9O1pTApdS/NRYDzxC9hmlvub80xC2uI1Vnhn04Z95Gh9KYh0H20UnlBJJ7ewvFPHzQ3zK8Z2O3kJOeZo0rX2d3yGOydyHlf1dX/auGnn8QVcr7w1jERQDLi5ZEAR+EGnYROvfGKjfP9rgaLoouTbEGXx7KV9QQjLUsmQ0q2yu+HoVlQaDtv7VEQTtFnvdmiVGYbWj+DhaquvTmHyiizO7hFOfvVYYFyOM2iFoRCY+dT3kapqc0DM94BUjxV3tMZX6MYNYfwnNwhNNpTXLVvVXP9cShL+ogwY/E0C2Fg2CYdY5/Ioe6hUbAiPx79dwzVfic=
|
8
12
|
gem: aws_assume_role
|
9
13
|
on:
|
10
14
|
tags: true
|
11
15
|
repo: scalefactory/aws-assume-role
|
16
|
+
notifications:
|
17
|
+
slack:
|
18
|
+
secure: RmJmJSSDI8qdIpM2KKYoXX2mpcL85YZ9r9gF4rauZH9TuqnYOPP3kQ5iYJsE0VUTuZpuvQ8Axoux5IQr+IDK7kMrmrI0iaZp1dAR9tGK+aLF73sprOmQEou6HIoDs97UQhOWlsAUR8max/7WYdJYJ1o78dqavfFtOy0VcHCkUMRf+WxcKzz+8MunsocIYi0HXuz5vC3RAZCOaK2h8epXzmnWq0ke8YeTmddpDWC85wzeDNjA9T1j5WD+y6gC9F0vyaqVqDCsCXlbRKZl7a1TU9QGDVyBzowoGsWmTpFR80v4CKofAn6nnMRqblwATOS1jMT+HC+Yku29qFzXPugYa2KAUSQaYQiOe+TE5IDa2Exe/57ZQCOq4ve8gKSE9aQXh4Riq3u8qccM+UeoQdcwgXQIciTeWjqi4LQro6Dbyrv8XrUbxdG0VPsWmf49jbWgq6PPAJqdcbXr9eGb+81uJ2REa1vhDYZu4T3JHv4erd5QlyYWzeBJ/LMQav/C5mnMF43jg8DzZ2g0BZBao/reO9xcZre/ka8eOus9Ll1i+8PCxmFZMx2KDPC9i5R7bXL/CwPBjzFInmvHM0cgKjxrRSY6xMWSPyBbgdsKJl2qag74K5xG+2VPlMcVx0ikTKVjsja5iPlOYKhflGAfCKvpzPcd2QoEWg8jZYqZtO9Nj+M=
|
19
|
+
on_success: change
|
20
|
+
on_failure: change
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
aws-assume-role
|
2
2
|
---------------
|
3
|
+
[![Build Status](https://travis-ci.org/scalefactory/aws-assume-role.svg?branch=master)](https://travis-ci.org/scalefactory/aws-assume-role)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/github/scalefactory/aws-assume-role/badge.svg?branch=master)](https://coveralls.io/github/scalefactory/aws-assume-role?branch=master)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/scalefactory/aws-assume-role/badges/gpa.svg)](https://codeclimate.com/github/scalefactory/aws-assume-role)
|
6
|
+
[![Dependencies](https://img.shields.io/librariesio/github/scalefactory/aws-assume-role.svg)](https://libraries.io/rubygems/aws_assume_role)
|
7
|
+
[![Gem Version](https://badge.fury.io/rb/aws_assume_role.svg)](https://badge.fury.io/rb/aws_assume_role)
|
3
8
|
|
4
9
|
aws-assume-role is a utility intended for developer and operator environments
|
5
10
|
who need to use 2FA and role assumption to access AWS services.
|
@@ -17,11 +22,11 @@ disk as unencrypted files.
|
|
17
22
|
|
18
23
|
It allows easy credential management and role assumption with a 2FA/MFA device.
|
19
24
|
|
20
|
-
For more information on role assumption, see the AWS documentation.
|
25
|
+
For more information on role assumption, see the [AWS documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html).
|
21
26
|
|
22
27
|
Requirements
|
23
28
|
------------
|
24
|
-
* Ruby ≥ 2.
|
29
|
+
* Ruby ≥ 2.1
|
25
30
|
* OS X KeyChain or GNOME Keyring
|
26
31
|
|
27
32
|
Install
|
@@ -179,14 +184,14 @@ where options is a hash with the following symbol keys:
|
|
179
184
|
`aws_assume_role` resolves credentials in almost the same way as the AWS SDK, i.e.:
|
180
185
|
|
181
186
|
```no-highlight
|
182
|
-
static credentials ⟶ environment variables ⟶ configured profiles
|
187
|
+
static credentials ⟶ environment variables ⟶ configured profiles role ⟶ assumption (look up source profile and check for 2FA)
|
183
188
|
```
|
184
189
|
|
185
190
|
Any of the above may get chained to do MFA or role assumption, or both,
|
186
191
|
in the following order:
|
187
192
|
|
188
193
|
```no-highlight
|
189
|
-
second factor ⟶
|
194
|
+
second factor ⟶ ecs/instance profile
|
190
195
|
```
|
191
196
|
|
192
197
|
These are the same as the AWS SDK equivalents whereever possible. The command line help will give an explanation of the rest.
|
data/Rakefile
CHANGED
@@ -1,8 +1,23 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
task default: :
|
2
|
+
task default: :test
|
3
3
|
|
4
4
|
begin
|
5
5
|
require "rspec/core/rake_task"
|
6
6
|
RSpec::Core::RakeTask.new(:spec)
|
7
7
|
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
8
8
|
end
|
9
|
+
|
10
|
+
begin
|
11
|
+
require "rubocop/rake_task"
|
12
|
+
RuboCop::RakeTask.new(:rubocop)
|
13
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
14
|
+
end
|
15
|
+
|
16
|
+
task :test => [:no_pry, :rubocop, :spec] # rubocop:disable Style/HashSyntax
|
17
|
+
|
18
|
+
task :no_pry do
|
19
|
+
files = Dir.glob("**/**").reject { |x| x.match(/^spec|Gemfile|coverage|\.gemspec$|Rakefile/) || File.directory?(x) }
|
20
|
+
files.each do |file|
|
21
|
+
raise "Use of pry found in #{file}." if File.read(file) =~ /"pry"/
|
22
|
+
end
|
23
|
+
end
|
data/aws_assume_role.gemspec
CHANGED
@@ -22,10 +22,10 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^bin/aws}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
|
-
spec.add_runtime_dependency "activesupport", "~> 4.
|
25
|
+
spec.add_runtime_dependency "activesupport", "~> 4.2"
|
26
26
|
spec.add_runtime_dependency "aws-sdk", "~> 2.7"
|
27
27
|
spec.add_runtime_dependency "dry-configurable", "~> 0.5"
|
28
|
-
spec.add_runtime_dependency "dry-
|
28
|
+
spec.add_runtime_dependency "dry-struct", "~> 0.1"
|
29
29
|
spec.add_runtime_dependency "dry-types", "~> 0.9"
|
30
30
|
spec.add_runtime_dependency "dry-validation", "~> 0.10"
|
31
31
|
spec.add_runtime_dependency "gli", "~> 2.15"
|
@@ -38,6 +38,8 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.add_development_dependency "rspec", "~> 3.5"
|
39
39
|
spec.add_development_dependency "rubocop", "~> 0.46"
|
40
40
|
spec.add_development_dependency "yard", "~> 0.9"
|
41
|
+
spec.add_development_dependency "simplecov", "~> 0.13"
|
42
|
+
spec.add_development_dependency "webmock", "~> 2.3"
|
41
43
|
|
42
44
|
case Gem::Platform.local.os
|
43
45
|
when "linux"
|
@@ -4,12 +4,15 @@ require_relative "../../profile_configuration"
|
|
4
4
|
class AwsAssumeRole::Cli::Actions::AbstractAction
|
5
5
|
include AwsAssumeRole
|
6
6
|
include AwsAssumeRole::Types
|
7
|
-
include Ui
|
7
|
+
include AwsAssumeRole::Ui
|
8
|
+
include AwsAssumeRole::Logging
|
8
9
|
CommandSchema = proc { raise "CommandSchema Not implemented" }
|
9
10
|
|
10
11
|
def initialize(global_options, options, args)
|
11
12
|
config = ProfileConfiguration.new_from_cli(global_options, options, args)
|
12
|
-
|
13
|
+
logger.debug "Config initialized with #{config.to_hash}"
|
14
|
+
result = validate_options(config.to_hash)
|
15
|
+
logger.debug "Config validated as #{result.to_hash}"
|
13
16
|
return act_on(config) if result.success?
|
14
17
|
Ui.show_validation_errors result
|
15
18
|
end
|
@@ -17,8 +20,9 @@ class AwsAssumeRole::Cli::Actions::AbstractAction
|
|
17
20
|
private
|
18
21
|
|
19
22
|
def try_for_credentials(config)
|
20
|
-
@provider ||= AwsAssumeRole::Credentials::Factories::DefaultChainProvider.new(config.
|
23
|
+
@provider ||= AwsAssumeRole::Credentials::Factories::DefaultChainProvider.new(config.to_hash)
|
21
24
|
creds = @provider.resolve(nil_with_role_not_set: true)
|
25
|
+
logger.debug "Got credentials #{creds}"
|
22
26
|
return creds unless creds.nil?
|
23
27
|
rescue NoMethodError
|
24
28
|
error "Cannot find any credentials"
|
@@ -1,13 +1,5 @@
|
|
1
|
-
|
2
|
-
require "aws-sdk"
|
3
|
-
require "dry-types"
|
1
|
+
require_relative "../includes"
|
4
2
|
require_relative "../../types"
|
5
|
-
require "dry-validation"
|
6
|
-
require "active_support/core_ext/hash/compact"
|
7
|
-
require "active_support/core_ext/hash/keys"
|
8
|
-
require "launchy"
|
9
|
-
require "open-uri"
|
10
|
-
require "json"
|
11
3
|
require_relative "../../../aws_assume_role"
|
12
4
|
|
13
5
|
module AwsAssumeRole
|
@@ -20,7 +20,7 @@ class AwsAssumeRole::Cli::Actions::Run < AwsAssumeRole::Cli::Actions::AbstractAc
|
|
20
20
|
def act_on(config)
|
21
21
|
credentials = try_for_credentials config.to_h
|
22
22
|
unless config.args.empty?
|
23
|
-
Runner.new(config.args,
|
23
|
+
Runner.new(command: config.args,
|
24
24
|
environment: { "AWS_DEFAULT_REGION" => resolved_region },
|
25
25
|
credentials: credentials)
|
26
26
|
end
|
@@ -17,7 +17,9 @@ class AwsAssumeRole::Cli::Actions::Test < AwsAssumeRole::Cli::Actions::AbstractA
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def act_on(config)
|
20
|
-
|
20
|
+
logger.debug "Will try for credentials"
|
21
|
+
credentials = try_for_credentials config
|
22
|
+
logger.debug "Got credentials #{credentials}"
|
21
23
|
client = Aws::STS::Client.new(credentials: credentials, region: resolved_region)
|
22
24
|
identity = client.get_caller_identity
|
23
25
|
out format(t("commands.test.output"), identity.account, identity.arn, identity.user_id)
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "../includes"
|
@@ -15,7 +15,7 @@ class AwsAssumeRole::Credentials::Factories::AbstractFactory
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.type(str)
|
18
|
-
@type = Types::Strict::Symbol.enum(:credential_provider, :second_factor_provider, :
|
18
|
+
@type = Types::Strict::Symbol.enum(:credential_provider, :second_factor_provider, :instance_role_provider)[str]
|
19
19
|
register_if_complete
|
20
20
|
end
|
21
21
|
|
@@ -4,11 +4,14 @@ require_relative "../providers/mfa_session_credentials"
|
|
4
4
|
|
5
5
|
class AwsAssumeRole::Credentials::Factories::AssumeRole < AwsAssumeRole::Credentials::Factories::AbstractFactory
|
6
6
|
include AwsAssumeRole::Credentials::Factories
|
7
|
-
type :
|
8
|
-
priority
|
7
|
+
type :credential_provider
|
8
|
+
priority 20
|
9
9
|
|
10
10
|
def initialize(options)
|
11
|
+
logger.debug "AwsAssumeRole::Credentials::Factories::AssumeRole initiated with #{options}"
|
12
|
+
return unless options[:profile] || options[:role_arn]
|
11
13
|
if options[:profile]
|
14
|
+
logger.debug "AwsAssumeRole: #{options[:profile]} found. Trying with profile"
|
12
15
|
try_with_profile(options)
|
13
16
|
else
|
14
17
|
if options[:use_mfa]
|
@@ -19,20 +22,16 @@ class AwsAssumeRole::Credentials::Factories::AssumeRole < AwsAssumeRole::Credent
|
|
19
22
|
end
|
20
23
|
|
21
24
|
def try_with_profile(options)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@
|
28
|
-
@region ||= AwsAssumeRole.shared_config.profile_region(@profiles)
|
25
|
+
return unless AwsAssumeRole.shared_config.config_enabled?
|
26
|
+
logger.debug "AwsAssumeRole: Shared Config enabled"
|
27
|
+
@profile = options[:profile]
|
28
|
+
@region = options[:region]
|
29
|
+
@credentials = assume_role_with_profile(options)
|
30
|
+
@region ||= AwsAssumeRole.shared_config.profile_region(@profile)
|
29
31
|
@role_arn ||= AwsAssumeRole.shared_config.profile_role(@profile)
|
30
32
|
end
|
31
33
|
|
32
|
-
def assume_role_with_profile(
|
33
|
-
AwsAssumeRole.shared_config.assume_role_credentials_from_config(
|
34
|
-
profile: prof,
|
35
|
-
region: region,
|
36
|
-
)
|
34
|
+
def assume_role_with_profile(options)
|
35
|
+
AwsAssumeRole.shared_config.assume_role_credentials_from_config(options)
|
37
36
|
end
|
38
37
|
end
|
@@ -6,77 +6,83 @@ require_relative "environment"
|
|
6
6
|
require_relative "repository"
|
7
7
|
require_relative "instance_profile"
|
8
8
|
require_relative "assume_role"
|
9
|
-
require_relative "shared_keyring"
|
10
9
|
require_relative "shared"
|
11
10
|
require_relative "static"
|
12
11
|
|
13
|
-
class AwsAssumeRole::Credentials::Factories::DefaultChainProvider
|
14
|
-
|
12
|
+
class AwsAssumeRole::Credentials::Factories::DefaultChainProvider < Dry::Struct
|
13
|
+
constructor_type :schema
|
15
14
|
include AwsAssumeRole::Credentials::Factories
|
15
|
+
include AwsAssumeRole::Logging
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
17
|
+
attribute :access_key_id, Dry::Types["strict.string"].optional
|
18
|
+
attribute :credentials, Dry::Types["object"].optional
|
19
|
+
attribute :secret_access_key, Dry::Types["strict.string"].optional
|
20
|
+
attribute :session_token, Dry::Types["strict.string"].optional
|
21
|
+
attribute :duration_seconds, Dry::Types["coercible.int"].optional
|
22
|
+
attribute :external_id, Dry::Types["strict.string"].optional
|
23
|
+
attribute :persist_session, Dry::Types["strict.bool"].default(true)
|
24
|
+
attribute :path, Dry::Types["strict.string"].optional
|
25
|
+
attribute :profile, Dry::Types["strict.string"].optional
|
26
|
+
attribute :profile_name, Dry::Types["strict.string"].optional
|
27
|
+
attribute :region, Dry::Types["strict.string"].optional
|
28
|
+
attribute :role_arn, Dry::Types["strict.string"].optional
|
29
|
+
attribute :role_session_name, Dry::Types["strict.string"].optional
|
30
|
+
attribute :serial_number, Dry::Types["strict.string"].optional
|
31
|
+
attribute :mfa_serial, Dry::Types["strict.string"].optional
|
32
|
+
attribute :use_mfa, Dry::Types["strict.bool"].default(false)
|
33
|
+
attribute :no_profile, Dry::Types["strict.bool"].default(false)
|
34
|
+
attribute :source_profile, Dry::Types["strict.string"].optional
|
35
|
+
attribute :instance_profile_credentials_retries, Dry::Types["strict.int"].default(0)
|
36
|
+
attribute :instance_profile_credentials_timeout, Dry::Types["coercible.float"].default(1.0)
|
35
37
|
|
36
|
-
def
|
37
|
-
if options
|
38
|
-
|
38
|
+
def self.new(options)
|
39
|
+
if options.respond_to? :resolve
|
40
|
+
finalize_instance new_with_seahorse(options)
|
39
41
|
else
|
40
|
-
|
42
|
+
finalize_instance(options)
|
41
43
|
end
|
42
|
-
|
43
|
-
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.finalize_instance(options)
|
47
|
+
new_opts = options.to_h
|
48
|
+
new_opts[:profile_name] ||= new_opts[:profile]
|
49
|
+
new_opts[:original_profile] = new_opts[:profile_name]
|
50
|
+
instance = allocate
|
51
|
+
instance.send(:initialize, new_opts)
|
52
|
+
instance
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.new_with_seahorse(resolver)
|
56
|
+
keys = resolver.resolve
|
57
|
+
options = keys.map do |k|
|
58
|
+
[k, resolver.send(k)]
|
59
|
+
end
|
60
|
+
finalize_instance(options.to_h)
|
44
61
|
end
|
45
62
|
|
46
63
|
def resolve(nil_with_role_not_set: false, explicit_default_profile: false)
|
47
64
|
resolve_final_credentials(explicit_default_profile)
|
48
|
-
nil_creds = Aws::Credentials.new(nil, nil, nil)
|
49
|
-
return
|
65
|
+
# nil_creds = Aws::Credentials.new(nil, nil, nil)
|
66
|
+
return nil if (nil_with_role_not_set &&
|
50
67
|
@role_arn &&
|
51
68
|
@credentials.credentials.session_token.nil?) || @credentials.nil?
|
52
69
|
@credentials
|
53
70
|
end
|
54
71
|
|
72
|
+
def to_h
|
73
|
+
to_hash
|
74
|
+
end
|
75
|
+
|
55
76
|
private
|
56
77
|
|
57
78
|
def resolve_final_credentials(explicit_default_profile = false)
|
58
79
|
resolve_credentials(:credential_provider, true, explicit_default_profile)
|
59
80
|
return @credentials if @credentials && @credentials.set? && !use_mfa && !role_arn
|
60
81
|
resolve_credentials(:second_factor_provider, true, explicit_default_profile)
|
61
|
-
return @credentials if @credentials && @credentials.set? && !role_arn
|
62
|
-
resolve_credentials(:role_assumption_provider, true, explicit_default_profile)
|
63
82
|
return @credentials if @credentials && @credentials.set?
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
def initialize_with_seahorse(resolver)
|
68
|
-
keys = resolver.resolve
|
69
|
-
options = keys.map do |k|
|
70
|
-
[k, resolver.send(k)]
|
71
|
-
end
|
72
|
-
__initialize__(options.to_h)
|
73
|
-
end
|
74
|
-
|
75
|
-
def to_h
|
76
|
-
instance_values.delete("__options__").symbolize_keys.merge(
|
77
|
-
instance_profile_credentials_retries: instance_profile_credentials_retries,
|
78
|
-
instance_profile_credentials_timeout: instance_profile_credentials_timeout,
|
79
|
-
)
|
83
|
+
resolve_credentials(:instance_role_provider, true, explicit_default_profile)
|
84
|
+
return @credentials if @credentials && @credentials.set?
|
85
|
+
nil
|
80
86
|
end
|
81
87
|
|
82
88
|
def resolve_credentials(type, break_if_successful = false, explicit_default_profile = false)
|
@@ -84,13 +90,16 @@ class AwsAssumeRole::Credentials::Factories::DefaultChainProvider
|
|
84
90
|
factories_to_try.each do |x|
|
85
91
|
options = to_h
|
86
92
|
options[:credentials] = credentials if credentials && credentials.set?
|
93
|
+
logger.debug "About to try credential lookup with #{x}"
|
87
94
|
factory = x.new(options)
|
88
95
|
@region ||= factory.region
|
89
96
|
@profile ||= factory.profile
|
90
97
|
@role_arn ||= factory.role_arn
|
91
98
|
next unless factory.credentials && factory.credentials.set?
|
99
|
+
logger.debug "Profile currently #{@profile}"
|
92
100
|
next if explicit_default_profile && (@profile == "default") && (@profile != @original_profile)
|
93
101
|
@credentials ||= factory.credentials
|
102
|
+
logger.debug "Got #{@credentials}"
|
94
103
|
break if break_if_successful
|
95
104
|
end
|
96
105
|
end
|
@@ -1,17 +1,13 @@
|
|
1
|
-
|
2
|
-
require "dry-types"
|
3
|
-
require "aws-sdk"
|
1
|
+
require_relative "../includes"
|
4
2
|
require_relative "../../logging"
|
5
3
|
require_relative "../../vendored/aws"
|
6
4
|
require_relative "../../../aws_assume_role"
|
7
5
|
|
8
|
-
module AwsAssumeRole
|
9
|
-
module
|
10
|
-
module
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
include AwsAssumeRole::Vendored::Aws
|
15
|
-
end
|
6
|
+
module AwsAssumeRole::Credentials
|
7
|
+
module Factories
|
8
|
+
Types = Dry::Types.module
|
9
|
+
include AwsAssumeRole
|
10
|
+
include AwsAssumeRole::Logging
|
11
|
+
include AwsAssumeRole::Vendored::Aws
|
16
12
|
end
|
17
13
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative "abstract_factory"
|
2
2
|
|
3
3
|
class AwsAssumeRole::Credentials::Factories::InstanceProfile < AwsAssumeRole::Credentials::Factories::AbstractFactory
|
4
|
-
type :
|
4
|
+
type :instance_role_provider
|
5
5
|
priority 40
|
6
6
|
|
7
7
|
def initialize(options = {})
|
@@ -9,7 +9,7 @@ class AwsAssumeRole::Credentials::Factories::Repository
|
|
9
9
|
FactoryRepositoryType = Types::Hash.schema(
|
10
10
|
credential_provider: SubFactoryRepositoryType,
|
11
11
|
second_factor_provider: SubFactoryRepositoryType,
|
12
|
-
|
12
|
+
instance_role_provider: SubFactoryRepositoryType,
|
13
13
|
)
|
14
14
|
|
15
15
|
def self.factories
|
@@ -20,7 +20,7 @@ class AwsAssumeRole::Credentials::Factories::Repository
|
|
20
20
|
@repository ||= FactoryRepositoryType[
|
21
21
|
credential_provider: {},
|
22
22
|
second_factor_provider: {},
|
23
|
-
|
23
|
+
instance_role_provider: {},
|
24
24
|
]
|
25
25
|
end
|
26
26
|
|
@@ -1,14 +1,16 @@
|
|
1
1
|
require_relative "abstract_factory"
|
2
|
+
require_relative "../providers/shared_keyring_credentials"
|
2
3
|
|
3
4
|
class AwsAssumeRole::Credentials::Factories::Shared < AwsAssumeRole::Credentials::Factories::AbstractFactory
|
4
5
|
type :credential_provider
|
5
|
-
priority
|
6
|
+
priority 30
|
6
7
|
|
7
8
|
def initialize(options = {})
|
8
|
-
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
9
|
+
logger.debug "Shared Factory initiated with #{options}"
|
10
|
+
@profile = options[:profile]
|
11
|
+
@credentials = AwsAssumeRole::Credentials::Providers::SharedKeyringCredentials.new(options)
|
12
|
+
@region = @credentials.region
|
13
|
+
@role_arn = @credentials.role_arn
|
12
14
|
rescue Aws::Errors::NoSuchProfileError
|
13
15
|
nil
|
14
16
|
end
|
@@ -1,9 +1,7 @@
|
|
1
|
+
require_relative "../includes"
|
1
2
|
require_relative "../../vendored/aws"
|
2
3
|
require_relative "../../ui"
|
3
4
|
require_relative "../../logging"
|
4
|
-
module AwsAssumeRole
|
5
|
-
module
|
6
|
-
module Providers
|
7
|
-
end
|
8
|
-
end
|
5
|
+
module AwsAssumeRole::Credentials
|
6
|
+
module Providers end
|
9
7
|
end
|
@@ -1,32 +1,29 @@
|
|
1
1
|
require_relative "includes"
|
2
2
|
require_relative "../../types"
|
3
|
+
require_relative "../../configuration"
|
3
4
|
|
4
|
-
class AwsAssumeRole::Credentials::Providers::MfaSessionCredentials
|
5
|
+
class AwsAssumeRole::Credentials::Providers::MfaSessionCredentials < Dry::Struct
|
6
|
+
constructor_type :schema
|
5
7
|
include AwsAssumeRole::Vendored::Aws::CredentialProvider
|
6
8
|
include AwsAssumeRole::Vendored::Aws::RefreshingCredentials
|
7
9
|
include AwsAssumeRole::Ui
|
8
10
|
include AwsAssumeRole::Logging
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
option :region, type: AwsAssumeRole::Types::Region.optional, default: proc { AwsAssumeRole.Config.region }
|
22
|
-
option :serial_number, type: AwsAssumeRole::Types::MfaSerial.optional, default: proc { "automatic" }
|
23
|
-
|
24
|
-
def initialize(*options)
|
25
|
-
super(*options)
|
11
|
+
|
12
|
+
attribute :permanent_credentials, Dry::Types["object"].optional
|
13
|
+
attribute :credentials, Dry::Types["object"].optional
|
14
|
+
attribute :expiration, Dry::Types["strict.time"].default(Time.now)
|
15
|
+
attribute :first_time, Dry::Types["strict.bool"].default(true)
|
16
|
+
attribute :persist_session, Dry::Types["strict.bool"].default(true)
|
17
|
+
attribute :duration_seconds, Dry::Types["coercible.int"].default(3600)
|
18
|
+
attribute :region, AwsAssumeRole::Types::Region.optional
|
19
|
+
attribute :serial_number, AwsAssumeRole::Types::MfaSerial.optional.default("automatic")
|
20
|
+
|
21
|
+
def initialize(options)
|
22
|
+
options.each { |key, value| instance_variable_set("@#{key}", value) }
|
26
23
|
@permanent_credentials ||= credentials
|
27
24
|
@credentials = nil
|
28
25
|
@serial_number = resolve_serial_number(serial_number)
|
29
|
-
AwsAssumeRole::Vendored::Aws::RefreshingCredentials.instance_method(:initialize).bind(self).call(
|
26
|
+
AwsAssumeRole::Vendored::Aws::RefreshingCredentials.instance_method(:initialize).bind(self).call(options)
|
30
27
|
end
|
31
28
|
|
32
29
|
private
|
@@ -67,14 +64,15 @@ class AwsAssumeRole::Credentials::Providers::MfaSessionCredentials
|
|
67
64
|
end
|
68
65
|
|
69
66
|
def credentials_from_keyring
|
70
|
-
@credentials_from_keyring ||= AwsAssumeRole::Store::Keyring.fetch
|
67
|
+
@credentials_from_keyring ||= AwsAssumeRole::Store::Keyring.fetch keyring_username
|
71
68
|
rescue Aws::Errors::NoSuchProfileError
|
72
69
|
logger.debug "Key not found"
|
73
70
|
@credentials_from_keyring = nil
|
71
|
+
return nil
|
74
72
|
end
|
75
73
|
|
76
74
|
def persist_credentials
|
77
|
-
AwsAssumeRole::Store::Keyring.save_credentials
|
75
|
+
AwsAssumeRole::Store::Keyring.save_credentials keyring_username, @credentials, expiration: @expiration
|
78
76
|
end
|
79
77
|
|
80
78
|
def instance_credentials(credentials)
|
@@ -84,7 +82,7 @@ class AwsAssumeRole::Credentials::Providers::MfaSessionCredentials
|
|
84
82
|
end
|
85
83
|
|
86
84
|
def set_credentials_from_keyring
|
87
|
-
instance_credentials credentials_from_keyring
|
85
|
+
instance_credentials credentials_from_keyring if credentials_from_keyring
|
88
86
|
initialized
|
89
87
|
refresh_using_mfa unless @credentials && !near_expiration?
|
90
88
|
end
|
@@ -98,5 +96,4 @@ class AwsAssumeRole::Credentials::Providers::MfaSessionCredentials
|
|
98
96
|
user_name = identity.arn.split("/")[1]
|
99
97
|
"arn:aws:iam::#{identity.account}:mfa/#{user_name}"
|
100
98
|
end
|
101
|
-
Dry::Types.register_class(self)
|
102
99
|
end
|
@@ -2,21 +2,38 @@ require_relative "includes"
|
|
2
2
|
require_relative "../../types"
|
3
3
|
|
4
4
|
class AwsAssumeRole::Credentials::Providers::SharedKeyringCredentials < ::Aws::SharedCredentials
|
5
|
+
include AwsAssumeRole::Logging
|
6
|
+
attr_reader :region, :role_arn
|
7
|
+
|
5
8
|
def initialize(options = {})
|
6
|
-
|
9
|
+
logger.debug "SharedKeyringCredentials initiated with #{options}"
|
7
10
|
@path = options[:path]
|
8
|
-
@path ||= shared_config.credentials_path
|
9
|
-
@profile_name = options[:profile_name]
|
11
|
+
@path ||= AwsAssumeRole.shared_config.credentials_path
|
12
|
+
@profile_name = options[:profile_name] ||= options[:profile]
|
10
13
|
@profile_name ||= ENV["AWS_PROFILE"]
|
11
|
-
@profile_name ||= shared_config.profile_name
|
12
|
-
|
13
|
-
|
14
|
+
@profile_name ||= AwsAssumeRole.shared_config.profile_name
|
15
|
+
logger.debug "SharedKeyringCredentials resolved profile name #{@profile_name}"
|
16
|
+
config = determine_config(@path, @profile_name)
|
17
|
+
@role_arn = config.profile_hash(@profile_name)
|
18
|
+
@region = config.profile_region(@profile_name)
|
19
|
+
@role_arn = config.profile_role(@profile_name)
|
20
|
+
attempted_credential = config.credentials(options)
|
21
|
+
return unless attempted_credential && attempted_credential.set?
|
22
|
+
@credentials = attempted_credential
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def determine_config(path, profile_name)
|
28
|
+
if path && path == AwsAssumeRole.shared_config.credentials_path
|
29
|
+
logger.debug "SharedKeyringCredentials found shared credential path"
|
30
|
+
AwsAssumeRole.shared_config
|
14
31
|
else
|
15
|
-
|
16
|
-
|
17
|
-
|
32
|
+
logger.debug "SharedKeyringCredentials found custom credential path"
|
33
|
+
AwsAssumeRole::Store::SharedConfigWithKeyring.new(
|
34
|
+
credentials_path: path,
|
35
|
+
profile_name: profile_name,
|
18
36
|
)
|
19
|
-
@credentials = config.credentials(profile: @profile_name)
|
20
37
|
end
|
21
38
|
end
|
22
39
|
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
require "i18n"
|
2
|
-
require "
|
2
|
+
require "active_support/json"
|
3
3
|
require "active_support/core_ext/object/blank"
|
4
4
|
require "active_support/core_ext/string/inflections"
|
5
|
+
require "active_support/core_ext/hash/compact"
|
5
6
|
require "active_support/core_ext/hash/keys"
|
6
|
-
require "active_support/core_ext/
|
7
|
+
require "active_support/core_ext/hash/slice"
|
7
8
|
require "aws-sdk"
|
8
9
|
require "aws-sdk-core/ini_parser"
|
9
10
|
require "dry-configurable"
|
10
|
-
require "dry-
|
11
|
+
require "dry-struct"
|
11
12
|
require "dry-validation"
|
12
13
|
require "dry-types"
|
13
14
|
require "English"
|
@@ -15,8 +16,13 @@ require "gli"
|
|
15
16
|
require "highline"
|
16
17
|
require "inifile"
|
17
18
|
require "json"
|
19
|
+
require "keyring"
|
20
|
+
require "launchy"
|
18
21
|
require "logger"
|
22
|
+
require "open-uri"
|
19
23
|
require "pastel"
|
24
|
+
require "securerandom"
|
25
|
+
require "set"
|
20
26
|
require "thread"
|
21
27
|
require "time"
|
22
28
|
|
@@ -1,29 +1,30 @@
|
|
1
1
|
require_relative "includes"
|
2
2
|
require_relative "logging"
|
3
3
|
|
4
|
-
class AwsAssumeRole::ProfileConfiguration
|
5
|
-
|
4
|
+
class AwsAssumeRole::ProfileConfiguration < Dry::Struct
|
5
|
+
constructor_type :schema
|
6
6
|
include AwsAssumeRole::Logging
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
7
|
+
attribute :access_key_id, Dry::Types["strict.string"].optional
|
8
|
+
attribute :credentials, Dry::Types["object"].optional
|
9
|
+
attribute :secret_access_key, Dry::Types["strict.string"].optional
|
10
|
+
attribute :session_token, Dry::Types["strict.string"].optional
|
11
|
+
attribute :duration_seconds, Dry::Types["coercible.int"].optional
|
12
|
+
attribute :external_id, Dry::Types["strict.string"].optional
|
13
|
+
attribute :path, Dry::Types["strict.string"].optional
|
14
|
+
attribute :persist_session, Dry::Types["strict.bool"].optional.default(true)
|
15
|
+
attribute :profile, Dry::Types["strict.string"].optional
|
16
|
+
attribute :region, Dry::Types["strict.string"].optional
|
17
|
+
attribute :role_arn, Dry::Types["strict.string"].optional
|
18
|
+
attribute :role_session_name, Dry::Types["strict.string"].optional
|
19
|
+
attribute :serial_number, Dry::Types["strict.string"].optional
|
20
|
+
attribute :mfa_serial, Dry::Types["strict.string"].optional
|
21
|
+
attribute :use_mfa, Dry::Types["strict.bool"].optional.default(false)
|
22
|
+
attribute :no_profile, Dry::Types["strict.bool"].optional.default(false)
|
23
|
+
attribute :shell_type, Dry::Types["strict.string"].optional
|
24
|
+
attribute :source_profile, Dry::Types["strict.string"].optional
|
25
|
+
attribute :args, Dry::Types["strict.array"].optional.default([])
|
26
|
+
attribute :instance_profile_credentials_retries, Dry::Types["strict.int"].default(0)
|
27
|
+
attribute :instance_profile_credentials_timeout, Dry::Types["coercible.float"].default(1.0)
|
27
28
|
|
28
29
|
attr_writer :credentials
|
29
30
|
|
@@ -64,8 +65,6 @@ class AwsAssumeRole::ProfileConfiguration
|
|
64
65
|
end
|
65
66
|
|
66
67
|
def to_h
|
67
|
-
|
68
|
+
to_hash
|
68
69
|
end
|
69
|
-
|
70
|
-
Dry::Types.register_class(self)
|
71
70
|
end
|
@@ -1,18 +1,17 @@
|
|
1
1
|
require_relative "includes"
|
2
2
|
require_relative "logging"
|
3
3
|
|
4
|
-
class AwsAssumeRole::Runner
|
4
|
+
class AwsAssumeRole::Runner < Dry::Struct
|
5
5
|
include AwsAssumeRole::Logging
|
6
|
-
|
6
|
+
constructor_type :schema
|
7
|
+
attribute :command, Dry::Types["coercible.array"].member(Dry::Types["strict.string"]).default([])
|
8
|
+
attribute :exit_on_error, Dry::Types["strict.bool"].default(true)
|
9
|
+
attribute :expected_exit_code, Dry::Types["strict.int"].default(0)
|
10
|
+
attribute :environment, Dry::Types["strict.hash"].default({})
|
11
|
+
attribute :credentials, Dry::Types["object"].optional
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
option :expected_exit_code, Dry::Types["strict.int"], default: proc { 0 }
|
11
|
-
option :environment, Dry::Types["strict.hash"], default: proc { {} }
|
12
|
-
option :credentials, optional: true
|
13
|
-
|
14
|
-
def initialize(params, options = {})
|
15
|
-
super(params, options)
|
13
|
+
def initialize(options)
|
14
|
+
super(options)
|
16
15
|
command_to_exec = command.join(" ")
|
17
16
|
process_credentials unless credentials.blank?
|
18
17
|
system environment, command_to_exec
|
@@ -1,14 +1,4 @@
|
|
1
|
-
|
2
|
-
require "active_support/core_ext/string/inflections"
|
3
|
-
require "active_support/core_ext/hash/slice"
|
4
|
-
require "active_support/json"
|
5
|
-
require "aws-sdk"
|
6
|
-
require "aws-sdk-core/ini_parser"
|
7
|
-
require "inifile"
|
8
|
-
require "json"
|
9
|
-
require "keyring"
|
10
|
-
require "time"
|
11
|
-
require "securerandom"
|
1
|
+
require_relative "../includes"
|
12
2
|
|
13
3
|
module AwsAssumeRole
|
14
4
|
module Store
|
@@ -38,8 +38,7 @@ module AwsAssumeRole::Store::Keyring
|
|
38
38
|
def fetch(id, backend: nil)
|
39
39
|
logger.debug "Fetching #{id} from keyring"
|
40
40
|
fetched = keyring(backend).get_password(KEYRING_KEY, id)
|
41
|
-
|
42
|
-
raise Aws::Errors::NoSuchProfileError unless fetched
|
41
|
+
raise Aws::Errors::NoSuchProfileError if fetched == "null" || fetched.nil? || !fetched
|
43
42
|
JSON.parse(fetched, symbolize_names: true)
|
44
43
|
end
|
45
44
|
|
@@ -10,14 +10,51 @@ class AwsAssumeRole::Store::SharedConfigWithKeyring < AwsAssumeRole::Vendored::A
|
|
10
10
|
|
11
11
|
attr_reader :parsed_config
|
12
12
|
|
13
|
+
# @param [Hash] options
|
14
|
+
# @option options [String] :credentials_path Path to the shared credentials
|
15
|
+
# file. Defaults to "#{Dir.home}/.aws/credentials".
|
16
|
+
# @option options [String] :config_path Path to the shared config file.
|
17
|
+
# Defaults to "#{Dir.home}/.aws/config".
|
18
|
+
# @option options [String] :profile_name The credential/config profile name
|
19
|
+
# to use. If not specified, will check `ENV['AWS_PROFILE']` before using
|
20
|
+
# the fixed default value of 'default'.
|
21
|
+
# @option options [Boolean] :config_enabled If true, loads the shared config
|
22
|
+
# file and enables new config values outside of the old shared credential
|
23
|
+
# spec.
|
13
24
|
def initialize(options = {})
|
14
|
-
|
15
|
-
@config_enabled =
|
16
|
-
@
|
17
|
-
|
25
|
+
@profile_name = determine_profile(options)
|
26
|
+
@config_enabled = options[:config_enabled]
|
27
|
+
@credentials_path = options[:credentials_path] ||
|
28
|
+
determine_credentials_path
|
29
|
+
@parsed_credentials = {}
|
30
|
+
load_credentials_file if loadable?(@credentials_path)
|
31
|
+
return unless @config_enabled
|
32
|
+
@config_path = options[:config_path] || determine_config_path
|
33
|
+
load_config_file if loadable?(@config_path)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @api private
|
37
|
+
def fresh(options = {})
|
38
|
+
@configuration = nil
|
39
|
+
@semaphore = nil
|
40
|
+
@assume_role_shared_config = nil
|
41
|
+
@profile_name = nil
|
42
|
+
@credentials_path = nil
|
43
|
+
@config_path = nil
|
44
|
+
@parsed_credentials = {}
|
45
|
+
@parsed_config = nil
|
46
|
+
@config_enabled = options[:config_enabled] ? true : false
|
47
|
+
@profile_name = determine_profile(options)
|
48
|
+
@credentials_path = options[:credentials_path] ||
|
49
|
+
determine_credentials_path
|
50
|
+
load_credentials_file if loadable?(@credentials_path)
|
51
|
+
return unless @config_enabled
|
52
|
+
@config_path = options[:config_path] || determine_config_path
|
53
|
+
load_config_file if loadable?(@config_path)
|
18
54
|
end
|
19
55
|
|
20
56
|
def credentials(opts = {})
|
57
|
+
logger.debug "SharedConfigWithKeyring asked for credentials with opts #{opts}"
|
21
58
|
p = opts[:profile] || @profile_name
|
22
59
|
validate_profile_exists(p) if credentials_present?
|
23
60
|
credentials_from_keyring(p, opts) || credentials_from_shared(p, opts) || credentials_from_config(p, opts)
|
@@ -59,20 +96,15 @@ class AwsAssumeRole::Store::SharedConfigWithKeyring < AwsAssumeRole::Vendored::A
|
|
59
96
|
end
|
60
97
|
|
61
98
|
def profile_region(profile_name)
|
62
|
-
|
63
|
-
resolve_region(@parsed_config, prof_cfg)
|
99
|
+
resolve_profile_parameter(profile_name, "region")
|
64
100
|
end
|
65
101
|
|
66
102
|
def profile_role(profile_name)
|
67
|
-
|
68
|
-
resolve_arn(@parsed_config, prof_cfg)
|
103
|
+
resolve_profile_parameter(profile_name, "role_arn")
|
69
104
|
end
|
70
105
|
|
71
|
-
def
|
72
|
-
|
73
|
-
ret ||= ENV["AWS_PROFILE"]
|
74
|
-
ret ||= "default"
|
75
|
-
ret
|
106
|
+
def profile_hash(profile_name)
|
107
|
+
{} || @parsed_config[profile_key(profile_name)]
|
76
108
|
end
|
77
109
|
|
78
110
|
private
|
@@ -86,21 +118,32 @@ class AwsAssumeRole::Store::SharedConfigWithKeyring < AwsAssumeRole::Vendored::A
|
|
86
118
|
end
|
87
119
|
end
|
88
120
|
|
89
|
-
def
|
121
|
+
def resolve_profile_parameter(profile_name, param)
|
122
|
+
return unless @parsed_config
|
123
|
+
prof_cfg = @parsed_config[profile_key(profile_name)]
|
124
|
+
resolve_parameter(param, @parsed_config, prof_cfg)
|
125
|
+
end
|
126
|
+
|
127
|
+
def resolve_parameter(param, cfg, prof_cfg)
|
90
128
|
return unless prof_cfg && cfg
|
91
|
-
return prof_cfg[
|
92
|
-
|
93
|
-
|
129
|
+
return prof_cfg[param] if prof_cfg.key? param
|
130
|
+
source_profile = prof_cfg["source_profile"]
|
131
|
+
return unless source_profile
|
132
|
+
source_cfg = cfg[source_profile]
|
133
|
+
return unless source_cfg
|
134
|
+
cfg[prof_cfg["source_profile"]][param] if source_cfg.key?(param)
|
135
|
+
end
|
136
|
+
|
137
|
+
def resolve_region(cfg, prof_cfg)
|
138
|
+
resolve_parameter("region", cfg, prof_cfg)
|
94
139
|
end
|
95
140
|
|
96
141
|
def resolve_arn(cfg, prof_cfg)
|
97
|
-
|
98
|
-
return prof_cfg["role_arn"] if prof_cfg.key? "role_arn"
|
99
|
-
source_cfg = cfg[prof_cfg["source_profile"]]
|
100
|
-
cfg[prof_cfg["source_profile"]]["role_arn"] if source_cfg && source_cfg.key?("role_arn")
|
142
|
+
resolve_parameter("role_arn", cfg, prof_cfg)
|
101
143
|
end
|
102
144
|
|
103
145
|
def assume_role_from_profile(cfg, profile, opts)
|
146
|
+
logger.debug "Entering assume_role_from_profile with #{cfg}, #{profile}, #{opts}"
|
104
147
|
prof_cfg = cfg[profile]
|
105
148
|
return unless cfg && prof_cfg
|
106
149
|
opts[:source_profile] ||= prof_cfg["source_profile"]
|
@@ -133,7 +176,7 @@ class AwsAssumeRole::Store::SharedConfigWithKeyring < AwsAssumeRole::Vendored::A
|
|
133
176
|
def mfa_session(cfg, profile, opts)
|
134
177
|
prof_cfg = cfg[profile]
|
135
178
|
return unless cfg && prof_cfg
|
136
|
-
opts[:serial_number] ||= prof_cfg["mfa_serial"]
|
179
|
+
opts[:serial_number] ||= opts[:mfa_serial] || prof_cfg["mfa_serial"]
|
137
180
|
opts[:source_profile] ||= prof_cfg["source_profile"]
|
138
181
|
opts[:region] ||= profile_region(profile)
|
139
182
|
return unless opts[:serial_number]
|
@@ -141,11 +184,26 @@ class AwsAssumeRole::Store::SharedConfigWithKeyring < AwsAssumeRole::Vendored::A
|
|
141
184
|
AwsAssumeRole::Credentials::Providers::MfaSessionCredentials.new(opts)
|
142
185
|
end
|
143
186
|
|
144
|
-
def credentials_from_keyring(profile,
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
187
|
+
def credentials_from_keyring(profile, opts)
|
188
|
+
logger.debug "Entering credentials_from_keyring"
|
189
|
+
return unless @parsed_config
|
190
|
+
logger.debug "credentials_from_keyring: @parsed_config found"
|
191
|
+
prof_cfg = @parsed_config[profile]
|
192
|
+
return unless prof_cfg
|
193
|
+
logger.debug "credentials_from_keyring: prof_cfg found"
|
194
|
+
opts[:serial_number] ||= opts[:mfa_serial] || prof_cfg[:mfa_serial] || prof_cfg[:serial_number]
|
195
|
+
if opts[:serial_number]
|
196
|
+
logger.debug "credentials_from_keyring detected mfa requirement"
|
197
|
+
mfa_session(@parsed_config, profile, opts)
|
198
|
+
else
|
199
|
+
logger.debug "Attempt to fetch #{profile} from keyring"
|
200
|
+
keyring_creds = Keyring.fetch(profile)
|
201
|
+
return unless keyring_creds
|
202
|
+
creds = Serialization.credentials_from_hash Keyring.fetch(profile)
|
203
|
+
creds if credentials_complete(creds)
|
204
|
+
end
|
205
|
+
rescue Aws::Errors::NoSourceProfileError, Aws::Errors::NoSuchProfileError
|
206
|
+
nil
|
149
207
|
end
|
150
208
|
|
151
209
|
def semaphore
|
@@ -170,6 +228,6 @@ module AwsAssumeRole
|
|
170
228
|
|
171
229
|
def shared_config
|
172
230
|
enabled = ENV["AWS_SDK_CONFIG_OPT_OUT"] ? false : true
|
173
|
-
@
|
231
|
+
@assume_role_shared_config ||= ::AwsAssumeRole::Store::SharedConfigWithKeyring.new(config_enabled: enabled)
|
174
232
|
end
|
175
233
|
end
|
@@ -2,6 +2,7 @@ require_relative "includes"
|
|
2
2
|
module AwsAssumeRole::Vendored::Aws
|
3
3
|
# @api private
|
4
4
|
class SharedConfig
|
5
|
+
include AwsAssumeRole::Logging
|
5
6
|
# @return [String]
|
6
7
|
attr_reader :credentials_path
|
7
8
|
|
@@ -102,9 +103,11 @@ module AwsAssumeRole::Vendored::Aws
|
|
102
103
|
# Will always attempt first to assume a role from the shared credentials
|
103
104
|
# file, if present.
|
104
105
|
def assume_role_credentials_from_config(opts = {})
|
106
|
+
logger.debug "Entered assume_role_credentials_from_config with #{opts}"
|
105
107
|
p = opts.delete(:profile) || @profile_name
|
106
108
|
credentials = assume_role_from_profile(@parsed_credentials, p, opts)
|
107
109
|
if @parsed_config
|
110
|
+
logger.debug "Parsed config loaded, testing"
|
108
111
|
credentials ||= assume_role_from_profile(@parsed_config, p, opts)
|
109
112
|
end
|
110
113
|
credentials
|
@@ -140,7 +143,7 @@ module AwsAssumeRole::Vendored::Aws
|
|
140
143
|
opts[:external_id] ||= prof_cfg["external_id"]
|
141
144
|
opts[:serial_number] ||= prof_cfg["mfa_serial"]
|
142
145
|
opts[:profile] = opts.delete(:source_profile)
|
143
|
-
|
146
|
+
AssumeRoleCredentials.new(opts)
|
144
147
|
else
|
145
148
|
raise ::Aws::Errors::NoSourceProfileError, "Profile #{profile} has a role_arn, and source_profile, but the"\
|
146
149
|
" source_profile does not have credentials."
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws_assume_role
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Topper
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-02-
|
13
|
+
date: 2017-02-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -18,14 +18,14 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - "~>"
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '4.
|
21
|
+
version: '4.2'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - "~>"
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: '4.
|
28
|
+
version: '4.2'
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: aws-sdk
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
@@ -55,19 +55,19 @@ dependencies:
|
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
version: '0.5'
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
|
-
name: dry-
|
58
|
+
name: dry-struct
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
61
|
- - "~>"
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: '
|
63
|
+
version: '0.1'
|
64
64
|
type: :runtime
|
65
65
|
prerelease: false
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
68
|
- - "~>"
|
69
69
|
- !ruby/object:Gem::Version
|
70
|
-
version: '
|
70
|
+
version: '0.1'
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: dry-types
|
73
73
|
requirement: !ruby/object:Gem::Requirement
|
@@ -242,6 +242,34 @@ dependencies:
|
|
242
242
|
- - "~>"
|
243
243
|
- !ruby/object:Gem::Version
|
244
244
|
version: '0.9'
|
245
|
+
- !ruby/object:Gem::Dependency
|
246
|
+
name: simplecov
|
247
|
+
requirement: !ruby/object:Gem::Requirement
|
248
|
+
requirements:
|
249
|
+
- - "~>"
|
250
|
+
- !ruby/object:Gem::Version
|
251
|
+
version: '0.13'
|
252
|
+
type: :development
|
253
|
+
prerelease: false
|
254
|
+
version_requirements: !ruby/object:Gem::Requirement
|
255
|
+
requirements:
|
256
|
+
- - "~>"
|
257
|
+
- !ruby/object:Gem::Version
|
258
|
+
version: '0.13'
|
259
|
+
- !ruby/object:Gem::Dependency
|
260
|
+
name: webmock
|
261
|
+
requirement: !ruby/object:Gem::Requirement
|
262
|
+
requirements:
|
263
|
+
- - "~>"
|
264
|
+
- !ruby/object:Gem::Version
|
265
|
+
version: '2.3'
|
266
|
+
type: :development
|
267
|
+
prerelease: false
|
268
|
+
version_requirements: !ruby/object:Gem::Requirement
|
269
|
+
requirements:
|
270
|
+
- - "~>"
|
271
|
+
- !ruby/object:Gem::Version
|
272
|
+
version: '2.3'
|
245
273
|
- !ruby/object:Gem::Dependency
|
246
274
|
name: gir_ffi-gnome_keyring
|
247
275
|
requirement: !ruby/object:Gem::Requirement
|
@@ -275,6 +303,8 @@ extra_rdoc_files: []
|
|
275
303
|
files:
|
276
304
|
- ".gitignore"
|
277
305
|
- ".rubocop.yml"
|
306
|
+
- ".ruby-version"
|
307
|
+
- ".simplecov"
|
278
308
|
- ".travis.yml"
|
279
309
|
- Gemfile
|
280
310
|
- LICENSE.md
|
@@ -305,6 +335,7 @@ files:
|
|
305
335
|
- lib/aws_assume_role/cli/commands/migrate.rb
|
306
336
|
- lib/aws_assume_role/cli/commands/run.rb
|
307
337
|
- lib/aws_assume_role/cli/commands/test.rb
|
338
|
+
- lib/aws_assume_role/cli/includes.rb
|
308
339
|
- lib/aws_assume_role/configuration.rb
|
309
340
|
- lib/aws_assume_role/core_ext/aws-sdk/credential_provider_chain.rb
|
310
341
|
- lib/aws_assume_role/core_ext/aws-sdk/includes.rb
|
@@ -317,8 +348,8 @@ files:
|
|
317
348
|
- lib/aws_assume_role/credentials/factories/instance_profile.rb
|
318
349
|
- lib/aws_assume_role/credentials/factories/repository.rb
|
319
350
|
- lib/aws_assume_role/credentials/factories/shared.rb
|
320
|
-
- lib/aws_assume_role/credentials/factories/shared_keyring.rb
|
321
351
|
- lib/aws_assume_role/credentials/factories/static.rb
|
352
|
+
- lib/aws_assume_role/credentials/includes.rb
|
322
353
|
- lib/aws_assume_role/credentials/providers/assume_role_credentials.rb
|
323
354
|
- lib/aws_assume_role/credentials/providers/includes.rb
|
324
355
|
- lib/aws_assume_role/credentials/providers/mfa_session_credentials.rb
|
@@ -360,7 +391,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
360
391
|
version: '0'
|
361
392
|
requirements: []
|
362
393
|
rubyforge_project:
|
363
|
-
rubygems_version: 2.5
|
394
|
+
rubygems_version: 2.4.5
|
364
395
|
signing_key:
|
365
396
|
specification_version: 4
|
366
397
|
summary: Manage AWS STS credentials with MFA
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require_relative "abstract_factory"
|
2
|
-
require_relative "../providers/shared_keyring_credentials"
|
3
|
-
|
4
|
-
class AwsAssumeRole::Credentials::Factories::SharedKeyring < AwsAssumeRole::Credentials::Factories::AbstractFactory
|
5
|
-
type :credential_provider
|
6
|
-
priority 19
|
7
|
-
|
8
|
-
def initialize(options = {})
|
9
|
-
@profile = options[:profile] || "default"
|
10
|
-
@credentials = AwsAssumeRole::Credentials::Providers::SharedKeyringCredentials.new(profile_name: @profile)
|
11
|
-
@region = AwsAssumeRole.shared_config.profile_region(@profile)
|
12
|
-
@role_arn = AwsAssumeRole.shared_config.profile_role(@profile)
|
13
|
-
rescue Aws::Errors::NoSuchProfileError
|
14
|
-
nil
|
15
|
-
end
|
16
|
-
end
|