Search code examples
amazon-web-servicesaws-lambdaamazon-iamaccess-control

AWS: Cross account access fails with not authorized to access this resource


I'm trying to set up cross account access in AWS. I'd like to access the parent account from a sub account. This is what I've done so far:

Parent Account:

Created a new role test_role and gave it full admin access. This is the trust policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::{sub_account_id}:root",
                ]
            },
            "Action": "sts:AssumeRole",
            "Condition": {}
        }
    ]
}

Sub Account:

I have a lambda that should be able to access the parent account. This is the lambda policy.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "route53:*"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::{parent_account_id}:role/test_role",
            "Effect": "Allow"
        }
    ]
}

When the lambda attempts to do something in the parent account (Route53-related actions), I'm getting the following exception:

User: arn:aws:sts::{sub_account_id}:assumed-role/{lambda_role_name}/{lambda_name} is not authorized to access this resource

Where am I making a mistake?


Solution

  • It appears your situation is:

    • A Parent AWS Account that has test_role, which permits the calling of AssumeRole from the Sub-Account
    • A Sub-Account with an AWS Lambda function.
    • The Lambda function has an IAM Role that permits calling AssumeRole on test_role in the Parent account, and can also call any Route 53 command.

    Your Lambda function will be automatically provided credentials from the IAM Role associated with the Lambda function.

    If you wish to access Route 53 in the sub-account, then you can simply make make API calls (eg ChangeResourceRecordSetsAsync).

    However, if you wish to access Route 53 in the Parent account, then your Lambda function will need to:

    • Add Route 53 permissions to test_role so that any code that assumes the role will have permission to access Route 53
    • Remove the Route 53 permissions from the Lambda function's IAM Role since that won't be used
    • Call AssumeRole()
    • Take the returned set of credentials and use them to create a new AWS session
    • Use those new session credentials to call Route 53. These requests will be sent to the Parent account.

    To explain... When accessing resources of the Parent account, the code will need credentials associated with the Parent account. This is what calling AssumeRole() provides -- it returns a new set of credentials associated with the Parent account. Your code when then use those credentials to access resources in the Parent account, using whatever permissions were assigned to test_role. The Route 53 permissions are not required in the Lambda IAM Role because those credentials will only be used to call AssumeRole() and won't be used to call Route 53.