# Looking for ideas: secure user management

**URL:** <https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098>\
**Category:** Ansible Project\
**Created:** [December 8, 2013, 12:33pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098 "2013-12-08T12:33:35Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jurgen\_Haas2](https://avatars.discourse-cdn.com/v4/letter/j/f0a364/32.png) [@Jurgen\_Haas2](https://forum.ansible.com/u/Jurgen_Haas2)\
**Post date:** [December 8, 2013, 12:33pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/1 "2013-12-08T12:33:35Z")

</div>

Let’s assume we have any array of users that should be present on any host with some defined permissions. To do that with ansible, the modules ‘user’ and ‘authorized\_key’ are perfect tools.

What I would like to achieve in addition is to make sure that no other user accounts are available on my hosts. My thinking is to go through the following steps:

1. Get a list of all user accounts on the host.

2. For all users in that list that are not in my list of allowed users, take some action:

3. Lock the user: usermod -L USERNAME

4. Clean the authorized\_keys file in $HOMEDIR/.ssh

This should make sure that neither login through passwords nor with certificates should be possible for those accounts but we do not delete them, as there are many system accounts that you never really want to delete.

I’m sure this could be done with shell scripts but wouldn’t it be nicer if the Ansible modules could offer that as well?

Also, using the module authorized\_key is always adding new public keys to a given user account. What’s missing seems to be a reset option, so that all previous public keys get removed and only the ones being added will be valid from then on. A rest isn’t that difficult and can be done by deleting the existing $HOMEDIR/.ssh/authorized\_keys file, but that required the knowledge of the home dir which isn’t available through Ansible either.

Maybe extending the facts might help? If we knew all users, their state and their homedir, that would allow us to do much more already with existing modules.

Just looking for ideas and how others are approaching this.

---

<div class="post-metadata">

**Author:** ![Diogene\_Laerce](https://avatars.discourse-cdn.com/v4/letter/d/958977/32.png) [@Diogene\_Laerce](https://forum.ansible.com/u/Diogene_Laerce)\
**Post date:** [December 8, 2013, 1:42pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/2 "2013-12-08T13:42:49Z")

</div>

Hi,

I'm new to ansible and I'd like to know if the software only deals with  
repositories or is it able to download latest sources and install them ?  
I didn't find any docs on that "maybe" feature.

Thank you

---

<div class="post-metadata">

**Author:** ![James\_Cammarata1](https://avatars.discourse-cdn.com/v4/letter/j/d26b3c/32.png) [@James\_Cammarata1](https://forum.ansible.com/u/James_Cammarata1)\
**Post date:** [December 8, 2013, 3:08pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/3 "2013-12-08T15:08:36Z")

</div>

The yum and apt repositories mainly deal with configured repositories, however (with at least the yum module I know), you can specify a URL or local path for the package name and it will be installed just as it would with yum. You can use the apt\_repository module to add source repos, or with yum you can deploy the .repo files with the template or copy module.

---

<div class="post-metadata">

**Author:** ![James\_Cammarata1](https://avatars.discourse-cdn.com/v4/letter/j/d26b3c/32.png) [@James\_Cammarata1](https://forum.ansible.com/u/James_Cammarata1)\
**Post date:** [December 8, 2013, 3:14pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/4 "2013-12-08T15:14:45Z")

</div>

You could always add that information through a local fact.d script ([http://www.ansibleworks.com/docs/playbooks\_variables.html#local-facts-facts-d](http://www.ansibleworks.com/docs/playbooks_variables.html#local-facts-facts-d)). Enumerating every installed user’s information in facts could be a ton of information, especially if your system is authenticating through a directory service, so that’s not something most users would want to be on by default.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [December 8, 2013, 3:52pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/5 "2013-12-08T15:52:49Z")

</div>

Yep, it’s a big part of app deployment to push things that aren’t packages, so we have lots of ways to do that.

Take a look at the module index, and you’ll find a lot of useful modules.

get\_url is ideal for fetching a tarball, but there are also modules for checking out source code from git, svn, hg, and bzr.

The “unarchive” module in 1.4 can also push a tarball and automatically extract it.

[http://ansibleworks.com/docs/modules.html](http://ansibleworks.com/docs/modules.html)

[http://ansibleworks.com/docs/modules.html#source-control](http://ansibleworks.com/docs/modules.html#source-control)

[http://ansibleworks.com/docs/modules.html#files](http://ansibleworks.com/docs/modules.html#files)

[http://ansibleworks.com/docs/modules.html#network](http://ansibleworks.com/docs/modules.html#network)

Hope this helps and let us know if you have other questions!

–Michael

---

<div class="post-metadata">

**Author:** ![kahlil.hodgson](https://avatars.discourse-cdn.com/v4/letter/k/b9bd4f/32.png) [@kahlil.hodgson](https://forum.ansible.com/u/kahlil.hodgson)\
**Post date:** [December 8, 2013, 8:18pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/6 "2013-12-08T20:18:22Z")

</div>

How about

---

<div class="post-metadata">

**Author:** ![kahlil.hodgson](https://avatars.discourse-cdn.com/v4/letter/k/b9bd4f/32.png) [@kahlil.hodgson](https://forum.ansible.com/u/kahlil.hodgson)\
**Post date:** [December 8, 2013, 8:22pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/7 "2013-12-08T20:22:55Z")

</div>

Oops, missing '-a' in perl oneliner. That should be

&nbsp;&nbsp;&nbsp;&nbsp;perl -ane -F: 'print $F[0] if $F[1] \> 499'

K

---

<div class="post-metadata">

**Author:** ![kahlil.hodgson](https://avatars.discourse-cdn.com/v4/letter/k/b9bd4f/32.png) [@kahlil.hodgson](https://forum.ansible.com/u/kahlil.hodgson)\
**Post date:** [December 8, 2013, 10:02pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/8 "2013-12-08T22:02:13Z")

</div>

Arghhh! Not enough coffee. Got my index's wrong too. I should be

&nbsp;&nbsp;&nbsp;&nbsp;perl -ane -F: 'print $F[0],"\n" if $F[2] \> 499'

There is an open pull request for a 'capture' jinja filter that would  
make all that unnecessary, but that should be discussed on the devel  
list 🙂

K

---

<div class="post-metadata">

**Author:** ![Jurgen\_Haas2](https://avatars.discourse-cdn.com/v4/letter/j/f0a364/32.png) [@Jurgen\_Haas2](https://forum.ansible.com/u/Jurgen_Haas2)\
**Post date:** [December 9, 2013, 8:51am UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/9 "2013-12-09T08:51:33Z")

</div>

Using

cat /etc/passwd | perl -ane -F: ‘print $F[0],“\n” if $F[2] \> 499’

Generates the following error message:

Warning: Use of “-F” without parentheses is ambiguous at -e line 1.  
syntax error at -e line 1, near “F:”  
Execution of -e aborted due to compilation errors.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [December 9, 2013, 2:14pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/10 "2013-12-09T14:14:39Z")

</div>

I have buried my Perl book and have it guarded by many layers of traps 🙂

That all being said, this would be a great thing to capture into a role, so it’s abstracted away and other people can use it, and then the complexity is reduced.

Our Galaxy site is launching next week so this might be a good one to think about including.

---

<div class="post-metadata">

**Author:** ![kahlil.hodgson](https://avatars.discourse-cdn.com/v4/letter/k/b9bd4f/32.png) [@kahlil.hodgson](https://forum.ansible.com/u/kahlil.hodgson)\
**Post date:** [December 9, 2013, 8:31pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/11 "2013-12-09T20:31:32Z")

</div>

cat /etc/passwd | perl -aF: -ne 'print $F[0],"\n" if $F[2] \> 499'

Arghh! -e must precede the expression -- yesterday was not a good day.

K

Kahlil (Kal) Hodgson GPG: C9A02289  
Head of Technology (m) +61 (0) 4 2573 0382  
DealMax Pty Ltd (w) +61 (0) 3 9008 5281

Suite 1415  
401 Docklands Drive  
Docklands VIC 3008 Australia

"All parts should go together without forcing. You must remember that  
the parts you are reassembling were disassembled by you. Therefore,  
if you can't get them together again, there must be a reason. By all  
means, do not use a hammer." -- IBM maintenance manual, 1925

---

<div class="post-metadata">

**Author:** ![Jurgen\_Haas2](https://avatars.discourse-cdn.com/v4/letter/j/f0a364/32.png) [@Jurgen\_Haas2](https://forum.ansible.com/u/Jurgen_Haas2)\
**Post date:** [December 10, 2013, 9:22am UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/12 "2013-12-10T09:22:06Z")

</div>

Great, that works. And with $F[5] we also get the home directory for each user. So I’ll see if I can turn that into a default playbook for general us as Michael DeHaan suggested.

---

<div class="post-metadata">

**Author:** ![Jurgen\_Haas2](https://avatars.discourse-cdn.com/v4/letter/j/f0a364/32.png) [@Jurgen\_Haas2](https://forum.ansible.com/u/Jurgen_Haas2)\
**Post date:** [December 10, 2013, 11:46am UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/13 "2013-12-10T11:46:21Z")

</div>

Here is the Ansible role on [github.com](http://github.com): [https://github.com/jurgenhaas/ansible-user-management](https://github.com/jurgenhaas/ansible-user-management)

It can be executed as a role, e.g. like this:

- name: “Manage Users”  
hosts: “all”  
connection: ssh  
gather\_facts: false  
sudo: yes  
roles:
- users

Enjoy!

My plan is to further enhance that role so that it is going to become the full user management role including the creation of user accounts and management of ssh keys plus many more ideas hopefully to come.

---

<div class="post-metadata">

**Author:** ![kahlil.hodgson](https://avatars.discourse-cdn.com/v4/letter/k/b9bd4f/32.png) [@kahlil.hodgson](https://forum.ansible.com/u/kahlil.hodgson)\
**Post date:** [December 10, 2013, 10:21pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/14 "2013-12-10T22:21:26Z")

</div>

Another approach occurs that does not require the Perl Crazy Glue:

- name: grab passwd entries for this host  
&nbsp;&nbsp;shell: cat /etc/passwd'  
&nbsp;&nbsp;register: passwd

- name: lock unknown users  
&nbsp;&nbsp;user: name={{ item.split(':').0 }} password='!!'

&nbsp;&nbsp;when: item.split(':').0 not in known\_users  
&nbsp;&nbsp;&nbsp;&nbsp;and item.split(':').2|int \> 499

&nbsp;&nbsp;with\_items: passwd.stdout\_lines

- name: lock out unknown users  
&nbsp;&nbsp;command: rm -rf {{ item.split(':').5 }}/.ssh

&nbsp;&nbsp;when: item.split(':').0 not in known\_users  
&nbsp;&nbsp;&nbsp;&nbsp;and item.split(':').2|int \> 499

&nbsp;&nbsp;with\_items: passwd.stdout\_lines

Kahlil (Kal) Hodgson GPG: C9A02289  
Head of Technology (m) +61 (0) 4 2573 0382  
DealMax Pty Ltd (w) +61 (0) 3 9008 5281

Suite 1415  
401 Docklands Drive  
Docklands VIC 3008 Australia

"All parts should go together without forcing. You must remember that  
the parts you are reassembling were disassembled by you. Therefore,  
if you can't get them together again, there must be a reason. By all  
means, do not use a hammer." -- IBM maintenance manual, 1925

---

<div class="post-metadata">

**Author:** ![Jurgen\_Haas2](https://avatars.discourse-cdn.com/v4/letter/j/f0a364/32.png) [@Jurgen\_Haas2](https://forum.ansible.com/u/Jurgen_Haas2)\
**Post date:** [December 11, 2013, 6:18pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/15 "2013-12-11T18:18:13Z")

</div>

Like that. Any objection if I included that in the github role?

---

<div class="post-metadata">

**Author:** ![kahlil.hodgson](https://avatars.discourse-cdn.com/v4/letter/k/b9bd4f/32.png) [@kahlil.hodgson](https://forum.ansible.com/u/kahlil.hodgson)\
**Post date:** [December 11, 2013, 9:05pm UTC](https://forum.ansible.com/t/looking-for-ideas-secure-user-management/14098/16 "2013-12-11T21:05:49Z")

</div>

No objection. Enjoy!

K

Kahlil (Kal) Hodgson GPG: C9A02289  
Head of Technology (m) +61 (0) 4 2573 0382  
DealMax Pty Ltd (w) +61 (0) 3 9008 5281

Suite 1415  
401 Docklands Drive  
Docklands VIC 3008 Australia

"All parts should go together without forcing. You must remember that  
the parts you are reassembling were disassembled by you. Therefore,  
if you can't get them together again, there must be a reason. By all  
means, do not use a hammer." -- IBM maintenance manual, 1925
