mhart / aws4

Signs and prepares Node.js requests using AWS Signature Version 4
MIT License
699 stars 175 forks source link

Account for STS no longer being a single region service #166

Closed ryanblock closed 3 months ago

ryanblock commented 3 months ago

Code in question: https://github.com/mhart/aws4/blob/master/aws4.js#L111

Per AWS: AWS recommends using Regional AWS STS endpoints instead of the global endpoint to reduce latency, build in redundancy, and increase session token validity.

Today, when you pass a region in a request to aws4, the signature specifies the passed region (e.g. 'AWS4-HMAC-SHA256 Credential=.../20240528/us-west-2/sts/aws4_request...), however the request always goes to sts.amazonaws.com, and not sts.$region.amazonaws.com, resulting in a 403 / SignatureDoesNotMatch error.

It appears that by default all STS regions are enabled and active by default since late 2015, witha manual opt-out (ref), so my expectation would be this should be a fairly safe change to make.

Happy to PR, as ever, if so desired!

ryanblock commented 3 months ago

Update: just found https://github.com/mhart/aws4/pull/162

mhart commented 3 months ago

Yeah, so just repeating the instructions there:

aws4.sign({ host: 'sts.us-west-2.amazonaws.com', path: '/?Action=AssumeRole' })

The backwards-compat cases will be if someone's using a non-us-east-1 region currently (potentially unwittingly – perhaps it's in a general config object) – then any calls would currently be going to sts.amazonaws.com and that would suddenly change.

In most cases you'd hope that change is beneficial! But as we all know, you can't predict how it might affect ppl.

If this is related to aws-lite and you're happy with assuming they want to use the regional endpoints (pretty safe assumption for a newer library), I think just be explicit and use hostnames. You should be able to use "region" and "service" as well as "host" if you'd like to be extra sure everything's going to sign ok. TBH in general being more explicit is always going to be what you want – otherwise you're relying on aws4 to do the guessing for you, and it might just get behind the times.

mhart commented 3 months ago

Just in case you hadn't seen it (though I'm sure you have), aws4 will only call the "guessing" code path if you don't pass in a host: https://github.com/mhart/aws4/blob/51d3a2f9177030e8f934467e4b93cebd9c7ca67f/aws4.js#L64-L65 Same with service and region: https://github.com/mhart/aws4/blob/51d3a2f9177030e8f934467e4b93cebd9c7ca67f/aws4.js#L55-L56 So ultimately you've got the most control if you specify all three.

Going to close this, but can keep in mind for a 2.x if such a thing is ever wanted/needed.