Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wait for ansible 2.10 release on RHEL] Rename cloudflare_account_api_token variable to avoid HTTP 400 errors. #86

Open
giannisalinetti opened this issue Feb 16, 2020 · 13 comments
Assignees

Comments

@giannisalinetti
Copy link

giannisalinetti commented Feb 16, 2020

The variable cloudflare_account_api_token should be renamed accordingly since the user should provide a global key and not an api token. The current naming leads to possible misunderstanng errors.

Steps to reproduce

Obtain an API Token in Cloudflare and assign it to the cloudflare_account_api_token.
Run the playbook.

Expected error message

The message will appear in the Ansible logs.

API bad request; Status: 400; Method: GET: Call: /zones?name=rhocplab.com; Error details: code: 6003, error: Invalid request headers; code: 6103, error: Invalid format for X-Auth-Key header;

Causes

When passing an
In Cloudflare APIs tokens are consumed as bearer token while global keys are consumed as X-Auth-Token.

The ansible module cloudflare_dns despite calling the related parameter account_api_token, sends a request passing an X-Auth-Token header. To match the kind of header the user should provide a global key.

Resolution

To help users to not fall in this issue I suggest to rename our variable cloudflare_account_api_token to cloudflare_account_global_key.

@giannisalinetti
Copy link
Author

If agreed, I would be happy to create a pull request to update the variable name.

@tomazb
Copy link

tomazb commented Feb 22, 2020

Cloudflare support is broken, because of this bug.

@giannisalinetti
Copy link
Author

giannisalinetti commented Feb 26, 2020

Update:

The cloudflare module issue has been fixed upstream. Now the module supports both api_token (using Authentication: Bearer) and account_api_key (using X-Auth-Key).
This is the related pull request:
ansible/ansible#62043
The latest Ansible version available on CentOS 7.7 is 2.7.5 which does not include the fix.

In my opinion there are two possible soultions:

  • Temporary add the updated module in a library folder in the project repository
  • Use the suggested variable name (cloudflare_account_global_key) in the role defaults to help users choose the correct approach. This option has a major drawback: the account global key opens up a greater attack surface from the security point of view while the api token can be profiled to work only on the specific domain.

@rbo rbo self-assigned this Feb 28, 2020
@giannisalinetti
Copy link
Author

@rbo can I help with a PR? If yes, which approach would be best?

@rbo
Copy link
Contributor

rbo commented Mar 4, 2020

Sure, PR always welcome! To be honest I don't know which approach ist the best. I had it to work-a-round if someone brakes an api. The suggested solution, sounds good:

  • Temporary add the updated module in a library folder in the project repository
  • Use the suggested variable name (cloudflare_account_global_key) in the role defaults to help users choose the correct approach. This option has a major drawback: the account global key opens up a greater attack surface from the security point of view while the api token can be profiled to work only on the specific domain.

We have to clean up the variables names too :-/

@giannisalinetti
Copy link
Author

The two options exclude each other.
If we include the module in a library folder we only have to modify the task in the related role and we can leave the exposed variable name unset in the defaults. This option requires more testing, too.

If we update the variable name and the documentation to direct users to use the account global key there is no need to change the module since we are going to use the old one. The only issue with this approach is from security point of view.

@rbo
Copy link
Contributor

rbo commented Mar 12, 2020

A little summery to understand the problem:

Cloudflare supports two kinds of API-Tokens:

  1. API-Token - related to one ore more zones and privileges. Example Curl:
    curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
        -H "Authorization: Bearer xxxxxxxxx" \
        -H "Content-Type:application/json"
    
  2. Global API Key - global account api key
     curl -X GET "https://api.cloudflare.com/client/v4/zones/$CF_Zone/dns_records?type=A,SRV" \
        -H "X-Auth-Email: $CF_Email" \
        -H "X-Auth-Key: $CF_Key" \
        -H "Content-Type: application/json" \
    

Ansible module cloudflare_dns supports ONLY 2. global account api key*

That means, hetzner-ocp4 also only support the global api key authentication.

With PR #62707 the ansible module cloudflare_dns changed the name from account_api_token to account_api_key. account_api_key is still an alias of account_api_token for backward compatibility.

* Ansible 2.10 add support for 1. API-Token.


Got it, the nameing is not perfect with cloudflare_account_api_token

    account_email: "{{ cloudflare_account_email }}"
    account_api_token: "{{ cloudflare_account_api_token }}"

BUT it's NOT breaking the function of hetzner-ocp4 & together with cloudflare. Of curse you have to use the global account key!

We should improve the documentation and if ansible 2.10 is available add the support for API-Token.

If someone provide a patch to rename cloudflare_account_api_token into cloudflare_account_(global)_api_key - I'm fine with that but cloudflare_account_api_token should be still available for backward compatibility.

rbo added a commit that referenced this issue Mar 12, 2020
@rbo
Copy link
Contributor

rbo commented Mar 12, 2020

Added some notes to documentation.

@rbo
Copy link
Contributor

rbo commented Jul 30, 2020

Ansible 2.9 on RHEL 8 still not support API-Token:

$ ansible --version
ansible 2.9.11
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, Dec  5 2019, 15:45:45) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
$ grep -B5 -A5 headers /usr/lib/python3.6/site-packages/ansible/modules/net_tools/cloudflare_dns.py
        if (self.type == 'DS'):
            if self.record == self.zone:
                self.module.fail_json(msg="DS records only apply to subdomains.")

    def _cf_simple_api_call(self, api_call, method='GET', payload=None):
        headers = {'X-Auth-Email': self.account_email,
                   'X-Auth-Key': self.account_api_token,
                   'Content-Type': 'application/json'}
        data = None
        if payload:
            try:
--
            except Exception as e:
                self.module.fail_json(msg="Failed to encode payload as JSON: %s " % to_native(e))

        resp, info = fetch_url(self.module,
                               self.cf_api_endpoint + api_call,
                               headers=headers,
                               data=data,
                               method=method,
                               timeout=self.timeout)

        if info['status'] not in [200, 304, 400, 401, 403, 429, 405, 415]:
$

@rbo rbo added the wait-for Wait for something ⏳ label Dec 23, 2020
@rbo rbo changed the title Rename cloudflare_account_api_token variable to avoid HTTP 400 errors. [wait for ansible 2.10 release on RHEL] Rename cloudflare_account_api_token variable to avoid HTTP 400 errors. Dec 23, 2020
@rbo
Copy link
Contributor

rbo commented Mar 19, 2021

Ansible 2.9 on RHEL 8 still not support API-Token: ansible-2.9.19-1.el8ae.noarch.rpm

$  ansible --version
ansible 2.9.19
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, Aug 18 2020, 08:33:21) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
$ grep -B5 -A5 headers /usr/lib/python3.6/site-packages/ansible/modules/net_tools/cloudflare_dns.py
        if (self.type == 'DS'):
            if self.record == self.zone:
                self.module.fail_json(msg="DS records only apply to subdomains.")

    def _cf_simple_api_call(self, api_call, method='GET', payload=None):
        headers = {'X-Auth-Email': self.account_email,
                   'X-Auth-Key': self.account_api_token,
                   'Content-Type': 'application/json'}
        data = None
        if payload:
            try:
--
            except Exception as e:
                self.module.fail_json(msg="Failed to encode payload as JSON: %s " % to_native(e))

        resp, info = fetch_url(self.module,
                               self.cf_api_endpoint + api_call,
                               headers=headers,
                               data=data,
                               method=method,
                               timeout=self.timeout)

        if info['status'] not in [200, 304, 400, 401, 403, 429, 405, 415]:
$ 

@rbo
Copy link
Contributor

rbo commented Dec 2, 2022

With the ansible-navigator, we can add supported for cloud-flare api token:

$ podman run -ti --rm quay.io/redhat-emea-ssa-team/hetzner-ocp4-ansible-ee:master ansible --version
/usr/local/lib/python3.8/site-packages/paramiko/transport.py:236: CryptographyDeprecationWarning: Blowfish has been deprecated
  "class": algorithms.Blowfish,
ansible [core 2.12.2.post0]
  config file = None
  configured module search path = ['/home/runner/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.8/site-packages/ansible
  ansible collection location = /home/runner/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.8.12 (default, Sep 21 2021, 00:10:52) [GCC 8.5.0 20210514 (Red Hat 8.5.0-3)]
  jinja version = 2.10.3
  libyaml = True

$ podman run -ti --rm quay.io/redhat-emea-ssa-team/hetzner-ocp4-ansible-ee:master  grep -B5 -A5 headers /usr/share/ansible/collections/ansible_collections/community/general/plugins/modules/net_tools/cloudflare_dns.py
            if self.record == self.zone:
                self.module.fail_json(msg="DS records only apply to subdomains.")

    def _cf_simple_api_call(self, api_call, method='GET', payload=None):
        if self.api_token:
            headers = {
                'Authorization': 'Bearer ' + self.api_token,
                'Content-Type': 'application/json',
            }
        else:
            headers = {
                'X-Auth-Email': self.account_email,
                'X-Auth-Key': self.account_api_key,
                'Content-Type': 'application/json',
            }
        data = None
--
            except Exception as e:
                self.module.fail_json(msg="Failed to encode payload as JSON: %s " % to_native(e))

        resp, info = fetch_url(self.module,
                               self.cf_api_endpoint + api_call,
                               headers=headers,
                               data=data,
                               method=method,
                               timeout=self.timeout)

        if info['status'] not in [200, 304, 400, 401, 403, 429, 405, 415]:

@rbo rbo removed the wait-for Wait for something ⏳ label Dec 16, 2022
@rbo
Copy link
Contributor

rbo commented Dec 16, 2022

First version (not tested yet) at branche issuer-86

@rbo
Copy link
Contributor

rbo commented Dec 16, 2022

failed: [host -> localhost] (item=*.apps) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "account_api_key": null,
            "account_email": null,
            "algorithm": null,
            "api_token": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "cert_usage": null,
            "hash_type": null,
            "key_tag": null,
            "port": null,
            "priority": 1,
            "proto": null,
            "proxied": false,
            "record": "*.apps.tester.openshift.pub",
            "selector": null,
            "service": null,
            "solo": null,
            "state": "present",
            "timeout": 30,
            "ttl": 1,
            "type": "A",
            "value": "116.202.157.224",
            "weight": 1,
            "zone": "openshift.pub"
        }
    },
    "item": "*.apps",
    "msg": "API bad request; Status: 400; Method: GET: Call: /zones?name=openshift.pub; Error details: code: 6003, error: Invalid request headers; code: 6111, error: Invalid format for Authorization header; "

@rbo rbo mentioned this issue Dec 16, 2022
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants