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

Unsupported parameters for (freeipa.ansible_freeipa.ipaclient_get_otp) module: password #608

Open
The-Judge opened this issue Jul 27, 2021 · 11 comments

Comments

@The-Judge
Copy link

Hi,

I am trying to apply the ipaclient role to a Debian buster node. In task Install - Get One-Time Password for client enrollment it fails:

fatal: [idtestlxc -> id1.my-dom.cloud]: FAILED! => {
    "changed": false,
    "failed_when_result": true,
    "invocation": {
        "module_args": {
            "ccache": null,
            "certificates": null,
            "fqdn": "idtestlxc",
            "ipaddress": null,
            "password": "**REMOVED**",
            "principal": "admin",
            "random": true,
            "sshpubkey": null,
            "state": "present"
        }
    },
    "msg": "Unsupported parameters for (freeipa.ansible_freeipa.ipaclient_get_otp) module: password. Supported parameters include: sshpubkey, random, fqdn, state, ccache, certificates, ipaddress, principal."
}

The value used for password is the value that is defined for ipaadmin_password. From the docs, it seems to be used correctly here; see 4th example in Usage section.

These are the parameters defined for idtestlxc and id1:

ansible $ ansible-inventory --host idtestlxc
{
    "ansible_host": "idtestlxc.my-dom.cloud",
    "ipaadmin_password": "{{ vault_ipaadmin_password }}",
    "ipaadmin_principal": "{{ vault_ipaadmin_principal }}",
    "ipaclient_install_packages": true,
    "ipaclient_no_ntp": true,
    "ipaclient_servers": "id1.my-dom.cloud,id2.my-dom.cloud",
    "ipaclient_use_otp": true,
    "ipadm_password": "{{ vault_ipadm_password }}",
    "ipaserver_auto_forwarders": false,
    "ipaserver_domain": "id.my-dom.cloud",
    "ipaserver_realm": "ID.MY-DOM.CLOUD",
    "ipaserver_setup_dns": true,
    "vault_ipaadmin_password": "**REMOVED**",
    "vault_ipaadmin_principal": "admin",
    "vault_ipadm_password": "**REMOVED**"
}

ansible $ ansible-inventory --host id1
{
    "ansible_host": "id1.my-dom.cloud",
    "ipaadmin_password": "{{ vault_ipaadmin_password }}",
    "ipaadmin_principal": "{{ vault_ipaadmin_principal }}",
    "ipadm_password": "{{ vault_ipadm_password }}",
    "ipaserver_auto_forwarders": false,
    "ipaserver_domain": "id.my-dom.cloud",
    "ipaserver_install_packages": false,
    "ipaserver_realm": "ID.MY-DOM.CLOUD",
    "ipaserver_setup_adtrust": true,
    "ipaserver_setup_dns": true,
    "ipaserver_setup_firewalld": false,
    "vault_ipaadmin_password": "**REMOVED**",
    "vault_ipaadmin_principal": "admin",
    "vault_ipadm_password": "**REMOVED**"
}

So - can someone tell what's the issue here?

@The-Judge
Copy link
Author

The-Judge commented Jul 28, 2021

OK, I am finally confused:

I installed ansible_freeipa from Ansible Galaxy, version 0.3.8 . According to Ansible Galaxy, this is already the latest version, released 15 days ago.

From my local file ~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa/roles/ipaclient/library/ipaclient_get_otp.py:

...
DOCUMENTATION = '''
---
module: ipaclient_get_otp
short description: Manage IPA hosts
description:
  Manage hosts in a IPA domain.
  The operation needs to be authenticated with Kerberos either by providing
  a password or a keytab corresponding to a principal allowed to perform
  host operations.
options:
  principal:
    description:
      User Principal allowed to promote replicas and join IPA realm
    required: yes
  ccache:
    description: The local ccache
    required: yes
  fqdn:
    description:
      The fully-qualified hostname of the host to add/modify/remove
    required: no
  certificates:
    description: A list of host certificates
    required: yes
  sshpubkey:
    description: The SSH public key for the host
    required: yes
  ipaddress:
    description: The IP address for the host
    required: yes
  random:
    description: Generate a random password to be used in bulk enrollment
    required: yes
  state:
    description: The desired host state
    required: yes
author:
    - "Florence Blanc-Renaud"
'''

EXAMPLES = '''
# Example from Ansible Playbooks
# Add a new host with a random OTP, authenticate using principal/password
- freeipa.ansible_freeipa.ipaclient_get_otp:
    principal: admin
    password: MySecretPassword
    fqdn: ipaclient.ipa.domain.com
    ipaddress: 192.168.100.23
    random: True
  register: result_ipaclient_get_otp
'''

The DOCUMENTATION does not list password parameter anymore, but EXAMPLES does.
The DOCUMENTATION seems to be the more recent variant here, since in the same file (lines 272:286) it reads:

def main():

    module = AnsibleModule(
        argument_spec=dict(
            principal=dict(default='admin'),
            ccache=dict(required=False, type='path'),
            fqdn=dict(required=True),
            certificates=dict(required=False, type='list'),
            sshpubkey=dict(required=False),
            ipaddress=dict(required=False),
            random=dict(default=False, type='bool'),
            state=dict(default='present', choices=['present', 'absent']),
        ),
        supports_check_mode=True,
    )

No password parameter found.

But at the same time, this is what the file ~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa/roles/ipaclient/tasks/install.yml looks like in lines 113:130:

    - name: Install - Get One-Time Password for client enrollment
      no_log: yes
      freeipa.ansible_freeipa.ipaclient_get_otp:
        state: present
        principal: "{{ ipaadmin_principal | default(omit) }}"
        password: "{{ ipaadmin_password | default(omit) }}"
        keytab: "{{ ipaadmin_keytab | default(omit) }}"
        fqdn: "{{ result_ipaclient_test.hostname }}"
        lifetime: "{{ ipaclient_lifetime | default(omit) }}"
        random: True
      register: result_ipaclient_get_otp
      # If the host is already enrolled, this command will exit on error
      # The error can be ignored
      failed_when: result_ipaclient_get_otp is failed and
                   "Password cannot be set on enrolled host" not
                       in result_ipaclient_get_otp.msg
      delegate_to: "{{ result_ipaclient_test.servers[0] }}"
      ignore_errors: yes

Please notice the usage of password parameter, which the module shipped does not seem to support!

The same is true for current master state; see:

ipaclient/tasks/install.yml and ipaclient/library/ipaclient_get_otp.py lines 72 and 274:286.

@t-woerner
Copy link
Member

Have you removed the delegate_to line? The password is used by the action plugin action_plugins/ipaclient_get_otp.py which is using the module library/ipaclient_get_otp.

@The-Judge
Copy link
Author

The-Judge commented Jul 28, 2021

No, I did not touch the structure under ~/.ansible at all.
Seems like the password parameter was removed from library/ipaclient_get_otp.py in 2017 by 38d7223 already.

The only things I did (steps to reproduce):

  1. Install ansible_freeipa from Ansible Galaxy
  2. Created the following Playbook:
---
- name: Playbook to configure IPA clients with username/password
  hosts: ipaclients
  become: true
  vars:
    # See https://github.com/freeipa/ansible-freeipa/issues/607
    - ansible_python_interpreter: /usr/bin/python2

  roles:
    - role: freeipa.ansible_freeipa.ipaclient
      state: present
      when:
        - "'ipaclients' in group_names"

  1. Defined ipaadmin_password in group_vars
  2. Executed that play. The rest comes from what is shipped from the Galaxy.

PS: What do you mean by:

The password is used by the action plugin action_plugins/ipaclient_get_otp.py which is using the module library/ipaclient_get_otp.
?

@The-Judge
Copy link
Author

Did anyone have the time to look into this? Is any additional info required?

@t-woerner
Copy link
Member

Please add your inventory file and if you are using your own playbook for client deployment also the playbook.

@The-Judge
Copy link
Author

I think I shared most of it already:

My playbook as from comment 888346397:

---
- name: Playbook to configure IPA clients with username/password
  hosts: ipaclients
  become: true
  vars:
    # See https://github.com/freeipa/ansible-freeipa/issues/607
    - ansible_python_interpreter: /usr/bin/python2

  roles:
    - role: freeipa.ansible_freeipa.ipaclient
      state: present
      when:
        - "'ipaclients' in group_names"

My inventory"file" is a folder:

inventory/
|-- group_vars
|   |-- ipaserver
|   |   |-- vars
|   |   `-- vault
|   |-- all
|   |   |-- vars
|   |   `-- vault
|   |-- ipareplicas
|   |   |-- vars
|   |   `-- vault
|   |-- ipaclients
|   |   |-- vars
|   |   `-- vault
|   `-- ipacluster
|       |-- vars
|       `-- vault
|-- hosts.yaml
`-- host_vars
    |-- id2
    |   |-- vars
    |   `-- vault
    |-- idtestlxc
    |   |-- vars
    |   `-- vault
    |-- idtestvm
    |   |-- vars
    |   `-- vault
    `-- id1
        |-- vars
        `-- vault

My hosts.yaml:

---
all:
  children:

    vm_dev:
      hosts:
        idtestvm:

    lxc_dev:
      hosts:
        idtestlxc:

    # https://github.com/freeipa/ansible-freeipa/blob/master/README.md#ansible-inventory-file
    #
    ipaserver:
      hosts:
        id1:

    ipareplicas:
      hosts:
        id2:

    ipaclients:
      hosts:
        idtestlxc:
        idtestvm:

    ipacluster:
      children:
        ipaserver:
        ipareplicas:
        ipaclients:

The parameters are as shared in comment 953900070:

ansible $ ansible-inventory --host idtestlxc
{
    "ansible_host": "idtestlxc.my-dom.cloud",
    "ipaadmin_password": "{{ vault_ipaadmin_password }}",
    "ipaadmin_principal": "{{ vault_ipaadmin_principal }}",
    "ipaclient_install_packages": true,
    "ipaclient_no_ntp": true,
    "ipaclient_servers": "id1.my-dom.cloud,id2.my-dom.cloud",
    "ipaclient_use_otp": true,
    "ipadm_password": "{{ vault_ipadm_password }}",
    "ipaserver_auto_forwarders": false,
    "ipaserver_domain": "id.my-dom.cloud",
    "ipaserver_realm": "ID.MY-DOM.CLOUD",
    "ipaserver_setup_dns": true,
    "vault_ipaadmin_password": "**REMOVED**",
    "vault_ipaadmin_principal": "admin",
    "vault_ipadm_password": "**REMOVED**"
}

ansible $ ansible-inventory --host id1
{
    "ansible_host": "id1.my-dom.cloud",
    "ipaadmin_password": "{{ vault_ipaadmin_password }}",
    "ipaadmin_principal": "{{ vault_ipaadmin_principal }}",
    "ipadm_password": "{{ vault_ipadm_password }}",
    "ipaserver_auto_forwarders": false,
    "ipaserver_domain": "id.my-dom.cloud",
    "ipaserver_install_packages": false,
    "ipaserver_realm": "ID.MY-DOM.CLOUD",
    "ipaserver_setup_adtrust": true,
    "ipaserver_setup_dns": true,
    "ipaserver_setup_firewalld": false,
    "vault_ipaadmin_password": "**REMOVED**",
    "vault_ipaadmin_principal": "admin",
    "vault_ipadm_password": "**REMOVED**"
}

This is all there is. Please let me know if there is still anything missing.

@t-woerner
Copy link
Member

What are you using for vault_ipaadmin_principal? Please add the output of the ansible-playbook output (at best wth -vv).

@The-Judge
Copy link
Author

To be honest, I do not get what you need:

I can't provide the output anymore. This issue got reported on 27 Jul; I hope you understand that I do not abandon a project for more than 1.5 months, waiting for an upstream reply. The code got replaced with something else; I re-wrote large parts for my own use in the meantime.

But I think I provided everything to make this comprehensible even without the original code available. This is not a border-case that happens with a very specific combination of unusual components only, but obvious by just looking at the provided codes.

@t-woerner
Copy link
Member

No, there are two Ansible parts that are involved here. There is the action plugin https://github.com/freeipa/ansible-freeipa/blob/master/roles/ipaclient/action_plugins/ipaclient_get_otp.py . Only this action module is supporting the password parameter. This action module is creating a temporary ccache that is copied to the client and then calling https://github.com/freeipa/ansible-freeipa/blob/master/roles/ipaclient/library/ipaclient_get_otp.py internally without the password parameter (https://github.com/freeipa/ansible-freeipa/blob/master/roles/ipaclient/action_plugins/ipaclient_get_otp.py#L243). This separation is done to not have the need to transfer the password to the client.

The question is why this action plugin is not used in your environment.

@t-woerner
Copy link
Member

t-woerner commented Oct 13, 2021

There is a new ansible-freeipa 0.4.2 release that is fixing this issue finally. The issue was that the collection was using the wrong path for the action plugin. Therefore it was not used and the normal plugin was used instead.

@t-woerner
Copy link
Member

PR #987 is changing the code for OTP. The action plugin is removed and the OTP is generated on the first entry in the server list returned by ipaclient_test.

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

2 participants