GMaster
GMaster

Reputation: 1521

Using lookup plugin to check SHA512 password hash

In my Ansible git repo, I have a var file with contents like this

vault_users:
  alex:
    password: $6$PwhqORmvn$tXctAkh9RLs60ZFhn9Cxz/eLZEx1UhQkbDIoM6xWsk7M18TApDd9/b8CHJnEiaiQE2YJ8mqu6kvsGuImDt4dy/
  danny:
    password: $6$PwhqORmvn$tXctAkh9RLs60ZFhn9Cxz/eLZEx1UhQkbDIoM6xWsk7M18TApDd9/b8CHJnEiaiQE2YJ8mqu6kvsGuImDt4dy/
  gary:
    password: $6$PwhqORmvn$tXctAkh9RLs60ZFhn9Cxz/eLZEx1UhQkbDIoM6xWsk7M18TApDd9/b8CHJnEiaiQE2YJ8mqu6kvsGuImDt4dy/

Now, I want to check if the password hashes from this var file matches the ones from the /etc/shadow file on a remote server. I know it is possible to mix Ansible and a bash/python script to get what I want. I would like to know if it is possible to do this using pure Ansible playbooks only (no bash/python scripts) using the lookup plugin or some other Ansible feature.

Upvotes: 0

Views: 1198

Answers (1)

Andrew
Andrew

Reputation: 4632

You can use line in file to check if line has changed, register result and store it in another variable if lineinfile module returned "changed".

Unfortunately, due to this bug you can't simply use with_items and backrefs in lineinfile module to check if strings are valid, so i used a little include hack.

So we have a playbook called playbook.yml and task called checkpasswords.yml, let's explain each of them.

playbook.yml

- hosts: localhost
  tasks:
    # execute checkpasswords.yml for each user in vault_users dict 
    # and pass each user (or item) as {{ user }} variable to included task
    - include: checkpasswords.yml user="{{ item }}"
      with_items: "{{ vault_users }}"
    - debug: msg="{{ changed_users|default([]) }}"

checkpasswords.yml

- name: check for user and hash
  lineinfile:
    dest: /etc/shadow
    regexp: '{{ user }}:([^:]+):(.*)'
    # replace sting with user:hashed_password:everything_that_remains
    line: '{{ user }}:{{ vault_users[user].password }}:\2'
    state: present
    backrefs: yes
  register: u

- name: changed users
  set_fact:
    # set changed_users list to [] if not present and add [user] element
    # when user password has changed
    changed_users: "{{ changed_users|default([]) + [user] }}"
  when: u.changed

hashvars.yml

vault_users:
  root:
    password: "nothing to see here"
  my_user:
    password: "nothing here"

I included variables to hashvars.yml file and changed hashes for my_user and root inside it. So the result of executing this playbook will be something like output below, don't forget --check!

ansible-playbook playbook.yml -e @hashvars.yml --check

   PLAY [localhost] ***************************************************************

   TASK [setup] *******************************************************************
   ok: [localhost]

   TASK [include] *****************************************************************
   included: /home/my_user/workspace/so/checkpasswords.yml for localhost
   included: /home/my_user/workspace/so/checkpasswords.yml for localhost

   TASK [check for user and hash] *************************************************
   changed: [localhost]

   TASK [changed users] ***********************************************************
   ok: [localhost]

   TASK [check for user and hash] *************************************************
   changed: [localhost]

   TASK [changed users] ***********************************************************
   ok: [localhost]

   TASK [debug] *******************************************************************
   ok: [localhost] => {
       "msg": [
           "my_user",
           "root"
       ]
   }

   PLAY RECAP *********************************************************************
   localhost                  : ok=8    changed=2    unreachable=0    failed=0

Upvotes: 2

Related Questions