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.