diff --git a/CloudFlare/cloudflare.py b/CloudFlare/cloudflare.py index c29c86e..6681bca 100644 --- a/CloudFlare/cloudflare.py +++ b/CloudFlare/cloudflare.py @@ -41,33 +41,42 @@ def call_with_no_auth(self, method, parts, params=None, data=None, files=None): """ Cloudflare v4 API""" - headers = { - 'User-Agent': self.user_agent, - 'Content-Type': 'application/json' - } + headers = {} + self._add_headers(headers) return self._call(method, headers, parts, identifier1, identifier2, identifier3, params, data, files) + def _add_headers(self, headers): + """ Add default headers """ + headers['User-Agent'] = self.user_agent + headers['Content-Type'] = 'application/json' + def _add_auth_headers(self, headers): """ Add authentication headers """ - if self.email: + if self.email is None and self.token is None: + raise CloudFlareAPIError(0, 'no email and no token defined') + if self.token is None: + raise CloudFlareAPIError(0, 'no token defined') + if self.email is None: + headers['Authorization'] = 'Bearer %s' % (self.token) + else: headers['X-Auth-Email'] = self.email headers['X-Auth-Key'] = self.token - else: - headers['Authorization'] = 'Bearer {}'.format(self.token) + + def _add_certtoken_headers(self, headers): + """ Add authentication headers """ + if self.certtoken is None: + raise CloudFlareAPIError(0, 'no cert token defined') + headers['X-Auth-User-Service-Key'] = self.certtoken def call_with_auth(self, method, parts, identifier1=None, identifier2=None, identifier3=None, params=None, data=None, files=None): """ Cloudflare v4 API""" - if self.email is '' or self.token is '': - raise CloudFlareAPIError(0, 'no email and/or token defined') - headers = { - 'User-Agent': self.user_agent, - 'Content-Type': 'application/json' - } + headers = {} + self._add_headers(headers) self._add_auth_headers(headers) if type(data) == str: # passing javascript vs JSON @@ -86,12 +95,8 @@ def call_with_auth_unwrapped(self, method, parts, params=None, data=None, files=None): """ Cloudflare v4 API""" - if self.email is '' or self.token is '': - raise CloudFlareAPIError(0, 'no email and/or token defined') - headers = { - 'User-Agent': self.user_agent, - 'Content-Type': 'application/json' - } + headers = {} + self._add_headers(headers) self._add_auth_headers(headers) if type(data) == str: # passing javascript vs JSON @@ -110,13 +115,9 @@ def call_with_certauth(self, method, parts, params=None, data=None, files=None): """ Cloudflare v4 API""" - if self.certtoken is '' or self.certtoken is None: - raise CloudFlareAPIError(0, 'no cert token defined') - headers = { - 'User-Agent': self.user_agent, - 'X-Auth-User-Service-Key': self.certtoken, - 'Content-Type': 'application/json' - } + headers = {} + self._add_headers(headers) + self._add_certtoken_headers(headers) return self._call(method, headers, parts, identifier1, identifier2, identifier3, params, data, files) @@ -245,7 +246,7 @@ def _network(self, method, headers, parts, self.logger.debug('Call: done!') except Exception as e: if self.logger: - self.logger.debug('Call: exception!') + self.logger.debug('Call: exception! "%s"' % (e)) raise CloudFlareAPIError(0, 'connection failed.') if self.logger: @@ -835,6 +836,12 @@ def __init__(self, email=None, token=None, certtoken=None, debug=False, raw=Fals if certtoken is None: certtoken = conf_certtoken + if email is '': + email = None + if token is '': + token = None + if certtoken is '': + certtoken = None self._base = self._v4base(email, token, certtoken, base_url, debug, raw, use_sessions) # add the API calls @@ -861,13 +868,24 @@ def __exit__(self, t, v, tb): def __str__(self): """ Cloudflare v4 API""" - return '["%s","%s"]' % (self._base.email, "REDACTED") + if self._base.email is None: + return '["%s"]' % ('REDACTED') + else: + return '["%s","%s"]' % (self._base.email, 'REDACTED') def __repr__(self): """ Cloudflare v4 API""" - return '%s,%s(%s,"%s","%s","%s",%s,"%s")' % ( - self.__module__, type(self).__name__, - self._base.email, 'REDACTED', 'REDACTED', - self._base.base_url, self._base.raw, self._base.user_agent - ) + if self._base.email is None: + return '%s,%s(%s,"%s","%s",%s,"%s")' % ( + self.__module__, type(self).__name__, + 'REDACTED', 'REDACTED', + self._base.base_url, self._base.raw, self._base.user_agent + ) + else: + return '%s,%s(%s,"%s","%s","%s",%s,"%s")' % ( + self.__module__, type(self).__name__, + self._base.email, 'REDACTED', 'REDACTED', + self._base.base_url, self._base.raw, self._base.user_agent + ) + diff --git a/CloudFlare/utils.py b/CloudFlare/utils.py index 0164d26..4feafd1 100644 --- a/CloudFlare/utils.py +++ b/CloudFlare/utils.py @@ -29,5 +29,7 @@ def sanitize_secrets(secrets): secrets_copy['X-Auth-Key'] = redacted_phrase elif 'X-Auth-User-Service-Key' in secrets_copy: secrets_copy['X-Auth-User-Service-Key'] = redacted_phrase + elif 'Authorization' in secrets_copy: + secrets_copy['Authorization'] = redacted_phrase return secrets_copy diff --git a/README.md b/README.md index ba40207..669c9d1 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ import CloudFlare 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. -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. +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. 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. diff --git a/README.rst b/README.rst index bdf5809..50675f1 100644 --- a/README.rst +++ b/README.rst @@ -225,10 +225,11 @@ 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. -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. +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. There is one call that presently doesn't need any email or token certification (the */ips* call); hence you can test without any values @@ -362,8 +363,8 @@ The other raised response is **CloudFlareInternalError** which can happen when calling an invalid method. In some cases more than one error is returned. In this case the return -value **e** is also an array. You can iterate over that array to see -the additional error. +value **e** is also an array. You can iterate over that array to see the +additional error. .. code:: python