ex-aws / ex_aws_sts

13 stars 31 forks source link

AssumeRoleCredentialsAdapter Doesn't Work With Anything except hard-coded values #35

Open geofflane opened 1 year ago

geofflane commented 1 year ago

Environment

Current behavior

Using AssumeRoleCredentialsAdapter just doesn't seem to work at all.

In the application config/dev.exs, I configured ex_aws to use AssumeRoleCredentialsAdapter and my awscli config:

config :ex_aws,
  secret_access_key: [{:awscli, "staging", 30}],
  access_key_id: [{:awscli, "staging", 30}],
  awscli_auth_adapter: ExAws.STS.AuthCache.AssumeRoleCredentialsAdapter

My local config uses a role_arn and a source_profile to allow me to assume role from another account:

[profile staging]
region = us-east-2
role_arn = arn:aws:iam::<<AWS::AccountId>>:role/developer-role
source_profile = default

An AWS request is made (to S3 in my case) and The ExAws.Config.AuthCache delegates to AssumeRoleCredentialsAdapter. AssumeRoleCredentialsAdapter resolves the awscli stuff, but to actually make the assume role, it has to make another request using the source profile credentials. In get_security_credentials ExAws.request` occurs for that. ExAws then goes back to ExAws.Config.AuthCache to try and resolve and cache the default credentials. But that's a GenServer so calling back into creates a deadlock and the GenServer terminates with an error.

[error] GenServer ExAws.Config.AuthCache terminating                                                                                                                                                                                                                                                                        
** (stop) exited in: GenServer.call(ExAws.Config.AuthCache, {:refresh_awscli_config, "fb2b_staging", 30000}, 30000)                                                                                                                                                                                                         
    ** (EXIT) process attempted to call itself                                                                                                                                                                                                                                                                              
    (elixir 1.14.4) lib/gen_server.ex:1031: GenServer.call/3                                                                                                                                                                                                                                                                
    (ex_aws 2.4.2) lib/ex_aws/config.ex:181: ExAws.Config.retrieve_runtime_value/2                                                                                                                                                                                                                                          
    (elixir 1.14.4) lib/stream.ex:612: anonymous fn/4 in Stream.map/2                                                                                                                                                                                                                                                       
    (elixir 1.14.4) lib/enum.ex:4751: Enumerable.List.reduce/3                                                                                                                                                                                                                                                              
    (elixir 1.14.4) lib/stream.ex:1813: Enumerable.Stream.do_each/4                                                                                                                                                                                                                                                         
    (elixir 1.14.4) lib/enum.ex:1150: Enum.find/3                                                                                                                                                                                                                                                                           
    (ex_aws 2.4.2) lib/ex_aws/config.ex:162: anonymous fn/2 in ExAws.Config.retrieve_runtime_config/1                                                                                                                                                                                                                       
    (stdlib 4.0.1) maps.erl:411: :maps.fold_1/3                                                                                                                                                                                                                                                                             
    (ex_aws 2.4.2) lib/ex_aws/config.ex:70: ExAws.Config.new/2                                                                                                                                                                                                                                                              
    (ex_aws 2.4.2) lib/ex_aws.ex:73: ExAws.request/2                                                                                                                                                                                                                                                                        
    (ex_aws_sts 2.3.0) lib/ex_aws/sts/auth_cache/assume_role_credentials_adapter.ex:36: ExAws.STS.AuthCache.AssumeRoleCredentialsAdapter.get_security_credentials/3                                                                                                                                                         
    (ex_aws 2.4.2) lib/ex_aws/config/auth_cache.ex:83: ExAws.Config.AuthCache.attempt_credentials_refresh/5                                                                                                                                                                                                                 
    (ex_aws 2.4.2) lib/ex_aws/config/auth_cache.ex:73: ExAws.Config.AuthCache.refresh_awscli_config/3                                                                                                                                                                                                                       
    (ex_aws 2.4.2) lib/ex_aws/config/auth_cache.ex:50: ExAws.Config.AuthCache.handle_call/3                                                                                                                                                                                                                                 
    (stdlib 4.0.1) gen_server.erl:1146: :gen_server.try_handle_call/4                                                                                                                                                                                                                                                       
    (stdlib 4.0.1) gen_server.erl:1175: :gen_server.handle_msg/6                                                                                                                                                                                                                                                            
    (stdlib 4.0.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3    

Expected behavior

STS should be able to assume role

The only workaround I've found is to disable "refreshable" on the source profile auth:

  def adapt_auth_config(%{source_profile: source_profile} = auth, _, expiration, loader) do
    source_profile_auth = loader.(source_profile) |> Map.put(:refreshable, false)
    get_security_credentials(auth, source_profile_auth, expiration)
  end

I don't exactly know what the implications of that are, but I assume that the base credentials could expire and it would just stop working after some time. This is OK for me right now because this is just for local development, but might not work in a long-running scenario.