ansible-collections / ansible.netcommon

Ansible Network Collection for Common Code
GNU General Public License v3.0
145 stars 104 forks source link

ansible.netcommon.network_cli doesn't consider ssh arguments for ciphers #430

Open iamgini opened 2 years ago

iamgini commented 2 years ago
SUMMARY

we want to use ansible.netcommon.network_cli (which is the recommended method over paramiko) but the old devices are only having old ciphers and unable to use it with ansible.netcommon.network_cli

 "msg": "ssh connection failed: ssh connect failed: kex error : no match for method kex algos: server [diffie-hellman-group1-sha1], client [curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512]"
ISSUE TYPE
COMPONENT NAME

ansible.netcommon.network_cli

ANSIBLE VERSION
$ ansible --version
ansible [core 2.11.1] 
  config file = /home/gmadappa/ansible/bau-ansible/nw-automation/ansible.cfg
  configured module search path = ['/home/gmadappa/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/gmadappa/pyvirt/ansible210/lib64/python3.10/site-packages/ansible
  ansible collection location = /home/gmadappa/ansible/bau-ansible/nw-automation/collections
  executable location = /home/gmadappa/pyvirt/ansible210/bin/ansible
  python version = 3.10.4 (main, Mar 25 2022, 00:00:00) [GCC 11.2.1 20220127 (Red Hat 11.2.1-9)]
  jinja version = 3.1.1
  libyaml = True
COLLECTION VERSION
$ ansible-galaxy collection list

# /home/gmadappa/ansible/bau-ansible/nw-automation/collections/ansible_collections
Collection        Version
----------------- -------
ansible.netcommon 3.0.0  
ansible.utils     2.6.1  
cisco.asa         3.0.0  
CONFIGURATION
$ ansible-config dump --only-changed
COLLECTIONS_PATHS(/home/gmadappa/ansible/bau-ansible/nw-automation/ansible.cfg) = ['/home/gmadapp>
DEFAULT_HOST_LIST(/home/gmadappa/ansible/bau-ansible/nw-automation/ansible.cfg) = ['/home/gmadapp>
DEFAULT_ROLES_PATH(/home/gmadappa/ansible/bau-ansible/nw-automation/ansible.cfg) = ['/home/gmadap>
DEFAULT_TIMEOUT(/home/gmadappa/ansible/bau-ansible/nw-automation/ansible.cfg) = 5
HOST_KEY_CHECKING(/home/gmadappa/ansible/bau-ansible/nw-automation/ansible.cfg) = False
OS / ENVIRONMENT
$ cat /etc/fedora-release 
Fedora release 35 (Thirty Five)

$ python -V
Python 3.10.4

Target Device: Cisco ASA (v9.8)

STEPS TO REPRODUCE
---
# Test Ansible version 2.11.1

- name: Network Connection Test
  hosts: asa #localhost #"{{ nw_device }}"
  gather_facts: no
  tasks:
    - name: Show the ASA version
      cisco.asa.asa_command:
        commands:
        - show version
      register: asa_version

ansible.cfg

[defaults]
#inventory file location
inventory = inventory 

host_key_checking = false

timeout = 5

roles_path = ./roles
COLLECTIONS_PATHS = ./collections

[persistent_connection]
ssh_type = libssh

inventory

[local]
localhost ansible_connection=local

[asa]
ciscoasa ansible_host=192.168.57.121

[asa:vars]
ansible_user=adminasa
ansible_ssh_pass=password
ansible_become=true
ansible_become_method=ansible.netcommon.enable
ansible_become_pass=password
ansible_connection=ansible.netcommon.network_cli
ansible_network_os=cisco.asa.asa
#ansible_python_interpreter=python
ansible_ssh_common_args=' -oKexAlgorithms=+diffie-hellman-group1-sha1 '
ansible_ssh_extra_args=' -oKexAlgorithms=+diffie-hellman-group1-sha1 '
EXPECTED RESULTS

Ansible is able to connect to the device and execute the commands.

ACTUAL RESULTS
$ansible-playbook 99_network-test.yaml -vvv
ansible-playbook [core 2.11.1] 
  config file = /home/gmadappa/ansible/bau-ansible/nw-automation/ansible.cfg
  configured module search path = ['/home/gmadappa/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/gmadappa/pyvirt/ansible210/lib64/python3.10/site-packages/ansible
  ansible collection location = /home/gmadappa/ansible/bau-ansible/nw-automation/collections
  executable location = /home/gmadappa/pyvirt/ansible210/bin/ansible-playbook
  python version = 3.10.4 (main, Mar 25 2022, 00:00:00) [GCC 11.2.1 20220127 (Red Hat 11.2.1-9)]
  jinja version = 3.1.1
  libyaml = True
Using /home/gmadappa/ansible/bau-ansible/nw-automation/ansible.cfg as config file
host_list declined parsing /home/gmadappa/ansible/bau-ansible/nw-automation/inventory as it did not pass its verify_file() method
script declined parsing /home/gmadappa/ansible/bau-ansible/nw-automation/inventory as it did not pass its verify_file() method
auto declined parsing /home/gmadappa/ansible/bau-ansible/nw-automation/inventory as it did not pass its verify_file() method
Parsed /home/gmadappa/ansible/bau-ansible/nw-automation/inventory inventory source with ini plugin
redirecting (type: action) cisco.asa.asa_command to cisco.asa.asa
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: 99_network-test.yaml *************************************************************************
1 plays in 99_network-test.yaml

PLAY [Network Connection Test] *************************************************************************
META: ran handlers
redirecting (type: action) cisco.asa.asa_command to cisco.asa.asa

TASK [Show the ASA version] ****************************************************************************
task path: /home/gmadappa/ansible/bau-ansible/nw-automation/99_network-test.yaml:13
redirecting (type: action) cisco.asa.asa_command to cisco.asa.asa
redirecting (type: action) cisco.asa.asa_command to cisco.asa.asa
The full traceback is:
  File "/home/gmadappa/ansible/bau-ansible/nw-automation/collections/ansible_collections/cisco/asa/plugins/module_utils/network/asa/asa.py", line 119, in get_capabilities
    capabilities = Connection(module._socket_path).get_capabilities()
  File "/home/gmadappa/pyvirt/ansible210/lib64/python3.10/site-packages/ansible/module_utils/connection.py", line 195, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
fatal: [ciscoasa]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "authorize": null,
            "commands": [
                "show version"
            ],
            "context": null,
            "interval": 1,
            "match": "all",
            "passwords": null,
            "provider": null,
            "retries": 10,
            "wait_for": null
        }
    },
    "msg": "ssh connection failed: ssh connect failed: kex error : no match for method kex algos: server [diffie-hellman-group1-sha1], client [curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512]"
}

PLAY RECAP *********************************************************************************************
ciscoasa                   : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
iamgini commented 2 years ago

I have installed and switched to paramkio as follows and its working

[persistent_connection]
#ssh_type = libssh
ssh_type = auto

Any idea why libssh is not able to handle this ?

iamgini commented 2 years ago

@ganeshrn My apologies for tagging you here.

I was referring to your article New LibSSH Connection Plugin for Ansible Network Replaces Paramiko, Adds FIPS Mode Enablement and noticed this is not really working in my case.

Do we have any other references or guidance on this ?

Thank in advance

sprootik commented 2 years ago

I think you need to try add in /etc/ssh/ssh_config this:

Legacy changes

KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512

and run: ssh-keygen -A

epicanthal commented 2 years ago

I had done something like this in the past on my Ansible control node for support of older IOS devices

  - name: add 'KexAlgorithms +diffie-hellman-group1-sha1' to /etc/ssh/ssh_config (for Cisco ssh support)
    blockinfile:
      path: /etc/ssh/ssh_config
      marker: "# >> {mark} ANSIBLE MANAGED BLOCK - Older Cisco IOS support SHA-1"
      insertafter: 'Host \*'
      block: |
        {{ item }}
    with_items:
      - '    KexAlgorithms +diffie-hellman-group1-sha1'
iamgini commented 2 years ago

@epicanthal and @sprootik Thank you for that. Yes, but with libssh it didn't work.

minestick commented 2 years ago

I am having the same issue with libssh not taking the cipher options. It also doesn't seem to be allowing paramiko to be used with the ios module.

Is there any work around to this?

o0-o commented 1 year ago

I think the best solution would be to fully support ansible_ssh_common_args. Currently, it can be used to define a proxy, but no other options. It is unclear to me why that restriction exists.

zou-can commented 1 year ago

I met the same issue for force10 networks, is there any progress?

I've tried to add var: ansible_libssh_config_file, but it doesn't work. Seems that another pr: https://github.com/ansible/pylibssh/pull/479 haven't been merged.

iamgini commented 1 year ago

Nothing as of now. Waiting! :(

denngie commented 9 months ago

using + to append algorithms/ciphers in ssh config files doesn't work either, related or should I open a separate issue for it?

jakestec commented 4 months ago

Ran into this same issue recently, after some testing I learned that if using libssh with network_cli it will read in configuration from your ~/.ssh/config file. Config in ansible.cfg doesn't seem to be respected in this case. Testing done with ansible.netcommon v6.0.0 on rhel8

For my situation, we were working with some old Cisco boxes and only needed the following in ssh config to make the connection:

Host cisco_boxs
  KexAlgorithms +diffie-hellman-group1-sha1

@epicanthal solution above shows how you can do this programmatically if needed: https://github.com/ansible-collections/ansible.netcommon/issues/430#issuecomment-1172721717

alehaa commented 6 days ago

@jakestec can you verify this is still working? Running on recent macOS, my ssh_config doesn't seem to be honored.

ansible [core 2.17.6]
  config file = [private]
  configured module search path = ['/Users/alexander/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /opt/homebrew/Cellar/ansible/10.6.0/libexec/lib/python3.12/site-packages/ansible
  ansible collection location = [private]
  executable location = /opt/homebrew/bin/ansible
  python version = 3.12.7 (main, Oct  1 2024, 02:05:46) [Clang 16.0.0 (clang-1600.0.26.3)] (/opt/homebrew/Cellar/ansible/10.6.0/libexec/bin/python)
  jinja version = 3.1.4
  libyaml = True
Host myswitch
  Ciphers aes256-ctr,aes256-cbc
  ControlMaster no
  HostKeyAlgorithms +ssh-rsa
  KexAlgorithms +diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
  Port 22
  PubkeyAcceptedKeyTypes +ssh-rsa
fatal: [MySwitch]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "commands": [
                "show version"
            ],
            "interval": 1,
            "match": "all",
            "retries": 9,
            "wait_for": null
        }
    },
    "msg": "ssh connection failed: ssh connect failed: kex error : no match for method mac algo client->server: server [hmac-sha1,hmac-sha1-96,hmac-md5,hmac-md5-96], client [hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512]"
}
jakestec commented 6 days ago

@alehaa Yup, the container executing our ansible code is connecting almost daily to devices using this configuration. Unfortunately I don't have access to any MacOS machines to test.