December 05, 2017

Creating a User in Ansible

^ Ad space to help offset hosting costs :D

Making users in Linux isn't necessarily as simple as making a username, and giving it a password. There are a few considerations you need to know about! Knowing these will make creating new users in Ansible easier.

First, some Linux distributions have the adduser command, wihch is a shortcut (with sensible defaults) to the useradd command.

By default, adduser command will create a new user that is able to login and has a home directory. The useradd command needs to be told to do all of these things. The way Ansible creates a user is more like useradd than the easier adduser.

Considerations

Here are a few things to know about creating a new user on Linux systems:

System vs Regular Users

By convention, users can be "system" users or "normal" users. System users often have a user id (UID) below 1000 and cannot be used to login. They are usually used to run programs. For example, users www-data or apache are often used to run web servers. Conversely, "regular" users typically have UID's at 1000 or higher and are allowed to log into the server.

If you're curious about how UID's are assigned, you can see the file /etc/login.defs to find variables like UID_MIN and UID_MAX set for system vs regular users:

#
# Min/max values for automatic uid selection in useradd
#
UID_MIN                  1000
UID_MAX                 60000
# System accounts
#SYS_UID_MIN              100
#SYS_UID_MAX              999

#
# Min/max values for automatic gid selection in groupadd
#
GID_MIN                  1000
GID_MAX                 60000
# System accounts
#SYS_GID_MIN              100
#SYS_GID_MAX              999

Ability to Login

Users cannot login (over SSH or otherwise) unless they are assigned a shell, usually /bin/bash. This shell is the program run when you login - it's why you can interact with the server.

The ability to login usually coincides with assigning the user a home directory. By convention (and default), this is created at /home/<username>, but can be any location.

Groups

Users have a primary group, which is usually the same name as their username. However, users can be assigned one or more secondary groups.

Creating a User in Ansible

Knowing the above, we can create a user in Ansible.

We'll create a user who is able to login with the following attributes:

  • User: fideloper
  • Password: secret
  • Home Directory: /home/fideloper
  • Shell: /bin/bash

We can see we're creating a "regular" user, one that can login. That user will likely be assigned a UID of 1000 or greater.

Here's a Ansible task file with a user definition for the above. It uses the user module to create a user:

---
 - name: Create a login user
     user:
      name: fideloper
      password: '???'
      groups: # Empty by default, here we give it some groups
       - docker
       - sudo
      state: present
      shell: /bin/bash       # Defaults to /bin/bash
      system: no             # Defaults to no
      createhome: yes        # Defaults to yes
      home: /home/fideloper  # Defaults to /home/<username>

Let's cover that task definition:

  1. name: Set the username (the primary group they belong to will be the same).
  2. password: Set their password, we'll cover how this works in a minute.
  3. groups: Assign secondary groups. Here we add this user to groups "docker" and "sudo" (group sudo allows the user to run sudo commands on Ubuntu and Debian linux).
  4. state: Tell ansible we want the user to exist.
  5. shell: You can define any shell. The default is /bin/bash. I just re-iterate the default here.
  6. system: Set this to "yes" to make it a system user. No shell or home directory will be made unless specified otherwise.
  7. createhome: Yes to create a home directory, no to not create one
  8. home: If you don't want to use the default location, set it here

Note that we have a few ways we can create users. Using the "system" setting we essentially flip a few defaults. A system user will have a lower UID, no shell, and no home directory. A "regular" user (system: no) will have these things assigned, and likely a UID at 1000 or over.

Generating Password Strings

The one thing I left off here is how to make a valid password string. You can't put a plaintext password into Ansible. Instead you need to generate one!

The easiest way to do this is with the mkpasswd command:

mkpasswd --method=sha-512

This will prompt you for the plaintext password and will give you a hashed password string you can paste into the task definition. For password secret, I get hash $6$F4NWXRFtSdCi8$DsB5vvMJYusQhSbvGXrYDXL6Xj37MUuqFCd4dGXdKd6NyxT3lpdELN07/Kpo7EjjWnm9zusFg/LLFv6oc.ynu/.

That would make my Yaml look like this:

---
 - name: Create a login user
     user:
      name: fideloper
      password: '$6$F4NWXRFtSdCi8$DsB5vvMJYusQhSbvGXrYDXL6Xj37MUuqFCd4dGXdKd6NyxT3lpdELN07/Kpo7EjjWnm9zusFg/LLFv6oc.ynu/'
      groups: docker, sudo   # Empty by default.
      state: present
      shell: /bin/bash       # Defaults to /bin/bash
      system: no             # Defaults to no
      createhome: yes        # Defaults to yes
      home: /home/fideloper  # Defaults to /home/<username>

Installing mkpasswd

To get the mkpasswd command:

  • On Debian/Ubuntu systems, mkpasswd likely exists, but if not, it's part of the whois package: sudo apt-get install -y whois.
  • On CentOS, I believe the expect package has it: sudo yum install expect. However, you can check to see if grub-crypt is available too and use it just like mkpasswd.
  • On Macintosh, you can install the mkpasswd gem via gem install mkpasswd. Source code here.

Resources

  1. Check the docs for more info, such as creating an SSH key on the fly
  2. Use the authorized_keys module to add an authorized public key

All Topics