Enterprise Cloud Consultancy in The UK and Europe

Allow Quic IPs

Background

If you use using Cloudflare as a Domain Name Server (DNS) and Web Application Firewall (WAF) and Quic.cloud as a Content Delivery Network (CDN) then you need to add Quic set of IP Addresses to the whitelist on Cloudflare. There are 134 IP addresses to add and these are located on a URL on the quic.cloud website

The Cloudflare screen whitelist IPs this does not allow bulk entry so it would be time consuming and potentially error prone to add each IP address one at a time.

Prototype Solution

I created a code snippet in PowerShell to open the IP lists file, then read the IP addresses then loop through the list using the Cloudflare API to add the IP address. For security you need an API token which was easy to create on Cloudflare and it was just a matter of working out what permissions I needed to set up for the token for the request to be authorized. There was a a bit of a challenge working how to run curl from a PC however I quickly found Invoke-WebRequest and the problem was solved. It did run quite slowly take about 120 seconds as it was establishing a new session for each call

This solution was fine for me but was not shareable. The next step to rewrite the function in python.

Python Solution

Next, I needed a development environment for my PC and I decided on PyCharm. This gave me basic debugging and test capabilities. The json and requests python libraries were required to handle the API calls to quic.cloud endpoints. I used requests.session to set up the headers with the authorisation token and the Cloudflare email address so the same connection is used for each call. This reduced the run time to a few seconds. Now it was working it was time to move it to AWS Lamdba

AWS Lambda Solution

I created a AWS Lamdba called AllowQuicIPs and dropped main.py file source file and I added the lambda handler which is parameterised wih an event and the context objects. It is the event which include the 3 input parameters: the Cloudflare API token, the Cloudflare Account email address and the Cloudflare zone ID on which the IP addressed will be whitelisted. This JSON response is of specific format required by the Amazon API Gateway containing statusCode with a HTTP status and body with additional information such as a message

def lambda_handler(event, context):
    res = {
        "statusCode": 200,
        "body": "",
        "headers": {
            "Content-Type": "application/json",
            "Access-Control-Allow-Origin": "*"
        }
    }

    if event.api_token & event.account_email & event.zone_id:
        source_ips = set_source(False)
        response = allow_ips(source_ips,
                     event.api_token,
                     event.account_email,
                     '',
                     event.zone_id)
        res['statusCode'] = response['statusCode']
        res['body'] = response['message']
    else:
        res['statusCode'] = 400
        res['body'] = "Bad request with missing parameters"

    return res

As regards the import of the depenent python json and requests libraries, these are added to a deployment package and this is saved on Amazon S3 as a ZIP file and referenced as a layer on the Code tab.
For testing, I used the AWS Lamdba Test tab with AWS Lambda to pass the parameters to the lamdba and verify it still works.

Exposing an API using AWS API Gateway

With API Gateway you can set up both HTTP APIs and REST APIs. For this case, the simpler and cheaper HTTP API is preferred. This allows use of API keys and Lambda authorizers so it is adequate for our purposes.

This step involves setting up the HTTP API and passing parameters through to the Lamdba functions. If the JSON response

I also set up Cross Origin Resource Sharing (CORS) such that the request is only accepted from this domain.

Lambda Authorizer

The Lambda authorizer provides another layer of security. The request is passed to the authorizer and the authorizer return the “authorized” result as true or false. For this I have an service API_Key sent in the headers and then the authorizer compares this to a production stage variable of the same name. Only f they match then the function is authorized to proceed.

Developing the Client Form

I used a Gravity Forms to build the web form to prompt the user for the API token, account email and zone ID. Gravity Forms stores the form entryvin the WordPress database by default so I had to nobble it such that nothing is stored. I am using the pre-submission hook to make the API call, on return it skips saving the form and just takes the user to a confirmation page which displays the result of the API calls.