PaloAltoNetworks / aws-elb-autoscaling

Auto Scaling VM-Series firewalls in AWS
http://live.paloaltonetworks.com/cloudtemplate
58 stars 64 forks source link

firewall template doesn't pick up unassociated EIP in 1.2.1 template #16

Open PerryKuhnen opened 6 years ago

PerryKuhnen commented 6 years ago

When testing the classic ELB 1.2.1 template there is a significant issue of the add_eni lambda not picking up unassociated EIPs. To empirically replicate the problem I first deployed the template with 3 AZ and no NAT gateway. After deployment it works just fine and 3 EIP are created because zero were allocated. Delete the stack and repeat. Now we have 6 EIP and only 3 are associated with the firewall interface. Delete the stack again and repeat. Now we have 9 EIP and yet only 3 are associated. To observe the erroneous behaviour, create however many EIP allowed in your VPC. In my case that's 10 for us-east-1. Once I deploy the classic ELB 1.2.1 template with no nat gateway and I have 10 allocated (max) EIPs everything goes haywire. Firewalls get created and shutdown immediately. This should not happen because the 10 EIP are allocated to the VPC but they are NOT associated to any ENI or instance. There is a function in in add_eni called getUnassociatedAddress. This is supposed to retrieve any EIPs that are not ASSOCIATED with any instances or ENIs.

However, this function is the problem. It looks for the AllocationId not the AssociationID. Of course free existing EIPs are ALLOCATED to the VPC but not ASSOCIATED with any instance or ENI. Therefore any EIP that are available in the VPC will not be picked up. Instead the lambda will allocate a new EIP. This is a huge problem as it requires my customer to release all EIPs from the VPC manually and have the lambda allocate new ones.

def getUnassociatedAddress(eip_list): fail = {'PublicIp': 'None', 'Domain': 'vpc', 'AllocationId': 'None'} logger.info("Trying to find and eip that is not associated") logger.info(eip_list) for eip_iter in eip_list['Addresses']:

is the public ip address associated with an instance id, if so don't use it

    logger.info('eip_iter is as follows:')
    logger.info(eip_iter)
    if "InstanceId" not in eip_iter:
        if "**AllocationId**" not in eip_iter: <----- looking for the AllocationID not AssociationID
            address = eip_iter['PublicIp']
            if address:
                return  eip_iter
return None