Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Fix auth headers, allow for multiple configurations, and update documentation" #8

Merged
merged 1 commit into from Dec 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
@@ -1,2 +1 @@
config.json
configs.json
33 changes: 12 additions & 21 deletions README.md
@@ -1,30 +1,21 @@
# pyflare
Updates Cloudflare with current IP

In addition to many other benefits, Cloudflare will host your DNS for free. This script provides an alternative to dynamic dns services by leveraging Cloudflare's API. It does this by taking your current IP and updating Cloudflare's DNS records. In doing so, Cloudflare will always point to your correct IP even as it changes.

Inspiration: https://www.reddit.com/r/raspberry_pi/comments/9nimtz/use_cloudflare_as_dynamic_dns_with_raspberry_pi/


# Prerequisites
You must have a Cloudflare account with one domain (zone) available. This script will update the records associated with this zone.
* Create an account with Cloudflare
* Set up at least one domain with them
* When logged in, go to your Profile > API Tokens > Create Token
* During token creation, enable permissions "Zone.Zone.Settings" and "Zone.Zone," and "Zone.DNS" with resources "All Zones"
So I got sick of all those free dynamic dns services and fortunately some nice person on Reddit came up with this idea:
https://www.reddit.com/r/raspberry_pi/comments/9nimtz/use_cloudflare_as_dynamic_dns_with_raspberry_pi/
If you are a Redditor please go give u/TheFirsh some tasty tasty karma.

Cloudflare will host your DNS for free, on top of a whole heap of other benefits, and they have a really good API for updating DNS records. The idea is that you run this script like you would a dynamic DNS client - it's python so entirely cross platform and uses minimal and very common libraries.

# config.json

Create a file named "config.json" in the same directory as pyflare.py. This file should be formatted as JSON. For multiple records, create a list (or array) of dictionaries (objects) containing your parameters.

You will need to create a config.json file in the same folder as pyflare.py - this file must be json formatted and contain the following 4 elements.
Note the curly braces are not to be included.
```
[
{
"email": "<YOUR CLOUDFLARE EMAIL ADDRESS>",
"key": "<YOUR CLOUDFLARE API KEY>",
"zone": "<THE DNS ZONE CONTAINING THE RECORD TO BE UPDATED (e.g. domain.com)>",
"record": "<THE SPECIFIC RECORD TO UPDATE (e.g. api.domain.com)>"
}
]
{
"email": "{the email address on your Cloudflare account}",
"key": "{your API key for Cloudflare}",
"zone": "{the DNS zone that contains the record you are updating}",
"record": "{the specific record to be updated}"
}
```
62 changes: 19 additions & 43 deletions pyflare.py
Expand Up @@ -6,11 +6,7 @@
class Cloudflare:
def __init__(self, email, key):
self.endpoint = "https://api.cloudflare.com/client/v4"
self.headers = {
'X-Auth-Email': email,
'Authorization': f'Bearer {key}',
'Content-Type': 'application/json'
}
self.headers = {'X-Auth-Email': email, 'X-Auth-Key': key, 'Content-Type': 'application/json'}

def getmyip(self):
r = requests.get("https://api.ipify.org/")
Expand All @@ -22,58 +18,38 @@ def user(self):

def zones(self, zone):
payload = {'name': zone}
r = requests.get(
self.endpoint + "/zones", headers=self.headers, params=payload)
r = requests.get(self.endpoint + "/zones", headers=self.headers, params=payload)
return r.json()

def dns_records(self, zone_id, record):
payload = {'name': record}
r = requests.get(
self.endpoint + "/zones/" + zone_id + "/dns_records",
headers=self.headers,
params=payload
)
r = requests.get(self.endpoint + "/zones/" + zone_id + "/dns_records", headers=self.headers, params=payload)
return r.json()

def update_record(self, zone_id, record_id, record, ip_address):
payload = {
'type': 'A',
'name': record,
'content': ip_address,
'proxied': True
}
r = requests.put(
self.endpoint + "/zones/" + zone_id + "/dns_records/" + record_id,
headers=self.headers,
data=json.dumps(payload)
)
payload = {'type': 'A', 'name': record, 'content': ip_address}
r = requests.put(self.endpoint + "/zones/" + zone_id + "/dns_records/" + record_id, headers=self.headers, data=json.dumps(payload))
return r.json()

def __call__(self,zone,record):
zone_id = cf.zones(zone)['result'][0]['id']
record_id = cf.dns_records(zone_id, record)['result'][0]['id']
ip_address = cf.getmyip()
if ip_address != cf.dns_records(
zone_id, record)['result'][0]['content']:
if ip_address != cf.dns_records(zone_id, record)['result'][0]['content']:
return cf.update_record(zone_id, record_id, record, ip_address)
else:
return f'OK: {zone} / {record}'
return "OK"

if __name__ == '__main__':
__location__ = os.path.realpath(
os.path.join(os.getcwd(), os.path.dirname(__file__))
)
try:
with open(os.path.join(__location__,'configs.json')) as f:
configs = json.load(f)
if type(configs) is dict:
configs = [configs]
for config in configs:
email = config.get('email')
key = config.get('key')
zone = config.get('zone')
record = config.get('record')
cf = Cloudflare(email, key)
print(cf(zone,record))
except IOError:
print("Unable to find config file.")
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
try:
with open(os.path.join(__location__,'config.json')) as json_data_file:
config = json.load(json_data_file)
email = config['email']
key = config['key']
zone = config['zone']
record = config['record']
cf = Cloudflare(email, key)
print(cf(zone,record))
except IOError:
print("Unable to find config file.")