Coder Social home page Coder Social logo

cloudflare / python-cloudflare Goto Github PK

View Code? Open in Web Editor NEW

This project forked from cloudflare-api/python-cloudflare-v4

680.0 680.0 159.0 1.02 MB

Python wrapper for the Cloudflare Client API v4

License: MIT License

Python 96.65% Makefile 1.72% Roff 1.63%

python-cloudflare's People

Contributors

aaranmcguire avatar acdha avatar ad-m avatar bellardia avatar bjoernpetersen avatar changaco avatar corywright avatar crlorentzen avatar daic115 avatar dargor avatar dkoston avatar fawaf avatar felixschwarz avatar ggerasimov avatar hlx98007 avatar issackelly avatar jacobbednarz avatar jaredpage avatar mahtin avatar martin40701 avatar mattjanssen avatar mnordhoff avatar nicholaskuechler avatar nijel avatar patryk avatar phntom avatar rita3ko avatar tugzrida avatar xens avatar yesbox avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-cloudflare's Issues

Issue trying to post new firewall rules

Hi guys,

Thanks for the excellent API work, love it so far.

I've been trying to create firewall rules using:

`` def ban_ip_for_zone_id(self, ip, zone_id):
rule = {'mode': 'block', 'configuration': {'target': 'ip', 'value': ip},
'notes': 'Automatic block placed via Python script for IP : ' + str(ip)}
print(json.dumps(rule))
self.cf.zones.firewall.access_rules.rules.post(zone_id, data=json.dumps(rule))

without a lot of success. I keep getting this error:
CloudFlare.exceptions.CloudFlareAPIError: firewallaccessrules.api.bad_json

The JSON I get back to send in is:
{"notes": "Automatic block placed via Python script for IP : 103.89.91.156", "configuration": {"target": "ip", "value": "103.89.91.156"}, "mode": "block"}

I already JSON linted this thing. Am I missing something on the data structure? Your input is appreciated.

Why can you only see 25 pieces of information when you look at the firewall whitelist?

Hello!
I found a question in use, hoping to help me to answer it.
When I called the query firewall interface, I found that I could only get 25 pieces of information at a time.
How can I get all the information at once?
######################################################
def main():
cf = CloudFlare.CloudFlare(email= email,token=token)
zones = cf.zones.firewall.access_rules.rules(Zone_ID)
print(len(zones['result_info']))
######################################################
My e-mail address is yuan.22811422.com
Thank you and your team for contributing such practical code!
A beginner's respect!

Can't find ip in user firewall: You must specify identifier1

Before inserting block rule to user/firewall/access_rules/rules I trying to find IP, if it is already blocked:
result = cf.user.firewall.access_rules.rules.get(data={'configuration': { 'target': 'ip', 'value': bad_guy_ip }})

but I get exception:

File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/CloudFlare/cloudflare.py", line 618, in get
    params, data)
  File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/CloudFlare/cloudflare.py", line 75, in call_with_auth
    params, data, files)
  File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/CloudFlare/cloudflare.py", line 424, in _call
    params, data, files)
  File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/CloudFlare/cloudflare.py", line 319, in _raw
    params, data, files)
  File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/CloudFlare/cloudflare.py", line 143, in _network
    raise CloudFlareAPIError(0, 'You must specify identifier1')
CloudFlare.exceptions.CloudFlareAPIError: You must specify identifier1

so how to specify it, and why I need to do it in user-level, this rules are 'global'?

Invalid or missing WAF Rule mode

Hello,

I am using Cloudflare's Python library to make some API calls. The following call generates API error every time:

cf.zones.firewall.waf.packages.rules.patch(ZoneID,RulesetID,RuleID, params={"mode":"off"})

The error is

File "/usr/lib/python2.7/site-packages/CloudFlare/cloudflare.py", line 625, in patch
    params, data)
  File "/usr/lib/python2.7/site-packages/CloudFlare/cloudflare.py", line 75, in call_with_auth
    params, data, files)
  File "/usr/lib/python2.7/site-packages/CloudFlare/cloudflare.py", line 467, in _call
    raise CloudFlareAPIError(code, message, error_chain)
CloudFlare.exceptions.CloudFlareAPIError: Invalid or missing WAF Rule mode

Everything is fine when submitting this call using curl as described here:

https://api.cloudflare.com/#waf-rules-edit-rule

Here's the code I'm using:

import CloudFlare

priv_key = "xxxx"
email = "xxxxx"
source = "xxxxx" # source zone id
target = "xxxxx" # target zone id
owasp = "xxx" # OWASP ruleset id

def replicate_rules():
    cf = CloudFlare.CloudFlare(email=email, token=priv_key, raw=True)
    for i in range (1,26):
        rules = cf.zones.firewall.waf.packages.rules(source,owasp, params={"per_page":100, "page":i})
        for x in rules["result"]:
                                   cf.zones.firewall.waf.packages.rules.patch(target,owasp,x["id"], params={"mode":"x['mode']"})



Getting "Failed to read certificate from Database" when trying to pull Origin CA certs

Works fine with the following curls:

curl -H "X-Auth-User-Service-Key: $CF_API_CERTKEY" "https://api.cloudflare.com/client/v4/certificates?zone_id=[ZONE_ID]"

curl -H "X-Auth-User-Service-Key: $CF_API_CERTKEY" "https://api.cloudflare.com/client/v4/certificates/[CERT_ID]

Am trying to call with cf.certificates.get(zone_id). User error or bug?

Error trying to change zone setting "always_use_https"

I can successfully change other similar zone settings, like "automatic_https_rewrites", and it works perfectly, however when I try to change "always_use_https" I receive this error:

Traceback (most recent call last): File "/home/gonguinguen/medios/gluon/restricted.py", line 227, in restricted exec ccode in environment File "/home/gonguinguen/medios/applications/webmedios/controllers/admin.py", line 598, in <module> File "/home/gonguinguen/medios/gluon/globals.py", line 393, in <lambda> self._caller = lambda f: f() File "/home/gonguinguen/medios/applications/webmedios/controllers/admin.py", line 593, in test cf.zones.settings.always_use_https.patch(zone_id, data={"value": "on"}) AttributeError: '_add_with_auth' object has no attribute 'always_use_https'

Notice the call I use is the same for both settings, as told by the official Cloudflare documentation. But the error happens only with "always_use_https".

I tried doing my self the call using python requests.

import requests
result = requests.patch('https://api.cloudflare.com/client/v4/zones/%s/settings/always_use_https' % 
    zone_id,
    data={'value': 'off'},
    headers={
        "Content-Type": "application/json",
        "X-Auth-Key": cloudflare_user_api_key,
        "X-Auth-Email": cloudflare_email
    }
)

But this returns the error code 6007 with the message "Malformed JSON in request body"

I've contacted Cloudflare support, and they told me that the call is right.
Is this a bug in python-cloudflare library? Could it be related to requests module?

UPDATE
I've tried directly using the curl command and it works ok, so it isn't a bug in the Cloudflare API. Also, I've tried with several different zones, and the problem remains.

Modify WAF rules

Hello.

Could you please help me?
How I can change settings for waf rules via cli4?

For example I need to change
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$zone_id/firewall/waf/packages/1e334934fd7ae32ad705667f8c1057aa/rules/100047WP" -H "Content-Type:application/json" -H "X-Auth-Key:$token" -H "X-Auth-Email:$login" --data '{"mode":"challenge"}'

Via cli4 it doesn't work :(
cli4 --patch mode=challenge /zones/:example.com/firewall/waf/packages/:1e334934fd7ae32ad705667f8c1057aa/rules/100047WP

Thank you for your work.

Unable to update TTL

If you call cli4 like so:
python -m cli4 --put name=$record type=A ttl=120 content=$ip /zones/:$domain/dns_records/:$record
you will get the following error:
cli4: /zones/:<ZONE_NAME>/dns_records/:<RECORD> - 1004 DNS Validation Error
Without the TTL Attribute this works fine and returns the Expected Record in JSON Format.

api_key vs token gotcha

So we can create an API object that authenticates using the email / API key combo or using an API token. That the token parameter to the initializer is overloaded for the two different uses (whether or not email is also specified is what decides which it is) is already a bit questionable IMHO, but ok, I can live with that.

But check this out: if you happen to have the CF_API_EMAIL environment variable defined then it will always interpret the token parameter as an API key not an API token... but it will apparently try to use it, even if the CF_API_KEY env var is also set. Or perhaps it stuffs all of the above into the headers. The result is that one gets "6003 Invalid request headers - api call failed" which isn't much of a clue to what's going on. Either there should be a more specific error, or it should just use the env vars, ignore the token param, and issue a warning.

Unable to connect to logpush endoint via cli4

Trying to check and configure logpush jobs and was hoping to use cli4 to do it quickly, but it doesn't know the logpush endpoint. It just returns the error /zones/:zoneid/logpush - not found. Confirmed that it does work as expected via curl.

Tested using version 2.3.0

requirements.txt should specify the request version

the json keyword on the session put & post methods requires requests>=2.4.2. Old Ubuntu LTS versions ship with an older version which will cause an exception: CloudFlare.exceptions.CloudFlareAPIError: connection failed.

Error 6007 when POST-ing to /user/load_balancers/monitors

When executing cli4 -v --post expected_codes=2xx interval=15 retries=2 path=/status type=https /user/load_balancers/monitors, I get a json: cannot unmarshal string into Go value of type uint error as return. The example comes from the CTM Setup Instructions (load-balancing-early-access-guide-20161002.pdf), so the content should be valid.

Doing a POST to for an example /user/load_balancers/notifiers works, and creates a notifier as expected.

Is this likely to be a bug in cli4, a problem with Cloudflare's API, or an error on my part?

Command output:

robert@butch ~/s/m/s/cloudflare-ctm> cli4 --version
Cloudflare library version: 1.3.2
robert@butch ~/s/m/s/cloudflare-ctm> cli4 -v --post expected_codes=2xx interval=15 retries=2 path=/status type=https /user/load_balancers/monitors
2016-11-29 10:04:37,744 - Python Cloudflare API v4 - DEBUG - Call: user/load_balancers/monitors,None,None,None,None
2016-11-29 10:04:37,744 - Python Cloudflare API v4 - DEBUG - Call: optional params and data None {'expected_codes': '2xx', 'path': '/status', 'interval': '15', 'type': 'https', 'retries': '2'}
2016-11-29 10:04:37,744 - Python Cloudflare API v4 - DEBUG - Call: method and url POST https://api.cloudflare.com/client/v4/user/load_balancers/monitors
2016-11-29 10:04:37,744 - Python Cloudflare API v4 - DEBUG - Call: headers {'X-Auth-Email': 'REDACTED', 'X-Auth-Key': 'REDACTED', 'Content-Type': 'application/json'}
2016-11-29 10:04:37,744 - Python Cloudflare API v4 - DEBUG - Call: doit!
2016-11-29 10:04:38,734 - Python Cloudflare API v4 - DEBUG - Call: done!
2016-11-29 10:04:38,738 - Python Cloudflare API v4 - DEBUG - Response: url https://api.cloudflare.com/client/v4/user/load_balancers/monitors
2016-11-29 10:04:38,738 - Python Cloudflare API v4 - DEBUG - Response: data {
  "result": null,
  "success": false,
  "errors": [
    {
      "code": 6007,
      "error": "json: cannot unmarshal string into Go value of type uint"
    }
  ],
  "messages": []
}

2016-11-29 10:04:38,739 - Python Cloudflare API v4 - DEBUG - Response: error 6007 json: cannot unmarshal string into Go value of type uint
cli4: /user/load_balancers/monitors - 6007 json: cannot unmarshal string into Go value of type uint

--quiet option yields TypeError

Python 3.6.9 and 3.5.2 (virtual envs, cloudflare-2.3.1)

$ cli4 -q /ips
Traceback (most recent call last):
  File "/tmp/python3-venv-20191218/bin/cli4", line 8, in <module>
    sys.exit(main())
  File "/tmp/python3-venv-20191218/lib/python3.6/site-packages/cli4/__main__.py", line 13, in main
    cli4(args)
  File "/tmp/python3-venv-20191218/lib/python3.6/site-packages/cli4/cli4.py", line 367, in cli4
    do_it(args)
  File "/tmp/python3-venv-20191218/lib/python3.6/site-packages/cli4/cli4.py", line 362, in do_it
    write_results(results, output)
  File "/tmp/python3-venv-20191218/lib/python3.6/site-packages/cli4/cli4.py", line 199, in write_results
    sys.stdout.write(results)
TypeError: write() argument must be str, not dict

Or python 2.7.12 (Ubuntu 16.04 w/ pip install cloudflare, 2.3.1)

$ cli4 -q /ips
Traceback (most recent call last):
  File "/usr/local/bin/cli4", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python2.7/dist-packages/cli4/__main__.py", line 13, in main
    cli4(args)
  File "/usr/local/lib/python2.7/dist-packages/cli4/cli4.py", line 367, in cli4
    do_it(args)
  File "/usr/local/lib/python2.7/dist-packages/cli4/cli4.py", line 362, in do_it
    write_results(results, output)
  File "/usr/local/lib/python2.7/dist-packages/cli4/cli4.py", line 199, in write_results
    sys.stdout.write(results)
TypeError: expected a string or other character buffer object

The --quiet option sets output to None, but write_results doesn't handle this case. So in this example, results is a dict, is not modified within write_results, and so the call to sys.stdout.write throws the above exception because it is not a string.

Expected results: --quiet should not output anything, not even a newline

Example for deleting DNS record

Hi,

Can you please provide an example of how to delete a specific DNS record (like a CNAME) from a given zone?

I checked the examples directory, the README and read the code, but I'm still not absolutely certain how this is done. Getting this wrong could mean accidentally deleting the entire zone instead of a specific DNS record so any help with this would be super appreciated.

Thanks,

Michael

Not clear how to edit page rules

I make following request

for r in rules:
        if r['actions'].pop()['id'] == 'always_use_https':
            #switch_rules.append(r)
            a = r['id']
            cf.zones.pagerules.patch(zones['id'], a, params={'status:disabled'})

how to pass optional parameters ?
I got error like connection failed

Inconsistent encoding between zone name and dns_records name for internationalized domains

Hi,
Take a look at this:

>>> my_domain = cf.zones.get(params = { 'name': 'xn--sanremomlheim-3ob.de' })
>>> my_domain[0]['name']
u'sanremom\u0102\u017alheim.de'
>>> my_domain = cf.zones.get(params = { 'name': 'sanremomülheim.de' })
>>> my_domain[0]['name']
u'sanremom\u0102\u017alheim.de'
>>> dns_records = cf.zones.dns_records.get(my_domain[0]['id'])
>>> dns_records[0]['name']
u'www.sanremom\xfclheim.de'
>>> print my_domain[0]['name']
sanremomĂźlheim.de
>>> print dns_records[0]['name']
www.sanremomülheim.de

The way the domain name is represented is different, sanremom\xfclheim.de vs sanremom\u0102\u017alheim.de.

Is this a bug?

How could I test if my_domain[0]['name'] is in dns_records[0]['name'] in python?

Thanks,
Max

Allow for timeout and retry configuration of the underlying `requests.Session`

Environment

cloudflare==2.1.0
requests==2.18.4

Current behavior

Using this module from inside China means that requests going to the Cloudflare API are quite unreliable. We find our code based on this module behaves consistently when run from outside of China, but in China will often hang for the first request, causing our script to run for a very long time. Since we run this script every minute on our ops server to update DNS records, if this script runs long, we will get an accumulation of instances running the script, which would eventually overload the server.

This one run got stuck for over 8 minutes:

^CTraceback (most recent call last):
  File "/srv/managebac/shared/bin/cloudflare_update.py", line 100, in <module>
    cf_zone = cf_get_zone(cf_client, zone_domain)
  File "/srv/managebac/shared/bin/cloudflare_update.py", line 37, in cf_get_zone
    zones = cf_client.zones.get(params={"name": zone_domain})
  File "/usr/local/lib/python2.7/dist-packages/CloudFlare/cloudflare.py", line 618, in get
    params, data)
  File "/usr/local/lib/python2.7/dist-packages/CloudFlare/cloudflare.py", line 75, in call_with_auth
    params, data, files)
  File "/usr/local/lib/python2.7/dist-packages/CloudFlare/cloudflare.py", line 424, in _call
    params, data, files)
  File "/usr/local/lib/python2.7/dist-packages/CloudFlare/cloudflare.py", line 319, in _raw
    params, data, files)
  File "/usr/local/lib/python2.7/dist-packages/CloudFlare/cloudflare.py", line 188, in _network
    data=data)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 521, in get
    return self.request('GET', url, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 508, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 618, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 440, in send
    timeout=timeout
  File "/usr/local/lib/python2.7/dist-packages/urllib3/connectionpool.py", line 601, in urlopen
    chunked=chunked)
  File "/usr/local/lib/python2.7/dist-packages/urllib3/connectionpool.py", line 346, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python2.7/dist-packages/urllib3/connectionpool.py", line 850, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python2.7/dist-packages/urllib3/connection.py", line 284, in connect
    conn = self._new_conn()
  File "/usr/local/lib/python2.7/dist-packages/urllib3/connection.py", line 141, in _new_conn
    (self.host, self.port), self.timeout, **extra_kw)
  File "/usr/local/lib/python2.7/dist-packages/urllib3/util/connection.py", line 73, in create_connection
    sock.connect(sa)
  File "/usr/lib/python2.7/socket.py", line 228, in meth
    return getattr(self._sock,name)(*args)
KeyboardInterrupt

real	8m9.595s
user	0m0.268s
sys	0m0.032s

Expected behavior

The library should follow the advice from http://docs.python-requests.org/en/master/user/quickstart/#timeouts and set a default timeout for all requests, and, if possible, make this user-configurable.

You can tell Requests to stop waiting for a response after a given number of seconds with the timeout parameter. Nearly all production code should use this parameter in nearly all requests. Failure to do so can cause your program to hang indefinitely:

A "nice to have" would be for the library to retry failed requests using urllib's HTTPAdapter. See http://docs.python-requests.org/en/master/_modules/requests/adapters/ and https://stackoverflow.com/a/15431343/3409092.

Unable to pull ELS schema fields via cli4

Per https://support.cloudflare.com/hc/en-us/articles/115003165991-Enterprise-Log-Share-ELS-Migrating-to-New-Endpoint, I should be able to pull down the list of defined fields for the received-time-ordered logs via cli4 --get /zones/:zone_id/logs/received/fields, but no go. I've even added the path entries to .cloudflare/cloudflare.cfg, and still no go. Initial error was "/zones/:zone_id/logs - not found", now I get "/zones/:zone_id/logs/received - not found".

Adding MX records does not work Priority is not set

I am trying to add MX records for some of my domains.

using the following

cli4 -v --post name="africlip.io" type="MX" PRIORITY=10  content="exch3.email.newsclip-sa.co.za"  /zones/:africlip.io/dns_records

I keep getting the same error. I have tried various quoting options.
PRIORITY="10" lower case priority=10.
Same error every time

2019-07-24 15:28:28,421 - Python Cloudflare API v4 - DEBUG - Response: error 1004 DNS Validation Error
cli4: /zones/:africlip.io/dns_records - 1004 DNS Validation Error

2019-07-24 15:28:27,072 - Python Cloudflare API v4 - DEBUG - Call: zones,None,None,None,None,None
2019-07-24 15:28:27,072 - Python Cloudflare API v4 - DEBUG - Call: optional params and data {'name': 'africlip.io', 'per_page': 1} None
2019-07-24 15:28:27,072 - Python Cloudflare API v4 - DEBUG - Call: method and url GET https://api.cloudflare.com/client/v4/zones
2019-07-24 15:28:27,072 - Python Cloudflare API v4 - DEBUG - Call: headers {'User-Agent': 'python-cloudflare/2.3.0/python-requests/2.22.0/python/3.7.3', 'X-Auth-Email': '[email protected]', 'X-Auth-Key': 'REDACTED', 'Content-Type': 'application/json'}
2019-07-24 15:28:27,072 - Python Cloudflare API v4 - DEBUG - Call: doit!
2019-07-24 15:28:27,744 - Python Cloudflare API v4 - DEBUG - Call: done!
2019-07-24 15:28:27,744 - Python Cloudflare API v4 - DEBUG - Response: url https://api.cloudflare.com/client/v4/zones?name=africlip.io&per_page=1
2019-07-24 15:28:27,744 - Python Cloudflare API v4 - DEBUG - Response: 200, application/json, {"result":[{"id":"redacted","name":"africlip.io","status":"active","paused":false,"type":"full","development_mode":0,"name_servers":["hans.ns.cloudflare.com","melinda.ns.cloudflare.com"],"original_name_servers":["titan.is.co.za","jupiter.is.co.za","demeter.is.co.za"],"original_registrar":null,"original_dnshost":null,"modified_on":"2019-04-16T07:27:18.194789Z","created_on":"2019-01-16T06:54:13.079417Z","activated_on":"2019-01-18T18:56:56.812146Z","meta":{"step":3,"wildcard_proxiable":false,"custom_certificate_quota":0,"page_rule_quota":3,"phishing_detected":false,"multiple_railguns_allowed":false},"owner":{"id":"redacted","type":"user","email":"redacted"},"account":{"id":"redacted","name":"Newsclip Primary Account"},"permissions":["#access:edit","#access:read","#analytics:read","#app:edit","#auditlogs:read","#billing:read","#cache_purge:edit","#dns_records:edit","#dns_records:read","#lb:edit","#lb:read","#legal:read","#logs:edit","#logs:read","#member:read","#organization:edit","#organization:read","#ssl:edit","#ssl:read","#stream:edit","#stream:read","#subscription:edit","#subscription:read","#waf:edit","#waf:read","#webhooks:edit","#webhooks:read","#worker:edit","#worker:read","#zone:edit","#zone:read","#zone_settings:edit","#zone_settings:read"],"plan":{"id":"0feeeeeeeeeeeeeeeeeeeeeeeeeeeeee","name":"Free Website","price":0,"currency":"USD","frequency":"","is_subscribed":true,"can_subscribe":false,"legacy_id":"free","legacy_discount":false,"externally_managed":false}}],"result_info":{"page":1,"per_page":1,"total_pages":1,"count":1,"total_count":1},"success":true,"errors":[],"messages":[]}
2019-07-24 15:28:27,744 - Python Cloudflare API v4 - DEBUG - Response: [{'id': 'redacted', 'name': 'africlip.io', 'status': 'active', 'paused': False, 'type': 'full', 'development_mode': 0, 'name_servers': ['hans.ns.cloudflare.com', 'melinda.ns.cloudflare.com'], 'original_name_servers': ['titan.is.co.za', 'jupiter.is.co.za', 'demeter.is.co.za'], 'original_registrar': None, 'original_dnshost': None, 'modified_on': '2019-04-16T07:27:18.194789Z', 'created_on': '2019-01-16T06:54:13.079417Z', 'activated_on': '2019-01-18T18:56:56.812146Z', 'meta': {'step': 3, 'wildcard_proxiable': False, 'custom_certificate_quota': 0, 'page_rule_quota': 3, 'phishing_detected': False, 'multiple_railguns_allowed': False}, 'owner': {'id': 'redacted', 'type': 'user', 'email': '[email protected]'}, 'account': {'id': 'redacted', 'name': 'Newsclip Primary Account'}, 'permissions': ['#access:edit', '#access:read', '#analytics:read', '#app:edit', '#auditlogs:read', '#billing:read', '#cache_purge:edit', '#dns_records:edit', '#dns_records:read', '#lb:edit', '#lb:read', '#legal:read', '#logs:edit', '#logs:read', '#member:read', '#organization:edit', '#organization:read', '#ssl:edit', '#ssl:read', '#stream:edit', '#stream:read', '#subscription:edit', '#subscription:read', '#waf:edit', '#waf:read', '#webhooks:edit', '#webhooks:read', '#worker:edit', '#worker:read', '#zone:edit', '#zone:read', '#zone_settings:edit', '#zone_settings:read'], 'plan': {'id': '0feeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'name': 'Free Website', 'price': 0, 'currency': 'USD', 'frequency': '', 'is_subscribed': True, 'can_subscribe': False, 'legacy_id': 'free', 'legacy_discount': False, 'externally_managed': False}}]
2019-07-24 15:28:27,744 - Python Cloudflare API v4 - DEBUG - Call: zones,redacted,dns_records,None,None,None
2019-07-24 15:28:27,744 - Python Cloudflare API v4 - DEBUG - Call: optional params and data None {'name': 'africlip.io', 'type': 'MX', 'priority': '10', 'content': 'exch3.email.newsclip-sa.co.za'}
2019-07-24 15:28:27,744 - Python Cloudflare API v4 - DEBUG - Call: method and url POST https://api.cloudflare.com/client/v4/zones/redacted/dns_records
2019-07-24 15:28:27,744 - Python Cloudflare API v4 - DEBUG - Call: headers {'User-Agent': 'python-cloudflare/2.3.0/python-requests/2.22.0/python/3.7.3', 'X-Auth-Email': '[email protected]', 'X-Auth-Key': 'REDACTED', 'Content-Type': 'application/json'}
2019-07-24 15:28:27,744 - Python Cloudflare API v4 - DEBUG - Call: doit!
2019-07-24 15:28:28,420 - Python Cloudflare API v4 - DEBUG - Call: done!
2019-07-24 15:28:28,420 - Python Cloudflare API v4 - DEBUG - Response: url https://api.cloudflare.com/client/v4/zones/redacted/dns_records
2019-07-24 15:28:28,420 - Python Cloudflare API v4 - DEBUG - Response: 400, application/json, {"success":false,"errors":[{"code":1004,"message":"DNS Validation Error","error_chain":[{"code":9104,"message":"priority must be an int between 0 and 65535."}]}],"messages":[],"result":null}

I am not sure what else I can do here.

2019-07-24 15:28:28,421 - Python Cloudflare API v4 - DEBUG - Response: error 1004 DNS Validation Error
cli4: /zones/:africlip.io/dns_records - 1004 DNS Validation Error


cli4 -V
Cloudflare library version: 2.3.0

Let me know if I can provide any other details

Add support for Access API

I would like to be able to use Access Apps and Access Policy through the API client and the cli4 tool but it doesn't seem like it's in there.

If I wanted to add it myself is it just a matter of adding the right entries to to api_v4.py?

Fully support Python 3

This module is not fully compatible with Python 3. There have been various attempts to fix this (c.f. #1, #3, #14, #21), but none of them have been merged and they were all incomplete. One particular area that hasn't been addressed in any of the pull requests is /examples, which relies heavily on Python 2 behavior (primarily print as a statement rather than a function). Please finish the migration to support Python 3. This is holding up packaging of the module for Fedora, which in turn is holding up packaging of the certbot-dns-cloudflare module for Fedora/EPEL.

Regression in 1.7.0 when adding TXT records

  • Expected result: Either a successful or "record already exists" result from API, as seen from version 1.6.2.
  • Instead got error: CloudFlare.exceptions.CloudFlareAPIError: DNS Validation Error, on version 1.7.0

Sample code to reproduce (replace relevant parts)

import CloudFlare
cf = CloudFlare.CloudFlare("[email]", "[key]")
zones = cf.zones.get(params={'name': "[domain]",'per_page': 1})
zone_id = zones[0]["id"]
print(cf.zones.dns_records.post(zone_id, data={'type': 'TXT', 'name': 'testtxt', 'content': 'test', 'ttl': 120}))

This bug will affect services that make use of TXT records (e.g. LetsEncrypt) when using the latest version of the Cloudflare module

Consistent issue with creating certain CNAMEs

I have a set of records that I am trying to create as CNAMEs in CloudFlare. Many of them are successful, however there are certain records that always fail to create and throw an error that is not terribly descriptive. I have found one reference to it in your codebase, but do not see why this error would be thrown for the same set of records everytime a call is attempted in trying to create them while other records succeed.

I have reached out to CloudFlare support, but they will not help since the error is coming from the Python module.

The error is: You must specify identifier1. The requests are being made with a token as opposed to a username and password. The call being made is:

CF_TOKEN = '<string of API token>'
CF_ZONE = '<string of zone ID>'
cf = CloudFlare.CloudFlare(token=CF_TOKEN)
new_cname = {'name': '<string name of CNAME record>',
                 'type': 'CNAME',
                 'content': '<string value of CNAME record>',}
try:
    cf.zones.dns_records.post(CF_ZONE, data=new_cname)
except CloudFlare.cloudflare.CloudFlareAPIError as e:
    print('There was a problem creating the DNS validation record for {} '.format('<string name of CNAME record>' + str(e))

An example of a failing new_cname dict is:

{'name': '_19b3a279aa2cb69039bd37c85c557c92.api.robinpowered.com.', 'type': 'CNAME', 'content': '_8d9d08826d5f4a56f590a47d674d5740.nhqijqilxf.acm-validations.aws.'}

Why would this record fail while others do not? Is there a better way to get a more useful error message?

Support the accounts endpoint

From: https://api.cloudflare.com/#organizations-properties

NOTE: This API is deprecated, please use equivalent /accounts API endpoints where possible. Account APIs provide a broader range of features, and are backwards-compatible to organization APIs.
>>> cf.accounts.get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'CloudFlare' object has no attribute 'accounts'

Incorrect number of records in zone

Hi!
I have the two sets of records in my zone: blablabla and blablabla-cdn. Content of all records are the same, for example:

Type Name Value
A blablabla 1.2.3.4
A blablabla-cdn 1.2.3.4
A blablabla 5.6.7.8
A blablabla-cdn 5.6.7.8

When I am trying to get this record via API I get the right number of blablabla-cdn records, but an incorrect number of blablabla records. I have 11 records in each set and I get 11 for blablabla-cdn and 4 for blablabla.
Here is code what I use:

cf = CloudFlare.CloudFlare(email=str(CF_API_EMAIL), token=str(CF_API_KEY))
dns_records = cf.zones.dns_records.get(zone_id)
for record in dns_records:
    if (re.match('blablabla', record['name'])):
        print(json.dumps(record,indent=4))

Is this a bug or I make something wrong?
Thanks!

zones.purge_cache.post() returns an incomplete response

Accordingly to the oficial documentation [1], the API call to purge specific URLs of a zone should return a dictionary like this one:

{
  "success": true,
  "errors": [],
  "messages": [],
  "result": {
    "id": "9a7806061c88ada191ed06f989cc3dac"
  }
}

However, in the response object I'm receiving only the inner dictionary, the one that corresponds to the "result" key. I'm not receiving the parent dictionary with the other keys (success, errors, messages). Could this be a bug?

I'm using the version 2.1.0 of the library.
This is my code:

>>> r = cf.zones.purge_cache.post(
            my_zone_id, 
            data={'files': [
                'https://mydomain.com/image.jpg',
                'http://mydomain.com/otherimage.jpg']
            })
>>> print r
>>> {'id':'23fe45167b3dad00ae810cd597587da1'}
>>> print r.get('success')
>>> None

[1] https://api.cloudflare.com/#zone-purge-files-by-url

DNS record deletion causes exception

DNS record deletion causes exception - it seems like API returns error, but without 'code' (it's not mandatory)

_raw() call returns {'error': 'You cannot use this API for domains with a .cf, .ga, .gq, .ml, or .tk TLD (top-level domain). To configure the DNS settings for this domain, use the Cloudflare Dashboard.'}

Exception trace:

In [10]: record = cf.zones.dns_records.get(zone['id'])[0]                                                                                                                                                                                     

In [11]: record['zone_id'], record['id']                                                                                                                                                                                                      
Out[11]: ('9d2e3522d6f813a1d32c85d0fe137443', 'a47180b9c7daa2e8ec92fcc7a5fb2da8')

In [12]: zone = cf.zones.get(params={'name': '42cc-testing-site.tk'})[0]                                                                                                                                                                      

In [13]: record = cf.zones.dns_records.get(zone['id'])[0]                                                                                                                                                                                     

In [14]: record['zone_id'], record['id']                                                                                                                                                                                                      
Out[14]: ('9d2e3522d6f813a1d32c85d0fe137443', 'a47180b9c7daa2e8ec92fcc7a5fb2da8')

In [15]: cf.zones.dns_records.delete(record['zone_id'], record['id'])                                                                                                                                                                         
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-15-06326d1a5ea4> in <module>
----> 1 cf.zones.dns_records.delete(record['zone_id'], record['id'])

~/.virtualenvs/pbn/lib/python3.6/site-packages/CloudFlare/cloudflare.py in delete(self, identifier1, identifier2, identifier3, params, data)
    683             return self._base.call_with_auth('DELETE', self._parts,
    684                                              identifier1, identifier2, identifier3,
--> 685                                              params, data)
    686 
    687     class _AddWithAuthUnwrapped(object):

~/.virtualenvs/pbn/lib/python3.6/site-packages/CloudFlare/cloudflare.py in call_with_auth(self, method, parts, identifier1, identifier2, identifier3, params, data, files)
    121             return self._call(method, headers, parts,
    122                               identifier1, identifier2, identifier3,
--> 123                               params, data, files)
    124 
    125         def call_with_auth_unwrapped(self, method, parts,

~/.virtualenvs/pbn/lib/python3.6/site-packages/CloudFlare/cloudflare.py in _call(self, method, headers, parts, identifier1, identifier2, identifier3, params, data, files)
    486             if response_data['success'] is False:
    487                 errors = response_data['errors'][0]
--> 488                 code = errors['code']
    489                 if 'message' in errors:
    490                     message = errors['message']

KeyError: 'code'

Please update examples

The examples are a bit outdated I believe, as I'm trying to write a supybot/limnoria plugin and I'm not able to get the package to load in any fashion other than to have it say that one or the other is not an attribute

import Cloudflare

class Cloudflare(callbacks.Plugin):
    """Allows access to the Cloudflare (tm) API"""
    threaded = True
    email = conf.supybot.plugins.Cloudflare.api.get('email')
    key = conf.supybot.plugins.Cloudflare.api.get('key')
    cf_send = Cloudflare.Cloudflare(email=email, token=key)

    def zones(self, irc, msg, args):
        """takes no arguments
        Lists the zones on the account."""
        listofzones = cf_send.zones.get()
        zonelist = []
        for zone in listofzones:
            zone_id = zone['id']
            zone_name = zone['name']
            zonelist.append("%s->%s" % (zone_id, zone_name))
        irc.reply("%s" % (" \xB7 ".join(zonelist)), notice=True, private=True)
    zones = wrap(zones, ['admin'])

Even when using import CloudFlare as it says in the example, I get the following.

14:27 <~Ken> !load Cloudflare
14:27 <+ElectroCode> Ken: Error: No module named 'CloudFlare'

Here is a traceback using import Cloudflare as cf

  File "/home/bots/electro/plugins/Cloudflare/plugin.py", line 53, in Cloudflare
    cf_send = cf.CloudFlare(email=email, token=key)
AttributeError: module 'Cloudflare' has no attribute 'CloudFlare'

"put" not available for dns_records

Hi,

the readme states that put is available for dns_records-operations:

GET PUT POST PATCH DELETE API call
(...) (...) (...) (...) (...) (...)
GET PUT POST   DELETE /zones/:identifier/dns_records
(...) (...) (...) (...) (...) (...)

However when using dns_records.put() (cf.zones.dns_records.put(zone_id, data=record)) the SDK throws an error: CloudFlare.exceptions.CloudFlareAPIError: Method PUT not available for that URI.

At least the readme should be correct about the available methods, but ideally an idempotent PUT should be available for dns_records to avoid duplicate records.

"logger" isn't an actual requirement

Went to install the CloudFlare python library and was surprised it was pulling in a module for logging called logger. Looked through the CF code and as best as i can tell it's not importing logger anywhere, which is good b/c that module as a single .py and config file with the following which would mess up the logging config for most anything utilizing logging.

import logging
import logging.config
import os
import sys
import types

logging.getLogger('paramiko').setLevel(logging.WARNING)
logging.getLogger('requests').setLevel(logging.WARNING)

config_file = os.path.join(os.path.dirname(__file__), 'logging.conf')

logging.config.fileConfig(config_file, disable_existing_loggers=False)
logger = logging.getLogger()


def error(self, msg, *args, **kwargs):
    self.error(msg, *args, **kwargs)
    sys.exit(1)

logger.interrupt = types.MethodType(error, logger)
logger.info = logger.info
logger.warn = logger.warn

Pretty sure that line should just be dropped from the requirements list since everything being used is part of the stdlib.

zone list is slow

hi,

I have an account of 206 domains, while I try to get the zone list using the API, even with 'per_page' set to 50, I found that there are 50 requests for the first 50 zones.

However, if I use 'curl' to get the data using the same API, all 50 results would be returned in one single request.

thanks

HTTPErrors should be caught and rethrown

I'm using the cloudflare.zones.custom_hostnames.delete endpoint and the endpoint throws a 500 error when a custom domain is in the state crypto.custom_hostnames.search.select.unknown_state. Instead, this should be caught and rethrown as a CloudFlareError so that all errors can be caught without specifying multiple exception classes.

HTTPError: 500 Server Error: Internal Server Error for url: https://api.cloudflare.com/client/v4/zones/...

screen shot 2018-08-06 at 11 49 24 am

No firewall.rules in module

I trying to use this api method, but i get error:

Traceback (most recent call last):
  File "Projects/tg/cloudflare_bot/main.py", line 138, in <module>
    pprint(cf.get_fw_rules(data['id']))
  File "Projects/tg/cloudflare_bot/main.py", line 28, in get_fw_rules
    return self.zones.firewall.rules.get(identifier)
AttributeError: '_add_unused' object has no attribute 'rules'

Code:


class CFAPI(CloudFlare):

    def __init__(self, token, email):
        super().__init__(token=token, email=email, debug=True)

    def get_fw_rules(self, identifier):
        #print(dir(self.zones.firewall))
        return self.zones.firewall.rules.get(identifier)

cf = CFAPI(CLOUDFLARE_API, CLOUDFLARE_EMAIL)
pprint(cf.get_fw_rules(data['id']))

I tried to check this with dir(self.zones.firewall), but I didn’t get rules in the list. Can you fix this?

[Question] DNS Zone Import

Hi,

I'm trying to call the dns_records/import endpoint using this python lib, but I can't find how to do it.

Please someone provide an example (add this one to examples directory).

Regards

Trying to use X-Auth-Key instead of X-Auth-Token?

Hi,

First time user of this module, with v. 2.3.0 from pypi.

I am doing the very simple example of listing zones. I generated an API token.

 def get_cf_dns(cftoken):                          
      cf = CloudFlare.CloudFlare(debug=True, token=cftoken)                                                                                        
      zones = cf.zones.get()                        
      for zone in zones:                            
          zone_id = zone['id']                      
          zone_name = zone['name']                  
          print(zone_id, zone_name)

The output throws me off with

2019-10-21 19:58:22,764 - Python Cloudflare API v4 - DEBUG - Response: url https://api.cloudflare.com/client/v4/zones
2019-10-21 19:58:22,764 - Python Cloudflare API v4 - DEBUG - Response: 400, application/json, {"success":false,"errors":[{"code":6003,"message":"Invalid request headers","error_chain":[{"code":6103,"message":"Invalid format for X-Auth-Key header"}]}],"messages":[],"result":null}
2019-10-21 19:58:22,764 - Python Cloudflare API v4 - DEBUG - Response: error 6003 Invalid request headers
Traceback (most recent call last):
  File "./main.py", line 39, in <module>
    get_cf_dns(cftoken)
  File "./main.py", line 30, in get_cf_dns
    zones = cf.zones.get()
  File "/home/xxx/.virtualenvs/cloudflare_vault_py-a7RkIZod/lib/python3.7/site-packages/CloudFlare/cloudflare.py", line 618, in get
    params, data)
  File "/home/xxx/.virtualenvs/cloudflare_vault_py-a7RkIZod/lib/python3.7/site-packages/CloudFlare/cloudflare.py", line 75, in call_with_auth
    params, data, files)
  File "/home/xxx/.virtualenvs/cloudflare_vault_py-a7RkIZod/lib/python3.7/site-packages/CloudFlare/cloudflare.py", line 467, in _call
    raise CloudFlareAPIError(code, message, error_chain)
CloudFlare.exceptions.CloudFlareAPIError: Invalid request headers

It's talking about the X-Auth-Key header, whereas I am guessing it should not since it is really a token and I am not passing any email parameter?

I validated my token against CF with curl, all good and sound:

{
  "result": {
    "id": "xxx",
    "status": "active"
  },
  "success": true,
  "errors": [],
  "messages": [
    {
      "code": 10000,
      "message": "This API Token is valid and active",
      "type": null
    }
  ]
}

Thanks.

Python 3.8 warnings about "is with a literal"

Python 3.8 is now displaying warnings when is is used with a literal.

Here are the warnings with 2.4.0:

/usr/lib/python3.8/site-packages/CloudFlare/cloudflare.py:839: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if email is '':
/usr/lib/python3.8/site-packages/CloudFlare/cloudflare.py:841: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if token is '':
/usr/lib/python3.8/site-packages/CloudFlare/cloudflare.py:843: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if certtoken is '':

See python/cpython#9642 for more info

I am also submitting a PR with a fix.

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.