Skip to content

Instantly share code, notes, and snippets.

@lexffe
Last active May 6, 2020 08:27
Show Gist options
  • Save lexffe/71b47e0c6351d9045db66db592da2ae8 to your computer and use it in GitHub Desktop.
Save lexffe/71b47e0c6351d9045db66db592da2ae8 to your computer and use it in GitHub Desktop.
Create DigitalOcean cloud firewall with Cloudflare IP populated.
#!/usr/bin/env python3
'''
This script
1. creates a DigitalOcean cloud firewall with incoming connection from Cloudflare allowed. (80/tcp, 443/tcp, 3012/tcp)
2. requires urllib3.
3. is non-interactive. You must edit this file for the variables.
4. is not production ready. (I honestly don't know.)
License: MIT
'''
from typing import List
import urllib3
import json
# const, env var
CF_DOMAIN = "www.cloudflare.com"
DO_ENDPOINT = "api.digitalocean.com"
FIREWALL_NAME = "CF-re"
DO_TOKEN = "aabbccddeeff"
# memory
cidr: List[str] = []
# fetch cf ips
cf_https = urllib3.HTTPSConnectionPool(CF_DOMAIN)
res = cf_https.request('GET', '/ips-v4')
if res.status != 200:
raise ConnectionError("failed to get from CF")
raw_ips: bytes = res.data
cidr.extend(list(map(lambda x: x.decode('ascii'), raw_ips.split())))
res = cf_https.request('GET', '/ips-v6')
if res.status != 200:
raise ConnectionError("failed to get from CF")
raw_ips: bytes = res.data
cidr.extend(list(map(lambda x: x.decode('ascii'), raw_ips.split())))
cf_https.close()
# post to DO
do_https = urllib3.HTTPSConnectionPool(DO_ENDPOINT)
req_body = json.dumps({
'name': FIREWALL_NAME,
'inbound_rules': [
{
'protocol': 'tcp',
'ports': '80',
'sources': {
'addresses': cidr
}
},
{
'protocol': 'tcp',
'ports': '443',
'sources': {
'addresses': cidr
}
},
{
'protocol': 'tcp',
'ports': '3012',
'sources': {
'addresses': cidr
}
}
]
}).encode('utf-8')
res: urllib3.HTTPResponse = do_https.request('POST', '/v2/firewalls', body=req_body, headers={"Content-Type": "application/json", "Authorization": "Bearer " + DO_TOKEN})
if res.status == 409: # None Conflict
print('Firewall with the name', FIREWALL_NAME, 'already exists.')
if res.status > 299 or res.status < 200:
raise ConnectionError("failed to post to DO", res.status, res.msg, res.reason)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment