aws icon indicating copy to clipboard operation
aws copied to clipboard

Using NullProvider for credentials with Localstack causes unexpected behavior

Open shadowhand opened this issue 4 years ago • 7 comments

I am using localstack for development and noticed a discrepancy between the official AWS SDK and Async AWS.

My configuration is:

[
  'region' => 'us-west-2',
  'endpoint' => 'http://localhost:4566',
]

If I use (eg) AsyncAws\Sqs\SqsClient to create a new queue called "test":

$client->createQueue(['QueueName' => 'test']);

When I check it via CLI:

aws --endpoint-url http://localhost:4566 --region us-west-2 sqs list-queues --no-cli-pager

There is no output, as if the queue wasn't created. But when I do:

aws --endpoint-url http://localhost:4566 --region us-east-1 sqs list-queues --no-cli-pager

{
    "QueueUrls": [
        "http://localhost:4566/000000000000/test"
    ]
}

It exists, but not in the region that I specified.

shadowhand avatar Oct 06 '21 19:10 shadowhand

Further making this weird is that not only do I have region set in the config, but also for my default profile in ~/.aws/config.

Somewhere along the line, Async AWS is losing track of the region.

shadowhand avatar Oct 06 '21 20:10 shadowhand

Digging deeper, it appears that using NullProvider as the credential provider causes this issue to appear. When I set credentials as:

- $credentials = new NullProvider();
+ $credentials = new ConfigurationProvider();

Then everything seems to work as expected.

shadowhand avatar Oct 06 '21 20:10 shadowhand

Could you please provide a reproducer? how do you create the client?

jderusse avatar Oct 06 '21 20:10 jderusse

In this case, it is SqsClient but the same applies to any AsyncAws client.

My configuration before, which was not working:

$config = [
    'region' => 'us-west-2',
    'endpoint' => 'http://localhost:4566',
];

$credentials = new NullProvider();
$client = new SqsClient($config, $credentials);

After figuring out the root cause and updating:

$config = [
    'region' => 'us-west-2',
    'endpoint' => 'http://localhost:4566',
    'accessKeyId' => 'test', 
    'accessKeySecret' => 'test',
];

$credentials = ChainProvider::createDefaultChain();
$client = new SqsClient($config, $credentials);

shadowhand avatar Oct 06 '21 20:10 shadowhand

Actually, AWS uses region for 2 things:

  • defining the endpoint URL (ie https://sqs.us-west-2.amazonaws.com.cn)
  • signing the request (the name of the region is part of the signature)

I don't know how localstack works internally, but I believe it extracts the region from the signature. That's why the request must be signed and you have to provide credentials.

I'm not sure what is the best solution for AsyncAws

  • always signing the request with empty is/secret. I'm :-1: for this one. Could break for 3rd party providers that does not expect a signature)
  • sign the request when user provides both region and endpoint (Could break providers too)
  • explain the issue in our documentation

WDYT @Nyholm ?

jderusse avatar Oct 08 '21 17:10 jderusse

I believe it extracts the region from the signature

That is correct.

I think the solution here is simply documenting that NullProvider cannot be used with Localstack and that ConfigurationProvider with test:test credentials should be used instead. Or creating a specific TestProvider that does exactly that: use test:test as the access id and secret.

shadowhand avatar Oct 08 '21 17:10 shadowhand

Interesting.

Yeah. I agree with both of you. Let's add a section in the docs about "Localstack" or local development.

Nyholm avatar Oct 08 '21 19:10 Nyholm