Identify AWS IAM user that assumed an IAM role - amazon-web-services

I'm working on a system that receives new findings from Amazon GuardDuty. Most access in our organization is delegated to IAM roles instead of directly to users, so the findings usually result from the actions of assumed roles, and the actor identity of the GuardDuty finding looks something like this:
"resource": {
"accessKeyDetails": {
"accessKeyId": "ASIALXUWSRBXSAQZECAY",
"principalId": "AROACDRML13PHK3X7J1UL:129545928468",
"userName": "my-permitted-role",
"userType": "AssumedRole"
},
"resourceType": "AccessKey"
},
I know that the accessKeyId is created when a security principal performs the iam:AssumeRole action. But I can't tell who assumed the role in the first place! If it was an IAM user, I want to know the username. Is there a way to programmatically map temporary AWS STS keys (starts with ASIA...) back to an original user?
Ideally I'm looking for a method that runs in less than 30 seconds so I can use it as part of my security event pipeline to enrich GuardDuty findings with the missing information.
I've already looked at aws-cli and found aws cloudtrail lookup-events but it lacks the ability to narrow the query to a specific accessKeyId so it takes a loooong time to run. I've explored the CloudTrail console but it's only about as capable as aws-cli here. I tried saving my CloudTrail logs to S3 and running an Athena query, but that was pretty slow too.
This seems like it would be a common requirement. Is there something obvious that I'm missing?

Actually, aws-cli can perform a lookup on the session! Just make sure to specify ResourceName as the attribute key in the lookup attributes.
$ aws cloudtrail lookup-events \
--lookup-attributes 'AttributeKey=ResourceName,AttributeValue=ASIALXUWSRBXSAQZECAY' \
--query 'Events[*].Username'
[
"the.user#example.com"
]

Related

Is there any way to check the value of aws:MultiFactorAuthPresent

I have a policy that denies operations except if aws global context key aws:MultiFactorAuthPresent is true. Meaning that the operation requires that you are authenticated via MFA.
The policy is working ok, and I can see that when I use my aws profile without mfa the operations are denied and when I use the profile with MFA they work.
Now, is there any command / api operation that tells me if my credentials used MFA (aws:MultiFactorAuthPresent)?
I need it for troubleshooting purpose mainly when other people complain that they are getting Operation Denied? Something like aws sts get-caller-identity but that also print out if the credentials used an MFA code.
If I understand correctly, you would want to check if certain users did authenticate themselves with MFA before doing some operations in your account.
I'm not aware of any kind of CLI command for this. What would be helpful for you is to take a look a the CloudTrail Event History. This should log all the operations done by other users. If you download this list of events as a JSON, you should be able find a section with sessionContext for every event.
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "...",
"arn": "...",
"accountId": "...",
"userName": "..."
},
"webIdFederationData": {},
"attributes": {
"creationDate": "2022-02-18T14:08:57Z",
"mfaAuthenticated": "false"
}
}
We can notice that every it is logged that session used by the user/role is MFA authenticated or not.
If you are willing to search for operations done by certain users, you should be able to detect if they were using MFA or not. Just as warning, this JSON file can be huge and could be really painful to go through it.
If you simply want to make sure that users are using MFA when working with AWS CLI you can also enforce MFA usage with aws sts get-session-token (see also https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sts/get-session-token.html). Therefore users start creating a temporary session with explicit MFA usage (see parameter --serial-numer and --token-code). All commands execute with these temporary session credentials are MFA enforced.

Temporary Security Credentials - How to get access, given a role name & AWS account id?

AWS documentation provides multiple approach, here.
In our environment, we have multiple AWS accounts.
Usage scenario is to switch between AWS accounts and run AWS cli commands from laptop, as part of automation.
Before running AWS cli command on a specific AWS account, we need to get temporary credentials for that account, given account id.
Getting access to(by switching over) multiple AWS accounts, helps us in automation.
Basically we would like to run some tool like ./some_aws_sdk_tool.py role_name aws_account_name, assuming a role_name to get credentials.
I want to test this with my single AWS account(personal).
1) What are the steps to configure my AWS account to create such role_name?
2)
What is the approach to get temporary credentials to a specific aws_account_name with some_aws_sdk_tool.py? to be able run AWS CLI commands for n minutes..
Do you want to do this from within your code or using the AWS CLI?
If you're using the CLI, the easiest way is to create profiles in your AWS credentials file, as described here. Each profile identifies a role ARN and the source login information that is allowed to assume that role.
Alternatively, you can run the sts assume-role command, parse the results, and set environment variables:
aws sts assume-role --role-arn 'arn:aws:iam::123456789012:role/Example' --role-session-name 'some_unique_but_relevant_string'
{
"Credentials": {
"AccessKeyId": "ASIAXXXXXXXXXXXXXXXX",
"SecretAccessKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"SessionToken": "XXXXXXXXXXXXXXX//////////XXX...XXXXX",
"Expiration": "2020-03-05T20:57:45Z"
},
"AssumedRoleUser": {
"AssumedRoleId": "AROAXXXXXXXXXXXXXXXXX:some_unique_but_relevant_string",
"Arn": "arn:aws:sts::123456789012:assumed-role/Example/some_unique_but_relevant_string"
}
}
If you want to do it from within your program, you can use code like this:
sts_client = boto3.client('sts')
role_arn = "..."
session_name = "some_unique_but_relevant_value"
response = sts_client.assume_role(
RoleArn=role_arn,
RoleSessionName=session_name
)
creds = response['Credentials']
actual_client = boto3.client('SERVICE',
aws_access_key_id=creds['AccessKeyId']
aws_secret_access_key=creds['SecretAccessKey']
aws_session_token=creds['SessionToken'])
That is not possible. You can only see a secret key on the first time it gets created, AWS will never show it to you again. See more here.
Some Identity Managers like Okta allow you to assume roles on CLI so you don't have to deal with credentials directly. You just assign a role to an user and he will be able to assume the role directly after the first login.

AWS CLI: Describing a Policy Without "p-" Prefix

I am trying to use AWS CLI to describe my AWS policy. However, AWS does not seem to be recognizing the policy-id.
I have executed this:
aws iam get-policy --policy-arn arn:aws:iam::160936793253:policy/MyAWSPolicy
and got the following returned:
{
"Policy": {
"PolicyName": "MyAWSPolicy",
"PolicyId": "ANPAIIJNOIYOWCAK6KH7I",
"Arn": "arn:aws:iam::160936796653:policy/MyAWSPolicy",
"Path": "/",
"DefaultVersionId": "v8",
"AttachmentCount": 2,
"IsAttachable": true,
"CreateDate": "2019-03-20T20:20:26Z",
"UpdateDate": "2019-04-01T18:19:08Z"
}
}
However when I enter in this command:
aws organizations describe-policy --policy-id ANPAIIJNOIYOWCAK6KH7I
I get an InvalidInputException because according to AWS documentation (https://docs.aws.amazon.com/cli/latest/reference/organizations/describe-policy.html#examples):
The unique identifier (ID) of the policy that you want details about. You can get the ID from the ListPolicies or ListPoliciesForTarget operations.
The regex pattern for a policy ID string requires "p-" followed by from 8 to 128 lower-case letters or digits.
However when I add p- to ANPAIIJNOIYOWCAK6KH7I AWS does not recognize this policy.
Any idea what is going on?
The documentation you reference suggests that you get the policy id from ListPolicies or ListPoliciesForTarget operations, which is likely referencing the operations on the organizations service. The ID you took is from an IAM policy.
I am not completely familiar with the interactions between IAM and orgnaizations, but I imagine they are using different policy objects with different identifiers.

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!

Is it possible to query the AWS SDK to determine the IAM role for the current credentials?

I would like to be able to query the AWS SDK to check what the IAM role of the current credentials is. I want to check if I am running using a particular role, and if not, then try to assume that role.
Is it possible to do this? I am using the AWS SDK for JavaScript for node.js. In the AWS.config.credentials, I have access to my keys, but not to which role they belong.
I think the method you want is GetCallerIdentity on the STS (Security Token Service) API:
API reference
JS example
This returns either nice user info (if no role in effect):
{
Account: "123456789012",
Arn: "arn:aws:iam::123456789012:user/Alice",
UserId: "AKIAI44QH8DHBEXAMPLE"
}
or info on the temporary session/user and role (if a role is in effect):
{
Account: "123456789012",
Arn: "arn:aws:sts::123456789012:assumed-role/my-role-name/my-role-session-name",
UserId: "AKIAI44QH8DHBEXAMPLE:my-role-session-name"
}
As noted, IAM().GetUser() (to return info on the current user) only works in the first instance, if no role is assumed. It fails if there is a role, so code defensively, but it's worth considering as when no role is in effect it returns a nicely formatted objects (though you could just regex-parse the arn:aws:iam::(.*):user/(.*) ARN from the GetCallerIdentity):
{
User: {
Arn: "arn:aws:iam::123456789012:user/Bob",
CreateDate: <Date Representation>,
Path: "/",
UserId: "AKIAIOSFODNN7EXAMPLE",
UserName: "Bob"
}
}
I suspect GetUser fails when a role is used because from what I can tell you are allocated a temporary user, I could see it being problematic to revert that role-assumption on the server, which would be necessary in order to make GetUser work in that case. And in some cases (instance profiles?) I think there isn't any real user account to revert back to.
To get the username of a user based on a set of keys you can use:
var iam = new AWS.IAM();
iam.getUser().User.UserName;
The API docs give the full details.
To get the role arn of an instance you'd probably have to use the instance metadata API endpoint as there is no method available in the SDK.
This answer and this one give details on different ways to query instance metadata.
Using just the AWS CLI:
aws sts get-caller-identity
The AWS Security Token Service (STS) returns something like:
{
"UserId": "ABBBCCC123123DDDDEEEE",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/bob"
}
(the username is within the Arn value, after the last :)
I will provide example how to do it in AWS CLI and you can convert it into NodeJS code:
aws sts get-caller-identity
get ARN from the response and get the user name from there (everything that comes after user/)
aws iam list-groups-for-user --user-name UserNameFromPreviousResponse
Then for each group you can dive in to the policies that are builtin or attached to that group:
aws iam list-group-policies --group-name GroupName
aws iam list-attached-group-policies --group-name GroupName
from here you can dive in into the policies to get their ARN if needed but I believe at this level it already should satisfy your needs.