Search code examples
amazon-route53aws-cdk

Add cross account delegation to existing hosted zone


I can create a new hosted zone with cross account delegation like this

const parentZone = new route53.PublicHostedZone(this, 'HostedZone', {
  zoneName: 'someexample.com',
  crossAccountZoneDelegationPrincipal: new iam.AccountPrincipal('12345678901'),
  crossAccountZoneDelegationRoleName: 'MyDelegationRole',
});

This is pretty straightforward. But what if hosted zone already exist

const parentHostedZone = route53.PublicHostedZone.fromLookup(this, 'HostedZone', {
    domainName: 'someexample.com',
})

How to add delegation to this zone?


Solution

  • What those props do is just create a role that can be assumed in another account and used for adding records to the parent zone.

    The code is here:

    if (props.crossAccountZoneDelegationPrincipal) {
      this.crossAccountZoneDelegationRole = new iam.Role(this, 'CrossAccountZoneDelegationRole', {
        roleName: props.crossAccountZoneDelegationRoleName,
        assumedBy: props.crossAccountZoneDelegationPrincipal,
        inlinePolicies: {
          delegation: new iam.PolicyDocument({
            statements: [
              new iam.PolicyStatement({
                actions: ['route53:ChangeResourceRecordSets'],
                resources: [this.hostedZoneArn],
              }),
              new iam.PolicyStatement({
                actions: ['route53:ListHostedZonesByName'],
                resources: ['*'],
              }),
            ],
          }),
        },
      });
    }
    

    You can simply create this role and it will achieve the same thing.

    It would look like this:

    const crossAccountZoneDelegationRole = new iam.Role(this, 'CrossAccountZoneDelegationRole', {
        roleName: 'MyDelegationRole',
        assumedBy: new iam.AccountPrincipal('12345678901'),
        inlinePolicies: {
          delegation: new iam.PolicyDocument({
            statements: [
              new iam.PolicyStatement({
                actions: ['route53:ChangeResourceRecordSets'],
                resources: [parentZone.hostedZoneArn],
              }),
              new iam.PolicyStatement({
                actions: ['route53:ListHostedZonesByName'],
                resources: ['*'],
              }),
            ],
          }),
        },
      });
    

    Then, in another account, you just do the usual thing. From the docs:

    // import the delegation role by constructing the roleArn
    const delegationRoleArn = Stack.of(this).formatArn({
      region: '', // IAM is global in each partition
      service: 'iam',
      account: 'parent-account-id',
      resource: 'role',
      resourceName: 'MyDelegationRole',
    });
    const delegationRole = iam.Role.fromRoleArn(this, 'DelegationRole', delegationRoleArn);
    
    // create the record
    new route53.CrossAccountZoneDelegationRecord(this, 'delegate', {
      delegatedZone: subZone,
      parentHostedZoneName: 'someexample.com', // or you can use parentHostedZoneId
      delegationRole,
    });