Bookmark this page

Managing Users and Authentication

Objectives

  • Manage Linux users and groups, configure SSH, and modify the Sudo configuration on managed hosts.

The User Module

The Ansible ansible.builtin.user module lets you create, configure, and remove user accounts on managed hosts. You can remove or add a user, set a user's home directory, set the UID for system user accounts, manage passwords, and assign a user to supplementary groups. To create a user that can log in to the machine, you need to provide a hashed password for the password parameter. See "How do I generate encrypted passwords for the user module?" for information on how to hash a password.

The following example demonstrates the ansible.builtin.user module:

- name: Create devops_user if missing, make sure is member of correct groups
  ansible.builtin.user:
    name: devops_user 1
    shell: /bin/bash 2
    groups: sys_admins, developers 3
    append: true

1

The name parameter is the only option required by the ansible.builtin.user module. Its value is the name of the service account or user account to create, remove, or modify.

2

The shell parameter sets the user's shell.

3

The groups parameter, when used with the append parameter, tells the machine to append the supplementary groups sys_admins and developers to this user. If you do not use the append parameter then the groups provided overwrite a user's existing supplementary groups. To set the primary group for a user, use the group option.

Note

The ansible.builtin.user module also provides information in return values, such as the user's home directory and a list of groups that the user is a member of. These return values can be registered into a variable and used in subsequent tasks. More information is available in the documentation for the module.

Table 9.1. Commonly Used Parameters for the User Module

ParameterComments
comment Optionally sets the description of a user account.
group Optionally sets the user's primary group.
groups Optionally sets a list of supplementary groups for the user. When set to a null value, all groups except the primary group are removed.
home Optionally sets the user's home directory location.
create_home Optionally takes a Boolean value of true or false. A home directory is created for the user if the value is set to true.
system Optionally takes a Boolean value of true or false. When creating an account, this makes the user a system account if the value is set to true. This setting cannot be changed on existing users.
uid Sets the UID number of the user.
state If set to present, create the account if it is missing (the default setting). If set to absent, remove the account if it is present.

Use the User Module to Generate an SSH Key

The ansible.builtin.user module can generate an SSH key if called with the generate_ssh_key parameter.

The following example demonstrates how the ansible.builtin.user module generates an SSH key:

- name: Create an SSH key for user1
  ansible.builtin.user:
    name: user1
    generate_ssh_key: true 1
    ssh_key_bits: 2048 2
    ssh_key_file: .ssh/id_my_rsa 3

1

The generate_ssh_key parameter accepts a Boolean value that specifies whether to generate an SSH key for the user. This does not overwrite an existing SSH key unless the force parameter is provided with the true value.

2

The ssh_key_bits parameter sets the number of bits in the new SSH key.

3

The ssh_key_file parameter specifies the file name for the new SSH private key (the public key adds the .pub suffix).

The Group Module

The ansible.builtin.group module adds, deletes, and modifies groups on the managed hosts. The managed hosts need to have the groupadd, groupdel, and groupmod commands available, which are provided by the shadow-utils package in Red Hat Enterprise Linux 9. For Microsoft Windows managed hosts, use the win_group module.

The following example demonstrates how the ansible.builtin.group module creates a group:

- name: Verify that the auditors group exists
  ansible.builtin.group:
    name: auditors 1
    state: present 2

1

The name parameter is the only required option for the ansible.builtin.group module. The value is the name of the group to manage.

2

The state parameter accepts the value absent or present, which removes or creates the group, respectively. The default value for the state parameter is present.

Table 9.2. Parameters for the Group Module

ParameterComments
gid This parameter sets the GID number to for the group. If omitted, the number is automatically selected.
local This parameter forces the use of local command alternatives (instead of commands that might change central authentication sources) on platforms that implement it.
name This parameter sets the name of the group to manage.
state This parameter determines whether the group should be present or absent on the remote host.
system If this parameter is set to true, then the group is created as a system group (typically, with a GID number below 1000).

The Known Hosts Module

The ansible.builtin.known_hosts module manages SSH host keys by adding or removing them on managed hosts. This ensures that managed hosts can automatically establish the authenticity of SSH connections to other managed hosts, ensuring that users are not prompted to verify a remote managed host's SSH fingerprint the first time they connect to it.

The following example demonstrates how the ansible.builtin.known_hosts module copies a host key to a managed host:

- name: Copy host keys to remote servers
  ansible.builtin.known_hosts:
    path: /etc/ssh/ssh_known_hosts 1
    name: servera.lab.example.com 2
    key: servera.lab.example.com,172.25.250.10 ssh-rsa ASDeararAIUHI324324 3

1

The path parameter specifies the path to the known_hosts file to edit. If the file does not exist, then it is created.

2

The name parameter specifies the name of the host to add or remove. The name must match the hostname or IP address of the key being added.

3

The key parameter is the SSH public host key as a string in a specific format. For example, the value for the key parameter must be in the format <hostname[,IP]> ssh-rsa <pubkey> for an RSA public host key (found in a host's /etc/ssh/ssh_host_rsa_key.pub key file), or <hostname[,IP]> ssh-ed25519 <pubkey> for an Ed25519 public host key (found in a host's /etc/ssh/ssh_host_ed25519_key.pub key file).

The following example demonstrates how to use the lookup plug-in to populate the key parameter from an existing file in the Ansible project:

- name: Copy host keys to remote servers
  ansible.builtin.known_hosts:
    path: /etc/ssh/ssh_known_hosts
    name: serverb
    key: "{{ lookup('ansible.builtin.file', 'pubkeys/serverb') }}" 1

1

This Jinja2 expression uses the lookup function with the ansible.builtin.file lookup plug-in to load the content of the pubkeys/servera.lab.example.com key file from the Ansible project as the value of the key option. You can list available lookup plug-ins using the ansible-navigator doc -l -t lookup command.

The following play is an example that uses some advanced techniques to construct an /etc/ssh/ssh_known_hosts file for all managed hosts in the inventory. There might be more efficient ways to accomplish this, because it runs a nested loop on all managed hosts.

It uses the ansible.builtin.slurp module to get the content of the RSA and Ed25519 SSH public host keys in Base64 format, and then processes the values of the registered variable with the b64decode and trim filters to convert those values back to plain text.

- name: Configure /etc/ssh/ssh_known_hosts files
  hosts: all

  tasks:
    - name: Collect RSA keys
      ansible.builtin.slurp:
        src: /etc/ssh/ssh_host_rsa_key.pub
      register: rsa_host_keys

    - name: Collect Ed25519 keys
      ansible.builtin.slurp:
        src: /etc/ssh/ssh_host_ed25519_key.pub
      register: ed25519_host_keys

    - name: Deploy known_hosts
      ansible.builtin.known_hosts:
        path: /etc/ssh/ssh_known_hosts
        name: "{{ item[0] }}" 1
        key: "{{ hostvars[ item[0] ]['ansible_facts']['fqdn'] }} {{ hostvars[ item[0] ][ item[1] ]['content'] | b64decode | trim }}" 2
        state: present
      with_nested:
        - "{{ ansible_play_hosts }}" 3
        - [ 'rsa_host_keys', 'ed25519_host_keys' ] 4

1

item[0] is an inventory hostname from the list in the ansible_play_hosts variable.

2

item[1] is the string rsa_host_keys or ed25519_host_keys. The b64decode filter converts the value stored in the variable from Base64 to plain text, and the trim filter removes an unnecessary newline. This is all one line starting with key, and there is a single space between the two Jinja2 expressions.

3

ansible_play_hosts is a list of the hosts remaining in the play at this point, taken from the inventory and removing hosts with failed tasks. The play must retrieve the RSA and Ed25519 public host keys for each of the other hosts when it constructs the known_hosts file on each host in the play.

4

This is a two-item list of the two variables that the play uses to store host keys.

Note

Lookup plug-ins and filters are covered in more detail in the course DO374: Developing Advanced Automation with Red Hat Ansible Automation Platform.

The Authorized Key Module

The ansible.posix.authorized_key module manages SSH authorized keys for user accounts on managed hosts.

The following example demonstrates how to use the ansible.posix.authorized_key module to add an SSH key to a managed host:

- name: Set authorized key
  ansible.posix.authorized_key:
    user: user1 1
    state: present 2
    key: "{{ lookup('ansible.builtin.file', 'files/user1/id_rsa.pub') }}" 3

1

The user parameter specifies the username of the user whose authorized_keys file is modified on the managed host.

2

The state parameter accepts the present or absent value with present as the default.

3

The key parameter specifies the SSH public key to add or remove. In this example, the lookup function uses the ansible.builtin.file lookup plug-in to load the contents of the files/user1/id_rsa.pub file in the Ansible project as the value for key. As an alternative, you can provide a URL to a public key file as this value.

Configuring Sudo Access for Users and Groups

In Red Hat Enterprise Linux 9, you can configure access for a user or group to run sudo commands without requiring a password prompt.

The following example demonstrates how to use the ansible.builtin.lineinfile module to provide a group with sudo access to the root account without prompting the group members for a password:

- name: Modify sudo to allow the group01 group sudo without a password
  ansible.builtin.lineinfile:
    path: /etc/sudoers.d/group01 1
    state: present 2
    create: true 3
    mode: 0440 4
    line: "%group01 ALL=(ALL) NOPASSWD: ALL" 5
    validate: /usr/sbin/visudo -cf %s 6

1

The path parameter specifies the file to modify in the /etc/sudoers.d/ directory. It is a good practice to match the file name with the name of the user or group you are providing access to. This makes it easier for future reference.

2

The state parameter accepts the present or absent value. The default value is present.

3

The create parameter takes a Boolean value and specifies if the file should be created if it does not already exist. The default value for the create parameter is false.

4

The mode parameter specifies the permissions on the sudoers file.

5

The line parameter specifies the line to add to the file. The format is specific, and an example can be found in the /etc/sudoers file under the "Same thing but without a password" comment. If you are configuring sudo access for a group, then you need to add a percent sign (%) to the beginning of the group name. If you are configuring sudo access for a user, then do not add the percent sign.

6

The validate parameter specifies the command to run to verify that the file is correct. When the validate parameter is present, the file is created in a temporary file path and the provided command validates the temporary file. If the validate command succeeds, then the temporary file is copied to the path specified in the path parameter and the temporary file is removed.

An example of the sudo validation command can be found in the examples section of the output from the ansible-navigator doc ansible.builtin.lineinfile command.

Revision: rh294-9.0-c95c7de