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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +31 -11
  4. data/Gemfile +7 -13
  5. data/LICENSE.md +201 -19
  6. data/README.md +176 -145
  7. data/aws_assume_role.gemspec +35 -21
  8. data/bin/aws-assume-role +1 -83
  9. data/i18n/en.yml +106 -0
  10. data/lib/aws_assume_role.rb +2 -3
  11. data/lib/aws_assume_role/cli.rb +15 -0
  12. data/lib/aws_assume_role/cli/actions/abstract_action.rb +53 -0
  13. data/lib/aws_assume_role/cli/actions/configure_profile.rb +21 -0
  14. data/lib/aws_assume_role/cli/actions/configure_role_assumption.rb +19 -0
  15. data/lib/aws_assume_role/cli/actions/console.rb +68 -0
  16. data/lib/aws_assume_role/cli/actions/delete_profile.rb +20 -0
  17. data/lib/aws_assume_role/cli/actions/includes.rb +18 -0
  18. data/lib/aws_assume_role/cli/actions/list_profiles.rb +10 -0
  19. data/lib/aws_assume_role/cli/actions/migrate_profile.rb +18 -0
  20. data/lib/aws_assume_role/cli/actions/reset_environment.rb +48 -0
  21. data/lib/aws_assume_role/cli/actions/run.rb +34 -0
  22. data/lib/aws_assume_role/cli/actions/set_environment.rb +60 -0
  23. data/lib/aws_assume_role/cli/actions/test.rb +31 -0
  24. data/lib/aws_assume_role/cli/commands/configure.rb +29 -0
  25. data/lib/aws_assume_role/cli/commands/console.rb +17 -0
  26. data/lib/aws_assume_role/cli/commands/delete.rb +11 -0
  27. data/lib/aws_assume_role/cli/commands/environment.rb +32 -0
  28. data/lib/aws_assume_role/cli/commands/list.rb +10 -0
  29. data/lib/aws_assume_role/cli/commands/migrate.rb +11 -0
  30. data/lib/aws_assume_role/cli/commands/run.rb +17 -0
  31. data/lib/aws_assume_role/cli/commands/test.rb +18 -0
  32. data/lib/aws_assume_role/configuration.rb +19 -0
  33. data/lib/aws_assume_role/core_ext/aws-sdk/credential_provider_chain.rb +2 -0
  34. data/lib/aws_assume_role/core_ext/aws-sdk/includes.rb +7 -0
  35. data/lib/aws_assume_role/credentials/factories.rb +9 -0
  36. data/lib/aws_assume_role/credentials/factories/abstract_factory.rb +31 -0
  37. data/lib/aws_assume_role/credentials/factories/assume_role.rb +38 -0
  38. data/lib/aws_assume_role/credentials/factories/default_chain_provider.rb +101 -0
  39. data/lib/aws_assume_role/credentials/factories/environment.rb +24 -0
  40. data/lib/aws_assume_role/credentials/factories/includes.rb +17 -0
  41. data/lib/aws_assume_role/credentials/factories/instance_profile.rb +17 -0
  42. data/lib/aws_assume_role/credentials/factories/repository.rb +35 -0
  43. data/lib/aws_assume_role/credentials/factories/shared.rb +15 -0
  44. data/lib/aws_assume_role/credentials/factories/shared_keyring.rb +16 -0
  45. data/lib/aws_assume_role/credentials/factories/static.rb +16 -0
  46. data/lib/aws_assume_role/credentials/providers/assume_role_credentials.rb +58 -0
  47. data/lib/aws_assume_role/credentials/providers/includes.rb +9 -0
  48. data/lib/aws_assume_role/credentials/providers/mfa_session_credentials.rb +102 -0
  49. data/lib/aws_assume_role/credentials/providers/shared_keyring_credentials.rb +22 -0
  50. data/lib/aws_assume_role/includes.rb +30 -0
  51. data/lib/aws_assume_role/logging.rb +16 -28
  52. data/lib/aws_assume_role/profile_configuration.rb +71 -0
  53. data/lib/aws_assume_role/runner.rb +39 -0
  54. data/lib/aws_assume_role/store/includes.rb +16 -0
  55. data/lib/aws_assume_role/store/keyring.rb +59 -0
  56. data/lib/aws_assume_role/store/serialization.rb +18 -0
  57. data/lib/aws_assume_role/store/shared_config_with_keyring.rb +175 -0
  58. data/lib/aws_assume_role/types.rb +30 -0
  59. data/lib/aws_assume_role/ui.rb +55 -0
  60. data/lib/aws_assume_role/vendored/aws.rb +4 -0
  61. data/lib/aws_assume_role/vendored/aws/README.md +2 -0
  62. data/lib/aws_assume_role/vendored/aws/assume_role_credentials.rb +68 -0
  63. data/lib/aws_assume_role/vendored/aws/includes.rb +9 -0
  64. data/lib/aws_assume_role/vendored/aws/refreshing_credentials.rb +60 -0
  65. data/lib/aws_assume_role/vendored/aws/shared_config.rb +220 -0
  66. data/lib/aws_assume_role/version.rb +3 -0
  67. metadata +264 -20
  68. data/.rspec +0 -2
  69. data/Rakefile +0 -2
  70. data/bin/test.rb +0 -39
  71. data/lib/aws_assume_role/credentials.rb +0 -92
  72. data/lib/aws_assume_role/profile.rb +0 -203
  73. data/lib/aws_assume_role/profile/assume_role.rb +0 -127
  74. data/lib/aws_assume_role/profile/basic.rb +0 -152
  75. data/lib/aws_assume_role/profile/list.rb +0 -57
@@ -0,0 +1,9 @@
1
+ require_relative "factories/repository"
2
+ require_relative "factories/abstract_factory"
3
+ require_relative "factories/default_chain_provider"
4
+ require_relative "factories/assume_role"
5
+ require_relative "factories/environment"
6
+ require_relative "factories/instance_profile"
7
+ require_relative "factories/shared_keyring"
8
+ require_relative "factories/shared"
9
+ require_relative "factories/static"
@@ -0,0 +1,31 @@
1
+ require_relative "includes"
2
+ require_relative "repository"
3
+ require_relative "../../profile_configuration"
4
+
5
+ class AwsAssumeRole::Credentials::Factories::AbstractFactory
6
+ include AwsAssumeRole
7
+ include AwsAssumeRole::Credentials::Factories
8
+ include AwsAssumeRole::Logging
9
+
10
+ Dry::Types.register_class(Aws::SharedCredentials)
11
+ attr_reader :credentials, :region, :profile, :role_arn
12
+
13
+ def initialize(_options)
14
+ raise "Not implemented"
15
+ end
16
+
17
+ def self.type(str)
18
+ @type = Types::Strict::Symbol.enum(:credential_provider, :second_factor_provider, :role_assumption_provider)[str]
19
+ register_if_complete
20
+ end
21
+
22
+ def self.priority(i)
23
+ @priority = Types::Strict::Int[i]
24
+ register_if_complete
25
+ end
26
+
27
+ def self.register_if_complete
28
+ return unless @type && @priority
29
+ Repository.register_factory(self, @type, @priority)
30
+ end
31
+ end
@@ -0,0 +1,38 @@
1
+ require_relative "abstract_factory"
2
+ require_relative "../providers/assume_role_credentials"
3
+ require_relative "../providers/mfa_session_credentials"
4
+
5
+ class AwsAssumeRole::Credentials::Factories::AssumeRole < AwsAssumeRole::Credentials::Factories::AbstractFactory
6
+ include AwsAssumeRole::Credentials::Factories
7
+ type :role_assumption_provider
8
+ priority 30
9
+
10
+ def initialize(options)
11
+ if options[:profile]
12
+ try_with_profile(options)
13
+ else
14
+ if options[:use_mfa]
15
+ options[:credentials] = AwsAssumeRole::Credentials::Providers::MfaSessionCredentials.new(options).credentials
16
+ end
17
+ @credentials = AwsAssumeRole::Credentials::Providers::AssumeRoleCredentials.new(options)
18
+ end
19
+ end
20
+
21
+ def try_with_profile(options)
22
+ if AwsAssumeRole.shared_config.config_enabled?
23
+ @profile = options[:profile]
24
+ @region = options[:region]
25
+ @credentials = assume_role_with_profile(options[:profle], options[:region])
26
+ end
27
+ @credentials = assume_role_with_profile(@profile, @region)
28
+ @region ||= AwsAssumeRole.shared_config.profile_region(@profiles)
29
+ @role_arn ||= AwsAssumeRole.shared_config.profile_role(@profile)
30
+ end
31
+
32
+ def assume_role_with_profile(prof, region)
33
+ AwsAssumeRole.shared_config.assume_role_credentials_from_config(
34
+ profile: prof,
35
+ region: region,
36
+ )
37
+ end
38
+ end
@@ -0,0 +1,101 @@
1
+ require_relative "includes"
2
+ require_relative "../../logging"
3
+ require_relative "../../profile_configuration"
4
+ require_relative "abstract_factory"
5
+ require_relative "environment"
6
+ require_relative "repository"
7
+ require_relative "instance_profile"
8
+ require_relative "assume_role"
9
+ require_relative "shared_keyring"
10
+ require_relative "shared"
11
+ require_relative "static"
12
+
13
+ class AwsAssumeRole::Credentials::Factories::DefaultChainProvider
14
+ extend Dry::Initializer::Mixin
15
+ include AwsAssumeRole::Credentials::Factories
16
+
17
+ option :access_key_id, Dry::Types["strict.string"].optional, default: proc { nil }
18
+ option :credentials, default: proc { nil }
19
+ option :secret_access_key, Dry::Types["strict.string"].optional, default: proc { nil }
20
+ option :session_token, Dry::Types["strict.string"].optional, default: proc { nil }
21
+ option :duration_seconds, Dry::Types["coercible.int"].optional, default: proc { nil }
22
+ option :external_id, Dry::Types["strict.string"].optional, default: proc { nil }
23
+ option :persist_session, Dry::Types["strict.bool"], default: proc { true }
24
+ option :profile, Dry::Types["strict.string"].optional, default: proc { nil }
25
+ option :profile_name, Dry::Types["strict.string"].optional, default: proc { @profile }
26
+ option :region, Dry::Types["strict.string"].optional, default: proc { nil }
27
+ option :role_arn, Dry::Types["strict.string"].optional, default: proc { nil }
28
+ option :role_session_name, Dry::Types["strict.string"].optional, default: proc { nil }
29
+ option :serial_number, Dry::Types["strict.string"].optional, default: proc { nil }
30
+ option :use_mfa, default: proc { false }
31
+ option :no_profile, default: proc { false }
32
+ option :source_profile, Dry::Types["strict.string"].optional, default: proc { nil }
33
+ option :instance_profile_credentials_retries, Dry::Types["strict.int"], default: proc { 0 }
34
+ option :instance_profile_credentials_timeout, Dry::Types["coercible.float"], default: proc { 1 }
35
+
36
+ def initialize(*options)
37
+ if options[0].is_a? Seahorse::Client::Configuration::DefaultResolver
38
+ initialize_with_seahorse(options[0])
39
+ else
40
+ super(*options)
41
+ end
42
+ @profile_name ||= @profile
43
+ @original_profile = @profile
44
+ end
45
+
46
+ def resolve(nil_with_role_not_set: false, explicit_default_profile: false)
47
+ resolve_final_credentials(explicit_default_profile)
48
+ nil_creds = Aws::Credentials.new(nil, nil, nil)
49
+ return nil_creds if (nil_with_role_not_set &&
50
+ @role_arn &&
51
+ @credentials.credentials.session_token.nil?) || @credentials.nil?
52
+ @credentials
53
+ end
54
+
55
+ private
56
+
57
+ def resolve_final_credentials(explicit_default_profile = false)
58
+ resolve_credentials(:credential_provider, true, explicit_default_profile)
59
+ return @credentials if @credentials && @credentials.set? && !use_mfa && !role_arn
60
+ 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
+ return @credentials if @credentials && @credentials.set?
64
+ Aws::Credentials.new(nil, nil, nil)
65
+ end
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
+ )
80
+ end
81
+
82
+ def resolve_credentials(type, break_if_successful = false, explicit_default_profile = false)
83
+ factories_to_try = Repository.factories[type]
84
+ factories_to_try.each do |x|
85
+ options = to_h
86
+ options[:credentials] = credentials if credentials && credentials.set?
87
+ factory = x.new(options)
88
+ @region ||= factory.region
89
+ @profile ||= factory.profile
90
+ @role_arn ||= factory.role_arn
91
+ next unless factory.credentials && factory.credentials.set?
92
+ next if explicit_default_profile && (@profile == "default") && (@profile != @original_profile)
93
+ @credentials ||= factory.credentials
94
+ break if break_if_successful
95
+ end
96
+ end
97
+ end
98
+
99
+ module AwsAssumeRole
100
+ DefaultProvider = AwsAssumeRole::Credentials::Factories::DefaultChainProvider
101
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "abstract_factory"
2
+
3
+ class AwsAssumeRole::Credentials::Factories::Environment < AwsAssumeRole::Credentials::Factories::AbstractFactory
4
+ type :credential_provider
5
+ priority 10
6
+
7
+ def initialize(_options, **)
8
+ key = %w(AWS_ACCESS_KEY_ID AMAZON_ACCESS_KEY_ID AWS_ACCESS_KEY)
9
+ secret = %w(AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY)
10
+ token = %w(AWS_SESSION_TOKEN AMAZON_SESSION_TOKEN)
11
+ region = %w(AWS_DEFAULT_REGION)
12
+ profile = %w(AWS_PROFILE)
13
+ @credentials = Aws::Credentials.new(envar(key), envar(secret), envar(token))
14
+ @region = envar(region)
15
+ @profile = envar(profile)
16
+ end
17
+
18
+ def envar(keys)
19
+ keys.each do |key|
20
+ return ENV[key] if ENV.key?(key)
21
+ end
22
+ nil
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ require "dry-initializer"
2
+ require "dry-types"
3
+ require "aws-sdk"
4
+ require_relative "../../logging"
5
+ require_relative "../../vendored/aws"
6
+ require_relative "../../../aws_assume_role"
7
+
8
+ module AwsAssumeRole
9
+ module Credentials
10
+ module Factories
11
+ Types = Dry::Types.module
12
+ include AwsAssumeRole
13
+ include AwsAssumeRole::Logging
14
+ include AwsAssumeRole::Vendored::Aws
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require_relative "abstract_factory"
2
+
3
+ class AwsAssumeRole::Credentials::Factories::InstanceProfile < AwsAssumeRole::Credentials::Factories::AbstractFactory
4
+ type :role_assumption_provider
5
+ priority 40
6
+
7
+ def initialize(options = {})
8
+ options[:retries] ||= options[:instance_profile_credentials_retries] || 0
9
+ options[:http_open_timeout] ||= options[:instance_profile_credentials_timeout] || 1
10
+ options[:http_read_timeout] ||= options[:instance_profile_credentials_timeout] || 1
11
+ @credentials = if ENV["AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"]
12
+ Aws::ECSCredentials.new(options)
13
+ else
14
+ Aws::InstanceProfileCredentials.new(options)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ require_relative "includes"
2
+ require_relative "abstract_factory"
3
+
4
+ class AwsAssumeRole::Credentials::Factories::Repository
5
+ include AwsAssumeRole::Credentials::Factories
6
+
7
+ SubFactoryRepositoryType = Types::Hash.schema(Types::Coercible::Int => Types::Strict::Array)
8
+
9
+ FactoryRepositoryType = Types::Hash.schema(
10
+ credential_provider: SubFactoryRepositoryType,
11
+ second_factor_provider: SubFactoryRepositoryType,
12
+ role_assumption_provider: SubFactoryRepositoryType,
13
+ )
14
+
15
+ def self.factories
16
+ repository.keys.map { |t| [t, flatten_factory_type_list(t)] }.to_h
17
+ end
18
+
19
+ def self.repository
20
+ @repository ||= FactoryRepositoryType[
21
+ credential_provider: {},
22
+ second_factor_provider: {},
23
+ role_assumption_provider: {},
24
+ ]
25
+ end
26
+
27
+ def self.register_factory(klass, type, priority)
28
+ repository[type][priority] ||= []
29
+ repository[type][priority] << klass
30
+ end
31
+
32
+ def self.flatten_factory_type_list(type)
33
+ repository[type].keys.sort.map { |x| @repository[type][x] }.flatten
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ require_relative "abstract_factory"
2
+
3
+ class AwsAssumeRole::Credentials::Factories::Shared < AwsAssumeRole::Credentials::Factories::AbstractFactory
4
+ type :credential_provider
5
+ priority 20
6
+
7
+ def initialize(options = {})
8
+ @profile = options[:profile] || "default"
9
+ @credentials = AwsAssumeRole::Vendored::Aws::SharedCredentials.new(profile_name: @profile)
10
+ @region = AwsAssumeRole.shared_config.profile_region(@profile)
11
+ @role_arn = AwsAssumeRole.shared_config.profile_role(@profile)
12
+ rescue Aws::Errors::NoSuchProfileError
13
+ nil
14
+ end
15
+ end
@@ -0,0 +1,16 @@
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
@@ -0,0 +1,16 @@
1
+ require_relative "abstract_factory"
2
+
3
+ class AwsAssumeRole::Credentials::Factories::Static < AwsAssumeRole::Credentials::Factories::AbstractFactory
4
+ type :credential_provider
5
+ priority 0
6
+
7
+ def initialize(options = {})
8
+ @credentials = Aws::Credentials.new(
9
+ options[:access_key_id],
10
+ options[:secret_access_key],
11
+ options[:session_token],
12
+ )
13
+ @region = options[:region]
14
+ @profile = options[:profile]
15
+ end
16
+ end
@@ -0,0 +1,58 @@
1
+ require_relative "includes"
2
+ require "set"
3
+
4
+ class AwsAssumeRole::Credentials::Providers::AssumeRoleCredentials
5
+ include AwsAssumeRole::Vendored::Aws::CredentialProvider
6
+ include AwsAssumeRole::Vendored::Aws::RefreshingCredentials
7
+
8
+ # @option options [required, String] :role_arn
9
+ # @option options [required, String] :role_session_name
10
+ # @option options [String] :policy
11
+ # @option options [Integer] :duration_seconds
12
+ # @option options [String] :external_id
13
+ # @option options [STS::Client] :client
14
+ #
15
+ #
16
+
17
+ STS_KEYS = [:role_arn, :role_session_name, :policy, :duration_seconds, :external_id, :client, :credentials, :region].freeze
18
+
19
+ def initialize(options = {})
20
+ client_opts = {}
21
+ @assume_role_params = {}
22
+ options.each_pair do |key, value|
23
+ if self.class.assume_role_options.include?(key)
24
+ @assume_role_params[key] = value
25
+ else
26
+ next unless STS_KEYS.include?(key)
27
+ client_opts[key] = value
28
+ end
29
+ end
30
+ @client = client_opts[:client] || ::Aws::STS::Client.new(client_opts)
31
+ super
32
+ end
33
+
34
+ # @return [STS::Client]
35
+ attr_reader :client
36
+
37
+ private
38
+
39
+ def refresh
40
+ c = @client.assume_role(@assume_role_params).credentials
41
+ @credentials = ::Aws::Credentials.new(
42
+ c.access_key_id,
43
+ c.secret_access_key,
44
+ c.session_token,
45
+ )
46
+ @expiration = c.expiration
47
+ end
48
+
49
+ class << self
50
+ # @api private
51
+ def assume_role_options
52
+ @aro ||= begin
53
+ input = ::Aws::STS::Client.api.operation(:assume_role).input
54
+ Set.new(input.shape.member_names)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,9 @@
1
+ require_relative "../../vendored/aws"
2
+ require_relative "../../ui"
3
+ require_relative "../../logging"
4
+ module AwsAssumeRole
5
+ module Credentials
6
+ module Providers
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,102 @@
1
+ require_relative "includes"
2
+ require_relative "../../types"
3
+
4
+ class AwsAssumeRole::Credentials::Providers::MfaSessionCredentials
5
+ include AwsAssumeRole::Vendored::Aws::CredentialProvider
6
+ include AwsAssumeRole::Vendored::Aws::RefreshingCredentials
7
+ include AwsAssumeRole::Ui
8
+ include AwsAssumeRole::Logging
9
+ include AwsAssumeRole
10
+ Types = Dry::Types.module
11
+ extend Dry::Initializer::Mixin
12
+
13
+ attr_reader :permanent_credentials
14
+
15
+ option :permanent_credentials, default: proc { credentials }
16
+ option :credentials
17
+ option :expiration, type: Types::Strict::Time, default: proc { Time.now }
18
+ option :first_time, type: Types::Strict::Bool, default: proc { true }
19
+ option :persist_session, type: Types::Strict::Bool, default: proc { true }
20
+ option :duration_seconds, type: Types::Coercible::Int, default: proc { 3600 }
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)
26
+ @permanent_credentials ||= credentials
27
+ @credentials = nil
28
+ @serial_number = resolve_serial_number(serial_number)
29
+ AwsAssumeRole::Vendored::Aws::RefreshingCredentials.instance_method(:initialize).bind(self).call(*options)
30
+ end
31
+
32
+ private
33
+
34
+ def keyring_username
35
+ @keyring_username ||= "#{@identity.to_json}|#{@serial_number}"
36
+ end
37
+
38
+ def sts_client
39
+ @sts_client ||= Aws::STS::Client.new(region: @region, credentials: @permanent_credentials)
40
+ end
41
+
42
+ def prompt_for_token(first_time)
43
+ text = first_time ? t("options.mfa_token.first_time") : t("options.mfa_token.other_times")
44
+ Ui.input.ask text
45
+ end
46
+
47
+ def initialized
48
+ @first_time = false
49
+ end
50
+
51
+ def refresh
52
+ return set_credentials_from_keyring if @persist_session && @first_time
53
+ refresh_using_mfa if near_expiration?
54
+ broadcast(:mfa_completed)
55
+ end
56
+
57
+ def refresh_using_mfa
58
+ token_code = prompt_for_token(@first_time)
59
+ token = sts_client.get_session_token(
60
+ duration_seconds: @duration_seconds,
61
+ serial_number: @serial_number,
62
+ token_code: token_code,
63
+ )
64
+ initialized
65
+ instance_credentials token.credentials
66
+ persist_credentials if @persist_session
67
+ end
68
+
69
+ def credentials_from_keyring
70
+ @credentials_from_keyring ||= AwsAssumeRole::Store::Keyring.fetch @keyring_username
71
+ rescue Aws::Errors::NoSuchProfileError
72
+ logger.debug "Key not found"
73
+ @credentials_from_keyring = nil
74
+ end
75
+
76
+ def persist_credentials
77
+ AwsAssumeRole::Store::Keyring.save_credentials @keyring_username, @credentials, expiration: @expiration
78
+ end
79
+
80
+ def instance_credentials(credentials)
81
+ return unless credentials
82
+ @credentials = AwsAssumeRole::Store::Serialization.credentials_from_hash(credentials)
83
+ @expiration = credentials.respond_to?(:expiration) ? credentials.expiration : Time.parse(credentials[:expiration])
84
+ end
85
+
86
+ def set_credentials_from_keyring
87
+ instance_credentials credentials_from_keyring
88
+ initialized
89
+ refresh_using_mfa unless @credentials && !near_expiration?
90
+ end
91
+
92
+ def identity
93
+ @identity ||= sts_client.get_caller_identity
94
+ end
95
+
96
+ def resolve_serial_number(serial_number)
97
+ return serial_number unless serial_number.nil? || serial_number == "automatic"
98
+ user_name = identity.arn.split("/")[1]
99
+ "arn:aws:iam::#{identity.account}:mfa/#{user_name}"
100
+ end
101
+ Dry::Types.register_class(self)
102
+ end