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

Support multiple CloudFlare accounts #42

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ $ export CF_EMAIL='[email protected]'
$ export CF_KEY='K9uX2HyUjeWg5AhAb'
```

You can supply multiple account credentials by separating them with one or more spaces. Accounts will be tried in the order given, until one is found that serves the relevant domain.
Leading, trailing, and extra spaces are ignored, so you can vertically align credential pairs for easy reading:

```
$ export CF_EMAIL='[email protected] [email protected]'
$ export CF_KEY=' K9uX2HyUjeWg5AhAtreb fdsfjhFdaKls45354kHJ9hsj'
```

Optionally, you can specify the DNS servers to be used for propagation checking via the `CF_DNS_SERVERS` environment variable (props [bennettp123](https://github.com/bennettp123)):

```
Expand Down
36 changes: 20 additions & 16 deletions hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@
logger.setLevel(logging.INFO)

try:
CF_HEADERS = {
'X-Auth-Email': os.environ['CF_EMAIL'],
'X-Auth-Key' : os.environ['CF_KEY'],
CF_HEADERS = [{
'X-Auth-Email': e,
'X-Auth-Key' : k,
'Content-Type': 'application/json',
}
} for e,k in zip(os.environ['CF_EMAIL'].split(), os.environ['CF_KEY'].split()) ]
except KeyError:
logger.error(" + Unable to locate Cloudflare credentials in environment!")
sys.exit(1)
Expand Down Expand Up @@ -78,15 +78,19 @@ def _has_dns_propagated(name, token):
def _get_zone_id(domain):
tld = get_tld('http://' + domain)
url = "https://api.cloudflare.com/client/v4/zones?name={0}".format(tld)
r = requests.get(url, headers=CF_HEADERS)
r.raise_for_status()
return r.json()['result'][0]['id']

for auth in CF_HEADERS:
r = requests.get(url, headers=auth)
r.raise_for_status()
r = r.json().get('result',())
if r:
return auth, r[0]['id']
logger.error(" + Domain {0} not found in any Cloudflare account".format(tld))
sys.exit(1)

# https://api.cloudflare.com/#dns-records-for-a-zone-dns-record-details
def _get_txt_record_id(zone_id, name, token):
def _get_txt_record_id(auth, zone_id, name, token):
url = "https://api.cloudflare.com/client/v4/zones/{0}/dns_records?type=TXT&name={1}&content={2}".format(zone_id, name, token)
r = requests.get(url, headers=CF_HEADERS)
r = requests.get(url, headers=auth)
r.raise_for_status()
try:
record_id = r.json()['result'][0]['id']
Expand All @@ -102,10 +106,10 @@ def create_txt_record(args):
domain, challenge, token = args
logger.debug(' + Creating TXT record: {0} => {1}'.format(domain, token))
logger.debug(' + Challenge: {0}'.format(challenge))
zone_id = _get_zone_id(domain)
auth, zone_id = _get_zone_id(domain)
name = "{0}.{1}".format('_acme-challenge', domain)

record_id = _get_txt_record_id(zone_id, name, token)
record_id = _get_txt_record_id(auth, zone_id, name, token)
if record_id:
logger.debug(" + TXT record exists, skipping creation.")
return
Expand All @@ -117,7 +121,7 @@ def create_txt_record(args):
'content': token,
'ttl': 120,
}
r = requests.post(url, headers=CF_HEADERS, json=payload)
r = requests.post(url, headers=auth, json=payload)
r.raise_for_status()
record_id = r.json()['result']['id']
logger.debug(" + TXT record created, CFID: {0}".format(record_id))
Expand All @@ -130,13 +134,13 @@ def delete_txt_record(args):
logger.info(" + http_request() error in letsencrypt.sh?")
return

zone_id = _get_zone_id(domain)
auth, zone_id = _get_zone_id(domain)
name = "{0}.{1}".format('_acme-challenge', domain)
record_id = _get_txt_record_id(zone_id, name, token)
record_id = _get_txt_record_id(auth, zone_id, name, token)

if record_id:
url = "https://api.cloudflare.com/client/v4/zones/{0}/dns_records/{1}".format(zone_id, record_id)
r = requests.delete(url, headers=CF_HEADERS)
r = requests.delete(url, headers=auth)
r.raise_for_status()
logger.debug(" + Deleted TXT {0}, CFID {1}".format(name, record_id))
else:
Expand Down