In last week, I was playing with cross-account IAM roles to achieve key-less job executions in our amazon web services environment. As a security prospective, IAM role is better option over aws keys as there is no need of aws keys ,awscli or s3cmd to access aws services. With proper use of IAM roles in environment, we can access/execute aws related resources without risk of loosing sensitive information due to leak of aws keys.
IAM roles can be created for providing access to services on local aws account to users/instance profiles on local account or cross-account. Cross account is either managed by you or third party. Providing cross account access means creating a trust between local account and other account so that other account can assume the particular role and use it for accessing services from origin account. For more information on roles, refer here
But there is a always a small loophole in every fine solution. As per theory, When you create a cross-account Iam role and pass it with instance-profile role , a instance should be launched using same instance-role and should be able to access services permitted by instance role. But practically, I would say it works, but partially. Lets take a look at similar scenario which I was trying to fix.
- Two aws accounts : XXXXXXX1234, XXXXXXX4567
- Services to be shared from XXXXXXX123 : s3-test-bucket, full access to ec2
- Instance profile role on XXXXXXX4567 : test-inst-role
In short, instance created using test-instance-role should be able to access s3 bucket and ec2 services on the account XXXXXXX123. So on XXXXXXX1234 account, a cross-account role “s3-ec2-access” is created like below,
Trust relationship
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::XXXXXXX4567:root" }, "Action": "sts:AssumeRole" } ] }
so that services on XXXXXXX4567 can assume s3-ec2-access.
and Iam policies attached as below,
s3-ec2-access
{ "Version": "2012-10-17", "Statement": [ { "Action": "ec2:*", "Effect": "Allow", "Resource": "*" }, . . . ], "Statement": [ { "Effect": "Allow", "Action": "s3:ListAllMyBuckets", "Resource": "arn:aws:s3:::*" }, { "Effect": "Allow", "Action": "s3:*", "Resource": [ "arn:aws:s3:::s3-test-bucket", "arn:aws:s3:::s3-test-bucket/*" ] } ] }
And on account XXXXXXX4567, a instance role “test-instance-role” is created like below,
Trust policy
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
And policies attached,
s3-assume-role
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::XXXXXXX1234:role/s3-ec2-access" }], "Statement": [{ "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "*" }] }
A instance is launched using instance role “test-instance-role”
I used awscli to access permitted aws services on this instance and I faced below problems,
- Instance was able to list permitted s3 bucket but could not download or upload from/to bucket.
- Instance was not able to perform any of the ec2 operation on permitted account.
I tried to troubleshoot in every way but I was getting same errors each time. Finally I decided to log a case with aws support and they are still working on fixing this issue. As of now, awscli has no way to identify permissions passed by cross-account role.
Meanwhile, I continued troubleshooting this issue and after going through several aws documents, I found that this issue can be temporarily solved by temporary access keys provided by simple commands. More information can be found at here
I created a simple series of command line which can be run on instance and access cross account permitted services.
aws sts assume-role --role-arn arn:aws:iam::XXXXXXX1234:role/s3-ec2-access- --role-session-name "RoleSession1" | grep -w 'AccessKeyId|SecretAccessKey|SessionToken' | awk '{print $2}' | sed 's/"//g;s/,//' > awscre;export AWS_ACCESS_KEY_ID=`sed -n '3p' awscre`;export AWS_SECRET_ACCESS_KEY=`sed -n '1p' awscre`;export AWS_SECURITY_TOKEN=`sed -n '2p' awscre`
It creates temporary access/security keys and exports it. And now awscli would produce as expected results.
You can un-export variables by
unset AWS_ACCESS_KEY_ID ;unset AWS_SECRET_ACCESS_KEY;unset AWS_SECURITY_TOKEN
so that instance can set back to use original instance role.
You can contact us at any time if you need assistance with AWS Cross-account service access. We can also help you implement AWS DevOps.