Fix regression in Cloudflare library
diff --git a/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py b/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py
index 81c053c04fa..b72f19f0816 100644
--- a/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py
+++ b/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py
@@ -39,7 +39,7 @@
 zones you need certificates for.
 
 Using Cloudflare Tokens also requires at least version 2.3.1 of the ``cloudflare``
-python module. If the version that automatically installed with this plugin is
+Python module. If the version that automatically installed with this plugin is
 older than that, and you can't upgrade it on your system, you'll have to stick to
 the Global key.
 
@@ -77,6 +77,18 @@
 including for renewal, and cannot be silenced except by addressing the issue
 (e.g., by using a command like ``chmod 600`` to restrict access to the file).
 
+.. note::
+    Please note that the ``cloudflare`` Python module used by the plugin has
+    additional methods of providing credentials to the module, e.g. environment
+    variables or the ``cloudflare.cfg`` configuration file. These methods are not
+    supported by Certbot. If any of those additional methods of providing
+    credentials is being used, they must provide the same credentials (i.e.,
+    email and API key *or* an API token) as the credentials file provided to
+    Certbot. If there is a discrepancy, the ``cloudflare`` Python module will
+    raise an error. Also note that the credentials provided to Certbot will take
+    precedence over any other method of providing credentials to the ``cloudflare``
+    Python module.
+
 
 Examples
 --------
diff --git a/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py b/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py
index eac29a85b9d..e8bf560c682 100644
--- a/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py
+++ b/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py
@@ -82,8 +82,9 @@ def _get_cloudflare_client(self) -> "_CloudflareClient":
         if not self.credentials:  # pragma: no cover
             raise errors.Error("Plugin has not been prepared.")
         if self.credentials.conf('api-token'):
-            return _CloudflareClient(None, self.credentials.conf('api-token'))
-        return _CloudflareClient(self.credentials.conf('email'), self.credentials.conf('api-key'))
+            return _CloudflareClient(api_token = self.credentials.conf('api-token'))
+        return _CloudflareClient(email = self.credentials.conf('email'),
+                                 api_key = self.credentials.conf('api-key'))
 
 
 class _CloudflareClient:
@@ -91,8 +92,19 @@ class _CloudflareClient:
     Encapsulates all communication with the Cloudflare API.
     """
 
-    def __init__(self, email: Optional[str], api_key: str) -> None:
-        self.cf = CloudFlare.CloudFlare(email, api_key)
+    def __init__(self, email: Optional[str] = None, api_key: Optional[str] = None,
+                 api_token: Optional[str] = None) -> None:
+        if email:
+            # If an email was specified, we're using an email/key combination and not a token.
+            # We can't use named arguments in this case, as it would break compatibility with
+            # the Cloudflare library since version 2.10.1, as the `token` argument was used for
+            # tokens and keys alike and the `key` argument did not exist in earlier versions.
+            self.cf = CloudFlare.CloudFlare(email, api_key)
+        else:
+            # If no email was specified, we're using just a token. Let's use the named argument
+            # for simplicity, which is compatible with all (current) versions of the Cloudflare
+            # library.
+            self.cf = CloudFlare.CloudFlare(token=api_token)
 
     def add_txt_record(self, domain: str, record_name: str, record_content: str,
                        record_ttl: int) -> None:
diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md
index 018eaa0491c..d02d2cdbaca 100644
--- a/certbot/CHANGELOG.md
+++ b/certbot/CHANGELOG.md
@@ -14,7 +14,10 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
 
 ### Fixed
 
-*
+* Fixed an incompatibility in the certbot-dns-cloudflare plugin and the Cloudflare library
+  which was introduced in the Cloudflare library version 2.10.1. The library would raise
+  an error if a token was specified in the Certbot `--dns-cloudflare-credentials` file as
+  well as the `cloudflare.cfg` configuration file of the Cloudflare library.
 
 More details about these changes can be found on our GitHub repo.
 

Fixes #9407

## Pull Request Checklist

- [x] The Certbot team has recently expressed interest in reviewing a PR for this. If not, this PR may be closed due our limited resources and need to prioritize how we spend them. (https://github.com/certbot/certbot/issues/9407#issuecomment-1257842294)
- [X] If the change being made is to a [distributed component](https://certbot.eff.org/docs/contributing.html#code-components-and-layout), edit the `master` section of `certbot/CHANGELOG.md` to include a description of the change being made.
- [X] Add or update any documentation as needed to support the changes in this PR.