4
votes

I have VPC peering to connect to a lambda in one aws account to a RDS instance in another aws account. This works fine but required the VPC peering to have DNS resolution option enabled.

By default DNS resolution is set to : DNS resolution from accepter VPC to private IP :Disabled.

This can be done via the AWS console and the CLI. I am not able to achieve the same using AWS CDK.
https://docs.aws.amazon.com/vpc/latest/peering/modify-peering-connections.html

The CfnVPCPeeringConnection does not seem to have this option. https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-ec2.CfnVPCPeeringConnection.html

Is there any other way of achieving this via CDK ?

  const cfnVPCPeeringConnection :CfnVPCPeeringConnection  =
    new CfnVPCPeeringConnection(
        stack,
        "vpcPeeringId",
        {
            peerVpcId : "<vpcId of acceptor account>",
            vpcId :  "<reference of the Id>",
            peerOwnerId : "<aws acc number>",
            peerRegion : "<region>",
            peerRoleArn :"<arn created in the acceptor account>"",
        }
    );
    
    //update route tables
    rdsConnectorVpc.isolatedSubnets.forEach(({ routeTable: { routeTableId } }, index) => {
        new CfnRoute(this.parentStack, 'PrivateSubnetPeeringConnectionRoute' + index, {
            destinationCidrBlock: '<CIDR>',
            routeTableId,
            vpcPeeringConnectionId: cfnVPCPeeringConnection.ref,
        })
    });
1

1 Answers

2
votes

You can use a CustomResource Construct in AWS CDK to achieve it:

import * as cdk from "@aws-cdk/core";
import ec2 = require("@aws-cdk/aws-ec2");
import iam = require("@aws-cdk/aws-iam");
import { AwsCustomResource, AwsCustomResourcePolicy, AwsSdkCall, PhysicalResourceId } from "@aws-cdk/custom-resources";
import { RetentionDays } from "@aws-cdk/aws-logs";

export interface AllowVPCPeeringDNSResolutionProps {
    vpcPeering: ec2.CfnVPCPeeringConnection,
}

export class AllowVPCPeeringDNSResolution extends cdk.Construct {

    constructor(scope: cdk.Construct, id: string, props: AllowVPCPeeringDNSResolutionProps) {
        super(scope, id);

        const onCreate:AwsSdkCall = {
            service: "EC2",
            action: "modifyVpcPeeringConnectionOptions",
            parameters: {
                VpcPeeringConnectionId: props.vpcPeering.ref, 
                AccepterPeeringConnectionOptions: {
                    AllowDnsResolutionFromRemoteVpc: true,
                },
                RequesterPeeringConnectionOptions: {
                    AllowDnsResolutionFromRemoteVpc: true
                }
            },
            physicalResourceId: PhysicalResourceId.of(`allowVPCPeeringDNSResolution:${props.vpcPeering.ref}`)
        };
        const onUpdate = onCreate;
        const onDelete:AwsSdkCall = {
            service: "EC2",
            action: "modifyVpcPeeringConnectionOptions",
            parameters: {
                VpcPeeringConnectionId: props.vpcPeering.ref, 
                AccepterPeeringConnectionOptions: {
                    AllowDnsResolutionFromRemoteVpc: false,
                },
                RequesterPeeringConnectionOptions: {
                    AllowDnsResolutionFromRemoteVpc: false
                }
            },
        };

        const customResource = new AwsCustomResource(this, "allow-peering-dns-resolution", {
            policy: AwsCustomResourcePolicy.fromStatements([
                new iam.PolicyStatement({
                    effect: iam.Effect.ALLOW,
                    resources: ["*"],
                    actions: [
                        "ec2:ModifyVpcPeeringConnectionOptions",
                    ]
                }),
            ]),
            logRetention: RetentionDays.ONE_DAY,
            onCreate,
            onUpdate,
            onDelete,
        });

        customResource.node.addDependency(props.vpcPeering);

    }
}

and use it like this:

[...]

const peerConnection = new ec2.CfnVPCPeeringConnection(this, "peerConnection", {
    vpcId: destinationVPC.vpcId,
    peerVpcId: lambdaVPCToDestinationVPC.vpcId,
});

new AllowVPCPeeringDNSResolution(this, "peerConnectionDNSResolution", {
    vpcPeering: peerConnection,
});

[...]