127 lines
8.6 KiB
Bash
Executable File
127 lines
8.6 KiB
Bash
Executable File
#!/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."
|