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

Commit a28a13e

Browse files
committed
handle email/key or token as per issue-114, plus fix some small issues with exception handling
1 parent 0523914 commit a28a13e

2 files changed

Lines changed: 71 additions & 74 deletions

File tree

CloudFlare/cloudflare.py

Lines changed: 64 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -26,45 +26,22 @@ def __init__(self, config):
2626
""" Cloudflare v4 API"""
2727

2828
self.config = config
29-
if 'email' in config:
30-
self.email = config['email']
31-
else:
32-
self.email = None
33-
if 'token' in config:
34-
self.token = config['token']
35-
else:
36-
self.token = None
37-
if 'certtoken' in config:
38-
self.certtoken = config['certtoken']
39-
else:
40-
self.certtoken = None
41-
if 'base_url' in config:
42-
self.base_url = config['base_url']
43-
else:
44-
# We must have a base_url value
45-
self.base_url = BASE_URL
29+
30+
self.api_email = config['email'] if 'email' in config else None
31+
self.api_key = config['key'] if 'key' in config else None
32+
self.api_token = config['token'] if 'token' in config else None
33+
self.api_certtoken = config['certtoken'] if 'certtoken' in config else None
34+
35+
# We must have a base_url value
36+
self.base_url = config['base_url'] if 'base_url' in config else BASE_URL
37+
4638
self.raw = config['raw']
4739
self.use_sessions = config['use_sessions']
4840
self.profile = config['profile']
4941
self.network = CFnetwork(use_sessions=self.use_sessions)
5042
self.user_agent = user_agent()
5143

52-
## We don't need to check this here as we test for
53-
## this when building the authentication headers
54-
##
55-
##if not isinstance(self.email, str):
56-
## raise ValueError('email argument not string')
57-
##if not isinstance(self.token, str):
58-
## raise ValueError('token argument not string')
59-
##if not isinstance(self.certtoken, str):
60-
## raise ValueError('certtoken argument not string')
61-
##if not isinstance(self.base_url, str):
62-
## raise ValueError('base url argument not string')
63-
64-
if 'debug' in config and config['debug']:
65-
self.logger = CFlogger(config['debug']).getLogger()
66-
else:
67-
self.logger = None
44+
self.logger = CFlogger(config['debug']).getLogger() if 'debug' in config and config['debug'] else None
6845

6946
def __del__(self):
7047
if self.network:
@@ -80,39 +57,52 @@ def _add_auth_headers(self, headers, method):
8057
""" Add authentication headers """
8158

8259
v = 'email' + '.' + method.lower()
83-
if v in self.config:
84-
email = self.config[v] # use specific value for this method
85-
else:
86-
email = self.email # use generic value for all methods
87-
60+
api_email = self.config[v] if v in self.config else self.api_email
61+
v = 'key' + '.' + method.lower()
62+
api_key = self.config[v] if v in self.config else self.api_key
8863
v = 'token' + '.' + method.lower()
89-
if v in self.config:
90-
token = self.config[v] # use specific value for this method
91-
else:
92-
token = self.token # use generic value for all methods
93-
94-
if email is None and token is None:
95-
raise CloudFlareAPIError(0, 'no email and no token defined')
96-
if token is None:
97-
raise CloudFlareAPIError(0, 'no token defined')
98-
if email is None:
99-
headers['Authorization'] = 'Bearer %s' % (token)
64+
api_token = self.config[v] if v in self.config else self.api_token
65+
66+
if api_email is None and api_key is None and api_token is None:
67+
raise CloudFlareAPIError(0, 'neither email/key or token defined')
68+
69+
if api_key is not None and api_token is not None:
70+
raise CloudFlareAPIError(0, 'confused info - both key and token defined')
71+
72+
if api_email is not None and api_key is None and api_token is None:
73+
raise CloudFlareAPIError(0, 'email defined however neither key or token defined')
74+
75+
# We know at this point that at-least one api_* is set and no confusion!
76+
77+
if api_email is None and api_token is not None:
78+
# post issue-114 - token is used
79+
headers['Authorization'] = 'Bearer %s' % (api_token)
80+
elif api_email is None and api_key is not None:
81+
# pre issue-114 - key is used vs token - backward compat
82+
headers['Authorization'] = 'Bearer %s' % (api_key)
83+
elif api_email is not None and api_key is not None:
84+
# boring old school email/key methodology (token ignored)
85+
headers['X-Auth-Email'] = api_email
86+
headers['X-Auth-Key'] = api_key
87+
elif api_email is not None and api_token is not None:
88+
# boring old school email/key methodology (token ignored)
89+
headers['X-Auth-Email'] = api_email
90+
headers['X-Auth-Key'] = api_token
10091
else:
101-
headers['X-Auth-Email'] = email
102-
headers['X-Auth-Key'] = token
92+
raise CloudFlareInternalError(0, 'coding issue!')
10393

10494
def _add_certtoken_headers(self, headers, method):
10595
""" Add authentication headers """
10696

10797
v = 'certtoken' + '.' + method.lower()
10898
if v in self.config:
109-
certtoken = self.config[v] # use specific value for this method
99+
api_certtoken = self.config[v] # use specific value for this method
110100
else:
111-
certtoken = self.certtoken # use generic value for all methods
101+
api_certtoken = self.api_certtoken # use generic value for all methods
112102

113-
if certtoken is None:
103+
if api_certtoken is None:
114104
raise CloudFlareAPIError(0, 'no cert token defined')
115-
headers['X-Auth-User-Service-Key'] = certtoken
105+
headers['X-Auth-User-Service-Key'] = api_certtoken
116106

117107
def do_no_auth(self, method, parts, identifiers, params=None, data=None, files=None):
118108
""" Cloudflare v4 API"""
@@ -857,10 +847,12 @@ def add(self, t, p1, p2=None, p3=None, p4=None, p5=None):
857847
else:
858848
setattr(branch, name, f)
859849

860-
def api_list(self, m=None, s=''):
850+
def api_list(self):
851+
"""recursive walk of the api tree returning a list of api calls"""
852+
return self._api_list(m=self)
853+
854+
def _api_list(self, m=None, s=''):
861855
"""recursive walk of the api tree returning a list of api calls"""
862-
if m is None:
863-
m = self
864856
w = []
865857
for n in sorted(dir(m)):
866858
if n[0] == '_':
@@ -894,31 +886,33 @@ def api_list(self, m=None, s=''):
894886
# handle underscores by returning the actual API call vs the method name
895887
w.append(str(a)[1:-1])
896888
# now recurse downwards into the tree
897-
w = w + self.api_list(a, s + '/' + n)
889+
w = w + self._api_list(a, s + '/' + n)
898890
return w
899891

900892
def api_from_web(self):
901893
""" Cloudflare v4 API"""
902894

903895
return api_decode_from_web(self._base.api_from_web())
904896

905-
def __init__(self, email=None, token=None, certtoken=None, debug=False, raw=False, use_sessions=True, profile=None, base_url=None):
897+
def __init__(self, email=None, key=None, token=None, certtoken=None, debug=False, raw=False, use_sessions=True, profile=None, base_url=None):
906898
""" Cloudflare v4 API"""
907899

900+
self._base = None
901+
908902
try:
909903
config = read_configs(profile)
910904
except Exception as e:
911-
raise CloudFlareAPIError(0, str(e))
905+
raise e
912906

913907
# class creation values override all configuration values
914908
if email is not None:
915909
config['email'] = email
910+
if key is not None:
911+
config['key'] = key
916912
if token is not None:
917913
config['token'] = token
918914
if certtoken is not None:
919915
config['certtoken'] = certtoken
920-
if base_url is not None:
921-
config['base_url'] = base_url
922916
if debug is not None:
923917
config['debug'] = debug
924918
if raw is not None:
@@ -927,6 +921,8 @@ def __init__(self, email=None, token=None, certtoken=None, debug=False, raw=Fals
927921
config['use_sessions'] = use_sessions
928922
if profile is not None:
929923
config['profile'] = profile
924+
if base_url is not None:
925+
config['base_url'] = base_url
930926

931927
# we do not need to handle item.call values - they pass straight thru
932928

@@ -942,7 +938,7 @@ def __init__(self, email=None, token=None, certtoken=None, debug=False, raw=Fals
942938
if 'extras' in config and config['extras']:
943939
api_extras(self, config['extras'])
944940
except Exception as e:
945-
raise CloudFlareAPIError(0, str(e))
941+
raise e
946942

947943
def __del__(self):
948944
""" Network for Cloudflare API"""
@@ -970,16 +966,16 @@ def __exit__(self, t, v, tb):
970966
def __str__(self):
971967
""" Cloudflare v4 API"""
972968

973-
if self._base.email is None:
969+
if self._base.api_email is None:
974970
s = '["%s","%s"]' % (self._base.profile, 'REDACTED')
975971
else:
976-
s = '["%s","%s","%s"]' % (self._base.profile, self._base.email, 'REDACTED')
972+
s = '["%s","%s","%s"]' % (self._base.profile, self._base.api_email, 'REDACTED')
977973
return s
978974

979975
def __repr__(self):
980976
""" Cloudflare v4 API"""
981977

982-
if self._base.email is None:
978+
if self._base.api_email is None:
983979
s = '%s,%s("%s","%s","%s","%s",%s,"%s")' % (
984980
self.__module__, type(self).__name__,
985981
self._base.profile, 'REDACTED', 'REDACTED',
@@ -988,7 +984,7 @@ def __repr__(self):
988984
else:
989985
s = '%s,%s("%s","%s","%s","%s","%s",%s,"%s")' % (
990986
self.__module__, type(self).__name__,
991-
self._base.profile, self._base.email, 'REDACTED', 'REDACTED',
987+
self._base.profile, self._base.api_email, 'REDACTED', 'REDACTED',
992988
self._base.base_url, self._base.raw, self._base.user_agent
993989
)
994990
return s

CloudFlare/read_configs.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ def read_configs(profile=None):
1111
""" reading the config file for Cloudflare API"""
1212

1313
# We return all these values
14-
config = {'email': None, 'token': None, 'certtoken': None, 'extras': None, 'base_url': None, 'profile': None}
14+
config = {'email': None, 'key': None, 'token': None, 'certtoken': None, 'extras': None, 'base_url': None, 'profile': None}
1515

1616
# envioronment variables override config files - so setup first
1717
config['email'] = os.getenv('CLOUDFLARE_EMAIL') if os.getenv('CLOUDFLARE_EMAIL') is not None else os.getenv('CF_API_EMAIL')
18-
config['token'] = os.getenv('CLOUDFLARE_API_KEY') if os.getenv('CLOUDFLARE_API_KEY') is not None else os.getenv('CF_API_KEY')
18+
config['key'] = os.getenv('CLOUDFLARE_API_KEY') if os.getenv('CLOUDFLARE_API_KEY') is not None else os.getenv('CF_API_KEY')
19+
config['token'] = os.getenv('CLOUDFLARE_API_TOKEN') if os.getenv('CLOUDFLARE_API_TOKEN') is not None else os.getenv('CF_API_TOKEN')
1920
config['certtoken'] = os.getenv('CLOUDFLARE_API_CERTKEY') if os.getenv('CLOUDFLARE_API_CERTKEY') is not None else os.getenv('CF_API_CERTKEY')
2021
config['extras'] = os.getenv('CLOUDFLARE_API_EXTRAS') if os.getenv('CLOUDFLARE_API_EXTRAS') is not None else os.getenv('CF_API_EXTRAS')
2122
config['base_url'] = os.getenv('CLOUDFLARE_API_URL') if os.getenv('CLOUDFLARE_API_URL') is not None else os.getenv('CF_API_URL')
@@ -29,9 +30,9 @@ def read_configs(profile=None):
2930
os.path.expanduser('~/.cloudflare/cloudflare.cfg')
3031
])
3132
except:
32-
raise Exception("%s: configuration file error" % (profile))
33+
raise Exception("%s: configuration file error" % ('.cloudflare.cfg'))
3334

34-
if len(cp.sections()) == 0 and profile is not None:
35+
if len(cp.sections()) == 0 and profile is not None and len(profile) > 0:
3536
# no config file and yet a config name provided - not acceptable!
3637
raise Exception("%s: configuration section provided however config file missing" % (profile))
3738

@@ -48,13 +49,13 @@ def read_configs(profile=None):
4849

4950
config['profile'] = profile
5051

51-
if len(cp.sections()) > 0:
52+
if len(profile) > 0 and len(cp.sections()) > 0:
5253
# we have a configuration file - lets use it
5354

5455
if not cp.has_section(profile):
5556
raise Exception("%s: configuration section missing - configuration file only has these sections: %s" % (profile, ','.join(cp.sections())))
5657

57-
for option in ['email', 'token', 'certtoken', 'extras', 'base_url']:
58+
for option in ['email', 'key', 'token', 'certtoken', 'extras', 'base_url']:
5859
try:
5960
config_value = cp.get(profile, option)
6061
if option == 'extras':

0 commit comments

Comments
 (0)