Skip to content

EX362 Exam Prep

This page contains the necessary resources to help you prepare for the Red Hat Certified Specialist in Identity Management exam, EX362. This follows the youtube playlist as much as possible with various examples and ideas. Soon to come, you will also find our own example practice exam for you to try your hand at to test your knowledge.

The list of objectives can be found here. Note that the exam objectives can change at any time. It is the responsibility of the reader to always review the objectives prior to studying and taking the exam to ensure success.

Affiliation and Exam Information

Please note that we are not affiliated with Red Hat. The materials and examples used are our own and do not reflect the training programs provided by Red Hat and are educational only. We do not disclose any of the tasks, questions, or material on the exam as it would violate the NDA. Any questions sent to us about anything directly related to the exam will not be answered. We also do not provide any one-on-one tutoring or online teaching courses.

If exam objectives have changed to where the videos and this material are missing information, we can add on at any time upon request. If exam objectives have not changed but operational tasks have, we will note them as we find them. If there are things about FreeIPA that you'd like to see in the videos that may fit into objective, we can add it also upon request. However, it is likely those extra things would be better suited in the separate FreeIPA section on this site.

Overview

This series goes over setting up FreeIPA in a lab/VM environment by following the objectives as outlined by Red Hat. The list of objectives can be found here.

Multi-method

Throughout this material, you will see a combination of both "Script or CLI" and "Ansible" methods of working with FreeIPA (or Red Hat IdM), in selectable tabs. This is because we believe in the user understanding and knowing how to do things by hand first and foremost before ever automating it. Automation cannot be fully achieved without having an understanding of the underlying software and applications.

In conclusion, we highly recommend that any user studying for their exam reading this guide understands how to do everything by hand first before attempting to redo it via ansible.

Exam Information

The EX362 exam tests your knowledge in a real world format style test - Meaning just like any Red Hat exam, it is performance-based and you perform tasks as if you were on the job. You are evaluated on the tasks you perform and if they meet the objective criteria. The EX362 is related to FreeIPA or Red Hat Identity Management and counts toward the RHCA (Red Hat Certified Architect). You are expected to have familiarity with ansible for this exam. As such, ansible setup and explanation will be limited.

To take the exam, you must have at least an RHCSA. If you are attempting to become a Red Hat Certified Architect, you must have an RHCE.

Ansible Information

As ansible is expected for this exam, you may be required to work with ansible collections to work with FreeIPA. The community version of the collection is simply freeipa.ansible_freeipa. This can be installed via ansible-galaxy or via dnf install ansible-freeipa. You will find that the Red Hat official collection name has a different name entirely.

Throughout this page, we will be using the ansible-galaxy version of the collection, which ensure we are using a FQCN. This is because if you are using Ansible Automation Platform (or AWX), you will need to use the FQCN in just about all cases.

Note

As ansible is a fairly new addition to this exam and to this study guide, there may be inaccuracies. We highly encourage PR's or comments that address problems with the ansible data we provide here.

Resources

Hardware Recommendations

The minimum requirements for IdM are fairly low. 2GB of RAM, 1 core, and a 10GB disk. However, we believe that's too low, especially if we plan on scaling out. And during upgrades, you would need at least 4GB of RAM for the operations to be successful. Below are our minimum recommendations:

  • 2 (virtual) CPU Core
  • 4 GB of RAM
  • 10GB+ disk or partition for /var/lib/dirsrv

Per the Red Hat documentation, consider that with at least 10k users and 100 groups, you would need at least 3GB of RAM and 1GB swap. If you end up having 100k users and 50k groups, then 16GB of RAM and 4GB of swap is recommended. In fact, in larger deployments, it's more effective to increase RAM than disk, as most data is stored in cache.

View the resources above in the previous section for directory server tuning information.

Expected lab systems

Below is a list of expected lab systems to perform the work on this page.

System Name IP Address Role
idm1.example.com 192.168.15.2 IdM Server
idm2.example.com 192.168.15.3 IdM Server
client.example.com 192.168.15.10 IdM Client
nfs.example.com 192.168.15.11 NFS Server
utility.example.com 192.168.15.12 Utility Server
ansible.example.com 192.168.15.50 Ansible controller

You may want to consider setting up an NTP server, if you do not wish to use the default from chrony. This can be done on the utility server. See Setup an NTP Server.

Setup Ansible Controller and Clients

As the exam may expect familiarity with ansible, setting up an ansible controller may be ideal.

Note

We still recommend basic familiarity with FreeIPA itself as it is ideal for understanding the entire stack. Learning by hand is important first before attempting to automate.

Controller Setup

# as root, install the necessary packages and create the user
% dnf install ansible -y
% useradd ansible

# ensure ansible can do root things locally.
% visudo -f /etc/sudoers.d/ansible
ansible ALL=(ALL) NOPASSWD: ALL

Become the ansible user, and finish the general configuration.

% ssh-keygen
% ansible-config init --disabled > ansible.cfg

Configure ansible.cfg in any way you see fit. We recommend these settings at a minimum.

[defaults]
roles_path    = roles:/usr/share/ansible/roles
collections_paths = collections:/usr/share/ansible/collections
remote_user = ansible
; id_rsa is the default generated key. you can use any format.
private_key_file = /home/ansible/.ssh/id_rsa
ansible_managed = EX362 Study

[inventory]
enable_plugins = host_list, virtualbox, yaml, constructed, script, ini, auto

Configure the base inventory. For the inventory, you should ensure all lab systems are listed.

[ipa:children]
ipaserver
ipareplicas
ipaclients

[ipa:vars]

[ipaserver:vars]

[ipareplica:vars]

[ipaclients:vars]

[ipaserver]
idm1.example.com    ansible_host=192.168.15.2

[ipareplica]
idm2.example.com    ansible_host=192.168.15.2

[ipaclients]
ansible.example.com ansible_connection=local
client.example.com  ansible_host=192.168.15.10
nfs.example.com     ansible_host=192.168.15.11
utility.example.com ansible_host=192.168.15.12

Install the required collections.

% ansible-galaxy collection install freeipa.ansible_freeipa

# if you plan on managing network manager using ansible, use this collection.
% ansible-galaxy collection install community.general

# if you plan on managing firewalld and other features, use this collection.
% ansible-galaxy collection install ansible.posix

At this point, you will need to configure all the clients with an ansible user and the public key. See the ansible documentation for more details.

Install and configure Red Hat Identity Management (IdM)

Install IdM using either scripts or using Ansible Automation Platform

System Name IP Address
idm1.example.com 192.168.15.2
idm2.example.com 192.168.15.3
ansible.example.com 192.168.15.50

Domain/Realm Information

The domain/realm for this will be example.com

Static Addresses

IPA Servers should either have a DHCP reservation or a static address. In the event that you have either, DNS should always be pointing at 127.0.0.1, especially if your replica serves DNS. Both of our replicas serve DNS, so loopback is sufficient and recommended for our name server.

In later versions of FreeIPA, there is support to force network manager to ensure resolv.conf is loopback without the need to set it by hand with nmcli.

% hostnamectl set-hostname idm1.example.com
# Set a static address - It's important for your IdM servers
# to have static addresses or a DHCP reservation.
% nmcli con mod eth0 ipv4.address 192.168.15.2/24
% nmcli con mod eth0 ipv4.gateway 192.168.15.1
% nmcli con mod eth0 ipv4.method manual
% nmcli con mod eth0 ipv4.dns-search example.com

# You should set this if your replica serves DNS! If not, set it to
# one or more of your IdM replicas that do.
% nmcli con mod eth0 ipv4.dns 127.0.0.1
% nmcli con up eth0
# Examples of using ipa-server-install
# RHEL 9
% dnf install ipa-server ipa-server-dns ipa-client sssd sssd-ipa
# Installation, interactive, does not setup specific components
% ipa-server-install

# Installation, mostly automatic (recommended)
# This will setup DNS and the necessary pieces for an AD trust
# Optionally, you can set --setup-adtrust use the --netbios-name switch
# to set your forest netbios name
% ipa-server-install --domain example.com --realm EXAMPLE.COM \
    --reverse-zone=15.168.192.in-addr.arpa. \
    --no-forwarders \
    --no-ntp \
    --setup-dns \
    -p Passw0rd! \
    -a Passw0rd!

# Same as the above, but sets NTP server to sync to before starting
# the installation.
% ipa-server-install --domain example.com --realm EXAMPLE.COM \
    --reverse-zone=15.168.192.in-addr.arpa. \
    --no-forwarders \
    --ntp-server=192.168.15.12 \
    --setup-dns \
    -p Passw0rd! \
    -a Passw0rd!
% firewall-cmd --permanent --add-service={freeipa-4,dns}
% kinit admin
# We need to make sure that any A records get a corresponding PTR record, otherwise you're making them manually.
% ipa dnsconfig-mod --allow-sync-ptr=True

Ensure that your ansible controller is setup and install the collections as needed.

Ensure ansible is operable on all machines

It is recommended that on all machines in this lab, you are configuring ansible as a user with full sudo rights.

Static Addressing, command vs collection

Earlier, it was suggested to install community.general as it provides an nmcli module. We will be using this. It should be noted that you may not have access to that collection on the exam.

We also suggested ansible.posix. You may not also have access to this on the exam.

Modify the inventory with the necessary variables and domain information.

[ipa:children]
ipaserver
ipareplicas
ipaclients

; Based on exam requirements, these vars might have to be set differently
[ipa:vars]
; if you are using an ntp server, set to false and  set ipaclient_ntp_servers
; ipaclient_no_ntp=false
; ipaclient_ntp_servers='["192.168.15.12"]'
ipaclient_no_ntp=true
; we plan on setting up roaming home directories. setting this
; to true shouldn't hurt.
ipaclient_mkhomedir=true
ipaclient_ssh_trust_dns=true

[ipaserver:vars]
ipaadmin_principal=admin
ipaadmin_password='Passw0rd!'
ipadm_password='Passw0rd!'

ipaserver_domain=example.com
ipaserver_realm=EXAMPLE.COM
ipaserver_setup_dns=true
ipaserver_setup_kra=true
ipaserver_setup_firewalld=true
ipaserver_no_forwarders=true
ipaserver_auto_forwarders=false
ipaserver_no_host_dns=true
ipaserver_reverse_zones='["15.168.192.in-addr.arpa."]'
ipaserver_external_ca=false
; ipaserver_setup_adtrust=true
; ipaserver_netbios_name=EXAMPLEAD

[ipareplica:vars]
ipaadmin_principal=admin
ipaadmin_password='Passw0rd!'
ipadm_password='Passw0rd!'

ipaserver_realm=EXAMPLE.COM
ipareplica_domain=example.com
ipareplica_setup_ca=true
ipareplica_setup_dns=true
ipareplica_setup_kra=true
ipareplica_setup_firewalld=true
ipareplica_no_forwarders=true
ipareplica_auto_forwarders=false
; ipareplica_setup_adtrust=true
; ipareplica_netbios_name=EXAMPLEAD

[ipaclients:vars]
ipaclient_domain=example.com
ipaclient_realm=EXAMPLE.COM
; the reason why we have a separate principal and password
; is because we may have a service account that enrolls instead
ipaadmin_principal=admin
ipaadmin_password='Passw0rd!'

[ipaserver]
idm1.example.com    ansible_host=192.168.15.2

[ipareplica]
idm2.example.com    ansible_host=192.168.15.2

[ipaclients]
ansible.example.com ansible_connection=local
client.example.com  ansible_host=192.168.15.10
nfs.example.com     ansible_host=192.168.15.11
utility.example.com ansible_host=192.168.15.12

Create the role.

% vi role_ipa_server.yml
---
- name: "Standup IPA Server"
  hosts: ipaserver
  become: true

  pre_tasks:
    # ensure hostname is what is expected
    - name: "Set hostname"
      ansible.builtin.hostname:
        name: idm1.example.com
        use: systemd

    # This sets up network manager using community.general.
    - name: "Set static address"
      community.general.nmcli:
        ifname: enp1s0
        conn_name: enp1s0
        type: ethernet
        method4: manual
        ip4:
          - 192.168.15.2/24
        gw4: 192.168.15.1
        dns4_search: example.com
        dns4: 127.0.0.1
        autoconnect: true
        state: present

  roles:
    - role: freeipa.ansible_freeipa.ipaserver
      state: present

  post_tasks:
    # We need to ensure firewalld was setup the way we wanted it to
    - name: "Ensure firewalld rules are accurate"
      ansible.posix.firewalld:
        service: "{{ item }}"
        permanent: true
        immediate: true
        state: enabled
      with_items:
        - "freeipa-4"
        - "dns"

    # We need to make sure that any A records get a PTR record.
    - name: "Ensure PTR is in sync"
      freeipa.ansible_freeipa.ipadnsconfig:
        ipaadmin_principal: "{{ ipaadmin_principal }}"
        ipaadmin_password: "{{ ipaadmin_password }}"
        allow_sync_ptr: true

Run the role to setup the server.

% ansible-playbook role_ipa_server.yml

Install and configure a replica IdM Server

% hostnamectl set-hostname idm2.example.com
% nmcli con mod eth0 ipv4.address 192.168.15.3/24
% nmcli con mod eth0 ipv4.gateway 192.168.15.1
% nmcli con mod eth0 ipv4.method manual
% nmcli con mod eth0 ipv4.dns-search example.com
% nmcli con mod eth0 ipv4.dns 192.168.15.2
% nmcli con up eth0
# Adding a replica, optionally change --no-ntp to --ntp-server
% ipa-replica-install --setup-dns \
    --setup-ca \
    --no-forwarders \
    --no-ntp

# Adding a replica unattended without forwarders.
# Optionally set --ntp-server.
% ipa-client-install --realm EXAMPLE.COM --no-ntp
% kinit admin
% ipa hostgroup-add-member --hosts=ipa02.example.com ipaservers
% ipa-replica-install --setup-dns \
    --setup-ca \
    --no-forwarders \
    --no-ntp \
    --unattended
% vi role_ipa_replica.yml
---
- name: "Standup IPA Replica"
  hosts: ipareplicas
  become: true

  pre_tasks:
    # ensure hostname is what is expected
    - name: "Set hostname"
      ansible.builtin.hostname:
        name: idm2.example.com
        use: systemd

    # This sets up network manager using community.general.
    - name: "Set static address"
      community.general.nmcli:
        ifname: enp1s0
        conn_name: enp1s0
        type: ethernet
        method4: manual
        ip4:
          - 192.168.15.3/24
        gw4: 192.168.15.1
        dns4_search: example.com
        dns4: 192.168.15.2
        autoconnect: true
        state: present

    - name: "Ensure firewalld rules are accurate"
      ansible.posix.firewalld:
        service: "{{ item }}"
        permanent: true
        immediate: true
        state: enabled
      with_items:
        - "freeipa-4"
        - "dns"

  roles:
    - role: freeipa.ansible_freeipa.ipareplica
      state: present

Run the role to setup the replica.

% ansible-playbook role_ipa_replica.yml

Create Users, Groups, and Policies

Users Login Name Type Group Role UID/GID
John Smith jsmith Normal admins Auto
Bob Rufus brufus Normal corp Auto
Larry Dufus ldufus Normal helpdesk Auto
Robert Cole rcole Staged Auto
Thomas Snyder tsnyder Preserved Auto
SysHost Management syshostmgt Normal Host Manager 10000
Groups Policy
HelpDesk helpdesk
corp
enrollers Enrollment Administrator
Roles Privilege
Host Manager Host administrators
Host group administrators
Netgroups administrators
Host enrollment

Custom UID/GID

It is possible to create the users with a custom uid/gid with the switches --uid and --gidnumber which you will see below. It is also possible to set random passwords with --random.

See ipa user-add --help for more switches.

Password Expiration

When you make a user with the --password switch or use ipa passwd to set a password, it is automatically expired and must be changed on next login. If you want to avoid this from happening, you will need to set a random password via --password or --random, and then use kpasswd username to change it to the desired password. This does not make the account non-expiring.

# Creating users with a password, create all the accounts from the table (except from syshost)
% ipa user-add --first="John" --last="Smith" --password jsmith

# Create the system account with a password of Sup3R$ecre7! and a UID of 10000
% ipa user-add --first="SysHost" --last="Management" --uid=10000 --gidnumber=10000 --password syshostmgt

# Stage a user
% ipa stageuser-add --first="Robert" --last="Cole" rcole

# Preserve a user
% ipa user-del tsynder --preserve

# Create a regular (POSIX) group
% ipa group-add corp

# Create a member only group
% ipa group-add --nonposix HelpDesk
% ipa group-add --nonposix enrollers

# Add the HelpDesk group to the helpdesk policy
# Add the enrollers group to the Enrollment Administrator role
% ipa role-add-member "helpdesk" --groups=HelpDesk
% ipa role-add-member "Enrollment Administrator" --groups=enrollers

# Create a role with privileges
% ipa role-add "Host Manager"
% ipa role-add-privilege "Host Manager" \
    --privileges="Host administrators" \
    --privileges="Host group administrators" \
    --privileges="Netgroups administrators" \
    --privileges="Host enrollment"

# Add the syshostmgt user as a member of the role
% ipa role-add-member "Host Manager" --users="syshostmgt"

# Set our user passwords to CentOS123!$ so that way we don't have to change them later
% kpasswd jsmith

# If we already set the password we want but we don't want it to expire without making a policy or prompt for a password change (NOT RECOMMENDED)
% ldapmodify -x -w 'Passw0rd!' -D 'cn=Directory Manager'
dn: uid=syshostmgt,cn=users,cn=accounts,dc=example,dc=com
changetype: modify
delete: krbLastPwdChange

(Press CTRL+D)
% vi create_ipa_users.yml
---
- name: "Create users"
  hosts: ipaserver
  become: false
  vars:
    # All users are setup as a dictionary
    users:
      - name: jsmith
        first: John
        last: Smith
        password: "CentOS123!$"
      - name: brufus
        first: Bob
        last: Rufus
        password: "CentOS123!$"
      - name: ldufus
        first: Larry
        last: Dufus
        password: "CentOS123!$"
      - name: syshostmgt
        first: SysHost
        last: Management
        uid: 10000
        gid: 10000
        password: "CentOS123!$"
      - name: tsnyder
        first: Thomas
        last: Snyder
        password: "CentOS123!$"
    staged_users:
      - name: rcole
        first: Robert
        last: Cole
    preserved_users:
      - tsnyder

  tasks:
    - name: Create all users
      freeipa.ansible_freeipa.ipauser:
        ipaadmin_password: "{{ ipaadmin_password }}"
        users: "{{ users }}"

    - name: Preserve users
      freeipa.ansible_freeipa.ipauser:
        ipaadmin_password: "{{ ipaadmin_password }}"
        name: "{{ item }}"
        state: absent
        preserve: true

    # The current freeipa collection doesn't support staged users
    - name: kinit as admin
      ansible.builtin.shell: "set -o pipefail && echo \"{{ ipaadmin_password }}\" | kinit {{ ipa_admin }}"

    - name: Stage users
      ansible.builtin.shell: 'ipa stageuser-add --first="{{ item.first }}" --last="{{ item.last }}" {{ item.name }}'
      loop: "{{ staged_users }}"
% vi create_ipa_groups.yml
---
- name: "Create groups and add users to them"
  hosts: ipaserver
  become: false
  vars:
    groups:
      - name: admins
        user:
          - jsmith
      - name: HelpDesk
        nonposix: true
        user:
          - ldufus
      - name: enrollers
        nonposix: true
      - name: corp
        posix: true
        user:
          - brufus

  tasks:
    - name: Create all groups
      freeipa.ansible_freeipa.ipagroup:
        ipaadmin_password: "{{ ipaadmin_password }}"
        groups: "{{ groups }}"
% vi create_ipa_policy.yml
---
- name: "Create policies"
  hosts: ipaserver
  become: false
  vars:
    roles:
      - name: "Host Manager"
        privilege:
          - Host administrators
          - Host group administrators
          - Netgroups administrators
          - Host enrollment
        user:
          - syshostmgt
      - name: "helpdesk"
        privilege:
          - Modify Group membership
          - Modify Users and Reset passwords
        group:
          - HelpDesk
      - name: "Enrollment Administrator"
        privilege:
          - Host Enrollment
        group:
          - enrollers

  tasks:
    - name: "Ensure all roles exist"
      freeipa.ansible_freeipa.iparole:
        ipaadmin_password: "{{ ipaadmin_principal }}"
        name: "{{ item.name }}"
        privilege: "{{ item.privilege|default(omit) }}"
        group: "{{ item.group|default(omit) }}"
        user: "{{ item.user|default(omit) }}"
      loop: "{{ roles }}"

New Passwords Expired

The common question we receive (and even the #freeipa IRC receive) is "Why can't we just set the password to not be expired right away?" See this page for information on why this is. You may also look at the pagure page and the Red Hat bugzilla related bug.

Implement Single Sign On (SSO)

Create an SSO client

To setup a very, very simple SSO, you can setup a simple location that requires a login.

% ipa-getkeytab -s idm1.example.com -p http/http.example.com -k /etc/httpd/conf/http.keytab
% vi /etc/httpd/conf.d/location.conf
<Location "/">
  AuthType Kerberos
  AuthName "IPA Kerberos Auth"
  # Keytab
  Krb5Keytab /etc/httpd/conf/http.keytab
  # Kerb settings
  KrbMethodNegotiate on
  KrbMethodK5Passwd on
  KrbServiceName HTTP
  KrbAuthRealms EXAMPLE.COM
  KrbSaveCredentials off
  Require valid-user
</Location>

Verify SSO client operation

...

Install and configure an IdM Client

Install and configure IdM Clients

Client Name IP Address
client.example.com 192.168.15.10
nfs.example.com 192.168.15.11
utility.example.com 192.168.15.12

Note

Depending on your architecture and setup, IdM clients should either be pointing directly at the IdM servers for DNS (at least two of them) or pointing at the DNS server in the environment that is delegating that domain to the IdM domain controllers.

In our lab, our IdM servers are our only DNS servers, thus it makes sense that our clients should point to them. In that scenario, you would configure your DHCP server to use the IdM servers as the name servers and/or configure them in a static manner depending on your environment.

# If your client is not pointing at the IdM DNS and you
# don't have another DNS server that's performing delegation,
# change your name servers.
% nmcli con mod eth0 ipv4.dns 192.168.15.2
% nmcli con mod eth0 +ipv4.dns 192.168.15.3
% nmcli con mod eth0 ipv4.dns-search example.com

# Optionally, if your clients don't have DHCP 
# reservations, set a static address.
% nmcli con mod eth0 ipv4.address 192.168.15.10/24
% nmcli con mod eth0 ipv4.gateway 192.168.15.1
% nmcli con mod eth0 ipv4.method manual

# It might be a good idea to set your hostname if you haven't already
% hostnamectl set-hostname client.example.com
% hostname client.example.com

# Install the ipa-client packages
% dnf install ipa-client -y
# Optionally set --no-ntp to --ntp-server
% ipa-client-install --realm EXAMPLE.COM --domain example.com --no-ntp
. . .
% id admin
uid=686600000(admin) gid=686600000(admins) groups=686600000(admins)

Create the role for the client.

% vi role_ipa_client.yml
---
- name: "Enroll client system"
  hosts: ipaclients
  become: true

  roles:
    - role: freeipa.ansible_freeipa.ipaclient
      state: present

Now run the role to setup the client.

% ansible-playbook role_ipa_client.yml

Configure Kerberized services

One of the things that you may end up doing, whether by hand or in an automated fashion, is creating kerberized services. In a later section, we address creating an NFS service for both a server and a client for the purpose of automating home directory mounts on a client when a user logs in. Before we dive into that, this just goes over simple kerberized service creation.

# Create kerberos service
% ipa service-add HTTP/http.example.com

Not only that, it's probably a good idea to actually get the keytab.

% kinit admin
% ipa-getkeytab -s idm1.example.com -p HTTP/http.example.com -k /etc/krb5.keytab

For an example of automating keytab creation and retrieval, see the CentOS/FreeIPA page on this site.

Manage the IdM integrated certificate authority

Configure and manage a certificate authority

By default FreeIPA stands up its own CA. And because of this, this allows you or your workplace to be able to issue certificates, that can be used in a wide variety of services, the most common or obvious one would be for Apache httpd.

There's a couple of ways you can get a certificate signed by FreeIPA. One method is to generate your own CSR and request it to be signed by FreeIPA. Another way is you can do it all from one command, ipa-getcert, and optionally, either have the certificate in PEM format or an NSS database. We'll address these examples.

# Creating an SSL certificate in the PEM format
% ipa service-add HTTP/http.example.com
% ipa-getcert request -f /etc/pki/tls/certs/http.pem -k /etc/pki/tls/private/http.key -K HTTP/http.example.com -D http.example.com
New signing request "20190902000318" added.
# Verify
% ipa-getcert list
Number of certificates and requests being tracked: 1.
Request ID '20190902000318':
        status: MONITORING
        stuck: no
        key pair storage: type=FILE,location='/etc/pki/tls/private/http.key'
        certificate: type=FILE,location='/etc/pki/tls/certs/http.pem'
        CA: IPA
        issuer: CN=Certificate Authority,O=EXAMPLE.COM
        subject: CN=http.example.com,O=EXAMPLE.COM
        expires: 2021-09-02 00:03:19 UTC
        dns: http.example.com
        principal name: HTTP/http.example.com@EXAMPLE.COM
        key usage: digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment
        eku: id-kp-serverAuth,id-kp-clientAuth
        pre-save command:
        post-save command:
        track: yes
        auto-renew: yes

# Create an SSL certificate in the NSS format
% ipa-getcert request -d /etc/pki/tls/certs/nss -n 'Test' -K HTTP/http.example.com -D http.example.com
New signing request "20190902000756" added.
# Verify
% ipa-getcert list
. . .
Request ID '20190902000756':
        status: MONITORING
        stuck: no
        key pair storage: type=NSSDB,location='/etc/pki/tls/certs/nss',nickname='Test',token='NSS Certificate DB'
        certificate: type=NSSDB,location='/etc/pki/tls/certs/nss',nickname='Test',token='NSS Certificate DB'
        CA: IPA
        issuer: CN=Certificate Authority,O=EXAMPLE.COM
        subject: CN=http.example.com,O=EXAMPLE.COM
        expires: 2021-09-02 00:07:57 UTC
        dns: http.example.com
        principal name: HTTP/http.example.com@EXAMPLE.COM
        key usage: digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment
        eku: id-kp-serverAuth,id-kp-clientAuth
        pre-save command:
        post-save command:
        track: yes
        auto-renew: yes

By default, when a certificate request is performed (and succeeds to be signed by the IPA CA), it is typically tracked and auto-renewed by default. This is done by the certmonger service, which eliminates the need to have to renew anything by hand.

Create Secret Vaults

When a domain supports the KRA role, it can hold password vaults or anything that's considered "secret". You can add the KRA role by installing the relevant package and installing the role.

On each IdM server, you will need to enable the role.

% dnf install ipa-server-kra
% ipa-kra-install

Create a private vault (as a user)

% kinit admin
% ipa vault-add admin_private --desc "Admin Private Vault"

(more to come)

If you are following the ansible method, you already have this role installed based on the inventory configuration. Now it's a matter of creating a simple secret.

---
- name: "Create Simple Vault"
  hosts: ipaserver
  become: true

  tasks:
    - name: "Create vault with simple data"
      freeipa.ansible_freeipa.ipavault:
        ipaadmin_password: "{{ ipaadmin_password }}"
        name: simplevault
        description: "A simple vault"
        username: admin
        password: "VaultPassword21!"
        data: "Simple data"
      action: member

Create and configure IdM users and user policies

In FreeIPA, there are two sets of policies:

  • Role Based Access Control (RBAC) which are the permissions, delegated or otherwise, that allow (or deny) access to various pieces of FreeIPA. This can be users that have the ability to reset passwords, modify groups, or perhaps they can issue keytabs. This was partially covered in a previous section.
  • Host Based Access Control (HBAC) which are the permissions granted to a user or users to access systems on various (PAM) services, such as ssh or logging into a desktop system (eg, GDM).

Configure Policies and User Access

HBAC, or Host Based Access Controls, are permissions that grant user or users access to systems via any number of services. The services are PAM services. No doubt you have looked in /etc/pam.d before and have seen quite a few files or even modified them by hand at some point.

% ls -l /etc/pam.d/
total 80
-rw-r--r--. 1 root root 272 May 11  2019 atd
-rw-r--r--. 1 root root 232 Apr 15 15:28 config-util
-rw-r--r--. 1 root root 328 Nov  8  2019 crond
lrwxrwxrwx. 1 root root  32 Jan 14  2020 fingerprint-auth -> /etc/authselect/fingerprint-auth
-rw-r--r--. 1 root root  70 Apr 24 06:35 ksu
-rw-r--r--. 1 root root 715 Apr 24 05:38 login
-rw-r--r--. 1 root root 154 Apr 15 15:28 other
-rw-r--r--. 1 root root 168 Apr  6 20:08 passwd
lrwxrwxrwx. 1 root root  29 Jan 14  2020 password-auth -> /etc/authselect/password-auth
-rw-r--r--. 1 root root 155 Apr  8 22:00 polkit-1
lrwxrwxrwx. 1 root root  25 Jan 14  2020 postlogin -> /etc/authselect/postlogin
-rw-r--r--. 1 root root 640 Apr 24 05:38 remote
-rw-r--r--. 1 root root 143 Apr 24 05:38 runuser
-rw-r--r--. 1 root root 138 Apr 24 05:38 runuser-l
lrwxrwxrwx. 1 root root  30 Jan 14  2020 smartcard-auth -> /etc/authselect/smartcard-auth
lrwxrwxrwx. 1 root root  25 Jun 15 10:18 smtp -> /etc/alternatives/mta-pam
-rw-r--r--. 1 root root  76 Apr  6 20:11 smtp.postfix
-rw-r--r--. 1 root root 727 Feb  4  2020 sshd
-rw-r--r--. 1 root root 214 Apr 23 20:48 sssd-shadowutils
-rw-r--r--. 1 root root 566 Apr 24 05:38 su
-rw-r--r--. 1 root root 154 Apr 23 19:40 sudo
-rw-r--r--. 1 root root 178 Apr 23 19:40 sudo-i
-rw-r--r--. 1 root root 137 Apr 24 05:38 su-l
lrwxrwxrwx. 1 root root  27 Jan 14  2020 system-auth -> /etc/authselect/system-auth
-rw-r--r--. 1 root root 248 Jul 21 07:57 systemd-user
-rw-r--r--. 1 root root  84 May 11  2019 vlock

On a typical Red Hat system, the most common ones (such as su, sshd, sudo) imports the system-auth file, so the login request is processed through those means. When defining HBAC rules, you either must allow "all" services or be selective. For example, if an HBAC rule allows "sshd", a user is allowed to ssh into a system, but wouldn't allow them to login locally on the console, as that goes through login. If you want the user to be able to run the su and sudo commands, you would also need to allow those services. Otherwise, the user is denied, even if sudo policies are available.

[label@mgt ~]$ sudo -i
[sudo] password for label:
sudo: PAM account management error: Permission denied

In FreeIPA, there is typically a rule already predefined that allows everyone to access all systems and all services. This can be removed or disabled and this removes host access to everything immediately. This is typically recommended in most environments where there are security standards and procedures in place.

# To disable
% ipa hbacrule-disable allow_all
# To delete instead
% ipa hbacrule-del allow_all

When performing a FreeIPA installation, it is possible to add --no-hbac-allow that will disable the allow_all rule.

Below are some examples of adding access.

# Allow all admins to access all systems
% ipa hbacrule-add --hostcat=all --servicecat=all --desc='Allow all admins to access all systems' All_Admins
% ipa hbacrule-add-user --groups=admins All_Admins

# And then test...
% ipa hbactest --rules=All_Admins --user=jsmith --host=client.example.com --service=login
# Allow the corp users to access the client system only using the sshd pam services
% ipa hbacrule-add --desc='Allow corp users to access client on ssh' corp_access
% ipa hbacrule-add-user --groups=corp corp_access
% ipa hbacrule-add-host --hosts=client.example.com corp_access
% ipa hbacrule-add-service --hbacsvcs=sshd corp_access

# And then test...
% ipa hbactest --rules=corp_access --user=brufus --host=client.example.com --service=sshd

To do this the ansible way, you can make a playbook like this.

---

Configure roaming or automounted home directories

You will need to configure your NFS server to serve up roaming home directories for users and then your client should have automouting enabled.

Client Kerberos Service

It may not be required to create an nfs kerberos service for the client. The ipa-client-automount command may already handle this but it does not hurt to create one. In fact, the host keytab is used on the client side anyway. Creating an NFS client keytab may have been required in the past.

# IDM Steps
% kinit admin
% ipa service-add nfs/nfs.example.com
% ipa service-add nfs/client.example.com

# Setup the automounting locations
% ipa automountmap-add default auto.home
% ipa automountkey-add default --key "/home" --info auto.home auto.master
% ipa automountkey-add default --key "*" --info "-fstype=nfs4,rw,sec=krb5,soft nfs.example.com:/exports/home/&" auto.home

# NFS Server Steps
% dnf install nfs-utils -y
% mkdir /exports/home
% vi /etc/exports
/exports/home *(rw,sec=sys:krb5:krb5i:krb5p)

# Make the home directories for all users and move them to /export/home
% mkhomedir_helper jsmith
% mv /home/jsmith /export/home/

# Create the necessary keytabs
% kinit admin
% ipa-getkeytab -s idm1.example.com -p nfs/nfs.example.com -k /etc/krb5.keytab

# Verify keytab
% klist -ket /etc/krb5.keytab

# Enable and start nfs
% systemctl enable nfs-server --now

# Open the necessary firewall ports
% firewall-cmd --add-service=nfs --permanent
% firewall-cmd --complete-reload

# Client steps
% kinit admin
% ipa-getkeytab -s idm1.example.com -p nfs/client.example.com -k /etc/krb5.keytab
% ipa-client-automount --location=default

# Verify keytab
% klist -ket /etc/krb5.keytab

To test, login to the system via ssh or console and verify the home directory has mounted. /var/log/messages and secure will display errors in case of failure.

Use Ansible Tower to configure and manage IdM Users

Several sections ago, we setup users either manually or via ansible playbooks. This would be generally the same, but may entail further configuration.

With that said, Ansible Tower (AWX or AAP) is out of scope for this guide, as there is no straight forward way to set it up in a lab. AWX for example has a kubernetes operator and they encourage the use of docker for testing purposes. You can do this, but this is not formally tested.

AAP on the other hand has installation steps for non-kubernetes environments. However, it is a Red Hat product and requires a subscription to use.

Configure IdM as an LDAP backend for external services

Most services and applications that authenticate users do typically have LDAP support. IdM can be used as an LDAP backend. You typically need only a few things to authenticate users from IdM to an application.

  • Base DN, this always ends up being the top level of your domain: dc=example,dc=com - All accounts share this common base.
  • Bind DN, this is a system account that binds to the directory to assist with searches and authentication
  • Attribute mappings
  • Groups, depending on the application

Below is a table of common DN's you may specify in an application:

DN's Path Filter (if applicable)
Base DN dc=example,dc=com
User DN cn=users,cn=accounts,dc=example,dc=com uid=...
Group DN cn=groups,cn=accounts,dc=example,dc=com (objectClass=groupOfNames)
Bind DN uid=account,cn=sysaccounts,cn=etc,dc=example,dc=com
% ipa user-show admin --all | grep '^dn'
  dn: uid=admin,cn=users,cn=accounts,dc=example,dc=com

Below is a table of common attributes that may be used to map user information in the application.

Type Attribute
Login Name uid
First Name givenName
Surname sn
Email mail
Groups memberOf
Full Name cn

Below are two ways to create a bind account (bind DN). The first way is the LDAP way. The second way is the ipa-ldap-updater.

% kinit admin
% ldapadd -Y GSSAPI
. . .
dn: uid=binder,cn=sysaccounts,cn=etc,dc=example,dc=com
objectclass: account
objectclass: simplesecurityobject
uid: binder
userPassword: password123
passwordExpirationTime: 20380119031407Z
nsIdleTimeout: 0
# Press CTRL+d
adding new entry "uid=binder,cn=sysaccounts,cn=etc,dc=example,dc=com"
% kinit admin
% cat << EOF > binder.update
dn: uid=binder,cn=sysaccounts,cn=etc,dc=example,dc=com
add:objectclass:account
add:objectclass:simplesecurityobject
add:uid:binder
add:userPassword:password123
add:passwordExpirationTime:20380119031407Z
add:nsIdleTimeout:0
EOF
% ipa-ldap-updater binder.update

When this account is created, you can then specify the full DN for that object into a bind DN field, along with it's password into an accompanying bind password field.

If you'd like an example of setting up Ansible Tower (or AWX, the open source version of tower) against IdM, you can click here.

Kerberos

On some applications, it is possible to use kerberos authentication rather than a straight bind account. The general idea is the same when picking out the base dn, attributes, and the like. However, instead you would create an account with an accompanying LDAP/... service principal to do the authentication.

Maintain IdM services

Configure NTP on all IdM components

NTP Server Setup

The utility server that is part of this lab can be used to run an NTP server. See Setup an NTP Server.

When the domain was initially setup, we may have used --no-ntp, including for the clients. This means there's no attempt to configure nor sync chrony. This automatically assumes chrony is working as intended with the default pool configured from the chrony package (or by IT policy via automation). However, for this lab, if you have an NTP server you want to use, you can set it up in the /etc/chrony.conf file.

% vi /etc/chrony.conf
. . .
# pool 2.centos.pool.ntp.org iburst
server 192.168.15.12
. . .

% systemctl restart chronyd.service
% chronyc tracking

Configure firewall on all IdM components

If the domain is working, then you setup firewalld correctly.

Back up an IdM infrastructure

There are multiple ways you can backup IPA.

  • Full backup: Default, shuts down IPA before performing a backup. This backs up with raw files. As such, it must be done offline.
  • Data backup: Backs up a copy of the ldap data and the changelog (the IPA-REALM instance, DogTag, IPA backend). This can be done online.
# Turns off IPA completely and perform a backup
% ipa-backup
# Backs up and gpg encrypts
% ipa-backup --gpg --gpg-keyring=/root/keys

To restore a backup, the ipa-restore command is available.

% ipa-restore /var/lib/ipa/backup/

. . .

Perform a backup without interruption of services

It is possible to perform a backup without taking down services. However, not everything will get backed up as a result.

The backup command allows you to pass an online flag to ensure a backup taken doesn't down the IPA services. Note that not everything can be backed up online.

# Backs up data only and doesn't take down IPA
% ipa-backup --data --online
# Backs up data only and gpg encrypts
% ipa-backup --gpg --gpg-keyring=/root/keys --data --online

. . .

Value Add

Use the REST api to query IdM

When you invoke the ipa command, you are actually communicating with the API that runs on the IdM replicas. Operations done are sent via a POST with JSON data. The return data is also in JSON and translated to be readable in the terminal. Because it's JSON, custom scripts can be made with say perl or python that communicates with the API to send the calls, perhaps for specific tasks, jobs, or other operations that could be automated. You can also use curl to do this also if you so choose.

The question becomes, "well, how do I know the right data to send?" You can issue the -vv switch to see the request being sent.

% ipa -vv ping
ipa: INFO: trying https://idm1.example.com/ipa/json
ipa: INFO: [try 1]: Forwarding 'schema' to json server 'https://idm1.example.com/ipa/json'
ipa: INFO: trying https://idm1.example.com/ipa/session/json
ipa: INFO: [try 1]: Forwarding 'ping/1' to json server 'https://idm1.example.com/ipa/session/json'
ipa: INFO: Request: {
    "id": 0, 
    "method": "ping/1", 
    "params": [
        [], 
        {
            "version": "2.251"
        }
    ]
}
ipa: INFO: Response: {
    "error": null, 
    "id": 0, 
    "principal": "admin@EXAMPLE.COM", 
    "result": {
        "summary": "IPA server version 4.10.2. API version 2.251"
    }, 
    "version": "4.10.2"
}
--------------------------------------------
IPA server version 4.10.2. API version 2.251
--------------------------------------------

If you look at the 'request' section, you can see the data that is sent. Each request has a method and params, where method is a command to be excuted and params is simply an array that contains positional arguments and a dictionary of options. If you take a look at say, group-show, you would see a different request.

% ipa -vv group-show admins
ipa: INFO: trying https://idm1.example.com/ipa/session/json
ipa: INFO: [try 1]: Forwarding 'group_show/1' to json server 'https://idm1.example.com/ipa/session/json'
ipa: INFO: Request: {
    "id": 0, 
    "method": "group_show/1", 
    "params": [
        [
            "admins"
        ], 
        {
            "version": "2.230"
        }
    ]
}
### Lots of output ###

Let's say I wanted to perform that in a simple bash script that uses curl. I would perform a kinit and then run the script below to have it login for me via kerberos and do the work.

#!/bin/bash
ipaReplica=idm1.example.com
cookieJar=my.cookie.jar

# Login with Kerberos
curl -v \
  -H referer:https://$ipaReplica/ipa \
  -c $cookieJar -b $cookieJar \
  --cacert /etc/ipa/ca.crt \
  --negotiate -u : \
  -X POST \
  https://$ipaReplica/ipa/session/login_kerberos

# Send user_find method request
curl -v \
  -H referer:https://$ipaReplica/ipa \
  -H "Content-Type:application/json" \
  -H "Accept:applicaton/json"\
  -c $cookieJar -b $cookieJar \
  --cacert /etc/ipa/ca.crt \
  -d  '{"method":"group_show/1","params":[["admins"],{}],"id":0}' \
  -X POST \
  https://$ipaReplica/ipa/session/json

Any of the commands ran via ipa can be reviewed with the -vv switch so you can see what kind of call it's making and how it's making it. Thus, making it easier to tie into your own scripts. On the Web UI, you can go to IPA Server -> API Browser to find more information on the specific API calls.

Implement an IdP

While not strictly a certification objective at this present time, there may be a chance it could be. FreeIPA 4.10+ have the ability to implement authentication to external identity providers. FreeIPA allows you to use RADIUS proxy authentication for example, but using this same method, an OAuth 2.0 authorization server could be used as well. When it comes to an IdP, you can instead configure IdP clients using ipa idp-add and use software like Keycloak or otherwise that supports OAuth 2.0 workflows. We recommend checking out the FreeIPA Workshop Unit 12 for more details.

Setup an NTP Server

It is unlikely you'll need to setup an NTP server on an exam. However, rather than relying on the built-in pool servers provided by the chrony package, you may ask IdM to use another NTP server or pool for itself and the clients that enroll. Using the utility server, we can setup a quick NTP server.

% vi /etc/chrony.conf
. . .
allow 192.168.15.0/24

% systemctl restart chronyd.service
% firewall-cmd --add-service=ntp --permanent
% firewall-cmd --reload

For your IdM domain, you can then add a SRV record. This is supposed to allow the client installation to automatically set the NTP server.

% ipa dnsrecord-add example.com _ntp \
  --srv-port=123 \
  --srv-target=utility.example.com. \
  --srv-weight=100 \
  --srv-priority=0

Active Directory Trust

Active Directory trusts are no longer part of the main objectives for the exam. However, that does not mean it will not be part of it. It is important to still know how to set it up manually. In the installation section of this guide, there are commented variables for a trust configuration.

Create trust relationships with Active Directory

AD Setup

We do not cover setting up an AD forest here. This is out of scope for this series. If you are using Server 2016 or higher and you are using "core", look up the commands:

Install-WindowsFeature AD-domain-services Import-Module ADDSDeployment Install-ADDSForest

Server Name IP Address
ad.example.net 192.168.15.15

For our trust, the AD server will need to be configured to be the example.net domain with the hostname of ad.example.net. This way, we are not colliding in DNS and both AD and IdM should be able to communicate with each other as two separate forests. It is recommended to use Windows Server 2016 (with the same domain functional level) for this setup, as experience with that product is a recommended prerequisite for the exam.

% dnf install ipa-server-trust-ad -y
% firewall-cmd --add-service=freeipa-trust --permanent
success
% firewall-cmd --reload
success
% ipa-adtrust-install
. . .
# This is the admin@REALM IPA account
admin password:

WARNING: The smb.conf already exists. Running ipa-adtrust-install will break your existing samba configuration.

# Type 'yes' here
Do you wish to continue? [no]: yes

Do you want to enable support for trusted domains in Schema Compatibility plugin?
This will allow clients older than SSSD 1.9 and non-Linux clients to work with trusted users.

# You can press enter here to accept the default. If you have BSD, Solaris, Omnios, HP-UX, AIX, or RHEL 5 and older clients
# you may want to enable this. Some apps may benefit from this also.
Enable trusted domains support in slapi-nis? [no]:

Enter the NetBIOS name for the IPA domain.
Only up to 15 uppercase ASCII letters, digits and dashes are allowed.
Example: EXAMPLE.

# You can accept the default or put your own.
NetBIOS domain name [IPA]: IPA0

WARNING: 4 existing users or groups do not have a SID identifier assigned.
Installer can run a task to have ipa-sidgen Directory Server plugin generate
the SID identifier for all these users. Please note, in case of a high
number of users and groups, the operation might lead to high replication
traffic and performance degradation. Refer to ipa-adtrust-install(1) man page
for details.

# You should always say yes.
Do you want to run the ipa-sidgen task? [no]: yes

. . .

# This will complete and list ports to open and such. We did this earlier.

Now that the AD trust components are prepped, depending on the setup, we'll need to do some DNS zone forwards. It is likely you have IPA and AD running their own DNS. Note: This may not be the case in a real world scenario.

# We need to create a forward zone here for the example.net zone
% ipa dnsforwardzone-add example.net --forwarder=192.168.15.15 --forward-policy=only
Server will check DNS forwarder(s).
This may take some time, please wait ...
  Zone name: example.net.
  Active zone: TRUE
  Zone forwarders: 192.168.15.15
  Forward policy: only

# We should probably create a few dns records...
# Assuming the AD netbios name is EXAMPLEAD, use the syntax hostname.NETBIOS here
% ipa dnsrecord-add example.com ad.EXAMPLEAD --a-ip-address=192.168.15.15
# Same idea here, but we're only doing the netbios name and saying the name server record is the AD server
% ipa dnsrecord-add example.com EXAMPLEAD --ns-hostname=ad.EXAMPLEAD

# We need to allow the zones to be transferable to the AD domain
% ipa dnszone-mod example.com --allow-transfer=192.168.15.15

On the AD side, we need to create the IPA zone. It's absolutely required.

C:\Windows\System32>dnscmd 127.0.0.1 /ZoneAdd example.com /Secondary 192.168.15.2
You should probably double check that the DNS records are returning on the IDM servers.

% dig _ldap._tcp.example.com SRV
; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> SRV _ldap._tcp.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14793
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;_ldap._tcp.example.com.      IN      SRV

;; ANSWER SECTION:
_ldap._tcp.example.com. 86400 IN      SRV     0 100 389 idm1.example.com.
_ldap._tcp.example.com. 86400 IN      SRV     0 100 389 idm2.example.com.

;; AUTHORITY SECTION:
example.com.          86400   IN      NS      idm1.example.com.
example.com.          86400   IN      NS      idm2.example.com.

;; ADDITIONAL SECTION:
idm1.example.com.      1200    IN      A       192.168.15.2
idm2.example.com.      1200    IN      A       192.168.15.3

# Same with the AD records
% dig _ldap._tcp.example.net SRV
; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> SRV _ldap._tcp.example.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12195
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 9

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;_ldap._tcp.example.net.       IN      SRV

;; ANSWER SECTION:
_ldap._tcp.example.net. 600    IN      SRV     0 100 389 ad.example.net.

. . .

Now that they are returning, intiate the trust.

% ipa trust-add --type=ad example.net --admin Administrator --password
Active Directiron domain administrator's password: (type password here)
-----------------------------------------------------
Added Active Directory trust for realm "example.net"
-----------------------------------------------------
  Realm name: example.net
  Domain NetBIOS name: EXAMPLEAD
  Domain Security Identifier: S-1-5-21-XXXXXXXXXX-YYYYYYYYY-ZZZZZZZZZZ
  Trust direction: Trusting forest
  Trust type: Active Directory domain
  Trust status: Established and verified

# Check that an AD user is resolvable. You can do this with DOMAIN\name or name@DOMAIN
% id EXAMPLEAD\\administrator
% id administrator@example.net

Authenticate users with an Active Directory domain

As we disabled the allow_all rule, let's create a set of groups first and then the HBAC rule.

# Create the starting AD group
% ipa group-add adusers
# Create an external group. This is required for AD users.
% ipa group-add --external adgroup_external
# Add an AD user into the external group
% ipa group-add-member --users=administrator@example.net adgroup_external
# Make the external group a member of ad users
% ipa group-add-member --groups=adgroup_external adusers

As we've made an HBAC rule before, this should be simple.

% ipa hbacrule-add --hostcat=all --servicecat=all --desc='ad users all access' adusers_access
% ipa hbacrule-add-user --groups=adusers adusers_access
% ipa hbactest --rules=adusers_access --user=administrator@example.net --host=client.example.com --service=sshd

The test should pass without any issues.

Group Types

While this may not be required information while working on the exam, it's important to understand that there are different group types in AD and the behavior changes based on the group type.

Groups in Active Directory have three types. These three types can actually change the behavior of how SSSD on the IPA domain controllers resolve them or if they'll even be resolvable at all. The three types are 'Domain Local', 'Global', and 'Universal'. If at all possible, avoid groups being 'Global'. Domain Local or Universal is recommended.

Comments