My company uses Ansible (which I am a novice at) and we have a playbook and a related role for joining new Linux machines to AD. Our admin accounts have their passwords rolled three times a day, and we can't set them ourselves. The Ansible playbook works so long as there is not a '
(single quote) in the password. There may be other characters that cause it to break, but I know that '
does it for sure.
Here are the relevant bits of the scripts:
cat setup-ad.yml
---
- hosts: "{{ hosts }}"
vars_prompt:
- name: "username"
prompt: "Enter admin account"
private: no
- name: "password"
prompt: "Enter Password"
unsafe: yes
private: yes
vars:
domain: "{{ 'mycompany.com' }}"
passwd: "{{ password | regex_escape() }}"
roles:
- join-ad
grep -B2 -A3 'passwd' ./roles/join-ad/tasks/main.yml
- name: join to active directory
command: net ads join MYCOMPANY.COM -U {{ username }}@MYCOMPANY.COM%'{{ passwd }}' createcomputer=Restricted/Servers/Unix --request-timeout=120 --no-dns-updates
no_log: false
when: ansible_distribution_major_version >= 6
- name: join to active directory
command: net ads join MYCOMPANY.COM -U {{ username }}@MYCOMPANY.COM%'{{ passwd }}' createcomputer=Restricted/Servers/Unix --request-timeout=120
no_log: false
when: ansible_distribution_major_version <= 5
The error we get is:
TASK [join-ad : join to active directory] ************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ValueError: No closing quotation
fatal: [newserver.mycompany.com]: FAILED! => {"changed": false, "module_stderr": "Shared connection to newserver.mycompany.com closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/root/.ansible/tmp/ansible-tmp-1590785720.2-224244797633747/AnsiballZ_command.py\", line 102, in <module>\r\n _ansiballz_main()\r\n File \"/root/.ansible/tmp/ansible-tmp-1590785720.2-224244797633747/AnsiballZ_command.py\", line 94, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File \"/root/.ansible/tmp/ansible-tmp-1590785720.2-224244797633747/AnsiballZ_command.py\", line 40, in invoke_module\r\n runpy.run_module(mod_name='ansible.modules.commands.command', init_globals=None, run_name='__main__', alter_sys=True)\r\n File \"/usr/lib64/python2.7/runpy.py\", line 176, in run_module\r\n fname, loader, pkg_name)\r\n File \"/usr/lib64/python2.7/runpy.py\", line 82, in _run_module_code\r\n mod_name, mod_fname, mod_loader, pkg_name)\r\n File \"/usr/lib64/python2.7/runpy.py\", line 72, in _run_code\r\n exec code in run_globals\r\n File \"/tmp/ansible_command_payload_4D4oFT/ansible_command_payload.zip/ansible/modules/commands/command.py\", line 344, in <module>\r\n File \"/tmp/ansible_command_payload_4D4oFT/ansible_command_payload.zip/ansible/modules/commands/command.py\", line 263, in main\r\n File \"/usr/lib64/python2.7/shlex.py\", line 279, in split\r\n return list(lex)\r\n File \"/usr/lib64/python2.7/shlex.py\", line 269, in next\r\n token = self.get_token()\r\n File \"/usr/lib64/python2.7/shlex.py\", line 96, in get_token\r\n raw = self.read_token()\r\n File \"/usr/lib64/python2.7/shlex.py\", line 172, in read_token\r\n raise ValueError, \"No closing quotation\"\r\nValueError: No closing quotation\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
PLAY RECAP *******************************************************************************************************
newserver.mycompany.com : ok=9 changed=0 unreachable=0 failed=1 skipped=2 rescued=0 ignored=0
Okay, so the issue is that at some point the '
is being interpreted as the beginning of a quoted series of characters, rather than as simply part of the password. My problem is I don't know how to get Ansible? Python? YAML? Jinja? to treat the string of characters the user inputs as nothing more than a string of characters. Is "string literal" the correct term here?
If I ssh to the target server and run the net ads join
command manually, and let it prompt for my password, it will work even with a '
in it, so at the very least I know it's not the Samba command that's the issue.
The things I've tried (which haven't helped) are:
- Add 'hard quotes' around
{{ passwd }}
- Add
unsafe: yes
to the password definition - Add
passwd: "{{ password | regex_escape() }}"
to escape metacharacters - Lots of internet searching on Stack and Google
Any and all help would be appreciated.