# Create a hashed password with 'debug'

**URL:** <https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280>\
**Category:** Get Help\
**Created:** [September 5, 2024, 1:28pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280 "2024-09-05T13:28:21Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![dulhaver](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/dulhaver/32/1061_2.png) [@dulhaver](https://forum.ansible.com/u/dulhaver)\
**Post date:** [September 5, 2024, 1:28pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/1 "2024-09-05T13:28:21Z")

</div>

as per advise from the documentation of the `user` module I try to create a hased password like

`ansible all -i localhost, -m debug -a "msg={{ 'Start-1234!' | password_hash('sha512', 'mysecretsalt') }}`

that does not seem to process the `!` character well.

```auto
$ ansible all -i localhost, -m debug -a "msg={{ 'Secret-1234!' | password_hash('sha512' , 'somesalt') }}"
-bash: !': event not found

```

Now, I want a `!` in the password but when I try to escape that with `\!` the password I am effectively getting in the end is:

- `Secret-1234\!` and not
- `Secret-1234!`

how can I solve this?

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [September 5, 2024, 2:29pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/2 "2024-09-05T14:29:00Z")

</div>

> [@dulhaver](#):
>
> ansible all -i localhost, -m debug -a "msg={{ ‘Start-1234!’ | password\_hash(‘sha512’, ‘mysecretsalt’) }}

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.

```bash
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`.

---

<div class="post-metadata">

**Author:** ![dulhaver](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/dulhaver/32/1061_2.png) [@dulhaver](https://forum.ansible.com/u/dulhaver)\
**Post date:** [September 5, 2024, 3:12pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/3 "2024-09-05T15:12:53Z")

</div>

> [@utoddl](#):
>
> `"msg={{ 'Start-1234"'!'"' }}"`

thx. Here for anybody who, like me, needs another 15 minutes to puzzle the above together again 🙂

```auto
ansible all -i localhost, -m debug -a "msg={{ 'Start-1234"'!'"' | password_hash('sha512' , 'somesalt') }}"

```

---

<div class="post-metadata">

**Author:** ![Denney-tech](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/denney-tech/32/1556_2.png) [@Denney-tech](https://forum.ansible.com/u/Denney-tech)\
**Post date:** [September 5, 2024, 4:07pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/4 "2024-09-05T16:07:15Z")

</div>

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.

```bash
ansible localhost -i /dev/null -m debug -a 'msg={{ "Start-1234!" | password_hash("sha512", "somesalt") }}'

```

---

<div class="post-metadata">

**Author:** ![dulhaver](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/dulhaver/32/1061_2.png) [@dulhaver](https://forum.ansible.com/u/dulhaver)\
**Post date:** [September 5, 2024, 7:31pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/5 "2024-09-05T19:31:11Z")

</div>

> [@Denney-tech](#):
>
> `ansible localhost -i /dev/null -m debug -a 'msg={{ "Start-1234!" | password_hash("sha512", "somesalt") }}'`

that works just alike. thnks!

With the inventory being `/dev/null` we kinda cheat ourselves around the bash issue here somehow?

---

<div class="post-metadata">

**Author:** ![Denney-tech](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/denney-tech/32/1556_2.png) [@Denney-tech](https://forum.ansible.com/u/Denney-tech)\
**Post date:** [September 5, 2024, 7:35pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/6 "2024-09-05T19:35:51Z")

</div>

> [@dulhaver](#):
>
> With the inventory being `/dev/null` we kinda cheat ourselves around the bash issue here somehow?

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 Ansible’s implicit localhost:

```bash
ansible localhost -i /dev/null -m debug -a 'var=ansible_connection'
localhost | SUCCESS => {
    "ansible_connection": "local"
}

```

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).

```bash
ansible all -i localhost, -m debug -a 'var=ansible_connection'
localhost | SUCCESS => {
    "ansible_connection": "ssh"
}

```

---

<div class="post-metadata">

**Author:** ![dulhaver](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/dulhaver/32/1061_2.png) [@dulhaver](https://forum.ansible.com/u/dulhaver)\
**Post date:** [September 12, 2024, 9:38am UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/7 "2024-09-12T09:38:56Z")

</div>

taking this a step further by incorporating the hash generation into a playbook/tasks file

- introducing a `stepuser_pw` variable in `vars/myuser\_pw.yml’

- those 2 tasks

```auto
- name: create pw_hash for stepuser
  delegate_to: localhost
  ansible.builtin.debug:
    msg: "{{ stepuser_pw | password_hash('sha512', 'somesalt') }}"
  register: pw_hash

- name: setting password & pw expiry to -1 for 'stepuser'
  ansible.builtin.user:
    name: "{{ user_item.name }}"
    comment: "{{ user_item.comment }}"
    shell: /bin/bash
    home: "{{ user_item.home }}"
    password: "{{ user_item.password }}"
    password_expire_max: -1
  become: true
  loop:
    - { name: "stepuser" , home: '/home/stepuser' , comment: "sudo user for step" , password: "{{ pw_hash }}" }
  loop_control:
    loop_var: user_item

```

this fails however with

```auto
[WARNING]: The input password appears not to have been hashed. The 'password' argument must be encrypted for this module to work properly.

```

and more concrete:

```auto
failed: [hostname] (item={'name': 'stepuser', 'home': '/home/stepuser', 'comment': 'sudo user for step', 'password': {'msg': '$6$somesalt$kP1JGowfJHOYHfpJTqC8qSnjkPfFUKGfEF34VIXTziiaINo72ISD7WqNn05d0oBZlNP4oBgK4PrObT4O1aHM61', 'failed': False, 'changed': False}}) => {"ansible_loop_var": "pw_item", "changed": false, "msg": "usermod: The password field cannot contain a colon character.\n", "name": "stepuser", "pw_item": {"comment": "sudo user for step", "home": "/home/stepuser", "name": "stepuser", "password": {"changed": false, "failed": false, "msg": "$6$somesalt$kP1JGowfJHOYHfpJTqC8qSnjkPfFUKGfEF34VIXTziiaINo72ISD7WqNn05d0oBZlNP4oBgK4PrObT4O1aHM61"}}, "rc": 1}

```

`'password': {'msg': '$6$somesalt$kP1JGowfJHOYHfpJTqC8qSnjkPfFUKGfEF34VIXTziiaINo72ISD7WqNn05d0oBZlNP4oBgK4PrObT4O1aHM61',`

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

any idea how to get over this?

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [September 12, 2024, 1:56pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/8 "2024-09-12T13:56:45Z")

</div>

I suggest you print (via debug) the value you have in `pw_hash`. Registered results of a debug task aren’t what you think.

If you’re trying to create a `pw_hash` variable/fact, you should be using `set_fact`, not `debug`.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [September 12, 2024, 1:58pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/9 "2024-09-12T13:58:55Z")

</div>

> [@dulhaver](#):
>
> ```auto
> - name: create pw_hash for stepuser
> delegate_to: localhost
> ansible.builtin.debug:
> 
> ```

Also, `debug` tasks always run on the controller anyway. No need to `delegate_to`.

---

<div class="post-metadata">

**Author:** ![Denney-tech](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/denney-tech/32/1556_2.png) [@Denney-tech](https://forum.ansible.com/u/Denney-tech)\
**Post date:** [September 12, 2024, 2:28pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/10 "2024-09-12T14:28:02Z")

</div>

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.

```yaml
- name: create pw_hash for stepuser
  vars:
    pw_salt: "{{ lookup('ansible.builtin.password', '/dev/null length=22 chars=ascii_letters,digits seed=' ~ inventory_hostname) }}"
  ansible.builtin.set_fact:
    pw_hash: "{{ stepuser_pw | ansible.builtin.password_hash('sha512', pw_salt) }}"

- name: setting password & pw expiry to -1 for 'stepuser'
  ansible.builtin.user:
    name: "{{ user_item.name }}"
    comment: "{{ user_item.comment }}"
    shell: /bin/bash
    home: "{{ user_item.home }}"
    password: "{{ user_item.password }}"
    password_expire_max: -1
  become: true
  loop:
    - { name: "stepuser" , home: '/home/stepuser' , comment: "sudo user for step" , password: "{{ pw_hash }}" }
  loop_control:
    loop_var: user_item

```

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/ansible/original/1X/1882d9a01da5d8996a862359b0913cc568a39b84.svg) [@system](https://forum.ansible.com/u/system)\
**Post date:** [October 12, 2024, 2:28pm UTC](https://forum.ansible.com/t/create-a-hashed-password-with-debug/8280/11 "2024-10-12T14:28:44Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
