"""
Update an AWS IP set with the the top 10 IP addresses from Apache logs
"""
import sys
import re
import boto3
from collections import Counter
from tabulate import tabulate

def get_top_n_ip_addresses(num):
    """
    Parses apache logs to find the top n X-Forwarded-For ip addresses
    """
    all_ip_addresses = []

    with open('/var/log/httpd/access_log') as content:
        for line in content:
            # the first "cell" surrounded with brackets is the X-Forwarded-For
            regex = re.search(r'\((.*?)\)', line)
            if regex:
                # format is X-Forwarded-For: client, proxy1, proxy2
                # we want the right most IP, the IP that hit cloudfront
                forwarded_for = re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', regex.group(0))
                if forwarded_for:
                    all_ip_addresses.append(forwarded_for[-1])

    return Counter(all_ip_addresses).most_common(num)

def main():
    """
    Grab top 10 X-Forwarded-For ip addresses and send to a WAF ip list
    """
    top_ip_addresses = get_top_n_ip_addresses(10)

    print
    print "Top 10 IP Addresses"
    print "==================="
    print
    print tabulate(top_ip_addresses, headers=["IP", "Count"])
    print

    updates_list = [{
        'Action': 'INSERT',
        'IPSetDescriptor': {
            'Type': 'IPV4',
            'Value': "%s/32" % ip[0]
        }
    } for ip in top_ip_addresses]

    waf = boto3.client('waf')
    waf_ip_sets = waf.list_ip_sets(
        Limit=100
    )['IPSets']

    if len(waf_ip_sets) < 1:
        sys.exit('WAF IP sets appear to be misconfigured.  Expecting 1 IP set.')

    waf_ip_set_id = waf_ip_sets[0]['IPSetId']
    print "Updating IP set: ", waf_ip_sets[0]['Name']

    waf.update_ip_set(IPSetId=waf_ip_set_id,
                      ChangeToken=waf.get_change_token()['ChangeToken'],
                      Updates=updates_list)

    print "Done!"

if __name__ == "__main__":
    main()