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,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
- # Mixin to provide global logging object
2
- module AWSAssumeRole
3
-
4
- module Logging
5
-
6
- require 'logger'
7
-
8
- class << self
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
- Logging.logger
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