I'm trying to create an IAM cross-account role following the example in https://repost.aws/knowledge-center/lambda-function-assume-iam-role. I want a central account (7935xxxxxxxxx) to be able to create a VPC association between a VPC in a workload account (6617xxxxxxxx) to a private hosted zone in the central account. The association can only be performed as though from the workload account. But I get this error:
"An error occurred (AccessDenied) when calling the AssociateVPCWithHostedZone operation: User: arn:aws:sts::6617xxxxxxxxx:assumed-role/AssumeFromCoreRole/cross_acct_lambda is not authorized to perform: route53:AssociateVPCWithHostedZone on resource: arn:aws:ec2:ap-southeast-2:6617xxxxxxxxx:vpc/vpc-0f37262673a5e9762 because no resource-based policy allows the route53:AssociateVPCWithHostedZone action"
I'm nor sure this error message is pointing me to the true problem as my understanding is that Route 53 doesn't have resource-based policies.
I've double-checked all my ducks are lined up:
- The workload account has a role that allows it to assume a role from the central account:
DNSACrossAccountRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: AssumeRole
Effect: Allow
Principal:
'AWS': !Sub 'arn:aws:iam::${CoreAccountID}:role/DNS-Automation-Factory-${Environment}'
Action: 'sts:AssumeRole'
RoleName: AssumeFromCoreRole
- The Lambda execution role in the central account allows the workload account to assume its role along with the necessary actions:
DNSAutomationRole:
Type: AWS::IAM::Role
Properties:
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSLambda_FullAccess
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: LambdaAssumeRole
Effect: Allow
Principal:
Service: 'lambda.amazonaws.com'
Action: 'sts:AssumeRole'
RoleName: !Sub DNS-Automation-Factory-${Environment}
Policies:
- PolicyName: 'work-with-private-hosted-zone'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- route53:CreateVPCAssociationAuthorization
- route53:CreateHostedZone
- route53:AssociateVPCWithHostedZone
- ec2:DescribeVpcs
Resource: '*'
- Sid: AllowCrossAccountAccess
Effect: Allow
Action:
- 'sts:AssumeRole'
Resource: arn:aws:iam::6617xxxxxxxxx:role/AssumeFromCoreRole
- The Python client code calls STS to assume the role to execute the API call:
def cross_account_client():
sts_connection = boto3.client('sts')
acct_b = sts_connection.assume_role(
RoleArn="arn:aws:iam::6617xxxxxxxxx:role/AssumeFromCoreRole",
RoleSessionName="cross_acct_lambda"
)
ACCESS_KEY = acct_b['Credentials']['AccessKeyId']
SECRET_KEY = acct_b['Credentials']['SecretAccessKey']
SESSION_TOKEN = acct_b['Credentials']['SessionToken']
# create service client using the assumed role credentials, e.g. S3
client = boto3.client(
'route53',
aws_access_key_id=ACCESS_KEY,
aws_secret_access_key=SECRET_KEY,
aws_session_token=SESSION_TOKEN,
)
return client
Then, I use it this way:
r53_cross_account_role_client = cross_account_client()
try:
logger.info('Calling associate_vpc_with_hosted_zone')
r53_cross_account_role_client.associate_vpc_with_hosted_zone(
HostedZoneId=phz_id,
VPC={
'VPCRegion': aws_region,
'VPCId': workload_vpc_id
}
)
But I must be missing something obvious. Has anyone else come across the same?
If I am reading this correctly, I think you have reverse relation between roles. Specifically, you mentioned that you want workload account to assume role in central account, but then your workload role is defined as:
Which does the opposite - it allows core account to assume it, not the other way around. If you want your workload role to be able to assume core account you need to use
Policies, notAssumeRolePolicyDocument. As per documentation,AssumeRolePolicyDocumentspecified who can assume this role.