Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a before_refresh callback to AssumeRoleCredentials #2663

Merged
merged 5 commits into from
Feb 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ def initialize(options = {})
@identity_id = options.delete(:identity_id)
@custom_role_arn = options.delete(:custom_role_arn)
@logins = options.delete(:logins) || {}
@before_refresh = options.delete(:before_refresh)

if !@identity_pool_id && !@identity_id
raise ArgumentError,
Expand Down Expand Up @@ -114,8 +113,6 @@ def identity_id
private

def refresh
@before_refresh.call(self) if @before_refresh

resp = @client.get_credentials_for_identity(
identity_id: identity_id,
custom_role_arn: @custom_role_arn
Expand Down
1 change: 1 addition & 0 deletions gems/aws-sdk-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Unreleased Changes
------------------

* Issue - Add a before_refresh callback to AssumeRoleCredentials (#2529).
* Issue - Raise a `NoSuchProfileError` when config and credentials files don't exist.

3.126.1 (2022-02-14)
Expand Down
18 changes: 18 additions & 0 deletions gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ module Aws
#
# If you omit `:client` option, a new {STS::Client} object will be
# constructed.
#
# The AssumeRoleCredentials also provides a `before_refresh` callback
mullermp marked this conversation as resolved.
Show resolved Hide resolved
# that can be used to help manage refreshing tokens.
# `before_refresh` is called when AWS credentials are required and need
# to be refreshed and it is called with the AssumeRoleCredentials object.
class AssumeRoleCredentials

include CredentialProvider
Expand All @@ -28,6 +33,16 @@ class AssumeRoleCredentials
# @option options [Integer] :duration_seconds
# @option options [String] :external_id
# @option options [STS::Client] :client
# @option options [Callable] before_refresh Proc called before
mullermp marked this conversation as resolved.
Show resolved Hide resolved
# credentials are refreshed. Useful for updating tokens.
# `before_refresh` is called when AWS credentials are
# required and need to be refreshed. Tokens can be refreshed using
# the following example:
#
# before_refresh = Proc.new do |assume_role_credentials| do
# assume_role_credentials.assume_role_params['token_code'] = update_token
# end
#
def initialize(options = {})
client_opts = {}
@assume_role_params = {}
Expand All @@ -45,6 +60,9 @@ def initialize(options = {})
# @return [STS::Client]
attr_reader :client

# @return [Hash]
attr_reader :assume_role_params

private

def refresh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ class AssumeRoleWebIdentityCredentials
# encoded UUID is generated as the session name
#
# @option options [STS::Client] :client
#
# @option options [Callable] before_refresh Proc called before
# credentials are refreshed. `before_refresh` is called
# with an instance of this object when
# AWS credentials are required and need to be refreshed.
def initialize(options = {})
client_opts = {}
@assume_role_web_identity_params = {}
Expand Down
4 changes: 4 additions & 0 deletions gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ class Non200Response < RuntimeError; end
# @option options [IO] :http_debug_output (nil) HTTP wire
# traces are sent to this object. You can specify something
# like $stdout.
# @option options [Callable] before_refresh Proc called before
# credentials are refreshed. `before_refresh` is called
# with an instance of this object when
# AWS credentials are required and need to be refreshed.
def initialize options = {}
@retries = options[:retries] || 5
@ip_address = options[:ip_address] || '169.254.170.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ class TokenExpiredError < RuntimeError; end
# @option options [Integer] :token_ttl Time-to-Live in seconds for EC2
# Metadata Token used for fetching Metadata Profile Credentials, defaults
# to 21600 seconds
# @option options [Callable] before_refresh Proc called before
# credentials are refreshed. `before_refresh` is called
# with an instance of this object when
# AWS credentials are required and need to be refreshed.
def initialize(options = {})
@retries = options[:retries] || 1
endpoint_mode = resolve_endpoint_mode(options)
Expand Down
15 changes: 13 additions & 2 deletions gems/aws-sdk-core/lib/aws-sdk-core/refreshing_credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ module RefreshingCredentials

def initialize(options = {})
@mutex = Mutex.new
@before_refresh = options.delete(:before_refresh) if Hash === options

@before_refresh.call(self) if @before_refresh
refresh
end

Expand All @@ -37,7 +40,11 @@ def expiration
# Refresh credentials.
# @return [void]
def refresh!
@mutex.synchronize { refresh }
@mutex.synchronize do
@before_refresh.call(self) if @before_refresh

refresh
end
end

private
Expand All @@ -47,7 +54,11 @@ def refresh!
def refresh_if_near_expiration
if near_expiration?
@mutex.synchronize do
refresh if near_expiration?
if near_expiration?
@before_refresh.call(self) if @before_refresh

refresh
end
end
end
end
Expand Down
5 changes: 5 additions & 0 deletions gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ class SSOCredentials
#
# @option options [SSO::Client] :client Optional `SSO::Client`. If not
# provided, a client will be constructed.
#
# @option options [Callable] before_refresh Proc called before
# credentials are refreshed. `before_refresh` is called
# with an instance of this object when
# AWS credentials are required and need to be refreshed.
def initialize(options = {})

missing_keys = SSO_REQUIRED_OPTS.select { |k| options[k].nil? }
Expand Down
16 changes: 16 additions & 0 deletions gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,21 @@ module Aws
c.credentials
end

it 'calls before_refresh with self' do
before_refresh_called = false
before_refresh = proc do |cred_provider|
before_refresh_called = true
expect(cred_provider).to be_instance_of(AssumeRoleCredentials)
end

AssumeRoleCredentials.new(
role_arn: 'arn',
role_session_name: 'session',
before_refresh: before_refresh
)

expect(before_refresh_called).to be(true)
end

end
end