Quoting is handled at so many levels. The first trick is to get the right combination of characters past bash, so lets skip the password_hash() bit and get the bash quoting right. Bash is trying to turn ! into a reference to part of your history. It does this when ! is unquoted, or when inside double-quoted strings, but not when inside single-quoted strings.
utoddl@tarna2:~$ ansible all -i localhost, -m debug -a "msg={{ 'Start-1234!' }}"
-bash: !': event not found
# ' <-That single quote is to fix syntax highlighting.
utoddl@tarna2:~$ ansible all -i localhost, -m debug -a "msg={{ 'Start-1234\!' }}"
localhost | SUCCESS => {
"msg": "Start-1234\\!"
}
utoddl@tarna2:~$ ansible all -i localhost, -m debug -a "msg={{ 'Start-1234\\!' }}"
localhost | SUCCESS => {
"msg": "Start-1234\\!"
}
utoddl@tarna2:~$ ansible all -i localhost, -m debug -a "msg={{ 'Start-1234"'!'"' }}"
localhost | SUCCESS => {
"msg": "Start-1234!"
}
That last one does the trick. Bash concatenates adjacent strings after quoting, and that expression takes the double-quoted string
"msg={{ 'Start-1234"
and concatenates it with the single-quoted string
'!'
and the following double-quoted string
" }}"
Now you can insert your
| password_hash('sha512' , 'somesalt')
bit into that last double-quoted string component and have the Right Thing™ seen by ansible.
I know this is marked solved already, but wanted to add an alternative solution, which is a habit of mine specifically because of this problem in bash.
Instead of escaping the quotes or the exclamation mark in order to make sure bash passes everything along correctly from cli to ansible, I just invert the order I use my quotes. I.e. start with single quotes and use double quotes for substrings. Bash will treat single-quoted strings more literally, and thus won’t evaluate the exclamation mark.
Nah, that’s irrelevant. I just prefer ansible localhost -i /dev/null vs ansible all -i localhost, because the former uses ansible_connection: local while the latter uses ansible_connection: ssh.
Edit: This uses an explicit/literal localhost (which generally resolves to 127.0.0.1 or ::1 or whatever might be in your /etc/hosts file, but also obeys any ssh config rules that apply to localhost as well).
ansible all -i localhost, -m debug -a 'var=ansible_connection'
localhost | SUCCESS => {
"ansible_connection": "ssh"
}
so it looks like I can’t get the mere hash $6$somesalt$kP1JGowfJHOYHfpJTqC8qSnjkPfFUKGfEF34VIXTziiaINo72ISD7WqNn05d0oBZlNP4oBgK4PrObT4O1aHM61 accross via the pw_hash variable, but only including the 'msg:' prefix
I too recommend using set_fact instead of debug to create your pw_hash variable.
However, I want to point out that the hash does exist in your registered debug variable. When you registered the debug task, it created a dictionary of {'msg': 'string', 'failed': boolean, 'changed': boolean}, where msg is the printed output. To use the hash in the debug registered variable, you’d reference the sub key msg, i.e. {{ pw_hash.msg }}. You would similarly have this problem anytime you use the registered variable of any task. You will get a dictionary of various sub properties that contain all the data you may possibly need.
In this case though, using set_fact to generate your pw_hash would make plenty of sense here. I don’t know how you’re creating your ‘somesalt’ value, but I wanted to also share how I generate salts. The following example will create a unique salt and password hash per host, while also making the hash idempotent so that the hash does not constantly change every time the play is run even though the password is unchanged.