Dealing with a password with special characters in Ansible

17,708

Solution 1

Probably a little late but the exact solution to your specific problem is:

ansible-playbook test-playbook.yml -i hosts -u daniel --extra-vars ansible_ssh_pass=$'"u5!vuL!<35Lf?<>n\'x"'

The shell treats $'<string>' specially and escapes the single quote inside (see the backslash)

The outermost double quotes are necessary so that jinja2 template engine does not get confused inside ansible.

That being said, it is quite a bad idea to run the command like this for at least two reasons:

  • It's not secure. Anyone with access to listing processes on the machine or to your shell history will be able to see the password.
  • It's not flexible. Ansible extra variables provided on the command line have the highest precedence. If you add an other host in your inventory with a different ssh password, you won't be able to differentiate the two passwords.

For the first problem, and if you are sure you will only have one machine (or the same password everywhere), you could ask for the password interactively with vars_prompt for example (http://docs.ansible.com/ansible/latest/user_guide/playbooks_prompts.html)

The best approach solving both issues is to add the password using vault encryption to your inventory for the particular host. You then provide the overall vault password interactively (--ask-vault-pass) or through a well secured vault password file (--vault-password-file=) when you call the playbook.

Solution 2

Finally figured this one out for a password changing script that couldn't use vars_prompts.

For my bash program that was running ansible I needed to first get the password from a user via read then do the following:

  1. Convert the bad string into base64 and save to b64_pass
  2. Pass b64_pass as b64_ansible_ssh_pass extra arg
  3. Use set_fact to set ansible_ssh_pass and use b64decode filter on extra arg b64_ansible_ssh_pass

Short example testba.sh:

#!/bin/bash
read -p -s "Enter ssh password: " ssh_pass

# Convert input or var to base64
b64_pass=$(printf '%s' "$ssh_pass" | base64)

# Run ansible command
ansible-playbook test.yml -m shell -a "echo OK" -e "b64_ansible_ssh_pass='$b64_pass'" -v

Playbook test.yml:

- hosts: all

  # Assign ansible_ssh_pass in vars OR below in task with set_fact
  vars:
    ansible_ssh_pass: "{{ b64_ansible_ssh_pass | b64decode }}"

  tasks:
    # Assign ansible_ssh_pass in task with set_fact
    - name: Set ssh pass
      set_fact:
        ansible_ssh_pass: "{{ b64_ansible_ssh_pass | b64decode }}"
      no_log: true

    - shell: echo hi

If you need to pass a password var into the user module

#!/bin/bash
read -p -s "Enter ssh password: " ssh_pass

# Convert input or var to base64
b64_pass=$(printf '%s' "$ssh_pass" | base64)

# Run ansible command
ansible <hosts_to_run_on> -m shell -a "echo OK" -e "new_pass=$b64_pass"

Then in your playbook

- hosts: all
  vars:
    my_new_pass: "{{ new_pass | b64decode }}" 
  tasks:
    user:
      name: "NewUser"
      password: "{{ my_new_pass }}"
Share:
17,708
radicaled
Author by

radicaled

Updated on July 11, 2022

Comments

  • radicaled
    radicaled almost 2 years

    I'm trying to run an ansible playbook with the ansible_ssh_pass option to connect to the destination server.

    ansible-playbook test-playbook.yml -i hosts -u daniel --extra-vars "{"ansible_ssh_pass":"u5!vuL!<35Lf?<>n'x"}"
    

    The problem is that the password has special characters. I tried saving it using.

    "password\'s"
    "password"
    "\"password\""
    

    Any idea how can I save the password?

  • tweeks200
    tweeks200 over 6 years
    If your using linux you could setup and ssh key for the user you want and bypass the password altogether
  • radicaled
    radicaled over 6 years
    We are not allowed to share keys between the server. The idea is to do the connection using user/pass.