libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From clewo...@apache.org
Subject [libcloud] branch trunk updated: Enable auth to Cloudflare DNS via API Tokens (#1564)
Date Sun, 14 Mar 2021 00:25:24 GMT
This is an automated email from the ASF dual-hosted git repository.

clewolff pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/libcloud.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 1dfd3cd  Enable auth to Cloudflare DNS via API Tokens (#1564)
1dfd3cd is described below

commit 1dfd3cdc9663f79e49ceaaa9ecb31c0b59167569
Author: Clemens Wolff <clewolff@apache.org>
AuthorDate: Sat Mar 13 19:25:17 2021 -0500

    Enable auth to Cloudflare DNS via API Tokens (#1564)
---
 CHANGES.rst                                        |  6 +++++
 docs/dns/drivers/cloudflare.rst                    |  8 +++++-
 .../dns/cloudflare/instantiate_driver_token.py     |  5 ++++
 libcloud/dns/drivers/cloudflare.py                 | 31 ++++++++++++++++++----
 libcloud/test/dns/test_cloudflare.py               | 10 +++++++
 5 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index b0fab73..5455c60 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -41,6 +41,12 @@ Compute
   (GITHUB-1555)
   [Rob Juffermans - @robjuffermans]
 
+DNS
+~~~
+
+- [CloudFlare] Enable authentication via API Tokens.
+  [Clemens Wolff - @c-w]
+
 Changes in Apache Libcloud 3.3.1
 --------------------------------
 
diff --git a/docs/dns/drivers/cloudflare.rst b/docs/dns/drivers/cloudflare.rst
index b55951e..fb814d7 100644
--- a/docs/dns/drivers/cloudflare.rst
+++ b/docs/dns/drivers/cloudflare.rst
@@ -13,12 +13,18 @@ Instantiating the driver
 ------------------------
 
 To instantiate the driver you need to pass email address associated with your
-account and API key available on the `account page`_ to the driver constructor
+account and a Global API key available on the `account page`_ to the driver constructor
 as shown below.
 
 .. literalinclude:: /examples/dns/cloudflare/instantiate_driver.py
    :language: python
 
+Alternatively, authentication can also be done via an API Token as shown below.
+It is recommended that the token at least has the Zone.DNS permissions.
+
+.. literalinclude:: /examples/dns/cloudflare/instantiate_driver_token.py
+   :language: python
+
 API Docs
 --------
 
diff --git a/docs/examples/dns/cloudflare/instantiate_driver_token.py b/docs/examples/dns/cloudflare/instantiate_driver_token.py
new file mode 100644
index 0000000..ebda102
--- /dev/null
+++ b/docs/examples/dns/cloudflare/instantiate_driver_token.py
@@ -0,0 +1,5 @@
+from libcloud.dns.types import Provider
+from libcloud.dns.providers import get_driver
+
+cls = get_driver(Provider.CLOUDFLARE)
+driver = cls('<api token>')
diff --git a/libcloud/dns/drivers/cloudflare.py b/libcloud/dns/drivers/cloudflare.py
index 84bb5bd..af6b36e 100644
--- a/libcloud/dns/drivers/cloudflare.py
+++ b/libcloud/dns/drivers/cloudflare.py
@@ -20,7 +20,8 @@ __all__ = [
 import itertools
 import json
 
-from libcloud.common.base import JsonResponse, ConnectionUserAndKey
+from libcloud.common.base import ConnectionKey, ConnectionUserAndKey
+from libcloud.common.base import JsonResponse
 from libcloud.common.types import InvalidCredsError, LibcloudError
 from libcloud.dns.base import DNSDriver, Zone, Record
 from libcloud.dns.types import Provider, RecordType
@@ -146,11 +147,16 @@ class CloudFlareDNSResponse(JsonResponse):
             raise exception_class(**kwargs)
 
 
-class CloudFlareDNSConnection(ConnectionUserAndKey):
+class BaseDNSConnection(object):
     host = API_HOST
     secure = True
     responseCls = CloudFlareDNSResponse
 
+    def encode_data(self, data):
+        return json.dumps(data)
+
+
+class GlobalAPIKeyDNSConnection(BaseDNSConnection, ConnectionUserAndKey):
     def add_default_headers(self, headers):
         headers['Content-Type'] = 'application/json'
         headers['X-Auth-Email'] = self.user_id
@@ -158,15 +164,20 @@ class CloudFlareDNSConnection(ConnectionUserAndKey):
 
         return headers
 
-    def encode_data(self, data):
-        return json.dumps(data)
+
+class TokenDNSConnection(BaseDNSConnection, ConnectionKey):
+    def add_default_headers(self, headers):
+        headers['Content-Type'] = 'application/json'
+        headers['Authorization'] = 'Bearer %s' % self.key
+
+        return headers
 
 
 class CloudFlareDNSDriver(DNSDriver):
     type = Provider.CLOUDFLARE
     name = 'CloudFlare DNS'
     website = 'https://www.cloudflare.com'
-    connectionCls = CloudFlareDNSConnection
+    connectionCls = GlobalAPIKeyDNSConnection
 
     RECORD_TYPE_MAP = {
         RecordType.A: 'A',
@@ -184,6 +195,16 @@ class CloudFlareDNSDriver(DNSDriver):
     RECORDS_PAGE_SIZE = 100
     MEMBERSHIPS_PAGE_SIZE = 50
 
+    def __init__(self, key, secret=None, secure=True, host=None, port=None,
+                 **kwargs):
+
+        if secret is None:
+            self.connectionCls = TokenDNSConnection
+
+        super(CloudFlareDNSDriver, self).__init__(
+            key=key, secret=secret, secure=secure,
+            host=host, port=port, **kwargs)
+
     def iterate_zones(self):
         def _iterate_zones(params):
             url = '{}/zones'.format(API_BASE)
diff --git a/libcloud/test/dns/test_cloudflare.py b/libcloud/test/dns/test_cloudflare.py
index 125edf2..5f97c55 100644
--- a/libcloud/test/dns/test_cloudflare.py
+++ b/libcloud/test/dns/test_cloudflare.py
@@ -21,6 +21,8 @@ from libcloud.common.types import LibcloudError
 from libcloud.test import unittest
 
 from libcloud.dns.drivers.cloudflare import CloudFlareDNSDriver
+from libcloud.dns.drivers.cloudflare import GlobalAPIKeyDNSConnection
+from libcloud.dns.drivers.cloudflare import TokenDNSConnection
 from libcloud.dns.drivers.cloudflare import ZONE_EXTRA_ATTRIBUTES
 from libcloud.dns.drivers.cloudflare import RECORD_EXTRA_ATTRIBUTES
 from libcloud.dns.types import RecordType
@@ -42,6 +44,14 @@ class CloudFlareDNSDriverTestCase(unittest.TestCase):
         CloudFlareMockHttp.use_param = 'a'
         self.driver = CloudFlareDNSDriver(*DNS_PARAMS_CLOUDFLARE)
 
+    def test_auth_key(self):
+        driver = CloudFlareDNSDriver('user@example.com', 'key')
+        self.assertEqual(driver.connectionCls, GlobalAPIKeyDNSConnection)
+
+    def test_auth_token(self):
+        driver = CloudFlareDNSDriver('sometoken')
+        self.assertEqual(driver.connectionCls, TokenDNSConnection)
+
     def test_list_record_types(self):
         record_types = self.driver.list_record_types()
         self.assertEqual(len(record_types), 9)


Mime
View raw message