Reputation: 555
I am trying to change password for a non-root Linux user from Ansible playbook. To do so I tried to follow this link
Following the instruction I can successfully change the password of a non-root user by typing the code below in the terminal.
$ echo -e "your_current_pass\nlinuxpassword\nlinuxpassword" | passwd
Changing password for testuser.
(current) UNIX password: Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully
After that I am trying to automate the code with an Ansible playbook like below,
---
- hosts: all
gather_facts: no
tasks:
- name: "Check if user exists"
register: user1_exists
raw: getent passwd {{ ansible_user }}
ignore_errors: true
- name: "Change {{ ansible_user }} password"
raw: echo -e "my_current_pass\nmy_new_pass\nmy_new_pass" | passwd
when: user1_exists|success
I am using the raw module of Ansible here as most of my machines don't have Python installed. I do not have superuser (sudo)
permission either to use become: True
in playbook.
Also using password based authentication here to run the Ansible playbook on target machine. Not ssh based authentication.
But while I am executing the playbook I am getting this error,
TASK [change user1 password] ***************************************************
fatal: [192.168.0.57]: FAILED! => {"changed": true, "failed": true, "rc": 10,
"stderr": "Shared connection to 192.168.0.57 closed.\r\n", "stdout": "Changing
password for testuser.\r\n(current) UNIX password: passwd: Authentication
token manipulation error\r\npasswd: password unchanged\r\n", "stdout_lines":
["Changing password for testuser.", "(current) UNIX password: passwd:
Authentication token manipulation error", "passwd: password unchanged"]}
Could anyone show me the mistakes I am making here?
Upvotes: 3
Views: 34811
Reputation: 3015
I came to this question because I need to change password and I also don't have superuser privileges. But I do have python installed in all machines. In this case this can be solved with ansible expect
module.
vars_prompt:
- name: current_password
prompt: Please enter the current password
private: true
unsafe: true
- name: new_password
prompt: Please enter the new password
private: true
confirm: true
unsafe: true
tasks:
- name: Change password
expect:
command: passwd
responses:
"Current password": "{{current_password}}"
"New password": "{{new_password}}"
"Retype new password": "{{new_password}}"
no_log: true
Upvotes: 0
Reputation: 1579
Use the built-in user module instead of a shell command. This requires become: True
in your playbook. Note that the password
parameter of the user module requires an encrypted value. The password_hash
jinja filter will help you there.
- name: change user's password
user:
name: foo
password: "{{ 'passwordsaresecret' | password_hash('sha512') }}"
Upvotes: 9
Reputation: 2154
Your playbook is almost correct. I had the same kind of requirement and I used your playbook. There was just one mistake in your playbook, you forgot to enclose your password variables in '{{}}' braces. So I changed your playbook like below and it worked for me.
hosts: all
gather_facts: no
tasks:
- name: "Check if user exists"
register: user1_exists
raw: getent passwd {{ ansible_user }}
ignore_errors: true
- name: "Change {{ ansible_user }} password"
raw: echo -e "{{ ansible_password }}\n{{newpwd}}\n{{newpwd}}" | passwd
when: user1_exists|success
Upvotes: 1
Reputation: 6492
I've hacked together the following to solve this. The password's don't show in log or even verbose log '-vvvvv' and are not visible in history on remote systems:
---
- name: Change password when connecting as a non-root/non-sudoer user.
#
# Ansible's 'user' module can only change a password if it is ran as a root user or 'become' is used.
# For a non-root user, when you run 'passwd', it asks for current password before you can enter a new one.
# Workaround: Create a a temporary script that updates the password and run that script remoteley
# and use 'no_log' directive to prevent passwords being visible in any log.
# Tested that passwords not visible in verbose output '-vvvvv' and not in 'history' of remote computers.
# The temporary script is deleted remotley automatically by 'script' module.
# Note:
# New password must comply with your passwd security policy.
hosts: all
gather_facts: no
vars_prompt:
- name: "curr_pass"
prompt: Type in current password
private: yes
- name: "new_pass"
prompt: Type in new password
private: yes
confirm: yes
## If you need to *temporary* hard-code credentials, use below.
## Delete after use or use vault if you want long-term storage.
#vars:
#- curr_pass: MyOldPass
#- new_pass: MyNewPass123!!
tasks:
- name: Create a temporary local script which will change the users password
copy:
dest: updatePassNonRootDynamic.sh
content: echo -e '{{curr_pass}}\n{{new_pass}}\n{{new_pass}}' | passwd
delegate_to: localhost
no_log: True
run_once: true
- name: Change password via temporary script on all hosts
script: updatePassNonRootDynamic.sh
- name: Remove the temporary local script
file:
path: updatePassNonRootDynamic.sh
state: absent
delegate_to: localhost
run_once: true
Upvotes: 0