fbpx

How exactly to relate IAM role action to corporate identity

AWS Security Token Service (AWS STS) now offers customers the ability to specify a unique identity attribute for their workforce identities and applications when they assume an AWS Identity and Access Management (IAM) role. This new SourceIdentity attribute makes it easier for you, as an Amazon Web Services (AWS) administrator, to determine the identity that performed the actions while the role was assumed. In this post, I’ll show you how to use the SourceIdentity attribute and how it can help you track usage of your APIs.

The source identity capability means &lt that when you view;a href=”http://aws.amazon.com/cloudtrail” target=”_blank” rel=”noopener noreferrer”>AWS CloudTrail logs, you can more see which identity is responsible for performing a particular action quickly. For example, you can request that all workforce identities in your company set their user name as the source identity when they assume an IAM role. CloudTrail shall log activity that is performed by that role, and when you view logs, you can rely on the user name to identify who is responsible for the action taken while the role was assumed. AWS also persists the source identity information if the workforce identity then assumes a different IAM role during the same session. Assuming a second role while in the first role’s session is called &lt still;a href=”https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html” target=”_blank” rel=”noopener noreferrer”>role chaining.

 

Previously, AWS administrators were required to set up a complex infrastructure to identify who was responsible for API actions performed while assuming an IAM role. This was difficult to manage and maintain, because it required multiple AWS Lambda functions, Amazon Simple Notification Service (Amazon SNS) topics, and an Amazon DynamoDB database to house and compare IAM access keys across many CloudTrail logs. This was the only method available to determine which identity assumed an IAM role and performed actions in an account. With the new SourceIdentity attribute, administrators can now either require developers to define a source identity when they assume an IAM role, or to specify in their identity provider (IdP) to be included when federating. And this attribute is found in most CloudTrail logs, which makes determining the original identity that assumed the role that much easier.

 

Use the SourceIdentity attribute

 

In order for the workforce identity or application to be able to define their source identity when they assume IAM roles, you must grant them permission for the &lt first;span>sts:SetSourceIdentity action. This will permit the workforce application or identity to set the source identity themselves without need for manual intervention. In addition to this permission, the AWS administrator can add a condition statement for the &lt also;span>sts:SourceIdentity key to a role’s trust policy, that would require the workforce identity to set their source identity when they assume the role. By setting this condition as a requirement, you enforce the setting of the SourceIdentity attribute, which allows for easier identification through CloudTrail logs. Let’s see how this new attribute can be used in a few different use cases.

 

Use the SourceIdentity attribute with identity federation

 

With the creation of the SourceIdentity condition and attribute, there also comes a parameter that can be passed when federation is used to assume a role. When the source is used by you identity attribute, the role trust policies for all roles that are connected to the &lt must be had by the IdP;span>sts:SetSourceIdentity permission. The AssumeRole operation will fail for any role connected to an IdP that is passing the source identity attribute without this permission. When you use IdPs to grant workforce identities access to AWS resources, you can define the source identity in the SAML Response XML file. The SAML Response XML file is then used to create an AWS session for the workforce identity to request access to AWS resources. To define the source identity in the SAML Response XML file, you must add the following snippet to the SAML assertion.

 

 

<Attribute Name="https://aws.amazon.com/SAML/Attributes/SourceIdentity">
 

UserNameDetail

  &lt Make sure to replace;em>UserNameDetail with the value that matches your use case. This could be an email address, user identity, or other value. Any identifying string can be used for this field. After the user authenticates to their IdP, a SAML assertion is returned that contains the user’s information, including the source identity set from the LDAP attribute you specified. This given information is sent to the AWS Single Sign-On (AWS SSO) endpoint, and in return the source identity that was passed is set as the value for the source identity parameter when the end user assumes the role.

 

 


 

“sub”: “johndoe”,
“aud”: “ac_oic_client”,
“jti”: “ZYUCeRMQVtqHypVPWAN3VB”,
“iss”: “https://example.com”,
“iat”: 1566583294,
“exp”: 1566583354,
“auth_time”: 1566583292,
“https://aws.amazon.com/source_identity”: ” UserNameDetail

 

 

 

After the role is assumed and the source identity set, the source identity cannot be changed for the duration of the assume role session. Even if the principal assumes another role during the same session then, the source identity shall carry over to the new role. In the event that the new role doesn’t have the sts:SetSourceIdentity permission, you will see an Access Denied error.

it is made by

This process convenient for you to identify source identity across role-chaining activities. Take a look at the following example CloudTrail event snippet. The SourceIdentity field is supplied in the event, which means that the principal can be identified by you making the API calls.

 

 

 "requestParameters": 
        "roleArn": "arn:aws:iam::111122223333:role/Developer_Role",
        "roleSessionName": "Session_Name",
        "sourceIdentity": "Admin"
    ,
 

 

 

This same information shall be included in every API call that is made, if the role assumes another role during the same session even.

 

Assume an IAM role

 

The SourceIdentity attribute can also be used with other types of role assumption. When you use any of the three Assume Role API operations ( AssumeRole , AssumeRoleWithSAML , or AssumeRoleWithWebIdentity ), you set a value for the –source-identity request parameter. Let’s look at a policy that’s associated to a user and go over each section.

 

 

 
    "Version": "2012-10-17",
    "Statement": [
        "Sid": "AssumeRole",
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::      <AccountId>      :role/Developer_Role"
    ,

        "Sid": "Set_AWSUserName_as_SourceIdentity",
        "Effect": "Allow",
        "Action": "sts:SetSourceIdentity",
        "Resource": "arn:aws:iam::      <AccountId>      :role/Developer_Role",
        "Condition": 
            "StringLike": 
                "sts:SourceIdentity": "$aws:username"



]

 

 

 

The first statement in the policy gives this user permission to call the sts:AssumeRole API and assume the Developer_Role IAM role. (You will need to replace the placeholder with your actual AWS account ID for the policy to be valid.)

 

 

 
            "Sid": "AssumeRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::            :role/Developer_Role"

 

 

The second portion of the policy is the most interesting. You’re granting permission for the sts:SetSourceIdentity API, as well as requiring it as a condition to complete the assume role request. In this full case, the condition states that the source identity must be set as the IAM user name in order to complete the request. If the user name isn’t passed as the source identity, the request to assume the Developer_Role role is denied.

 

 

 
            "Sid": "Set_AWSUserName_as_SourceIdentity",
            "Effect": "Allow",
            "Action": "sts:SetSourceIdentity",
            "Resource": "arn:aws:iam::            :role/Developer_Role",
            "Condition": 
                "StringLike": 
                    "sts:SourceIdentity": "$aws:username"

 

any string can be required by

The condition value of your choosing. This includes exact values such as an AWS user name or a predefined list of values. You can also set this condition in the trust policy of an IAM role, thus requiring the source identity from any principal that wants to assume the role. The command line interface (CLI) command to pass the SourceIdentity parameter when assuming a role would look similar to the following example.

 

 

 aws sts assume-role --role-arn arn:aws:iam::            :role/Developer_Role --role-session-name Audit --source-identity Admin
 

 

 

Identifying the API activity across this identity works like it did for federation just. Simply follow the source identity across the CloudTrail logs to see what API calls were performed. In the following example, a CloudTrail can be seen by you API call after a role was assumed through the AssumeRole API.

 

 

 "requestParameters": 
        "roleArn": "arn:aws:iam::111122223333:role/Developer_Role",
        "roleSessionName": "Session_Name",
        "sourceIdentity": "Admin"
    ,
 

 

 

Put the SourceIdentity attribute to work

 

Now that I’ve shown you how the new SourceIdentity attribute works, let’s follow it through some API calls to see how easy identifying the source identity shall be. In the first API call, you’ll perform the AssumeRole API operation to assume the Developer_Role .

 

 

 
    "eventVersion": "1.08",
    "userIdentity": 
        "type": "IAMUser",
        "principalId": "AIDACKCEVSQ6C2EXAMPLE",
        "arn": "arn:aws:iam::111122223333:user/user_1",
        "accountId": "111122223333",
        "accessKeyId": "AKIAIOSFODNN7EXAMPLE",
        "userName": "user_1"
    ,
    "eventTime": "2021-01-21T23:46:28Z",
    "eventSource": "sts.amazonaws.com",
    "eventName": "AssumeRole",
    "awsRegion": "global",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "aws-cli/1.18.216 Python/3.6.12 Linux/4.9.230-0.1.ac.223.84.332.metal1.x86_64 botocore/1.19.56",
    "requestParameters": 
        "roleArn": "arn:aws:iam::111122223333:role/Developer_Role",
        "roleSessionName": "Session_Name",
        "sourceIdentity": "Admin"
    ,
    "responseElements": 
        "credentials": 
            "accessKeyId": "ASIAIOSFODNN7EXAMPLE",
            "expiration": "Jan 22, 2021 12:46:28 AM",
            "sessionToken": "FwoGZXIvYXdzEDcaDJzPCaIgEdPDNCpwpiLNAUawkSIVuHDGLtDe1McHzt6lb9bb8aXA01Hu01P7IZz4tRIUWhC0hVCZtZV6vV11AvSy7x+8aCAchIJDSzM033UnJcn06OI7EZlCbM51EFjtdbVysj4ofYkPyQE0aLzz5TIO6YQ9QQI4/4GmZWMVlmnc3nJx9fAMmzcDslgBK2EgaCRN2SNMWdDqE/bd+nFuX/puyWhX1g6B3nCJ59wMaWEptyqWdmVun6YV5L1SDJB03qNj5TigIsKJl99CoP67SDdTm7gs9vOpbYVGEEgo1KSogAYyMt30kteqQ5ONKZ5RsjGhp3e4sMsww0ZLd/nSOEZfXPXvsTMxKoaCXEd7TzL5mGoXtYYY"
        ,
        "assumedRoleUser": 
            "assumedRoleId": "AROACKCEVSQ6C2EXAMPLE:Session_Name",
            "arn": "arn:aws:sts::111122223333:assumed-role/Developer_Role/Session_Name"
        ,
        "sourceIdentity": "Admin"
    ,
    "requestID": "dc4ecf82-c52e-4ac8-bd2f-2f854f017911",
    "eventID": "c632753c-5835-464d-91d6-b2d75dc8d7fc",
    "readOnly": true,
    "resources": [
        "accountId": "111122223333",
        "type": "AWS::IAM::Role",
        "ARN": "arn:aws:iam::111122223333:role/Developer_Role"

],
"eventType": "AwsApiCall",
"managementEvent": true,
"recipientAccountId": "111122223333",
"eventCategory": "Management"

 

 

 

Now that you’ve assumed the role and set your source identity attribute, let’s see what another API call log would look like. In this example, I’ll perform the ListRoles API call.

 

 

 
    "eventVersion": "1.08",
    "userIdentity": 
        "type": "AssumedRole",
        "principalId": "AROACKCEVSQ6C2EXAMPLE:Session_Name",
        "arn": "arn:aws:sts::111122223333:assumed-role/Developer_Role/Session_Name",
        "accountId": "111122223333",
        "accessKeyId": "ASIAIOSFODNN7EXAMPLE",
        "sessionContext": 
            "sessionIssuer": 
                "type": "Role",
                "principalId": "AROACKCEVSQ6C2EXAMPLE",
                "arn": "arn:aws:iam::111122223333:role/Developer_Role",
                "accountId": "111122223333",
                "userName": "Developer_Role"
            ,
            "webIdFederationData": ,
            "attributes": 
                "mfaAuthenticated": "false",
                "creationDate": "2021-01-21T23:46:28Z"
            ,
            "sourceIdentity": "Admin"
,
"eventTime": "2021-01-21T23:48:09Z",
"eventSource": "iam.amazonaws.com",
"eventName": "ListRoles",
"awsRegion": "us-east-1",
"sourceIPAddress": "AWS Internal",
"userAgent": "aws-cli/1.18.216 Python/3.6.12 Linux/4.9.230-0.1.ac.223.84.332.metal1.x86_64 botocore/1.19.56",
"requestParameters": null,
"responseElements": null,
"requestID": "99a23348-0f68-4ced-baab-e4282c320086",
"eventID": "88a02896-e1a4-4170-8f60-48f8009fc608",
"readOnly": true,
"eventType": "AwsApiCall",
"managementEvent": true,
"eventCategory": "Management",
"recipientAccountId": "111122223333"

 

 

see how the source identity attribute will follow the session

To, from this role you can perform the AssumeRole API call on another role, from this same session. You can see that log example following.

 

 

 {
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROACKCEVSQ6C2EXAMPLE:Session_Name",
        "arn": "arn:aws:sts::111122223333:assumed-role/Developer_Role/Session_Name",
        "accountId": "111122223333",
        "accessKeyId": "ASIAIOSFODNN7EXAMPLE",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "AROACKCEVSQ6C2EXAMPLE",
                "arn": "arn:aws:iam::111122223333:role/Developer_Role",
                "accountId": "111122223333",
                "userName": "Developer_Role"
            },
            "webIdFederationData": {
         },
        "attributes": {
            "mfaAuthenticated": "false",
            "creationDate": "2021-01-21T23:46:28Z"
        },
        "sourceIdentity": "Admin"
    }
},
"eventTime": "2021-01-21T23:49:38Z",
"eventSource": "sts.amazonaws.com",
"eventName": "AssumeRole",
"awsRegion": "us-east-1",
"sourceIPAddress": "AWS Internal",
"userAgent": "aws-cli/1.18.216 Python/3.6.12 Linux/4.9.230-0.1.ac.223.84.332.metal1.x86_64 botocore/1.19.56",
"requestParameters": {
    "roleArn": "arn:aws:iam::444455556666:role/Developer_Role_Admin",
    "roleSessionName": "Session_Name_Two",
    "sourceIdentity": "Admin"
}
 

 

 

 

And one final log example to showcase the further session continuance of the source identity attribute—in the following example, {you can see another API call log that uses the second role that is assumed.|another API can be seen by you call log that uses the second role that is assumed.}

 

 

 {
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROACKCEVSQ6C2EXAMPLE:Session_Name_Two",
        "arn": "arn:aws:sts::444455556666:assumed-role/Developer_Role_Admin/Session_Name_Two",
        "accountId": "444455556666",
        "accessKeyId": "ASIAIOSFODNN7EXAMPLE",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "AROAUYE7YFMOUKDGPBVHZ",
                "arn": "arn:aws:iam::444455556666:role/Developer_Role_Admin",
                "accountId": "444455556666",
                "userName": "Developer_Role_Admin"
            },
            "webIdFederationData": {},
            "attributes": {
                "mfaAuthenticated": "false",
                "creationDate": "2021-01-21T23:49:38Z"
            },
            "sourceIdentity": "Admin"
        }
    },
    "eventTime": "2021-01-21T23:51:52Z",
    "eventSource": "iam.amazonaws.com",
    "eventName": "ListPolicies",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "aws-cli/1.18.216 Python/3.6.12 Linux/4.9.230-0.1.ac.223.84.332.metal1.x86_64 botocore/1.19.56",
    "requestParameters": {
        "onlyAttached": false,
        "marker": "AAIY4mMzWCZE8V8dhsZEnIHXBxUGgrWryA010zyDtHD/XY0PVi3eIjDnN9YA3KYGgGwrD2SGquWm01a0vOqaIpot/n7KcDZppXPqU4TDflTyVA=="
    },
    "responseElements": null,
    "requestID": "5560e442-6c3b-431a-bf7e-9159a2d51f23",
    "eventID": "7b89c2b1-ff59-44d1-86ac-bc4487cd7b0a",
    "readOnly": true,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "eventCategory": "Management",
    "recipientAccountId": "444455556666"
}
 

 

 

Conclusion

 

In this post, I introduced you to the new AWS STS SourceIdentity attribute. {I showed you how to set up the attribute with federation to AWS resources,|You were showed by me how to set up the attribute with federation to AWS resources,} as well as through API calls like AssumeRole , AssumeRoleWithSAML , and AssumeRoleWithWebIdentity . I supplied CloudTrail logs to show how the source identity will appear in logs and provided multiple logs over one session to demonstrate the continuance of the source identity attribute. {You can now use this attribute to more easily identify identity and API usage across role sessions.|You can now use this attribute to more identify identity and API usage across role sessions easily.} Test it out for yourself by using the CLI to set the SourceIdentity when assuming an IAM role.

 

If you have feedback about this post, submit comments in the Comments section below. If you have questions about this post, start a new thread on the AWS IAM forum or contact AWS Support .

 

Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter .