#!/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_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_clamscan            Run a daily ClamAV + rkhunter + chkrootkit scan (02:00) and report
#                               the result to CheckMK via a local check (Ansipa_ClamScan). Requires
#                               dev_mod_anti-malware (tools) and dev_mon_base (agent that collects
#                               the check). Leaving the group removes the scan + check.
#   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_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=$(ansipa_fqdn)

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."
