2023-03-26 23:16:26 +01:00
|
|
|
import os
|
2023-08-01 04:39:12 +01:00
|
|
|
import pathlib
|
|
|
|
|
2023-03-20 18:40:08 +00:00
|
|
|
import requests
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
|
2023-08-01 04:39:12 +01:00
|
|
|
class Config:
|
|
|
|
def __init__(self, token, account_id):
|
|
|
|
# Set token using setter
|
|
|
|
self.token = token
|
|
|
|
if account_id is None:
|
|
|
|
raise ValueError("No account ID provided")
|
|
|
|
|
|
|
|
@property
|
|
|
|
def token(self):
|
|
|
|
return self._token
|
|
|
|
@token.setter
|
|
|
|
def token(self, token):
|
|
|
|
if token is None:
|
|
|
|
raise ValueError("No token provided")
|
|
|
|
else:
|
|
|
|
url = 'https://api.cloudflare.com/client/v4/user/tokens/verify'
|
|
|
|
headers = {
|
|
|
|
'Authorization': f'Bearer {token}',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
}
|
|
|
|
response = requests.get(url, headers=headers, timeout=10)
|
|
|
|
if response.json()['success'] is False:
|
|
|
|
raise ValueError('Invalid token')
|
|
|
|
else:
|
|
|
|
# Token needs the following scopes:
|
|
|
|
# Zero Trust: Read/Edit
|
|
|
|
# Account Firewall Access Rules: Read/Edit
|
|
|
|
# Access Apps and Policies: Read/Edit
|
|
|
|
self._token = token
|
|
|
|
@property
|
|
|
|
def account_id(self):
|
|
|
|
return self._account_id
|
|
|
|
@account_id.setter
|
|
|
|
def account_id(self, account_id):
|
|
|
|
if account_id is None:
|
|
|
|
raise ValueError("No account ID provided")
|
|
|
|
else:
|
|
|
|
# Possibly make a request to lists to check if the account ID exists
|
|
|
|
self._account_id = account_id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-03-20 18:40:08 +00:00
|
|
|
# List Utils
|
|
|
|
|
2023-03-26 23:16:26 +01:00
|
|
|
|
2023-03-20 18:40:08 +00:00
|
|
|
# Convert a hosts file to a simple hostname list
|
2023-03-26 23:16:26 +01:00
|
|
|
def convert_to_list(file: pathlib.Path) -> list:
|
|
|
|
with open(file, "r") as f:
|
2023-08-01 04:39:12 +01:00
|
|
|
# Don't read commented lines; strip whitespace;
|
|
|
|
# remove 127.0.0.1 from beginning of line;
|
|
|
|
# ignore lines with "localhost"; ignore lines with "::1";
|
|
|
|
# ignore newlines
|
2023-03-26 23:16:26 +01:00
|
|
|
hosts = [
|
|
|
|
i[10:].strip()
|
|
|
|
for i in f.readlines()
|
|
|
|
if not i.startswith("#") and "localhost" not in i and "::1" not in i
|
|
|
|
]
|
2023-03-20 18:40:08 +00:00
|
|
|
# Equivalent to:
|
|
|
|
# for x in f.readlines():
|
|
|
|
# if not x.startswith('#') and 'localhost' not in x and '::1' not in x:
|
|
|
|
# hosts.append(x[10:].strip())
|
2023-08-01 04:39:12 +01:00
|
|
|
|
|
|
|
# If there are any empty strings in the list, remove them
|
|
|
|
# For some reason, whitelist seems to still be present
|
2023-03-26 23:16:26 +01:00
|
|
|
hosts = [i for i in hosts if i != ""]
|
2023-03-20 18:40:08 +00:00
|
|
|
return hosts
|
|
|
|
|
2023-03-26 23:16:26 +01:00
|
|
|
|
2023-03-20 18:40:08 +00:00
|
|
|
# General Utils
|
|
|
|
|
2023-03-26 23:16:26 +01:00
|
|
|
|
2023-03-20 18:40:08 +00:00
|
|
|
# Load environment variables
|
2023-08-01 04:39:12 +01:00
|
|
|
# def load_env() -> dict:
|
|
|
|
# load_dotenv(".env")
|
|
|
|
# if not os.environ.get("CLOUDFLARE_TOKEN") and not os.environ.get(
|
|
|
|
# "CLOUDFLARE_ACCOUNT_ID"
|
|
|
|
# ):
|
|
|
|
# load_dotenv(".envrc")
|
|
|
|
# if not os.environ.get("CLOUDFLARE_TOKEN") or not os.environ.get(
|
|
|
|
# "CLOUDFLARE_ACCOUNT_ID"
|
|
|
|
# ):
|
|
|
|
# print(
|
|
|
|
# "No environment variables found. Please create a .env file or .envrc file"
|
|
|
|
# )
|
|
|
|
# exit()
|
|
|
|
# else:
|
|
|
|
# return {
|
|
|
|
# "CLOUDFLARE_TOKEN": os.environ.get("CLOUDFLARE_TOKEN"),
|
|
|
|
# "CLOUDFLARE_ACCOUNT_ID": os.environ.get("CLOUDFLARE_ACCOUNT_ID"),
|
|
|
|
# }
|
|
|
|
|
|
|
|
|
|
|
|
def get_lists(account_id, token) -> dict:
|
|
|
|
url = f"https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/lists"
|
2023-03-20 18:40:08 +00:00
|
|
|
headers = {
|
2023-08-01 04:39:12 +01:00
|
|
|
"Authorization": f"Bearer {token}",
|
2023-03-20 18:40:08 +00:00
|
|
|
"Content-Type": "application/json",
|
|
|
|
}
|
2023-03-26 23:16:26 +01:00
|
|
|
response = requests.get(url, headers=headers, timeout=10)
|
2023-03-20 18:40:08 +00:00
|
|
|
if response.status_code != 200:
|
2023-03-26 23:16:26 +01:00
|
|
|
print(f"Error getting lists: {response.text}")
|
|
|
|
return response.json()["result"]
|
|
|
|
|
2023-03-20 18:40:08 +00:00
|
|
|
|
|
|
|
def filter_adblock_lists(lists: dict) -> dict:
|
|
|
|
adblock_lists = []
|
|
|
|
for lst in lists:
|
2023-03-26 23:16:26 +01:00
|
|
|
if lst["name"].startswith("adblock-list") and lst["type"] == "DOMAIN":
|
2023-03-20 18:40:08 +00:00
|
|
|
adblock_lists.append(lst)
|
|
|
|
return adblock_lists
|
|
|
|
|
2023-03-26 23:16:26 +01:00
|
|
|
|
2023-08-01 04:39:12 +01:00
|
|
|
def get_gateway_rules(account_id, token) -> dict:
|
|
|
|
url = f"https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules"
|
2023-03-26 23:16:26 +01:00
|
|
|
headers = {
|
2023-08-01 04:39:12 +01:00
|
|
|
"Authorization": f"Bearer {token}",
|
2023-03-26 23:16:26 +01:00
|
|
|
"Content-Type": "application/json",
|
|
|
|
}
|
|
|
|
response = requests.get(url, headers=headers, timeout=10)
|
|
|
|
if response.status_code != 200:
|
|
|
|
print(f"Error getting lists: {response.text}")
|
|
|
|
return response.json()["result"]
|