ansible-collections / cisco.iosxr

Ansible Network Collection for Cisco IOSXR
GNU General Public License v3.0
69 stars 48 forks source link

IOS/XR iosxr_user module on 5.3 and 6.1 release does not work #328

Open pimvanpelt opened 1 year ago

pimvanpelt commented 1 year ago
SUMMARY

Is cisco.iosxr.iosxr_user meant to work on old IOS/XR versions? Notably:

Cisco IOS XR Software, Version 6.1.3[Default]
Cisco IOS XR Software, Version 5.3.4[Default]

The former is an IOS XRv instance that I am developing on, and the latter are ASR9001/9006/9010 running in production at 5.3 version. Upgrading them is difficult due to older RSP/linecard combos.

Calling something like:

$ cat roles/iosxr-users/tasks/main.yml
- name: User exists
  cisco.iosxr.iosxr_user:
    name: dapke
    configured_password: mypassword
    admin: true
    state: present
$ ---
- name: Configure Users on IOS-XR devices
  hosts: iosxr
  gather_facts: false
  connection: netconf # network_cli
  vars_files: config/iosxr-vault.yml
  roles:
    - { role: iosxr-users, tags: users }

Will return:

The full traceback is:
  File "/usr/local/lib/python3.9/site-packages/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py", line 123, in get_capabilities
    capabilities = Connection(module._socket_path).get_capabilities()
  File "/usr/local/lib/python3.9/site-packages/ansible/module_utils/connection.py", line 200, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
[WARNING]: Module did not set no_log for update_password
fatal: [xrv01.zrh56.mgmt.ip-max.net]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "admin": true,
            "aggregate": null,
            "configured_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "group": null,
            "groups": null,
            "name": "dapke",
            "public_key": null,
            "public_key_contents": null,
            "purge": false,
            "state": "present",
            "update_password": "always"
        }
    },
    "msg": "name 'etree' is not defined"
}

Using network_cli transport also fails:

[WARNING]: ansible-pylibssh not installed, falling back to paramiko
The full traceback is:
  File "/usr/local/lib/python3.9/site-packages/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py", line 470, in load_config
    response = conn.edit_config(
  File "/usr/local/lib/python3.9/site-packages/ansible/module_utils/connection.py", line 200, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
[WARNING]: Module did not set no_log for update_password
fatal: [xrv01.zrh56.mgmt.ip-max.net]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "admin": true,
            "aggregate": null,
            "configured_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "group": null,
            "groups": null,
            "name": "dapke",
            "public_key": null,
            "public_key_contents": null,
            "purge": false,
            "state": "present",
            "update_password": "always"
        }
    },
    "msg": "commit show-error\r\n\r                                      ^\r\n% Invalid input detected at '^' marker.\r\nRP/0/0/CPU0:ios(admin-config)#"
}
ISSUE TYPE
COMPONENT NAME

Component is iosxr_user.

ANSIBLE VERSION
ansible [core 2.13.2]
  config file = /usr/home/pim/src/ipmax-ansible/ansible.cfg
  configured module search path = ['/home/pim/.ansible/plugins/modules', '/usr/local/share/py39-ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
  ansible collection location = /home/pim/.ansible/collections:/usr/local/share/py39-ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.9.16 (main, Dec 17 2022, 01:13:33) [Clang 13.0.0 (git@github.com:llvm/llvm-project.git llvmorg-13.0.0-0-gd7b669b3a
  jinja version = 3.0.1
  libyaml = True
ashwini-mhatre commented 1 year ago

could you please try without admin: true?

- name: User exists
  cisco.iosxr.iosxr_user:
    name: dapke
    configured_password: mypassword
    state: present
pimvanpelt commented 1 year ago

Confirmed success without admin key set. While doing this, I realised that if the user exists in the admin scope, you cannot create it in the non-admin scope.

To recap:

pimvanpelt commented 1 year ago

Related to this - when creating a user with public_key_contents and admin:false, the resulting command is incorrect:

crypto key import authentication rsa username dapke harddisk:/publickey_dapke.b64

IOS/XR wants the non-admin case to be crypto key import authentication rsa <filename> which will be read into the key as the current connected user, and in the admin case it must include the ...username <user> ... part, in which case it will be read into the key of the specified user.

The module will successfully copy the key into harddisk:/publickey_dapke.b64 but it cannot apply it:

"module_stderr": "crypto key import authentication rsa username dapke harddisk:/publickey_dapke.b64\r\n\r                                                            ^\r\n% Invalid input detected at '^' marker.\r\n
RP/0/0/CPU0:ios#", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error"}

This variant of the command can not succeed - the command pattern crypto ... username ... is only available in admin scope.

In non-admin scope:

RP/0/0/CPU0:ios#crypto key import authentication rsa ?
  WORD  Path to RSA pubkey file

In admin scope:

RP/0/0/CPU0:ios(admin)#crypto key import authentication rsa ?            
  username  Username
RP/0/0/CPU0:ios(admin)#crypto key import authentication rsa username dapke ?                          
  WORD  Path to RSA pubkey file
RP/0/0/CPU0:ios(admin)#crypto key import authentication rsa username dapke harddisk:/publickey_dapke.b64

.. after which the key is imported. I think that this implies that the module can only ever import an sshkey if it specifies admin:true.

pimvanpelt commented 1 year ago

Current state of this bugreport:

pimvanpelt commented 1 year ago

A workaround is to have two tasks, one to create the user (in non-admin) and then one to set the sshkey (in admin):

- name: User exists
  cisco.iosxr.iosxr_user:
    name: "{{ item.key }}"
    state: "{{ item.value.state | default('present') }}"
    configured_password: "{{ item.value.password }}"
    update_password: "on_create"
    group: "{{ item.value.group | default('root-system') }}"
  loop: "{{ iosxr_users.users | dict2items }}"
  loop_control:
    label: "{{ item.key }}"

- name: User SSH Key exists
  cisco.iosxr.iosxr_user:
    name: "{{ item.key }}"
    public_key_contents: "{{ item.value.sshkey }}"
    admin: true
  when: (item.value.state | default('present') == 'present') and (item.value.sshkey is defined)
  loop: "{{ iosxr_users.users | dict2items }}"
  loop_control:
    label: "{{ item.key }}"
jorgenspange commented 1 year ago

Good day, @ashwini-mhatre @pimvanpelt

Seems to be some other problems aswell:

When trying to purge all users except admin it does not work in the admin space:

- name: configure_cisco.iosxr.iosxr | Purge all users except admin in admin scope.
  cisco.iosxr.iosxr_user:
    purge: true
    admin: true

It says okey, but no users are removed:

ok: [9K1] => changed=false
  commands: []
  invocation:
    module_args:
      admin: true
      aggregate: null
      configured_password: null
      group: null
      groups: null
      name: null
      public_key: null
      public_key_contents: null
      purge: true
      state: present
      update_password: always

Root user is still there:

RP/0/RSP0/CPU0:9K1#admin show run username
Mon Oct 23 12:56:09.722 CET
username root
 group root-system
 secret 5 ....
!
username admin
 group root-system
 secret 5 ....
!

When doing it without admin: true it works, but only for standard scope.

Also when creating users it fails, I've tried all kinds of ways to play this tasks, but fails like this:

The full traceback is:
  File "/Users/jorgenspange/.ansible/collections/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py", line 467, in load_config
    response = conn.edit_config(
               ^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/ansible/8.5.0_1/libexec/lib/python3.11/site-packages/ansible/module_utils/connection.py", line 200, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
fatal: [9K1]: FAILED! => changed=false
  invocation:
    module_args:
      admin: false
      aggregate:
      - admin: true
        configured_password: VALUE_SPECIFIED_IN_NO_LOG_PARAMETER
        group: root-system
        groups: null
        name: admin
        public_key: null
        public_key_contents: null
        state: present
        update_password: on_create
      configured_password: null
      group: null
      groups: null
      name: null
      public_key: null
      public_key_contents: null
      purge: false
      state: present
      update_password: always
  msg: |-
    commit show-error

    % Failed to commit one or more configuration items during a pseudo-atomic operation. All changes made have been reverted.
- name: configure_cisco.iosxr.iosxr | Configure local admin user in admin scope.
  cisco.iosxr.iosxr_user:
    aggregate:
      - name: admin
        admin: true
        update_password: on_create
        group: root-system
        configured_password: "{{ user_admin_password }}"
    state: present

Best regards