In one of my ansible playbooks I need to obtain a file from a Windows share. I can’t find a module that handles this so I’m using the shell module to call the smbclient command to do what I need. The problem with this solution is that smbclient prompts for a password (and I don’t want to supply it on the command itself for security reasons.)
I tried using ansible’s built-in expect module, but frustratingly it only works on systems that have pexpect >= 3.3 , which CentOS 7 & Ubuntu 14.04 do not have.
My solution to this is to install the expect command on the host, and then use the ansible shell module to call it, following the example given in Ansible’s shell module page
Part of the process in my playbook is registering stdout from that command for later use. I then ran into a problem where I would run smbclient -c “ls <filename>” but ansible would register nothing. After some digging I found I also need to include the interact
command after sending the password. Without it, anything after sending the password is not registered to stdout. Thanks to rostyslav-fridman on Stack Overflow for the answer.
My final problem was I was sending a password that had a ] character in it. It was causing this error on run:
missing close-bracket\n while executing\n\"send
I found here (thanks glenn-jackman) it was due to the fact that the expect syntax uses tcl language, which treats those brackets as special characters. To get around this I had to use an ansible filter, specifically regex_escape()
Lastly I ran into an issue specifically with how I was spawning smbclient. I kept getting this message:
"stderr": "send: spawn id exp4 not open\n while executing\n\"send
It boiled down to single vs double quotes. If I put my -c arguments in single quotes it failed; with double quotes, it worked.
My completed play is below. Finally, success!
- name: Get RSA filename
shell: |
set timeout 300
spawn smbclient {{standards_location}} -W DOMAIN -U {{username}} -c "ls {{file_location}}*.tar"
expect "password:"
send {{ password | regex_escape() }}\r
interact
exit 0
args:
executable: /usr/bin/expect
changed_when: false
no_log: true
register: RSA_filename_raw
Great article. It solved one probelm for me. however, I am not able to substitute password from group_vars. the following does not substitue any password. if I remove regex_escape, it wont work either as passwords have special characters.
send {{ password_from_group_vars | regex_escape() }}\r
Any suggestions?
try like
send — “{{ pw | regescape }}\r”
Hi Bob,
Can u pls help me?
I want to use expect to pass password for a shell cmd on which i have sudo access.
Can i use it?