eigenstate-ipa

Inventory Use Cases

Related docs:

  INVENTORY PLUGIN     INVENTORY CAPABILITIES     IDM VAULT USE CASES     DOCS MAP  

Purpose

This page contains worked examples for eigenstate.ipa.idm.

Use the capability guide to choose the IdM object class. Use this page when you need the corresponding inventory files and playbook targets.

Not every caller is an IdM administrator. A delegated operator can use this collection inside their own jurisdiction as long as the principal they run under can read the hosts, hostgroups, netgroups, or HBAC rules that matter to that scope.

Contents

Use Case Flow

flowchart LR
    question["Operational question"] --> source["Choose IdM source"]
    source --> inventory["Render Ansible inventory"]
    inventory --> run["Target hosts by role,\naccess boundary, or policy"]

Assumed Example Estate

All examples assume an IdM domain corp.example.com with these patterns:

1. Full Estate Compliance Scan

When the job must run against every enrolled system, use hosts.

flowchart LR
    H["All IdM hosts"] --> I["sources: [hosts]"] --> T["compliance scan on entire estate"]

Inventory:

plugin: eigenstate.ipa.idm
server: idm-01.corp.example.com
ipaadmin_password: "{{ lookup('env', 'IPA_ADMIN_PASSWORD') }}"
verify: /etc/ipa/ca.crt
sources:
  - hosts
compose:
  ansible_host: idm_fqdn

Playbook target:

- name: Quarterly compliance scan
  hosts: all
  tasks:
    - ansible.builtin.command:
        cmd: oscap xccdf eval --profile stig /usr/share/xml/scap/content.xml
      failed_when: false

Kerberos is especially profitable here when the scan runner lives in AAP or a shared automation account:

2. Role-Based Application Deployment

When IdM hostgroups already define the runtime role boundary, use hostgroups.

flowchart LR
    HG["webservers + databases"] --> I["sources: [hosts, hostgroups]"] --> T["role-specific deploys"]

Inventory:

plugin: eigenstate.ipa.idm
server: idm-01.corp.example.com
ipaadmin_password: "{{ lookup('env', 'IPA_ADMIN_PASSWORD') }}"
verify: /etc/ipa/ca.crt
sources:
  - hosts
  - hostgroups
hostgroup_filter:
  - webservers
  - databases
host_filter_from_groups: true
compose:
  ansible_host: idm_fqdn

Playbook target:

- name: Deploy frontend config
  hosts: idm_hostgroup_webservers
  tasks:
    - ansible.builtin.template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf

- name: Restart database tier
  hosts: idm_hostgroup_databases
  tasks:
    - ansible.builtin.service:
        name: postgresql
        state: restarted

This is also a good delegated-operator pattern. The caller does not need global IdM admin rights if their principal is allowed to read the hostgroups for their team or business unit.

3. Nested Application Tier Maintenance

When the meaningful role boundary is a nested hostgroup, let the plugin resolve it.

flowchart LR
    HG["all-app-servers\nnested hostgroup"] --> I["resolved group membership"] --> T["single maintenance tier"]

Inventory:

plugin: eigenstate.ipa.idm
server: idm-01.corp.example.com
ipaadmin_password: "{{ lookup('env', 'IPA_ADMIN_PASSWORD') }}"
verify: /etc/ipa/ca.crt
sources:
  - hosts
  - hostgroups
hostgroup_filter:
  - all-app-servers
host_filter_from_groups: true

Playbook target:

- name: Rolling application-tier patch window
  hosts: idm_hostgroup_all_app_servers
  serial: 2
  tasks:
    - ansible.builtin.dnf:
        name: "*"
        state: latest

Delegated operators often use this pattern for their own service slice because the parent hostgroup already defines the boundary they are responsible for.

4. Patch By Metadata Rather Than Named Group

When IdM metadata is useful but there is no explicit hostgroup for it, keep hosts and derive groups with keyed_groups.

flowchart LR
    M["idm_location / idm_os"] --> G["keyed_groups"] --> T["target by metadata"]

Inventory:

plugin: eigenstate.ipa.idm
server: idm-01.corp.example.com
ipaadmin_password: "{{ lookup('env', 'IPA_ADMIN_PASSWORD') }}"
verify: /etc/ipa/ca.crt
sources:
  - hosts
keyed_groups:
  - key: idm_location
    prefix: dc
    separator: "_"
  - key: idm_os
    prefix: os
    separator: "_"

Playbook target:

- name: Patch east datacenter first
  hosts: dc_DC_East
  serial: 2
  tasks:
    - ansible.builtin.dnf:
        name: "*"
        state: latest

Kerberos pays off here because it lets a non-admin operator run the same inventory source repeatedly from AAP or a bastion without storing a password in the playbook.

5. Keep AAP Inventory Sync Metadata Narrow

When Automation Controller only needs a small metadata surface for smart inventories or grouped targeting, keep the inventory plugin on hosts and trim the exported idm_* variables.

flowchart LR
    IDM["IdM hosts"] --> INV["sources: [hosts]"]
    INV --> FILTER["hostvars_include"]
    FILTER --> AAP["lean synced inventory"]

Inventory:

plugin: eigenstate.ipa.idm
server: idm-01.corp.example.com
use_kerberos: true
kerberos_keytab: /runner/env/ipa/admin.keytab
verify: /etc/ipa/ca.crt
sources:
  - hosts
hostvars_include:
  - idm_location
  - idm_os
  - idm_hostgroups
keyed_groups:
  - key: idm_location
    prefix: dc
    separator: "_"

Why this helps:

6. Access-Scope Audit

When the question is who can reach the systems, use netgroups.

flowchart LR
    NG["ops-admin-access"] --> I["sources: [hosts, netgroups]"] --> T["access-scope audit"]

Inventory:

plugin: eigenstate.ipa.idm
server: idm-01.corp.example.com
ipaadmin_password: "{{ lookup('env', 'IPA_ADMIN_PASSWORD') }}"
verify: /etc/ipa/ca.crt
sources:
  - hosts
  - netgroups
netgroup_filter:
  - ops-admin-access
host_filter_from_groups: true

Playbook target:

- name: Record operations access scope
  hosts: idm_netgroup_ops_admin_access
  tasks:
    - ansible.builtin.lineinfile:
        path: /tmp/ops_access_hosts.txt
        line: "{{ idm_fqdn }} - {{ idm_location }}"
        create: true
      delegate_to: localhost

This is not a global-admin task. It is a jurisdictional audit task: a delegated operator can inspect the hosts their team may touch without needing broader IdM privileges.

7. Policy-Scoped SSH Hardening

When the target boundary is the policy itself, use HBAC rules.

flowchart LR
    HB["allow_ssh_ops"] --> I["sources: [hosts, hbacrules]"] --> T["policy-scoped hardening"]

Inventory:

plugin: eigenstate.ipa.idm
server: idm-01.corp.example.com
ipaadmin_password: "{{ lookup('env', 'IPA_ADMIN_PASSWORD') }}"
verify: /etc/ipa/ca.crt
sources:
  - hosts
  - hbacrules
hbacrule_filter:
  - allow_ssh_ops
host_filter_from_groups: true

Playbook target:

- name: Harden SSH on systems in the ops SSH policy boundary
  hosts: idm_hbacrule_allow_ssh_ops
  tasks:
    - ansible.builtin.template:
        src: sshd_config_hardened.j2
        dest: /etc/ssh/sshd_config
        validate: sshd -t -f %s

For non-admin teams, this is the common pattern: the HBAC rule already encodes the scope they are allowed to manage, and the collection simply turns that policy into a target set.

8. Estate-Wide Policy Coverage Check

When an HBAC rule uses hostcategory=all, the group becomes an easy audit and validation boundary.

flowchart LR
    HB["allow_all\nhostcategory=all"] --> I["expands to every host"] --> T["policy coverage check"]

Inventory:

plugin: eigenstate.ipa.idm
server: idm-01.corp.example.com
ipaadmin_password: "{{ lookup('env', 'IPA_ADMIN_PASSWORD') }}"
verify: /etc/ipa/ca.crt
sources:
  - hosts
  - hbacrules
hbacrule_filter:
  - allow_all

Playbook target:

- name: Ensure monitoring agent is present on all policy-covered systems
  hosts: idm_hbacrule_allow_all
  tasks:
    - ansible.builtin.package:
        name: insights-client
        state: present

Kerberos Is A Good Default Here

Kerberos is especially useful for delegated inventory work because:

Use password auth only when you do not have a service principal or a keytab workflow available.

For the decision model behind these scenarios, return to INVENTORY CAPABILITIES.