Debugging a GetSessionToken issue

When the sts.getSessionToken() request returns the "AccessDenied - Cannot call GetSessionToken with session credentials" error, it indicates that we are trying to use temporary credentials to obtain another set of temporary credentials.

1. The situation

I wanted to connect an EC2 instance to Mongo Atlas when I received the following error message:

AccessDenied: Cannot call GetSessionToken with session credentials

My EC2 instance had an instance role attached, which I added to the database users in Mongo Atlas.

What could have happened?

2. Explanation

The error message indicates that I wanted to get temporary credentials using another set of temporary credentials.

Mongo Atlas supports passwordless authentication using AWS IAM. The Mongo driver will read the temporary credentials (access key id, secret access key and session token) from the EC2 metadata.

My idea of using the instance role’s temporary credentials was correct. But somewhere deep in the code, where the database connection gets set up, we called the GetSessionToken STS API endpoint to receive temporary credentials in certain situations.

3. The solution

The GetSessionToken API endpoint returns temporary credentials for AWS accounts or IAM users.

An EC2 instance role, similarly to a Lambda execution role or an ECS Task role, already works with temporary credentials. None of them are an AWS account or an IAM user.

When I want to test my application from my laptop, I might use my own AWS user credentials.

Users have long-term credentials (an access key id and a secret access key), so calling the GetSessionToken endpoint and adding the temporary credentials to the database connection string is a great way to reduce the attack surface.

But in the case of an EC2 instance, the temporary credentials are already present, and we can call Atlas with them straight away. We don’t need to get another set of credentials.

4. About GetSessionToken

We must call the GetSessionToken operation with long-term credentials. In theory, both the root user and an IAM user can invoke the endpoint, although it’s a bad practice to use the root user for everyday operations.

The endpoint returns a set of temporary credentials containing an access key id, secret access key, and session token. We can use these credentials in operations that require multi-factor authentication or connecting to a database in a passwordless way.

In most cases, we want to use temporary credentials in our applications to connect to the database or other AWS services.

The request to GetSessionToken can have a DurationSeconds parameter that specifies how long the credentials should remain valid. The length of the user sessions can vary between 15 minutes and three days, with 12 hours being the default.

But we cannot call any STS API endpoints with the credentials provided by GetSessionToken, except AssumeRole and GetCallerIdentity. It means that we are not allowed to invoke, for example, GetSessionToken again with the credentials the endpoint has already provided.

5. Conclusion

The AccessDenied: Cannot call GetSessionToken with session credentials error message shows that we invoked the STS endpoint with a set of temporary credentials. The operation doesn’t allow this call.

The solution is either call GetSessionToken with long-term credentials (an IAM user) or remove the additional temporary credentials call from the workflow.

The application’s role should be sufficient for the successful connection, given the credentials have the relevant permissions.

6. Further reading

GetSessionToken - API documentation