If AWS_SESSION_TOKEN is to represent/encode the temporary validity, why we still needs the first two fields (because after the expiration, we will need to get another AWS_SESSION_TOKEN anyway)?
It may feel like we as clients just send all three values to AWS — we have to make all of them available to the AWS CLI or SDKs — but there's a big difference between what the AWS CLI or SDKs know and what actually gets sent to AWS services in the cloud.
In particular, the "secret access key" isn't actually sent to the cloud; rather, it's used to sign the request, using "AWS Signature Version 4", which uses HMACs to authenticate the client and ensure that the request hasn't been tampered with. An HMAC is a kind of signature based on a shared secret key; the sender computes an HMAC and sends it alongside the message, and the recipient computes the same HMAC and verifies that it matches what was sent. An eavesdropper or man-in-the-middle can't forge messages or even tamper with them, because they won't have the shared secret key to sign the message with. In the case of AWS service requests, multiple levels of HMACs are used (presumably to limit the "blast radius" of a server-side compromise), but for purposes of your question, the important thing to understand is that they're ultimately derived from the secret access key, which therefore isn't sent over the wire.
The "access key ID" is sent to the cloud; it tells the service what secret access key is used, so that it can compute the right HMAC. (There's no point in sharing a secret key if the other party can't figure out what key you're using!)
At this point you might ask, why not combine the "access key ID" and the "security token" (a.k.a. "session token") into a single field?
That doesn't seem to be documented, but:
- The access key ID isn't secret [source], whereas the security token presumably is. If they were combined, then the combination would be as sensitive as the more-secure element. I assume that AWS services make internal use of the fact that the access key ID is not secret — logging it, using it as a cache key, etc. — in a way that AWS would not consider acceptable for security tokens.
- The access key ID is limited to 128 characters [doc link], and used to be limited to 32 characters [archived doc link] whereas security tokens can be potentially unboundedly large [doc link]. That, too, would interfere with internal (or even public) uses of the access key ID.
You could still potentially imagine sending the access key ID and security token to clients as a single field, letting clients send them back as a unit, and making the server-side parse them out; but AWS is a large organization (literally thousands of engineers, I believe), so it's not only important to provide a clean API for clients, it's also important to provide a clean API for internal teams. I imagine that service teams would push back on a design that asked them to parse a field in order to split it out this way, when it's so straightforward to just keep them separate to begin with. And every point of custom parsing is another opportunity for potential bugs, security vulnerabilities, etc., as well as another point of difficulty in maintaining backward-compatibility in the next version.
If my client call the STS API twice, between two responses returned from aws sts assume-role
, will/could AWS_ACCESS_KEY_ID be same?
The documentation states that "Temporary security credentials are not stored with the user but are generated dynamically and provided to the user when requested" [doc link], which seems to mean that they will not be reused.
To be sure, I wouldn't necessarily want to rely on that assumption. I'm pretty sure that signing keys must get cached or predistributed or something (because AWS Signature Version 4 seems specifically designed to enable that), which gives some motivation for a latency/availability improvement whereby access key IDs and secret access keys (but not security tokens) are re-vended by successive calls to assume the same role, so as to take advantage of cached copies of the original.
But given that this is not the only thing that suggests that IAM won't re-vend a secret access key — the same is true of long-lived credentials, where you have to save the secret access key when you first get it, because there's no way to re-fetch it later — I think that that potential latency/availability benefit has lost out to a security consideration. (After all, it provides better "defense in depth" if the internal service that's responsible for storing secret access keys literally doesn't provide any mechanism at all to fetch them, and only vends fully-computed signing keys with the aforementioned "blast radius" protections in place.)