Skip to content
This repository was archived by the owner on Nov 22, 2024. It is now read-only.

Commit ca5cb96

Browse files
committed
auth methods cleaned up to allow empty/null strings in values plus confirmed all authentication code is consistent. Updated README.
1 parent f71c3e2 commit ca5cb96

File tree

4 files changed

+61
-40
lines changed

4 files changed

+61
-40
lines changed

CloudFlare/cloudflare.py

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -41,33 +41,42 @@ def call_with_no_auth(self, method, parts,
4141
params=None, data=None, files=None):
4242
""" Cloudflare v4 API"""
4343

44-
headers = {
45-
'User-Agent': self.user_agent,
46-
'Content-Type': 'application/json'
47-
}
44+
headers = {}
45+
self._add_headers(headers)
4846
return self._call(method, headers, parts,
4947
identifier1, identifier2, identifier3,
5048
params, data, files)
5149

50+
def _add_headers(self, headers):
51+
""" Add default headers """
52+
headers['User-Agent'] = self.user_agent
53+
headers['Content-Type'] = 'application/json'
54+
5255
def _add_auth_headers(self, headers):
5356
""" Add authentication headers """
54-
if self.email:
57+
if self.email is None and self.token is None:
58+
raise CloudFlareAPIError(0, 'no email and no token defined')
59+
if self.token is None:
60+
raise CloudFlareAPIError(0, 'no token defined')
61+
if self.email is None:
62+
headers['Authorization'] = 'Bearer %s' % (self.token)
63+
else:
5564
headers['X-Auth-Email'] = self.email
5665
headers['X-Auth-Key'] = self.token
57-
else:
58-
headers['Authorization'] = 'Bearer {}'.format(self.token)
66+
67+
def _add_certtoken_headers(self, headers):
68+
""" Add authentication headers """
69+
if self.certtoken is None:
70+
raise CloudFlareAPIError(0, 'no cert token defined')
71+
headers['X-Auth-User-Service-Key'] = self.certtoken
5972

6073
def call_with_auth(self, method, parts,
6174
identifier1=None, identifier2=None, identifier3=None,
6275
params=None, data=None, files=None):
6376
""" Cloudflare v4 API"""
6477

65-
if self.email is '' or self.token is '':
66-
raise CloudFlareAPIError(0, 'no email and/or token defined')
67-
headers = {
68-
'User-Agent': self.user_agent,
69-
'Content-Type': 'application/json'
70-
}
78+
headers = {}
79+
self._add_headers(headers)
7180
self._add_auth_headers(headers)
7281
if type(data) == str:
7382
# passing javascript vs JSON
@@ -86,12 +95,8 @@ def call_with_auth_unwrapped(self, method, parts,
8695
params=None, data=None, files=None):
8796
""" Cloudflare v4 API"""
8897

89-
if self.email is '' or self.token is '':
90-
raise CloudFlareAPIError(0, 'no email and/or token defined')
91-
headers = {
92-
'User-Agent': self.user_agent,
93-
'Content-Type': 'application/json'
94-
}
98+
headers = {}
99+
self._add_headers(headers)
95100
self._add_auth_headers(headers)
96101
if type(data) == str:
97102
# passing javascript vs JSON
@@ -110,13 +115,9 @@ def call_with_certauth(self, method, parts,
110115
params=None, data=None, files=None):
111116
""" Cloudflare v4 API"""
112117

113-
if self.certtoken is '' or self.certtoken is None:
114-
raise CloudFlareAPIError(0, 'no cert token defined')
115-
headers = {
116-
'User-Agent': self.user_agent,
117-
'X-Auth-User-Service-Key': self.certtoken,
118-
'Content-Type': 'application/json'
119-
}
118+
headers = {}
119+
self._add_headers(headers)
120+
self._add_certtoken_headers(headers)
120121
return self._call(method, headers, parts,
121122
identifier1, identifier2, identifier3,
122123
params, data, files)
@@ -245,7 +246,7 @@ def _network(self, method, headers, parts,
245246
self.logger.debug('Call: done!')
246247
except Exception as e:
247248
if self.logger:
248-
self.logger.debug('Call: exception!')
249+
self.logger.debug('Call: exception! "%s"' % (e))
249250
raise CloudFlareAPIError(0, 'connection failed.')
250251

251252
if self.logger:
@@ -835,6 +836,12 @@ def __init__(self, email=None, token=None, certtoken=None, debug=False, raw=Fals
835836
if certtoken is None:
836837
certtoken = conf_certtoken
837838

839+
if email is '':
840+
email = None
841+
if token is '':
842+
token = None
843+
if certtoken is '':
844+
certtoken = None
838845
self._base = self._v4base(email, token, certtoken, base_url, debug, raw, use_sessions)
839846

840847
# add the API calls
@@ -861,13 +868,24 @@ def __exit__(self, t, v, tb):
861868
def __str__(self):
862869
""" Cloudflare v4 API"""
863870

864-
return '["%s","%s"]' % (self._base.email, "REDACTED")
871+
if self._base.email is None:
872+
return '["%s"]' % ('REDACTED')
873+
else:
874+
return '["%s","%s"]' % (self._base.email, 'REDACTED')
865875

866876
def __repr__(self):
867877
""" Cloudflare v4 API"""
868878

869-
return '%s,%s(%s,"%s","%s","%s",%s,"%s")' % (
870-
self.__module__, type(self).__name__,
871-
self._base.email, 'REDACTED', 'REDACTED',
872-
self._base.base_url, self._base.raw, self._base.user_agent
873-
)
879+
if self._base.email is None:
880+
return '%s,%s(%s,"%s","%s",%s,"%s")' % (
881+
self.__module__, type(self).__name__,
882+
'REDACTED', 'REDACTED',
883+
self._base.base_url, self._base.raw, self._base.user_agent
884+
)
885+
else:
886+
return '%s,%s(%s,"%s","%s","%s",%s,"%s")' % (
887+
self.__module__, type(self).__name__,
888+
self._base.email, 'REDACTED', 'REDACTED',
889+
self._base.base_url, self._base.raw, self._base.user_agent
890+
)
891+

CloudFlare/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,7 @@ def sanitize_secrets(secrets):
2929
secrets_copy['X-Auth-Key'] = redacted_phrase
3030
elif 'X-Auth-User-Service-Key' in secrets_copy:
3131
secrets_copy['X-Auth-User-Service-Key'] = redacted_phrase
32+
elif 'Authorization' in secrets_copy:
33+
secrets_copy['Authorization'] = redacted_phrase
3234

3335
return secrets_copy

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ import CloudFlare
198198

199199
If the account email and API key are not passed when you create the class, then they are retrieved from either the users exported shell environment variables or the .cloudflare.cfg or ~/.cloudflare.cfg or ~/.cloudflare/cloudflare.cfg files, in that order.
200200

201-
If you're using an API Token, any `cloudflare.cfg` file must not contain an `email` attribute and the `CF_API_EMAIL` environment variable must be unset, otherwise the token will be treated as a key and will throw an error.
201+
If you're using an API Token, any `cloudflare.cfg` file must either not contain an `email` attribute or be a zero length string and the `CF_API_EMAIL` environment variable must be unset or be a zero length string, otherwise the token will be treated as a key and will throw an error.
202202

203203
There is one call that presently doesn't need any email or token certification (the */ips* call); hence you can test without any values saved away.
204204

README.rst

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,11 @@ class, then they are retrieved from either the users exported shell
225225
environment variables or the .cloudflare.cfg or ~/.cloudflare.cfg or
226226
~/.cloudflare/cloudflare.cfg files, in that order.
227227

228-
If you're using an API Token, any ``cloudflare.cfg`` file must not
229-
contain an ``email`` attribute and the ``CF_API_EMAIL`` environment
230-
variable must be unset, otherwise the token will be treated as a key
231-
and will throw an error.
228+
If you're using an API Token, any ``cloudflare.cfg`` file must either
229+
not contain an ``email`` attribute or be a zero length string and the
230+
``CF_API_EMAIL`` environment variable must be unset or be a zero length
231+
string, otherwise the token will be treated as a key and will throw an
232+
error.
232233

233234
There is one call that presently doesn't need any email or token
234235
certification (the */ips* call); hence you can test without any values
@@ -362,8 +363,8 @@ The other raised response is **CloudFlareInternalError** which can
362363
happen when calling an invalid method.
363364

364365
In some cases more than one error is returned. In this case the return
365-
value **e** is also an array. You can iterate over that array to see
366-
the additional error.
366+
value **e** is also an array. You can iterate over that array to see the
367+
additional error.
367368

368369
.. code:: python
369370

0 commit comments

Comments
 (0)