How to obtain the IP Addresses of a Network Load Balancer in CloudFormation

Cloud Migration Scenarios

Four scenarios to migrate to AWS – from infrastructure to ML

In order for the network load balancer to execute a Health Check, you need to create
a security group using the IP addresses of the load balancer.
Unfortunately, you cannot obtain the ip addresses of the load balancers in CloudFormation.
This forces you to grant access to the entire VPC CIDR or the relevant subnet CIDRs in which
the load balancer is deployed.

With this custom CloudFormation Provider you can obtain the actual private ip addresses of the
load balancers, allowing you to create a security group to explicitly grant access
to a specific load balancer.

How do get the IP addresses of a Load Balancer?

It is quite easy: you specify a CloudFormation resource of the Custom::LBIpAddresses, as follows:

  LBIpAddresses:
    Type: Custom::LBIpAddress
    Properties:
      LoadBalancerArn: !Ref NetworkLoadBalancer
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-lb-ip-address-provider'

Outputs:
  PrivateIpAddresses:
    Type: String
    Value: !Ref LBIpAddresses.PrivateIpAddresses
      

The IP addresses of the Load Balancer are returned as the PrivateIpAddresses attribute. It is an array of IP addresses in /32 CIDR notation. You may use these values to create a security group as shown below:

  LoadBalancerHealthCheckSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      Groupcontent: !Sub 'load balancer'
      VpcId: !Ref 'VPC'
      SecurityGroupIngress:
        - content: lb health check
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Select [ 0, !GetAtt 'Ips.PrivateIpAddresses']
        - content: lb health check
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Select [ 1, !GetAtt 'Ips.PrivateIpAddresses']
        - content: lb health check
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Select [ 2, !GetAtt 'Ips.PrivateIpAddresses']
      Tags:
        - Key: Name
          Value: !Sub 'load balancer health checks'

Caveats

This resource depends on the informal link between the Load Balancer and the Network Interface based on the name of the content in the network interface. If AWS changes this, this provider will break.

Installation

To install this custom resource, type:

aws cloudformation create-stack \
 --capabilities CAPABILITY_IAM \
 --stack-name cfn-lb-ip-address-provider \
 --template-body file://cloudformation/cfn-lb-ip-address-provider.json 

aws cloudformation wait stack-create-complete  --stack-name cfn-lb-ip-address-provider 

This CloudFormation template will use our pre-packaged provider from s3://binxio-public-${AWS_REGION}/lambdas/cfn-lb-ip-address-provider-0.2.5.zip.

Demo

To install the simple sample of the Custom Resource, type:

VPC_ID=$(aws ec2  --output text --query 'Vpcs[?IsDefault].VpcId' describe-vpcs)
SUBNET_IDS=$(aws ec2 --output text --query 'RouteTables[?Routes[?GatewayId == null]].Associations[].SubnetId' describe-route-tables --filters Name=vpc-id,Values=$VPC_ID | tr '\t' ',')
aws cloudformation create-stack --stack-name cfn-lb-ip-address-demo \
 --template-body file://cloudformation/demo-stack.yaml \
 --parameters "ParameterKey=VPC,ParameterValue=$VPC_ID"  \
          "ParameterKey=Subnets,ParameterValue=\"$SUBNET_IDS\""
aws cloudformation wait stack-create-complete  --stack-name cfn-lb-ip-address-demo

Conclusion

With this custom CloudFormation Provider you can create security groups which allow the Network Load Balancer to perform the health checks, without opening the port up to the whole VPC CIDR. You can use the exact ip addresses of that load balancer.

Mark van Holsteijn is a senior software systems architect, and CTO of binx.io. He is passionate about removing waste in the software delivery process and keeping things clear and simple.
Share this article: Tweet this post / Post on LinkedIn