The Confusing assumeRole and Trust Policy
The IAM Role, IAM User, Trust Relationship, Trust… I initially thought I only needed to understand the basic units like Users, Roles paired with Policies, which seemed simple and easy to get. But then I found more abstract terms like assumeRole and Trust policy, so I'm writing this article to help me remember these concepts.
TL;DR
assumeRole is useful in situations where you don't want to specify users or list a bunch of access permissions for S3. Instead, you only allow users with assumeRole permission, and those who meet the assumeRole requirements get temporary access.
Just like…
Instead of giving everyone a permanent pass, it's better to let anyone have a chance to see if they qualify and get a temporary pass. And this pass has a time limit too, so it will expire automatically when you're done using it.
Or…
- Even if you're on the guest list (trust policy)
- You still need the actual invitation (user or resource policy) to get in
Trusted Policy

IAM Role with Trust Policy
- A Role is just a collection of permission definitions
- Roles are used by other entities (like Users)
In simple terms, it defines who (principal) I trust to assume my role
When you create a Role, there's a Trust Relationship tab that won't be empty.
For example, the basic AWSServiceRoleForECS:
This code means: ECS service is a trusted entity/unit that can assume this role.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Or you can also customize it, like appleRole:
This code means: Not only can AWS services be Principals, but the Principal field can also include external entities or other AWS accounts.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
// Within AWS: other users or other AWSaccounts
"arn:aws:iam::ACCOUNT-ID-1:user/username1",
"arn:aws:iam::ACCOUNT-ID-2:root",
"arn:aws:iam::ACCOUNT-ID-3:role/some-role",
// or use array is fine
["arn:aws:iam::ACCOUNT-ID-4:user/*"] // all users under spec account
],
// Outside AWS: through OIDC
"Federated": [
"cognito-identity.amazonaws.com", // AWS Cognito
"accounts.google.com", // Google
"graph.facebook.com", // Facebook
"www.amazon.com" // Amazon
],
// for aws services
"Service": [
"lambda.amazonaws.com",
"ec2.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
Required IAM User Permissions
What roles can I assume? This is defined in the Resource
Just being mentioned in the Role's Principal isn't enough - I still need to declare in my policy that "I'm allowed to assume certain roles"
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::ACCOUNT-ID:role/appleRole"
}
]
}
When I need to do something, like accessing S3, I first need to get a temporary pass, with controllable access duration.
S3 Bucket Policy
Depending on the situation:
- If the IAM Role itself has S3-related permissions
- No need to specify in S3 Bucket Policy, Bucket Policy can be empty
- If Bucket Policy exists, it needs to explicitly allow that role like this:
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::ACCOUNT-ID:role/appleRole" }, "Action": ["s3:GetObject", "s3:ListBucket"], "Resource": [ "arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*" ] }] }
Benefits of this design
You do not have to distribute or embed long-term AWS security credentials with an application.
You can provide access to your AWS resources to users without having to define an AWS identity for them. Temporary credentials are the basis for roles and identity federation.
… After temporary security credentials expire, they cannot be reused. You can specify how long the credentials are valid, up to a maximum limit.
code
// Import the AWS SDK const AWS = require('aws-sdk'); // Create an STS client const sts = new AWS.STS(); // Parameters for assume role operation const params = { RoleArn: 'arn:aws:iam::ACCOUNT_ID:role/S3AccessRole', RoleSessionName: 'S3AccessSession', DurationSeconds: 3600 // Set explicit duration - 1 hour (can be 900-43200 seconds) }; sts.assumeRole(params, (err, data) => { const credentials = data.Credentials; // Configure AWS to use the temporary credentials const s3 = new AWS.S3({ accessKeyId: credentials.AccessKeyId, secretAccessKey: credentials.SecretAccessKey, sessionToken: credentials.SessionToken }); // Now you can use the S3 client with the temporary credentials // For example, list buckets s3.listBuckets((err, data) => { if (err) { console.error('Error: ', err); } else { console.log('Buckets:', data.Buckets); } }); });
https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html