aws_assume_role 0.0.3 → 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 +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +31 -11
- data/Gemfile +7 -13
- data/LICENSE.md +201 -19
- data/README.md +176 -145
- data/aws_assume_role.gemspec +35 -21
- data/bin/aws-assume-role +1 -83
- data/i18n/en.yml +106 -0
- data/lib/aws_assume_role.rb +2 -3
- data/lib/aws_assume_role/cli.rb +15 -0
- data/lib/aws_assume_role/cli/actions/abstract_action.rb +53 -0
- data/lib/aws_assume_role/cli/actions/configure_profile.rb +21 -0
- data/lib/aws_assume_role/cli/actions/configure_role_assumption.rb +19 -0
- data/lib/aws_assume_role/cli/actions/console.rb +68 -0
- data/lib/aws_assume_role/cli/actions/delete_profile.rb +20 -0
- data/lib/aws_assume_role/cli/actions/includes.rb +18 -0
- data/lib/aws_assume_role/cli/actions/list_profiles.rb +10 -0
- data/lib/aws_assume_role/cli/actions/migrate_profile.rb +18 -0
- data/lib/aws_assume_role/cli/actions/reset_environment.rb +48 -0
- data/lib/aws_assume_role/cli/actions/run.rb +34 -0
- data/lib/aws_assume_role/cli/actions/set_environment.rb +60 -0
- data/lib/aws_assume_role/cli/actions/test.rb +31 -0
- data/lib/aws_assume_role/cli/commands/configure.rb +29 -0
- data/lib/aws_assume_role/cli/commands/console.rb +17 -0
- data/lib/aws_assume_role/cli/commands/delete.rb +11 -0
- data/lib/aws_assume_role/cli/commands/environment.rb +32 -0
- data/lib/aws_assume_role/cli/commands/list.rb +10 -0
- data/lib/aws_assume_role/cli/commands/migrate.rb +11 -0
- data/lib/aws_assume_role/cli/commands/run.rb +17 -0
- data/lib/aws_assume_role/cli/commands/test.rb +18 -0
- data/lib/aws_assume_role/configuration.rb +19 -0
- data/lib/aws_assume_role/core_ext/aws-sdk/credential_provider_chain.rb +2 -0
- data/lib/aws_assume_role/core_ext/aws-sdk/includes.rb +7 -0
- data/lib/aws_assume_role/credentials/factories.rb +9 -0
- data/lib/aws_assume_role/credentials/factories/abstract_factory.rb +31 -0
- data/lib/aws_assume_role/credentials/factories/assume_role.rb +38 -0
- data/lib/aws_assume_role/credentials/factories/default_chain_provider.rb +101 -0
- data/lib/aws_assume_role/credentials/factories/environment.rb +24 -0
- data/lib/aws_assume_role/credentials/factories/includes.rb +17 -0
- data/lib/aws_assume_role/credentials/factories/instance_profile.rb +17 -0
- data/lib/aws_assume_role/credentials/factories/repository.rb +35 -0
- data/lib/aws_assume_role/credentials/factories/shared.rb +15 -0
- data/lib/aws_assume_role/credentials/factories/shared_keyring.rb +16 -0
- data/lib/aws_assume_role/credentials/factories/static.rb +16 -0
- data/lib/aws_assume_role/credentials/providers/assume_role_credentials.rb +58 -0
- data/lib/aws_assume_role/credentials/providers/includes.rb +9 -0
- data/lib/aws_assume_role/credentials/providers/mfa_session_credentials.rb +102 -0
- data/lib/aws_assume_role/credentials/providers/shared_keyring_credentials.rb +22 -0
- data/lib/aws_assume_role/includes.rb +30 -0
- data/lib/aws_assume_role/logging.rb +16 -28
- data/lib/aws_assume_role/profile_configuration.rb +71 -0
- data/lib/aws_assume_role/runner.rb +39 -0
- data/lib/aws_assume_role/store/includes.rb +16 -0
- data/lib/aws_assume_role/store/keyring.rb +59 -0
- data/lib/aws_assume_role/store/serialization.rb +18 -0
- data/lib/aws_assume_role/store/shared_config_with_keyring.rb +175 -0
- data/lib/aws_assume_role/types.rb +30 -0
- data/lib/aws_assume_role/ui.rb +55 -0
- data/lib/aws_assume_role/vendored/aws.rb +4 -0
- data/lib/aws_assume_role/vendored/aws/README.md +2 -0
- data/lib/aws_assume_role/vendored/aws/assume_role_credentials.rb +68 -0
- data/lib/aws_assume_role/vendored/aws/includes.rb +9 -0
- data/lib/aws_assume_role/vendored/aws/refreshing_credentials.rb +60 -0
- data/lib/aws_assume_role/vendored/aws/shared_config.rb +220 -0
- data/lib/aws_assume_role/version.rb +3 -0
- metadata +264 -20
- data/.rspec +0 -2
- data/Rakefile +0 -2
- data/bin/test.rb +0 -39
- data/lib/aws_assume_role/credentials.rb +0 -92
- data/lib/aws_assume_role/profile.rb +0 -203
- data/lib/aws_assume_role/profile/assume_role.rb +0 -127
- data/lib/aws_assume_role/profile/basic.rb +0 -152
- data/lib/aws_assume_role/profile/list.rb +0 -57
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "includes"
|
2
|
+
require_relative "../../types"
|
3
|
+
|
4
|
+
class AwsAssumeRole::Credentials::Providers::SharedKeyringCredentials < ::Aws::SharedCredentials
|
5
|
+
def initialize(options = {})
|
6
|
+
shared_config = AwsAssumeRole.shared_config
|
7
|
+
@path = options[:path]
|
8
|
+
@path ||= shared_config.credentials_path
|
9
|
+
@profile_name = options[:profile_name]
|
10
|
+
@profile_name ||= ENV["AWS_PROFILE"]
|
11
|
+
@profile_name ||= shared_config.profile_name
|
12
|
+
if @path && @path == shared_config.credentials_path
|
13
|
+
@credentials = shared_config.credentials(profile: @profile_name)
|
14
|
+
else
|
15
|
+
config = AwsAssumeRole::Store::SharedConfig.new(
|
16
|
+
credentials_path: @path,
|
17
|
+
profile_name: @profile_name,
|
18
|
+
)
|
19
|
+
@credentials = config.credentials(profile: @profile_name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "i18n"
|
2
|
+
require "keyring"
|
3
|
+
require "active_support/core_ext/object/blank"
|
4
|
+
require "active_support/core_ext/string/inflections"
|
5
|
+
require "active_support/core_ext/hash/keys"
|
6
|
+
require "active_support/core_ext/object/json"
|
7
|
+
require "aws-sdk"
|
8
|
+
require "aws-sdk-core/ini_parser"
|
9
|
+
require "dry-configurable"
|
10
|
+
require "dry-initializer"
|
11
|
+
require "dry-validation"
|
12
|
+
require "dry-types"
|
13
|
+
require "English"
|
14
|
+
require "gli"
|
15
|
+
require "highline"
|
16
|
+
require "inifile"
|
17
|
+
require "json"
|
18
|
+
require "logger"
|
19
|
+
require "pastel"
|
20
|
+
require "thread"
|
21
|
+
require "time"
|
22
|
+
|
23
|
+
module AwsAssumeRole
|
24
|
+
module_function
|
25
|
+
|
26
|
+
def shared_config
|
27
|
+
enabled = ENV["AWS_SDK_CONFIG_OPT_OUT"] ? false : true
|
28
|
+
@shared_config ||= SharedConfigWithKeyring.new(config_enabled: enabled)
|
29
|
+
end
|
30
|
+
end
|
@@ -1,36 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def logger
|
11
|
-
@logger ||= Logger.new($stderr)
|
12
|
-
end
|
13
|
-
|
14
|
-
attr_writer :logger
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.included(base)
|
19
|
-
|
20
|
-
class << base
|
21
|
-
|
22
|
-
def logger # rubocop:disable Lint/NestedMethodDefinition
|
23
|
-
Logging.logger
|
24
|
-
end
|
25
|
-
|
1
|
+
require_relative "includes"
|
2
|
+
require_relative "configuration"
|
3
|
+
module AwsAssumeRole::Logging
|
4
|
+
module ClassMethods
|
5
|
+
def logger
|
6
|
+
@logger ||= begin
|
7
|
+
logger = Logger.new($stderr)
|
8
|
+
logger.level = AwsAssumeRole::Config.log_level
|
9
|
+
logger
|
26
10
|
end
|
27
|
-
|
28
11
|
end
|
12
|
+
end
|
29
13
|
|
14
|
+
module InstanceMethods
|
30
15
|
def logger
|
31
|
-
|
16
|
+
self.class.logger
|
32
17
|
end
|
33
|
-
|
34
18
|
end
|
35
19
|
|
20
|
+
def self.included(base)
|
21
|
+
base.extend ClassMethods
|
22
|
+
base.include InstanceMethods
|
23
|
+
end
|
36
24
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative "includes"
|
2
|
+
require_relative "logging"
|
3
|
+
|
4
|
+
class AwsAssumeRole::ProfileConfiguration
|
5
|
+
extend Dry::Initializer
|
6
|
+
include AwsAssumeRole::Logging
|
7
|
+
option :access_key_id, Dry::Types["strict.string"].optional, default: proc { nil }
|
8
|
+
option :credentials, default: proc { nil }
|
9
|
+
option :secret_access_key, Dry::Types["strict.string"].optional, default: proc { nil }
|
10
|
+
option :session_token, Dry::Types["strict.string"].optional, default: proc { nil }
|
11
|
+
option :duration_seconds, Dry::Types["coercible.int"].optional, default: proc { nil }
|
12
|
+
option :external_id, Dry::Types["strict.string"].optional, default: proc { nil }
|
13
|
+
option :persist_session, Dry::Types["strict.bool"], default: proc { true }
|
14
|
+
option :profile, Dry::Types["strict.string"].optional, default: proc { nil }
|
15
|
+
option :region, Dry::Types["strict.string"].optional, default: proc { nil }
|
16
|
+
option :role_arn, Dry::Types["strict.string"].optional, default: proc { nil }
|
17
|
+
option :role_session_name, Dry::Types["strict.string"].optional, default: proc { nil }
|
18
|
+
option :serial_number, Dry::Types["strict.string"].optional, default: proc { nil }
|
19
|
+
option :mfa_serial, Dry::Types["strict.string"].optional, default: proc { nil }
|
20
|
+
option :use_mfa, default: proc { false }
|
21
|
+
option :no_profile, default: proc { false }
|
22
|
+
option :shell_type, Dry::Types["strict.string"].optional, default: proc { nil }
|
23
|
+
option :source_profile, Dry::Types["strict.string"].optional, default: proc { nil }
|
24
|
+
option :args, default: proc { [] }
|
25
|
+
option :instance_profile_credentials_retries, Dry::Types["strict.int"], default: proc { 0 }
|
26
|
+
option :instance_profile_credentials_timeout, Dry::Types["coercible.float"], default: proc { 1 }
|
27
|
+
|
28
|
+
attr_writer :credentials
|
29
|
+
|
30
|
+
def self.merge_mfa_variable(options)
|
31
|
+
new_hash = options.key?(:mfa_serial) ? options.merge(serial_number: options[:mfa_serial]) : options
|
32
|
+
new_hash[:use_mfa] ||= new_hash.fetch(:serial_number, nil) ? true : false
|
33
|
+
if new_hash.key?(:serial_number) && new_hash[:serial_number] == "automatic"
|
34
|
+
new_hash.delete(:serial_number)
|
35
|
+
end
|
36
|
+
new_hash
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.new_from_cli(global_options, options, args)
|
40
|
+
options = global_options.merge options
|
41
|
+
options = options.map do |k, v|
|
42
|
+
[k.to_s.underscore.to_sym, v]
|
43
|
+
end.to_h
|
44
|
+
options[:args] = args
|
45
|
+
new merge_mfa_variable(options)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.new_from_credential_provider_initialization(options)
|
49
|
+
logger.debug "new_from_credential_provider_initialization with #{options.to_h}"
|
50
|
+
new_from_credential_provider(options, credentials: nil, delete: [])
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.new_from_credential_provider(options = {}, credentials: nil, delete: [])
|
54
|
+
option_hash = options.to_h
|
55
|
+
config = option_hash.fetch(:config, {}).to_h
|
56
|
+
hash_to_merge = option_hash.merge config
|
57
|
+
hash_to_merge.merge(credentials: credentials) if credentials
|
58
|
+
delete.each do |k|
|
59
|
+
hash_to_merge.delete k
|
60
|
+
end
|
61
|
+
hash = merge_mfa_variable(hash_to_merge)
|
62
|
+
logger.debug "new_from_credential_provider with #{hash}"
|
63
|
+
new hash
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_h
|
67
|
+
instance_values.delete("__options__").symbolize_keys
|
68
|
+
end
|
69
|
+
|
70
|
+
Dry::Types.register_class(self)
|
71
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative "includes"
|
2
|
+
require_relative "logging"
|
3
|
+
|
4
|
+
class AwsAssumeRole::Runner
|
5
|
+
include AwsAssumeRole::Logging
|
6
|
+
extend Dry::Initializer
|
7
|
+
|
8
|
+
param :command, Dry::Types["coercible.array"].member(Dry::Types["strict.string"])
|
9
|
+
option :exit_on_error, Dry::Types["strict.bool"], default: proc { true }
|
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)
|
16
|
+
command_to_exec = command.join(" ")
|
17
|
+
process_credentials unless credentials.blank?
|
18
|
+
system environment, command_to_exec
|
19
|
+
exit_status = $CHILD_STATUS.exitstatus
|
20
|
+
process_error(exit_status) if exit_status != expected_exit_code
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def process_credentials
|
26
|
+
cred_env = {
|
27
|
+
"AWS_ACCESS_KEY_ID" => credentials.credentials.access_key_id,
|
28
|
+
"AWS_SECRET_ACCESS_KEY" => credentials.credentials.secret_access_key,
|
29
|
+
"AWS_SESSION_TOKEN" => credentials.credentials.session_token,
|
30
|
+
}
|
31
|
+
@environment = environment.merge cred_env
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_error(exit_status)
|
35
|
+
logger.error "#{command} failed with #{exit_status}"
|
36
|
+
exit exit_status if exit_on_error
|
37
|
+
raise "#{command} failed with #{exit_status}"
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "active_support/core_ext/object/blank"
|
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"
|
12
|
+
|
13
|
+
module AwsAssumeRole
|
14
|
+
module Store
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative "includes"
|
2
|
+
require_relative "serialization"
|
3
|
+
require_relative "../configuration"
|
4
|
+
require_relative "../logging"
|
5
|
+
|
6
|
+
module AwsAssumeRole::Store::Keyring
|
7
|
+
include AwsAssumeRole
|
8
|
+
include AwsAssumeRole::Store
|
9
|
+
include AwsAssumeRole::Logging
|
10
|
+
|
11
|
+
module_function
|
12
|
+
|
13
|
+
KEYRING_KEY = "AwsAssumeRole".freeze
|
14
|
+
|
15
|
+
def semaphore
|
16
|
+
@semaphore ||= Mutex.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def keyrings
|
20
|
+
@keyrings ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def try_backend_plugin
|
24
|
+
return if AwsAssumeRole::Config.backend_plugin.blank?
|
25
|
+
logger.info "Attempting to load #{AwsAssumeRole::Config.backend_plugin} plugin"
|
26
|
+
require AwsAssumeRole::Config.backend_plugin
|
27
|
+
end
|
28
|
+
|
29
|
+
def keyring(backend = AwsAssumeRole::Config.backend)
|
30
|
+
keyrings[backend] ||= begin
|
31
|
+
try_backend_plugin
|
32
|
+
klass = backend ? "Keyring::Backend::#{backend}".constantize : nil
|
33
|
+
logger.debug "Initializing #{klass} backend"
|
34
|
+
::Keyring.new(klass)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def fetch(id, backend: nil)
|
39
|
+
logger.debug "Fetching #{id} from keyring"
|
40
|
+
fetched = keyring(backend).get_password(KEYRING_KEY, id)
|
41
|
+
return nil if fetched == "null" || fetched.nil?
|
42
|
+
raise Aws::Errors::NoSuchProfileError unless fetched
|
43
|
+
JSON.parse(fetched, symbolize_names: true)
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete_credentials(id, backend: nil)
|
47
|
+
semaphore.synchronize do
|
48
|
+
keyring(backend).delete_password(KEYRING_KEY, id)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def save_credentials(id, credentials, expiration: nil, backend: nil)
|
53
|
+
credentials_to_persist = Serialization.credentials_to_hash(credentials)
|
54
|
+
credentials_to_persist[:expiration] = expiration if expiration
|
55
|
+
semaphore.synchronize do
|
56
|
+
keyring(backend).set_password(KEYRING_KEY, id, credentials_to_persist.to_json)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module AwsAssumeRole::Store::Serialization
|
2
|
+
module_function
|
3
|
+
|
4
|
+
def credentials_from_hash(credentials)
|
5
|
+
creds_for_deserialization = credentials.respond_to?("[]") ? credentials : credentials_to_hash(credentials)
|
6
|
+
Aws::Credentials.new(creds_for_deserialization[:access_key_id],
|
7
|
+
creds_for_deserialization[:secret_access_key],
|
8
|
+
creds_for_deserialization[:session_token])
|
9
|
+
end
|
10
|
+
|
11
|
+
def credentials_to_hash(credentials)
|
12
|
+
{
|
13
|
+
access_key_id: credentials.access_key_id,
|
14
|
+
secret_access_key: credentials.secret_access_key,
|
15
|
+
session_token: credentials.session_token,
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require_relative "includes"
|
2
|
+
require_relative "../logging"
|
3
|
+
require_relative "keyring"
|
4
|
+
require_relative "../profile_configuration"
|
5
|
+
require_relative "../credentials/providers/mfa_session_credentials"
|
6
|
+
|
7
|
+
class AwsAssumeRole::Store::SharedConfigWithKeyring < AwsAssumeRole::Vendored::Aws::SharedConfig
|
8
|
+
include AwsAssumeRole::Store
|
9
|
+
include AwsAssumeRole::Logging
|
10
|
+
|
11
|
+
attr_reader :parsed_config
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
super(options)
|
15
|
+
@config_enabled = true
|
16
|
+
@config_path = determine_config_path
|
17
|
+
load_config_file
|
18
|
+
end
|
19
|
+
|
20
|
+
def credentials(opts = {})
|
21
|
+
p = opts[:profile] || @profile_name
|
22
|
+
validate_profile_exists(p) if credentials_present?
|
23
|
+
credentials_from_keyring(p, opts) || credentials_from_shared(p, opts) || credentials_from_config(p, opts)
|
24
|
+
end
|
25
|
+
|
26
|
+
def save_profile(profile_name, hash)
|
27
|
+
ckey = "profile #{profile_name}"
|
28
|
+
merged_config = configuration[ckey].deep_symbolize_keys.merge hash.to_h
|
29
|
+
merged_config[:mfa_serial] = merged_config[:serial_number] if merged_config[:serial_number]
|
30
|
+
credentials = Aws::Credentials.new(merged_config.delete(:aws_access_key_id),
|
31
|
+
merged_config.delete(:aws_secret_access_key))
|
32
|
+
semaphore.synchronize do
|
33
|
+
Keyring.save_credentials profile_name, credentials if credentials.set?
|
34
|
+
merged_config = merged_config.slice :region, :role_arn, :mfa_serial, :source_profile,
|
35
|
+
:role_session_name, :external_id, :duration_seconds
|
36
|
+
configuration.delete_section ckey
|
37
|
+
configuration[ckey] = merged_config.compact
|
38
|
+
save_configuration
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def profiles
|
43
|
+
configuration.sections.map { |c| c.gsub("profile ", "") }
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete_profile(profile_name)
|
47
|
+
# Keyring does not return errors for non-existent things, so always attempt.
|
48
|
+
Keyring.delete_credentials(profile_name)
|
49
|
+
semaphore.synchronize do
|
50
|
+
raise KeyError if configuration["profile #{profile_name}"].blank?
|
51
|
+
configuration.delete_section("profile #{profile_name}")
|
52
|
+
save_configuration
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def migrate_profile(profile_name)
|
57
|
+
validate_profile_exists(profile_name)
|
58
|
+
save_profile(profile_name, configuration["profile #{profile_name}"])
|
59
|
+
end
|
60
|
+
|
61
|
+
def profile_region(profile_name)
|
62
|
+
prof_cfg = @parsed_config[profile_key(profile_name)]
|
63
|
+
resolve_region(@parsed_config, prof_cfg)
|
64
|
+
end
|
65
|
+
|
66
|
+
def profile_role(profile_name)
|
67
|
+
prof_cfg = @parsed_config[profile_key(profile_name)]
|
68
|
+
resolve_arn(@parsed_config, prof_cfg)
|
69
|
+
end
|
70
|
+
|
71
|
+
def determine_profile(options)
|
72
|
+
ret = options[:profile_name]
|
73
|
+
ret ||= ENV["AWS_PROFILE"]
|
74
|
+
ret ||= "default"
|
75
|
+
ret
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def profile_key(profile)
|
81
|
+
logger.debug "About to lookup #{profile}"
|
82
|
+
if profile == "default" || profile.nil? || profile == ""
|
83
|
+
"default"
|
84
|
+
else
|
85
|
+
profile
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def resolve_region(cfg, prof_cfg)
|
90
|
+
return unless prof_cfg && cfg
|
91
|
+
return prof_cfg["region"] if prof_cfg.key? "region"
|
92
|
+
source_cfg = cfg[prof_cfg["source_profile"]]
|
93
|
+
cfg[prof_cfg["source_profile"]]["region"] if source_cfg && source_cfg.key?("region")
|
94
|
+
end
|
95
|
+
|
96
|
+
def resolve_arn(cfg, prof_cfg)
|
97
|
+
return unless prof_cfg && cfg
|
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")
|
101
|
+
end
|
102
|
+
|
103
|
+
def assume_role_from_profile(cfg, profile, opts)
|
104
|
+
prof_cfg = cfg[profile]
|
105
|
+
return unless cfg && prof_cfg
|
106
|
+
opts[:source_profile] ||= prof_cfg["source_profile"]
|
107
|
+
if opts[:source_profile]
|
108
|
+
opts[:credentials] = credentials(profile: opts[:source_profile])
|
109
|
+
if opts[:credentials]
|
110
|
+
opts[:role_session_name] ||= prof_cfg["role_session_name"]
|
111
|
+
opts[:role_session_name] ||= "default_session"
|
112
|
+
opts[:role_arn] ||= prof_cfg["role_arn"]
|
113
|
+
opts[:external_id] ||= prof_cfg["external_id"]
|
114
|
+
opts[:serial_number] ||= prof_cfg["mfa_serial"]
|
115
|
+
opts[:region] ||= profile_region(profile)
|
116
|
+
if opts[:serial_number]
|
117
|
+
mfa_opts = { credentials: opts[:credentials], region: opts[:region], serial_number: opts[:serial_number] }
|
118
|
+
mfa_creds = mfa_session(cfg, opts[:source_profile], mfa_opts)
|
119
|
+
opts.delete :serial_number
|
120
|
+
end
|
121
|
+
opts[:credentials] = mfa_creds if mfa_creds
|
122
|
+
opts[:profile] = opts.delete(:source_profile)
|
123
|
+
AwsAssumeRole::Credentials::Providers::AssumeRoleCredentials.new(opts)
|
124
|
+
else
|
125
|
+
raise ::Aws::Errors::NoSourceProfileError, "Profile #{profile} has a role_arn, and source_profile, but the"\
|
126
|
+
" source_profile does not have credentials."
|
127
|
+
end
|
128
|
+
elsif prof_cfg["role_arn"]
|
129
|
+
raise ::Aws::Errors::NoSourceProfileError, "Profile #{profile} has a role_arn, but no source_profile."
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def mfa_session(cfg, profile, opts)
|
134
|
+
prof_cfg = cfg[profile]
|
135
|
+
return unless cfg && prof_cfg
|
136
|
+
opts[:serial_number] ||= prof_cfg["mfa_serial"]
|
137
|
+
opts[:source_profile] ||= prof_cfg["source_profile"]
|
138
|
+
opts[:region] ||= profile_region(profile)
|
139
|
+
return unless opts[:serial_number]
|
140
|
+
opts[:credentials] ||= credentials(profile: opts[:profile])
|
141
|
+
AwsAssumeRole::Credentials::Providers::MfaSessionCredentials.new(opts)
|
142
|
+
end
|
143
|
+
|
144
|
+
def credentials_from_keyring(profile, _options)
|
145
|
+
return unless @parsed_config && @parsed_config[profile_key(profile)]
|
146
|
+
logger.debug "Attempt to fetch #{profile} from keyring"
|
147
|
+
creds = Serialization.credentials_from_hash Keyring.fetch(profile)
|
148
|
+
creds if credentials_complete(creds)
|
149
|
+
end
|
150
|
+
|
151
|
+
def semaphore
|
152
|
+
@semaphore ||= Mutex.new
|
153
|
+
end
|
154
|
+
|
155
|
+
def configuration
|
156
|
+
@configuration ||= IniFile.new(filename: determine_config_path, default: "default")
|
157
|
+
end
|
158
|
+
|
159
|
+
# Please run in a mutex
|
160
|
+
def save_configuration
|
161
|
+
bytes_required = File.size(determine_config_path)
|
162
|
+
random_bytes = SecureRandom.random_bytes(bytes_required)
|
163
|
+
File.write(determine_config_path, random_bytes)
|
164
|
+
configuration.save
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
module AwsAssumeRole
|
169
|
+
module_function
|
170
|
+
|
171
|
+
def shared_config
|
172
|
+
enabled = ENV["AWS_SDK_CONFIG_OPT_OUT"] ? false : true
|
173
|
+
@assuome_role_shared_config ||= ::AwsAssumeRole::Store::SharedConfigWithKeyring.new(config_enabled: enabled)
|
174
|
+
end
|
175
|
+
end
|