Dotfiles/docs/md/ansipa-administration.md

12 KiB

ansipa Administration Guide

Day-to-day operation of the ansipa management plane: the full policy catalogue and how to apply, target, and revert each policy. For the deployment/ports/ reverse-proxy story see the ansipa Setup Guide; for the architecture and container internals see FreeIPA & Ansible.


How administration works

Everything is driven by FreeIPA group membership. You never log into a client to change its policy — you add or remove a host or user from a group on the FreeIPA server, and the fleet converges on the next timer tick.

Two independent client-side mechanisms consume that membership, both installed by the Ansible playbooks and both idempotent and reversible (leaving a group undoes the change on the next run):

Mechanism Timer Reads Applies
Policy enforcer (ansipa-enforce-policies.sh) ansipa-enforce-policies.timer, every 30 min host + user groups daemon/sudo/ssh/monitoring/scan/SMB/block policies
Installer timers (ansipa-install-*.sh) ansipa-install*.timer, every 30 min dev_pkg_*, dev_mod_*, dev_fp_* host groups packages, setup modules, Flatpaks

Because it is all client-pull, everything works across NAT (the server never initiates a connection to a client). To apply a change immediately instead of waiting for the timer, run the relevant script on the client as root:

sudo /usr/local/bin/ansipa-enforce-policies.sh     # policies
sudo /usr/local/bin/ansipa-install-packages.sh     # dev_pkg_*
sudo /usr/local/bin/ansipa-install-modules.sh      # dev_mod_*
sudo /usr/local/bin/ansipa-install-flatpaks.sh     # dev_fp_*

The two group scopes

  • Host groups (dev_*) — a device policy. Applies to the machine(s) you add to the group. Managed with ipa hostgroup-*.
  • User groups (usr_*) — a user policy that follows the user to every enrolled machine they log into. Applies while the group exists; managed with ipa group-*. Several user policies key off the group merely existing (not the specific host), because the enforcer runs on every host.

The two ways to bind a target

Most policies encode their target in the group name suffix (dev_local-sudo-alice, dev_pkg_htop, usr_block-binary-nano). A few need extra data (a printer URI, an SMB credential) which lives in the group description, set with ipa group-mod <grp> --desc='…' — noted per-policy below.

Everyday commands

# Create + populate a host group (device policy)
ipa hostgroup-add dev_mon_base --desc "CheckMK monitored hosts"
ipa hostgroup-add-member dev_mon_base --hosts=client01.corp.example.com
ipa hostgroup-remove-member dev_mon_base --hosts=client01.corp.example.com

# Create + populate a user group (user policy)
ipa group-add usr_admin --desc "Fleet-wide sudoers"
ipa group-add-member usr_admin --users=alice
ipa group-remove-member usr_admin --users=alice

# Inspect
ipa host-show client01.corp.example.com | grep -A3 'Member of host-groups'
ipa hostgroup-show dev_pkg_htop

Everything below can equally be done from the FreeIPA web UI (Identity → Host Groups / User Groups).


Device policies (dev_* host groups)

dev_daemon-enable-<unit> / dev_daemon-disable-<unit>

Force a systemd unit on or off fleet-wide.

  • Apply: enable → systemctl enable --now <unit>; disable → disable --now.
  • Revert (leave group): the opposite action.
  • The .service suffix is optional (appended automatically for a bare name); any unit type works. A unit in both enable and disable groups is skipped with a warning.
  • Example: ipa hostgroup-add dev_daemon-disable-bluetooth then add hosts → bluetooth.service is stopped and masked-off on them.

⚠️ Enabling sshd this way and later reverting will stop sshd — don't lock yourself out of a headless box you only reach over SSH.

dev_timeshift-backup

Enforce a daily Timeshift snapshot at 03:00 (requires timeshift; add the host to dev_mod_timeshift to install it). Leaving the group removes the cron.

dev_no-local-users

Lock the password of every local account — root (UID 0) and all regular users (UID ≥ 1000) — with passwd -l, so only FreeIPA accounts can authenticate. Accounts already locked are left untouched and not tracked; revert unlocks only what this policy locked. State: /var/lib/ansipa-policies/no-local-users.

dev_local-sudo-<username>

Grant <username> full sudo on this specific device via a sudoers drop-in. Device-scoped (unlike usr_admin). Leaving the group removes the drop-in.

  • Example: ipa hostgroup-add dev_local-sudo-alice + add lab-pc-3 → alice gets sudo on lab-pc-3 only.

dev_ssh_<userid>

Distribute <userid>'s SSH public keys from their IPA profile to /home/<userid>/.ssh/authorized_keys on hosts in the group (in an ansipa-managed section; hand-added keys are preserved). Store the keys in IPA:

ipa user-mod alice --sshpubkey='ssh-ed25519 AAAA...'
ipa hostgroup-add dev_ssh_alice && ipa hostgroup-add-member dev_ssh_alice --hosts=

Leaving the group removes only the ansipa-managed section.


Monitoring policies (dev_mon_*, usr_mon_*)

All CheckMK monitoring requires the CheckMK stack to be up and ansipa-checkmk-setup.sh to have run on the FreeIPA container (seeds the dev_mon_base credentials + the monitoring groups in IPA). All checks are collected by the agent, so every monitored host must also be in dev_mon_base.

dev_mon_base (required for all monitoring)

Installs the CheckMK agent, registers the host in CheckMK (under /ansipa), and opens the agent for collection: pull mode on check_mk.socket (port 6556) where the server can reach the client, or push mode (cmk-agent-ctl → server :8000) for NAT clients. Built-in CPU/RAM/disk/uptime plus an installed-package count check (Ansipa_Packages). Leaving the group deregisters the host and disables the agent.

Credentials are auto-discovered from the dev_mon_base group description (cmk://<host>:<port>/<site>:automation:<secret>), which the server populates. Set CMK_ADVERTISED_URL in .env to a client-routable address.

dev_mon_clamscan

Run a daily ClamAV + rkhunter + chkrootkit scan at 02:00 and report the result to CheckMK as the Ansipa_ClamScan service (OK = clean, WARN = stale DB or rkhunter warnings, CRIT = infected). Self-contained — it runs the scan and writes the local check; results no longer go over SMB.

  • Prerequisites: dev_mod_anti-malware (tools) + dev_mon_base (agent).
  • Revert: removes the cron, scan script, log, and local check.

dev_mon_timeshift

Ansipa_Timeshift check on the newest Timeshift snapshot age: WARN > 5 days, CRIT > 10 days or none found. Pair with dev_timeshift-backup (which creates them) and dev_mon_base.

dev_mon_power

Ansipa_Power check on CPU-package power via Intel RAPL (preferred) or lm-sensors: WARN ≥ 65 W, CRIT ≥ 95 W. Add the host to dev_mod_* that installs lm_sensors if RAPL is unavailable.

usr_mon_logins (user group)

Ansipa_Logins check reporting SSH login attempts in the last 24 h (successful + failed + invalid-user), with thresholds. Installed fleet-wide when the group exists; needs dev_mon_base on the hosts.


Software-installer policies (dev_pkg_*, dev_mod_*, dev_fp_*)

These are the GPO-like software-deployment groups, applied by the ansipa-install-* timers (not the policy enforcer). Join → installed; leave → removed. Install state is tracked so revert only touches what ansipa installed.

dev_pkg_<package>

Install a single distro package (via pacman/dnf/apt — auto-detected).

ipa hostgroup-add dev_pkg_htop && ipa hostgroup-add-member dev_pkg_htop --hosts=

dev_mod_<name>

Apply a whole setup module from setup/modules/optional-Modules/apps/ — e.g. dev_mod_docker, dev_mod_anti-malware, dev_mod_timeshift, dev_mod_ollama. This is how you install the tools other policies need (dev_mod_anti-malware before dev_mon_clamscan, dev_mod_timeshift before dev_timeshift-backup).

dev_fp_<app>

Install a Flathub Flatpak. Encode the app ID with __ in place of .:

# org.gimp.Gimp
ipa hostgroup-add dev_fp_org__gimp__Gimp
ipa hostgroup-add-member dev_fp_org__gimp__Gimp --hosts=

User policies (usr_* user groups)

usr_admin

Full sudo on every enrolled host for members, via a %usr_admin sudoers drop-in resolved through SSSD. Active while the group exists; the drop-in is removed when the group is deleted (not merely when a member leaves — removing a member just drops that user's sudo, since it is group-based).

usr_block-binary-<name>

Prevent members from running <name> on any enrolled host via a PATH-priority wrapper that checks group membership at runtime. Use __ for . to block a Flatpak (usr_block-binary-org__gimp__Gimp). Non-members are unaffected (the wrapper transparently execs the real binary). Deleting the IPA group removes the wrapper.

usr_prt_<printer>

Auto-add <printer> to CUPS on any host where a member is logged in. Store the printer URI in the group description:

ipa group-add usr_prt_frontdesk --desc='ipps://printserver/printers/frontdesk'
ipa group-add-member usr_prt_frontdesk --users=alice

Requires cups (installed by the policy deploy). Leaving/deleting removes the printer.

usr_smb_r_<name> / usr_smb_rw_<name>

Auto-mount a Samba share at ~/<name> for logged-in members (rw wins if a user is in both). Store the credential in the group description (written by ansipa-smb-setup.sh for the built-in shares):

cifs://<ipa-host>:<samba-user>:<password>

Requires cifs-utils (installed by the policy deploy). Leaving unmounts on the next run.

usr_smb_adm_policystore

Mount the policy store at ~/policystore (rw) for admin members, so you can edit the live policies.d/*.sh files directly on the share — changes take effect fleet-wide on the next 30-min enforcer tick, no redeploy needed. Credential in the group description (auto-set by ansipa-smb-setup.sh).


BaseUser sync (BaseUser group)

Not a policy script — a systemd.path unit (deployed by deploy-baseuser-sync.yml) that, on login, adds any member of the FreeIPA BaseUser group to the local baseusers group. Use it to grant a baseline local group to all standard users.


Common recipes

Onboard a new workstation (identity + monitoring + a couple of apps):

H=ws-42.corp.example.com
ipa hostgroup-add-member dev_mon_base     --hosts=$H
ipa hostgroup-add-member dev_mon_clamscan --hosts=$H
ipa hostgroup-add-member dev_mod_anti-malware --hosts=$H   # installs clamav/rkhunter
ipa hostgroup-add-member dev_mod_docker   --hosts=$H
ipa hostgroup-add-member dev_pkg_htop     --hosts=$H
# then, on the box (or wait 30 min):
sudo /usr/local/bin/ansipa-enforce-policies.sh
sudo /usr/local/bin/ansipa-install-modules.sh

Give a helpdesk user sudo everywhere, block a risky tool:

ipa group-add-member usr_admin --users=bob
ipa group-add usr_block-binary-tcpdump && ipa group-add-member usr_block-binary-tcpdump --users=intern

Edit policy logic live (as an admin in usr_smb_adm_policystore):

$EDITOR ~/policystore/dev_mon_clamscan.sh    # applied fleet-wide next enforcer tick

Troubleshooting

Symptom Check
Policy not applying sudo /usr/local/bin/ansipa-enforce-policies.sh on the client; read the [ansipa-policies] discovery line — is the group listed?
Host not in CheckMK Is it in dev_mon_base? Is CMK_ADVERTISED_URL client-routable? ipa hostgroup-show dev_mon_base description present?
ClamAV shows "no scan yet" Scans run 02:00; trigger once with sudo /usr/local/bin/ansipa-clamscan.sh. Tools installed via dev_mod_anti-malware?
Package group ignored dev_pkg_* uses the installer timer, not the enforcer — run sudo /usr/local/bin/ansipa-install-packages.sh.
Enforcer error ipa: command not found The host is not enrolled — run freeipa-enroll.sh first.
Changes take up to 30 min That's the timer cadence; run the script manually to apply now.

State for all policies lives under /var/lib/ansipa-policies/; logs go to the journal under the ansipa-policies tag (journalctl -t ansipa-policies).