rundeck-plugins / ansible-plugin

Ansible Integration for Rundeck
MIT License
331 stars 100 forks source link

NodeExecutor to support network devices #69

Open nexusvista opened 8 years ago

nexusvista commented 8 years ago

ISSUE TYPE Feature Request

COMPONENT NAME AnsibleNodeExecutor.java

ANSIBLE VERSION ansible 2.3.0 config file = /etc/ansible/ansible.cfg configured module search path = ['/usr/share/ansible/ntc-ansible/library', '/usr/share/ansible/ansible-xml/library']

CONFIGURATION

Thu Oct 13 12:17:05 BST 2016

edit below

ansible-ssh-auth-type=password ansible-ssh-timeout=30 ansible-ssh-user=admin executable=/bin/bash project.ansible-executable=/bin/sh project.ansible-ssh-auth-type=password project.ansible-ssh-timeout=30 project.ansible-ssh-user=admin project.description= project.name=network project.nodeCache.delay=30 project.nodeCache.enabled=true project.ssh-authentication=privateKey project.ssh-keypath=/var/lib/rundeck/.ssh/id_rsa resources.source.1.config.file=/var/rundeck/projects/network/etc/resources.xml resources.source.1.config.format=resourcexml resources.source.1.config.generateFileAutomatically=true resources.source.1.config.includeServerNode=true resources.source.1.config.requireFileExists=false resources.source.1.type=file service.FileCopier.default.provider=com.batix.rundeck.plugins.AnsibleFileCopier service.NodeExecutor.default.provider=com.batix.rundeck.plugins.AnsibleNodeExecutor

OS / ENVIRONMENT Linux centos7spark02 3.10.0-123.el7.x86_64 #1 SMP Mon Jun 30 12:09:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

SUMMARY I'm trying to execute a command against a network device, in particular, a Cisco Nexus 7K. Unfortunately the network device does not accept "shell" command and the connection is not handled correctly.

12:20:01 192.168.222.109 Using /etc/ansible/ansible.cfg as config file 12:20:02 192.168.222.109 | UNREACHABLE! => { 12:20:02 "changed": false, 12:20:02 "msg": "Failed to connect to the host via ssh: User Access Verification\nPermission denied (publickey,password,keyboard-interactive).\r\n", 12:20:02 "unreachable": true 12:20:02 } 12:20:02 Failed: AnsibleError: ERROR: Ansible execution returned with non zero code.

12:20:02 centos7spark02 Execution failed: 120: [Workflow result: , step failures: {1=Dispatch failed on 1 nodes: [192.168.222.109: AnsibleError: ERROR: Ansible execution returned with non zero code.]}, Node failures: {192.168.222.109=[AnsibleError: ERROR: Ansible execution returned with non zero code.]}, status: failed]

STEPS TO REPRODUCE Add a network device as a Node in Rundeck, and execute an ad-hoc command against this node.

EXPECTED RESULTS [ { "name": "default", "status": "active", "vlan_id": "1" }, { "name": "web", "status": "active", "vlan_id": "1o" } ]

SUGGESTIONS I wonder if we could have an option to select a module for ad-hoc command. Ideally, I'd like to use ntc-ansible extra module to execute "show" command. The module name is "ntc_show_command" and it takes extra key-values from command arguments.

I tried to modify cmdArgs.append(" '").append(cmd).append("'"); to include extra arguments such as "connection=ssh host=192.168.222.109 username=admin" and so on and change jobConf.put(AnsibleDescribable.ANSIBLE_MODULE,"shell"); to "ntc_show_command". But it didn't work out when I tried to add it as a plugin to the project.

Thanks in advance!

James

yassineazzouz commented 8 years ago

Hi @nexusvista ,

Thanks for the suggestion, yes I agree that could be a good idea, to be able to configure a custom node executor. But The error you reported seems to be related to ssh authentication 12:20:02 192.168.222.109 | UNREACHABLE! => { 12:20:02 "changed": false, 12:20:02 "msg": "Failed to connect to the host via ssh: User Access Verification\nPermission denied (publickey,password,keyboard-interactive).\r\n", 12:20:02 "unreachable": true 12:20:02 }

I'm not sure how "Cisco Nexus 7K" works, can you post a working ansible command and the configuration of your Node Executor ?

Thanks,

nexusvista commented 8 years ago

Hi Yassine, @yassineazzouz

Thanks for your reply. So essentially network devices run closed operating systems that normally does not accept ssh keys for authentication. It will ask for a password when you ssh to it.

Here is the process for a user to ssh into the switch. [root@centos7spark02 ~]# ssh admin@192.168.222.108 User Access Verification Password: Cisco NX-OS Software Copyright (c) 2002-2014, Cisco Systems, Inc. All rights reserved. NX-OS/Titanium software ("NX-OS/Titanium Software") and related documentation, files or other reference materials ("Documentation") are the proprietary property and confidential information of Cisco Systems, Inc. ("Cisco") and are protected, without limitation, pursuant to United States and International copyright and trademark laws in the applicable jurisdiction which provide civil and criminal penalties for copying or distribution without Cisco's authorization. The use of NX-OS/Titanium Software and Documentation is strictly limited to Cisco's internal use.

Any use or disclosure, in whole or in part, of the NX-OS/Titanium Software or Documentation to any third party for any purposes is expressly prohibited except as otherwise authorized by Cisco in writing. The copyrights to certain works contained herein are owned by other third parties and are used and distributed under license. Some parts of this software may be covered under the GNU Public License or the GNU Lesser General Public License. A copy of each such license is available at http://www.gnu.org/licenses/gpl.html and http://www.gnu.org/licenses/lgpl.html

switch#

When I tried to run the ntc_show_command function from ntc-ansible module, I got the following output:-

[root@centos7spark02 ~]# ansible 192.168.222.108 -m ntc_show_command -u admin -vvvv Using /etc/ansible/ansible.cfg as config file Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/site-packages/ansible/plugins/callback/init.pyc Using module file /usr/share/ansible/ntc-ansible/library/ntc_show_command.py <192.168.222.108> ESTABLISH SSH CONNECTION FOR USER: admin <192.168.222.108> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=admin -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r 192.168.222.108 '/bin/sh -c '"'"'( umask 77 && mkdir -p "echo $HOME/.ansible/tmp/ansible-tmp-1476694787.82-84362947607917" && echo ansible-tmp-1476694787.82-84362947607917="echo $HOME/.ansible/tmp/ansible-tmp-1476694787.82-84362947607917" ) && sleep 0'"'"'' 192.168.222.108 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: OpenSSH_6.4, OpenSSL 1.0.1e-fips 11 Feb 2013\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/sshconfig line 51: Applying options for \r\ndebug1: auto-mux: Trying existing master\r\ndebug1: Control socket \"/root/.ansible/cp/ansible-ssh-192.168.222.108-22-admin\" does not exist\r\ndebug2: ssh_connect: needpriv 0\r\ndebug1: Connecting to 192.168.222.108 [192.168.222.108] port 22.\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug1: fd 3 clearing O_NONBLOCK\r\ndebug1: Connection established.\r\ndebug3: timeout: 9989 ms remain after connect\r\ndebug1: permanently_set_uid: 0/0\r\ndebug3: Incorrect RSA1 identifier\r\ndebug3: Could not load \"/root/.ssh/id_rsa\" as a RSA1 public key\r\ndebug1: identity file /root/.ssh/id_rsa type 1\r\ndebug1: identity file /root/.ssh/id_rsa-cert type -1\r\ndebug1: identity file /root/.ssh/id_dsa type -1\r\ndebug1: identity file /root/.ssh/id_dsa-cert type -1\r\ndebug1: identity file /root/.ssh/id_ecdsa type -1\r\ndebug1: identity file /root/.ssh/id_ecdsa-cert type -1\r\ndebug1: Enabling compatibility mode for protocol 2.0\r\ndebug1: Local version string SSH-2.0-OpenSSH_6.4\r\ndebug1: Remote protocol version 2.0, remote software version OpenSSH_5.9 FIPS\r\ndebug1: match: OpenSSH_5.9 FIPS pat OpenSSH5\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug3: load_hostkeys: loading entries for host \"192.168.222.108\" from file \"/root/.ssh/known_hosts\"\r\ndebug3: load_hostkeys: found key type RSA in file /root/.ssh/known_hosts:3\r\ndebug3: load_hostkeys: loaded 1 keys\r\ndebug3: order_hostkeyalgs: prefer hostkeyalgs: ssh-rsa-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-rsa\r\ndebug1: SSH2_MSG_KEXINIT sent\r\ndebug1: SSH2_MSG_KEXINIT received\r\ndebug2: kex_parse_kexinit: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1\r\ndebug2: kex_parse_kexinit: ssh-rsa-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-rsa,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-dss-cert-v00@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-dss\r\ndebug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-gcm@openssh.com,aes256-gcm@openssh.com,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se\r\ndebug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-gcm@openssh.com,aes256-gcm@openssh.com,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se\r\ndebug2: kex_parse_kexinit: hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96\r\ndebug2: kex_parse_kexinit: hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96\r\ndebug2: kex_parse_kexinit: zlib@openssh.com,zlib,none\r\ndebug2: kex_parse_kexinit: zlib@openssh.com,zlib,none\r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: first_kex_follows 0 \r\ndebug2: kex_parse_kexinit: reserved 0 \r\ndebug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1\r\ndebug2: kex_parse_kexinit: ssh-rsa\r\ndebug2: kex_parse_kexinit: aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,aes128-ctr,aes192-ctr,aes256-ctr\r\ndebug2: kex_parse_kexinit: aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,aes128-ctr,aes192-ctr,aes256-ctr\r\ndebug2: kex_parse_kexinit: hmac-sha1,hmac-sha1-96\r\ndebug2: kex_parse_kexinit: hmac-sha1,hmac-sha1-96\r\ndebug2: kex_parse_kexinit: none,zlib@openssh.com\r\ndebug2: kex_parse_kexinit: none,zlib@openssh.com\r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: first_kex_follows 0 \r\ndebug2: kex_parse_kexinit: reserved 0 \r\ndebug2: mac_setup: found hmac-sha1\r\ndebug1: kex: server->client aes128-ctr hmac-sha1 zlib@openssh.com\r\ndebug2: mac_setup: found hmac-sha1\r\ndebug1: kex: client->server aes128-ctr hmac-sha1 zlib@openssh.com\r\ndebug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<7680<8192) sent\r\ndebug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP\r\ndebug2: dh_gen_key: priv key bits set: 170/320\r\ndebug2: bits set: 4090/8192\r\ndebug1: SSH2_MSG_KEX_DH_GEX_INIT sent\r\ndebug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY\r\ndebug1: Server host key: RSA 0d:b4:d4:64:29:85:98:45:05:a6:ad:44:60:b5:40:2f\r\ndebug3: load_hostkeys: loading entries for host \"192.168.222.108\" from file \"/root/.ssh/known_hosts\"\r\ndebug3: load_hostkeys: found key type RSA in file /root/.ssh/known_hosts:3\r\ndebug3: load_hostkeys: loaded 1 keys\r\ndebug1: Host '192.168.222.108' is known and matches the RSA host key.\r\ndebug1: Found key in /root/.ssh/known_hosts:3\r\ndebug2: bits set: 4070/8192\r\ndebug1: ssh_rsa_verify: signature correct\r\ndebug2: kex_derive_keys\r\ndebug2: set_newkeys: mode 1\r\ndebug1: SSH2_MSG_NEWKEYS sent\r\ndebug1: expecting SSH2_MSG_NEWKEYS\r\ndebug2: set_newkeys: mode 0\r\ndebug1: SSH2_MSG_NEWKEYS received\r\ndebug1: Roaming not allowed by server\r\ndebug1: SSH2_MSG_SERVICE_REQUEST sent\r\ndebug2: service_accept: ssh-userauth\r\ndebug1: SSH2_MSG_SERVICE_ACCEPT received\r\ndebug2: key: /root/.ssh/id_rsa (0x7f6651070ef0),\r\ndebug2: key: /root/.ssh/id_dsa ((nil)),\r\ndebug2: key: /root/.ssh/id_ecdsa ((nil)),\r\ndebug3: input_userauth_banner\r\nUser Access Verification\ndebug1: Authentications that can continue: publickey,password,keyboard-interactive\r\ndebug3: start over, passed a different list publickey,password,keyboard-interactive\r\ndebug3: preferred gssapi-with-mic,gssapi-keyex,hostbased,publickey\r\ndebug3: authmethod_lookup publickey\r\ndebug3: remaining preferred: ,gssapi-keyex,hostbased,publickey\r\ndebug3: authmethod_is_enabled publickey\r\ndebug1: Next authentication method: publickey\r\ndebug1: Offering RSA public key: /root/.ssh/id_rsa\r\ndebug3: send_pubkey_test\r\ndebug2: we sent a publickey packet, wait for reply\r\ndebug1: Authentications that can continue: publickey,password,keyboard-interactive\r\ndebug1: Trying private key: /root/.ssh/id_dsa\r\ndebug3: no such identity: /root/.ssh/id_dsa: No such file or directory\r\ndebug1: Trying private key: /root/.ssh/id_ecdsa\r\ndebug3: no such identity: /root/.ssh/id_ecdsa: No such file or directory\r\ndebug2: we did not send a packet, disable method\r\ndebug1: No more authentication methods to try.\r\nPermission denied (publickey,password,keyboard-interactive).\r\n", "unreachable": true } [root@centos7spark02 ~]#

[root@centos7spark02 ~]# ansible 192.168.222.108 -m ntc_show_command -u admin -k -vvvv Using /etc/ansible/ansible.cfg as config file SSH password: Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/site-packages/ansible/plugins/callback/init.pyc Using module file /usr/share/ansible/ntc-ansible/library/ntc_show_command.py <192.168.222.108> ESTABLISH SSH CONNECTION FOR USER: admin <192.168.222.108> SSH: EXEC sshpass -d13 ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o User=admin -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r 192.168.222.108 '/bin/sh -c '"'"'( umask 77 && mkdir -p "echo $HOME/.ansible/tmp/ansible-tmp-1476694945.27-116936090727318" && echo ansible-tmp-1476694945.27-116936090727318="echo $HOME/.ansible/tmp/ansible-tmp-1476694945.27-116936090727318" ) && sleep 0'"'"'' 192.168.222.108 | UNREACHABLE! => { "changed": false, "msg": "Authentication or permission failure. In some cases, you may have been able to authenticate and did not have permissions on the remote directory. Consider changing the remote temp path in ansible.cfg to a path rooted in \"/tmp\". Failed command was: ( umask 77 && mkdir -p \"echo $HOME/.ansible/tmp/ansible-tmp-1476694945.27-116936090727318\" && echo ansible-tmp-1476694945.27-116936090727318=\"echo $HOME/.ansible/tmp/ansible-tmp-1476694945.27-116936090727318\" ), exited with result 16: Syntax error while parsing '/bin/sh -c '( umask 77 && mkdir -p \"echo $HOME/.ansible/tmp/ansible-tmp-1476694945.27-116936090727318\" && echo ansible-tmp-1476694945.27-116936090727318=\"echo $HOME/.ansible/tmp/ansible-tmp-1476694945.27-116936090727318\" ) && sleep 0''\n\n\nCmd exec error.\n", "unreachable": true } [root@centos7spark02 ~]# ansible 192.168.222.108 -m ntc_show_command -u admin -k -vvvv --connection local Using /etc/ansible/ansible.cfg as config file Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/site-packages/ansible/plugins/callback/init.pyc Using module file /usr/share/ansible/ntc-ansible/library/ntc_show_command.py <192.168.222.108> ESTABLISH LOCAL CONNECTION FOR USER: root <192.168.222.108> EXEC /bin/sh -c '( umask 77 && mkdir -p "echo $HOME/.ansible/tmp/ansible-tmp-1476694964.53-234985547682333" && echo ansible-tmp-1476694964.53-234985547682333="echo $HOME/.ansible/tmp/ansible-tmp-1476694964.53-234985547682333" ) && sleep 0' <192.168.222.108> PUT /tmp/tmpmo7k6x TO /root/.ansible/tmp/ansible-tmp-1476694964.53-234985547682333/ntc_show_command.py <192.168.222.108> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1476694964.53-234985547682333/ /root/.ansible/tmp/ansible-tmp-1476694964.53-234985547682333/ntc_show_command.py && sleep 0' <192.168.222.108> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1476694964.53-234985547682333/ntc_show_command.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1476694964.53-234985547682333/" > /dev/null 2>&1 && sleep 0' 192.168.222.108 | FAILED! => { "changed": false, "failed": true, "invocation": { "module_args": { "connection": "netmiko_ssh", "delay": 1, "index_file": "index", "optional_args": {}, "port": 22, "template_dir": "ntc-templates/templates", "use_keys": false, "use_templates": true }, "module_name": "ntc_show_command" }, "msg": "missing required arguments: platform,command" } [root@centos7spark02 ~]#

As you can see, network devices won't let file copying to the remote node, and the module requires a password authentication and other parameters defined in the arguments section.

And a successful response is shown below with all params defined in the arguments section.

[root@centos7spark02 ntc-ansible]# ansible 192.168.222.108 -m ntc_show_command -a "host=192.168.222.108 platform=cisco_nxos command='show vlan' username=admin password=cisco123" -u admin -k -vvvv --connection local Using /etc/ansible/ansible.cfg as config file Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/site-packages/ansible/plugins/callback/init.pyc Using module file /usr/share/ansible/ntc-ansible/library/ntc_show_command.py <192.168.222.108> ESTABLISH LOCAL CONNECTION FOR USER: root <192.168.222.108> EXEC /bin/sh -c '( umask 77 && mkdir -p "echo $HOME/.ansible/tmp/ansible-tmp-1476695797.04-50633925802343" && echo ansible-tmp-1476695797.04-50633925802343="echo $HOME/.ansible/tmp/ansible-tmp-1476695797.04-50633925802343" ) && sleep 0' <192.168.222.108> PUT /tmp/tmpY1zy7w TO /root/.ansible/tmp/ansible-tmp-1476695797.04-50633925802343/ntc_show_command.py <192.168.222.108> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1476695797.04-50633925802343/ /root/.ansible/tmp/ansible-tmp-1476695797.04-50633925802343/ntc_show_command.py && sleep 0' <192.168.222.108> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1476695797.04-50633925802343/ntc_show_command.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1476695797.04-50633925802343/" > /dev/null 2>&1 && sleep 0' 192.168.222.108 | SUCCESS => { "changed": false, "invocation": { "module_args": { "command": "show vlan", "connection": "netmiko_ssh", "delay": "1", "file": null, "host": "192.168.222.108", "index_file": "index", "key_file": null, "local_file": null, "optional_args": {}, "password": "cisco123", "platform": "cisco_nxos", "port": "22", "secret": null, "template_dir": "ntc-templates/templates", "trigger_device_list": null, "use_keys": false, "use_templates": true, "username": "admin" }, "module_name": "ntc_show_command" }, "response": [ { "name": "default", "status": "active", "vlan_id": "1" } ], "response_list": [] } [root@centos7spark02 ntc-ansible]#

It seems that currently the underline module for Ad-Hoc command page in Rundeck is hard coded to "shell", would it be possible to add some other fields to put in other modules, and a field to pass in additional command args?

Thanks again!

James