Dotfiles/setup/modules/FreeipaAnsible/ansible/ansipa-enforce-policies.sh

127 lines
8.6 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env bash
# ansipa-enforce-policies.sh — enforce FreeIPA host-group-driven policies on this client.
#
# Policies are idempotent and reversible: joining a group applies the policy;
# leaving the group removes it on the next run (every 30 min via systemd timer).
#
# Host-group naming conventions (device policies — applied to the whole machine):
# dev_daemon-enable-<unit> Ensure <unit> is enabled and running (systemctl enable --now).
# Leaving the group reverts: service is disabled and stopped.
# dev_daemon-disable-<unit> Ensure <unit> is disabled and stopped (systemctl disable --now).
# Leaving the group reverts: service is re-enabled and started.
# <unit> may omit the .service suffix; all systemd unit types work.
# If a unit appears in both enable and disable groups it is skipped.
# dev_timeshift-backup Enforce a daily Timeshift snapshot (requires timeshift installed)
# dev_security-scan Enforce daily ClamAV + rkhunter + chkrootkit scans
# dev_no-local-users Lock passwords for root and all local users (UID >= 1000) so
# that only FreeIPA domain accounts with centrally-managed sudo
# rules can authenticate and gain elevated privileges.
# Leaving the group reverts: every account locked by this policy
# is unlocked on the next run.
# dev_local-sudo-<username> Grant <username> full sudo on this specific device by adding
# them to the local sudoers drop-in. Leaving the group removes
# the drop-in on the next run.
# dev_ssh_<userid> Distribute <userid>'s SSH public keys from their IPA profile to
# /home/<userid>/.ssh/authorized_keys on this device (ansipa-managed
# section; manually added keys are preserved). Leaving the group
# removes only the ansipa-managed section on the next run.
# Keys stored in IPA via: ipa user-mod <userid> --sshpubkey='...'
#
# CheckMK monitoring host-groups (device policies — require dev_mon_base first):
# dev_mon_base Install CheckMK agent; register host in CheckMK under /ansipa;
# enable check_mk.socket (port 6556) for pull mode, or
# cmk-agent-ctl push timer for push mode (when server can't
# reach the client directly).
# Built-in sections report CPU, RAM, disk, uptime.
# Custom check: installed package count (rpm / dpkg / pacman).
# Credentials are auto-discovered from the IPA dev_mon_base
# description (populated by ansipa-checkmk-setup.sh on the server).
# Leaving the group deregisters the host and disables the agent.
# dev_mon_malware Local check reporting ClamAV scan results from the
# dev_security-scan log. Requires dev_security-scan to run first;
# both groups can coexist independently.
# dev_mon_timeshift Local check for most-recent Timeshift snapshot age.
# WARN if >5 days, CRIT if >10 days; CRIT if no snapshots found.
# dev_mon_power Local check for CPU package power via Intel RAPL (preferred)
# or lm-sensors fallback. WARN >65 W, CRIT >95 W.
#
# User-group naming conventions (per-user policies — follow the user across devices):
# usr_admin Members get full sudo on every enrolled host via a sudoers
# drop-in (/etc/sudoers.d/ansipa-usr-admin). Applied while the
# FreeIPA user group exists; drop-in is removed when the group is
# deleted. Uses SSSD so group membership resolves without local
# accounts.
# usr_block-binary-<name> Prevent members of this FreeIPA user group from running <name>
# on any enrolled host. Use __ in place of . to support Flatpak
# app IDs (e.g. usr_block-binary-org__gimp__Gimp blocks the
# Flatpak org.gimp.Gimp). Enforced via a PATH-priority wrapper
# that checks group membership at runtime via SSSD/id(1).
# Removing the user group from FreeIPA reverts the wrapper.
# usr_prt_<printer> Auto-add <printer> to CUPS on any enrolled host where a member
# is logged in. The printer URI is stored in the IPA group
# description (e.g. ipps://host/printers/name). Access is
# per-user only (allow:<username>); each new member who logs in
# gets added to the allow list. When the IPA group is deleted
# or all members leave, the printer is removed from CUPS on that
# host. A profile.d snippet + NOPASSWD sudo rule trigger the
# enforcer at login for immediate setup.
# usr_scan-notify Members receive scan alert notifications on every enrolled device
# they log into. The fetch-alerts timer is installed fleet-wide
# when the group exists; the notification daemon starts on login
# only for group members (checked via id(1) / SSSD).
# Deleting the IPA user group removes the timer and profile.d
# snippet on the next enforcer run.
# usr_smb_r_<name> Mount a read-only Samba share as ~/name for members on any
# usr_smb_rw_<name> enrolled host where they are logged in. rw membership takes
# precedence over r when both exist for the same share name.
# Credential string is stored in the IPA group description by
# ansipa-smb-setup.sh (cifs://<host>:<user>:<pass>).
# Leaving the group unmounts the share on the next run.
# Requires: cifs-utils installed on the client.
# usr_smb_adm_policystore Mount the ansipa policy store at ~/policystore (rw) for members.
# Credential in IPA group description (set by ansipa-smb-setup.sh).
# Also used by the enforcer itself to sync policy files from the
# server before applying them — edits on the SMB share take effect
# on the next 30-min enforcer tick fleet-wide.
# usr_mon_logins (CheckMK) Local check for SSH login attempts in the last 24 h:
# successful + failed + invalid-user counts with thresholds.
# WARN: ≥10 failed or ≥5 invalid; CRIT: ≥50 failed or ≥20 invalid.
# Installed fleet-wide when the group exists; requires dev_mon_base.
#
# Notes:
# - Install scan tools first: add the host to dev_mod_anti-malware.
# - Configure Timeshift (type + target device) before enabling dev_timeshift-backup.
# - CheckMK server must be running and accessible before adding hosts to dev_mon_base.
# Run ansipa-checkmk-setup.sh on the FreeIPA container to seed credentials and groups.
# - Policy files live in /usr/local/lib/ansipa/policies.d/ on enrolled clients.
# The enforcer syncs them from the ansipa-policystore SMB share before each run;
# edit files on the share directly (~/policystore if you are in usr_smb_adm_policystore)
# to update policies without re-running Ansible.
set -euo pipefail
# shellcheck source=lib/ansipa-policy.sh
source /usr/local/lib/ansipa/policy.sh
HOST_FQDN=$(hostname -f 2>/dev/null || hostname)
command -v ipa &>/dev/null || { warn "ipa not found — host not enrolled in FreeIPA. Exiting."; exit 0; }
kinit -k "host/$HOST_FQDN" &>/dev/null || true
mkdir -p "$STATE_DIR"
log "Discovering groups..."
_ansipa_discover
log "Syncing policy store..."
_ansipa_sync_policystore
log "Applying policies..."
for _p in "$POLICY_DIR"/*.sh; do
[[ -f "$_p" ]] || continue
# shellcheck disable=SC1090
source "$_p"
done
log "Policy enforcement complete."