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,AssumeRolePolicyDocument
specified who can assume this role.