How to check if an AWS STS access token is valid - amazon-web-services

I have a lambda function that uses AWS STS to generate temporary credentials and then sends the access token via HTTP to a Web API in an EC2 instance.
Is there a way to validate the received access token from the API?

Calling STS GetCallerIdentity will tell you if the credentials are usable to make API calls, and it will identify the underlying AWS account and assumed role.
For example:
aws sts get-caller-identity
{
"UserId": "AROAABCDEFGHIJKLMNOPQ:xyz",
"Account": "123456781234",
"Arn": "arn:aws:sts::123456781234:assumed-role/somerole"
}
Notes about the response object:
Account is the AWS account number of the account that owns/contains the calling entity
UserId is the unique identifier of the calling entity. The exact value depends on the type of entity that is making the call.

AWS security architecture assures you that any token generated by IAM represents a valid token, and that the given service that generated the token had permissions to do so. If you are concerned that some entity with elevated privileges generated a token, and that that token is not to be trusted, then you have a security configuration problem. You would need to check CloudWatch to see what entity generated the token, and revoke its permissions.
As #jarmod suggests, if a given token works, then it is valid. That is all you can know about its validity.

Related

What is the access key Id and Secret returned in get credentials for identity call in aws cognito?

I have set up aws cognito and would like to use their federated identities to authenticate users against my own database but on getting a token after calling the get_open_id_token_for_developer_identity() and then calling the get_credentials_for_identity() the response is identityID , AccessKey , clientSecret and session token but this accesskey and client secret do not match the security credentials for my root user or even the IAM users and when used in postman with the AWS SIGNATURE authorization it throws an unauthorized error . I am getting the credentials after calling the get_credentials_for_identity() using identity id and in login{"cognito-identity.amazonaws.com":<token_from_get_open_id>} but the response which includes accesskey and client secret does not let me hit the api now secured using cognito
this accesskey and client secret do not match the security credentials for my root user or even the IAM users
These are new and temporary credentials not linked to your root or other IAM users in your account. From docs:
You can use Amazon Cognito to deliver temporary, limited-privilege credentials to your application, so that your users can access AWS resources.
This is explained more here:
When a user logs in to your app, Amazon Cognito generates temporary AWS credentials for the user. These temporary credentials are associated with a specific IAM role. The IAM role lets you define a set of permissions to access your AWS resources.

AWS STS Assume Role: Get session token

I am trying to get a session token for the given IAM in postman but not able to receive a token.
If I use boto3.client('sts'), I am able to get the token.
Use Case: I am trying to Invoke VPC Rest Endpoint from EC2 instance where ServiceNow mid-server instance is running. Since we have ServiceNow mid-server agent running on EC2 instance, I want to use IAM Role attached to EC2 to authenticate other VPC endpoints that are deployed in the same AWS account.
I have permission policy attached to IAM Role to allow Assume Role policy. If there any other approach, please suggest.
here HTML HTML response in postman. Postman redirecting to IAM Docs
client = boto3.client('sts')
response = client.assume_role(
RoleArn='arn:aws:iam::**************:role/ServiceNow-midserver-Role',
RoleSessionName='Session1',
DurationSeconds=3600
)
print(response)
anything wrong with postman request body or endpoint.
Authentication on postman is none.
To call AssumeRole from Postman (or curl etc.) as opposed to using a supported AWS SDK, you should follow the AssumeRole API documentation. You will also need to authenticate using AWS credentials.
Specifically, the request is an HTTP GET and parameters are passed as query strings, for example:
GET https://sts.amazonaws.com/
?Version=2011-06-15
&Action=AssumeRole
&RoleSessionName=stackoverflow-64706420
&RoleArn=arn:aws:iam::123456781234:role/myrole
&DurationSeconds=3600
Here's what this looks like in Postman:
And you will need to add AWS credentials so that your API request is signed correctly, for example:
Click 'Send' and the response will look something like this:
<AssumeRoleResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleResult>
<AssumedRoleUser>
<Arn>arn:aws:sts::123456781234:assumed-role/123456781234/stackoverflow-64706420</Arn>
<AssumedRoleId>ARO123EXAMPLE123:stackoverflow-64706420</AssumedRoleId>
</AssumedRoleUser>
<Credentials>
<AccessKeyId>ASIAIOSFODNN7EXAMPLE</AccessKeyId>
<SecretAccessKey>wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY</SecretAccessKey>
<SessionToken>
AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQW
LWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGd
QrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU
9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz
+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA==
</SessionToken>
<Expiration>2020-12-09T13:34:41Z</Expiration>
</Credentials>
<PackedPolicySize>6</PackedPolicySize>
</AssumeRoleResult>
<ResponseMetadata>
<RequestId>c6104cbe-af31-11e0-8154-cbc7ccf896c7</RequestId>
</ResponseMetadata>
</AssumeRoleResponse>
You need to use credentials for an IAM user or an IAM role to call AssumeRole. boto3 must be getting credentials from the standard locations it look for (like ~/.aws/config) [ref:https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html]. May be you could try providing the AWS creds in Authorization tab in Postman selecting type as AWS Signature and then call assumeRole.

AWS Cognito refreshing tokens against a different user pool also returns valid tokens

I was trying the AWS CLI for cognito.
I have a refresh token issued by user pool, let's say "A" with client ID "clientA".
I used this against a different user pool "B" in the same region. I specified client ID as "clientA" instead of B's own. This command worked and returned new access and ID tokens successfully.
$ aws cognito-idp admin-initiate-auth --user-pool-id "B"
--region eu-west-1 --client-id clientA --auth-flow
REFRESH_TOKEN_AUTH --auth-parameters "REFRESH_TOKEN=<refresh-token-from-A>"
It seems like AWS Cognito does not really use the "user-pool-id" parameter and only considers the client ID. Or otherwise this is a security loophole.
The documentation isn't massively clear about this, but the REFRESH_TOKEN flow does not use the client-id or user-pool-id as these are effectively provided by the Refresh Token itself. (Although the body won't validate without them...)
If you do some further commands on the CLI you'll see that the tokens you got back from that command only allow you to act as the originally issued client-id/user-pool-id.

How can I determine which role I've received after logging into AWS Cognito via JavaScript?

After I log in to AWS Cognito via my browser, I get an access key and a secret access key along w/a session token, but I can't see which role I've been assigned. I know which role I should be assigned, but is there a way to programmatically validate this?
I'm trying to use the role I've been assigned to access a restricted bucket, but am so far not having any success and one of the ways for me to trouble shoot this is to determine which role I've been assigned.
With sts.GetCallerIdentity.
cli example (js link above):
aws --profile XXXXXXXX sts get-caller-identity
{
"UserId": "AIDAIXXXXXXXXTHOVLM",
"Account": "123456789098",
"Arn": "arn:aws:iam::123456789098:user/dan"
}
It is indeed frustrating to debug without this, and it didn't used to exist, but now it does. Hurrah!

Aws lambda cross account access

I have a lambda that consumes data from another AWS account's Athena. So I have a role that my lambda assumes which have cross-account access. I had used STS client in my lambda. sometimes lambda is running perfectly fine and sometimes it breaks and gives me this error.
"errorMessage": "An error occurred (ExpiredTokenException) when calling the StartQueryExecution operation: The security token included in the request is expired",
"errorType": "ClientError",
STS client i used in my code is :
def assume_role_to_session(role_arn, session_name):
client = boto3.client('sts')
response = client.assume_role(RoleArn=role_arn, RoleSessionName=session_name, DurationSeconds=900)
return boto3.Session(
aws_access_key_id=response['Credentials']['AccessKeyId'],
aws_secret_access_key=response['Credentials']['SecretAccessKey'],
aws_session_token=response['Credentials']['SessionToken'],
region_name='us-east-1')
assume_role_athena_session = assume_role_to_session(role_arn='arn:aws:iam::XXXXXXXXXXX:role/role-name',
session_name='AthenaLambdaSession')
How does this work? I want my lambda to run anytime not just sometimes. What could be the problem?
Look at this document
RoleSessionName (string) -- [REQUIRED]
An identifier for the assumed role session.
Use the role session name to uniquely identify a session when the same
role is assumed by different principals or for different reasons. In
cross-account scenarios, the role session name is visible to, and can
be logged by the account that owns the role. The role session name is
also used in the ARN of the assumed role principal. This means that
subsequent cross-account API requests using the temporary security
credentials will expose the role session name to the external account
in their CloudTrail logs.
So try to replace AthenaLambdaSession with unique RoleSessionName. Or if you want to reuse existing session, try to check session timeout to make sure that enough time to execute your lambda task (max 5 minutes). If < 5 minutes, re-new it.