aws_assume_role 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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