Ansible for user management -removing dead accounts
Asked Answered
A

3

6

How to efficiently manage user accounts in Ansible? I want to keep user accounts and certificates in list.

When running playbook I would like to create every account from list (thats easy). I also want to remove accounts existing on host, but not present in list.

For now, I figured out list existing accounts awk -F: '($3 >= 1000) {printf "%s\n",$1}' /etc/passwd

and compare it with my list- removing unwanted accounts.

Is there easier way- module that does that out-of-the-box?

Alvarez answered 25/5, 2016 at 15:36 Comment(1)
I have one thought: use your snippet in a local fact (docs.ansible.com/ansible/…) so that the users on each server can be accessed as an array from the playbook.Wisniewski
G
4

WARNING CAUTION Do it only if you are absolutely sure about the user to be removed. This may make your system useless if you remove system users like root.

Few lines of Ansible can do what you are asking for. Leverage the user module.

  vars:
    myusers: ['root', 'bin', 'mail', 'obama', 'trump', 'clinton', 'you', 'me']

  tasks:
  - shell: 'cut -d: -f1 /etc/passwd'
    register: users
  - user: name={{item}} state=absent remove=yes
    with_items: users.stdout_lines
    when: item not in myusers
Gloat answered 25/5, 2016 at 17:30 Comment(5)
You need to be really careful about doing things this way. You would need to specify all of the system users or it will remove them.Mellophone
@smiller171 you are correct. If not used correctly, it will render the machine useless.Gloat
The solution I use has you specify users to remove, rather than deleting everything not in a list.Mellophone
Also just suggested an edit so that your example doesn't mark anything as changed unless it has changed something.Mellophone
With more recent versions of Ansible you'd use loop. Having said that, this code will fail with `'dict object' has no attribute 'stdout_lines' if no items exist (e.g. if you try extending this code to groups).Desdee
M
8

Search for user-id > 1000 when parsing /etc/passwd and add nobody to the list of valid users. This way you're not removing any system users.

vars:
  myusers: ['nobody', 'obama', 'trump', 'clinton', 'you', 'me']

tasks:
- shell: "getent passwd | awk -F: '$3 > 1000 {print $1}'"
  register: users

- user: name={{item}} state=absent remove=yes
  with_items: users.stdout_lines
  when: item not in myusers

Remember to add nobody to your list of valid users.

Mensurable answered 11/8, 2017 at 12:28 Comment(5)
Unfortunately, getent passwd does not list remote users, e.g. coming from sssd.Conto
Well, you won't get coffee out of a tea maker.Mensurable
On Centos 7 with NFS instead of nobody you will have nfsnobody user.Leisha
Why do you want remote users to be listed here, @yktoo? I think that you should remove them in their source, like LDAP, in a source-specific way.Leisha
shouldn't it be getent passwd | awk -F: '$3 >= 1000 {print $1}' ?Corrugate
G
4

WARNING CAUTION Do it only if you are absolutely sure about the user to be removed. This may make your system useless if you remove system users like root.

Few lines of Ansible can do what you are asking for. Leverage the user module.

  vars:
    myusers: ['root', 'bin', 'mail', 'obama', 'trump', 'clinton', 'you', 'me']

  tasks:
  - shell: 'cut -d: -f1 /etc/passwd'
    register: users
  - user: name={{item}} state=absent remove=yes
    with_items: users.stdout_lines
    when: item not in myusers
Gloat answered 25/5, 2016 at 17:30 Comment(5)
You need to be really careful about doing things this way. You would need to specify all of the system users or it will remove them.Mellophone
@smiller171 you are correct. If not used correctly, it will render the machine useless.Gloat
The solution I use has you specify users to remove, rather than deleting everything not in a list.Mellophone
Also just suggested an edit so that your example doesn't mark anything as changed unless it has changed something.Mellophone
With more recent versions of Ansible you'd use loop. Having said that, this code will fail with `'dict object' has no attribute 'stdout_lines' if no items exist (e.g. if you try extending this code to groups).Desdee
M
0

Try using this Ansible role I wrote: https://galaxy.ansible.com/smiller171/manage_users

Mellophone answered 25/5, 2016 at 17:1 Comment(2)
URL leads to 404.Leisha
Looks like my username ended up changing, breaking the URL I've edited my answerMellophone

© 2022 - 2024 — McMap. All rights reserved.