Dotfiles/setup/modules/FreeipaAnsible/ansible/policies.d/usr_policystore.sh

120 lines
5.1 KiB
Bash

#!/usr/bin/env bash
# policy: usr_policystore — auto-mount the ansipa policy store for admins.
# When the IPA user group usr_smb_adm_policystore exists, members who are
# logged in get the ansipa-policystore SMB share mounted at ~/policystore (rw).
# The mount is tracked in state and removed when the group is deleted or the
# user is no longer a member.
# Credential: cifs://<host>:smb-policystore:<pass> in the IPA group description,
# written by ansipa-smb-setup.sh.
PS_MOUNT_STATE="$STATE_DIR/policystore-mounts"
PS_CREDS_DIR="$STATE_DIR/smb-creds"
PS_CREDS_FILE="$PS_CREDS_DIR/policystore.creds"
[[ -f "$PS_MOUNT_STATE" ]] || touch "$PS_MOUNT_STATE"
mkdir -p "$PS_CREDS_DIR"
chmod 700 "$PS_CREDS_DIR"
_ps_grp_exists=false
grep -qxF "usr_smb_adm_policystore" <<< "$_ALL_USER_GROUPS" && _ps_grp_exists=true
_ps_member() { id -nG "$1" 2>/dev/null | tr ' ' '\n' | grep -qxF "usr_smb_adm_policystore"; }
if [[ "$_ps_grp_exists" == true ]] && command -v mount.cifs &>/dev/null; then
_PS_CRED=$(_smb_parse_cred "usr_smb_adm_policystore")
if [[ -z "$_PS_CRED" ]]; then
warn "usr_smb_adm_policystore: no cifs:// credential in IPA group description"
warn " — run ansipa-smb.service on the FreeIPA container first"
else
read -r _PS_HOST _PS_SUSER _PS_SPASS <<< "$_PS_CRED"
printf 'username=%s\npassword=%s\ndomain=WORKGROUP\n' "$_PS_SUSER" "$_PS_SPASS" \
> "$PS_CREDS_FILE"
chmod 600 "$PS_CREDS_FILE"
# Collect logged-in users.
declare -A _PS_SESS
_ps_add_sess() {
local _u
[[ "$2" == "loginctl" ]] && _u=$(awk '{print $3}' <<< "$1") \
|| _u=$(awk '{print $1}' <<< "$1")
[[ -z "$_u" || "$_u" == "root" || "$_u" == "USER" ]] && return 0
local _h; _h=$(getent passwd "$_u" | cut -d: -f6 2>/dev/null) || return 0
[[ -d "$_h" ]] && _PS_SESS["$_u"]="$_h"
}
if loginctl list-sessions --no-legend &>/dev/null; then
while IFS= read -r _L; do _ps_add_sess "$_L" "loginctl"
done < <(loginctl list-sessions --no-legend 2>/dev/null)
else
while IFS= read -r _L; do _ps_add_sess "$_L" "who"
done < <(who 2>/dev/null)
fi
unset _L
# Mount for logged-in members.
for _PS_U in "${!_PS_SESS[@]}"; do
_ps_member "$_PS_U" || continue
_PS_H="${_PS_SESS[$_PS_U]}"
_PS_MP="$_PS_H/policystore"
if mountpoint -q "$_PS_MP" 2>/dev/null; then
grep -qxF "$_PS_U" "$PS_MOUNT_STATE" 2>/dev/null || \
echo "$_PS_U" >> "$PS_MOUNT_STATE"
continue
fi
mkdir -p "$_PS_MP"
chown "$_PS_U" "$_PS_MP" 2>/dev/null || true
if mount -t cifs "//${_PS_HOST}/ansipa-policystore" "$_PS_MP" \
-o "credentials=${PS_CREDS_FILE},uid=${_PS_U},gid=${_PS_U},file_mode=0664,dir_mode=02775,nounix,noserverino" \
2>/dev/null; then
log "Mounted //${_PS_HOST}/ansipa-policystore → $_PS_MP for $_PS_U"
grep -qxF "$_PS_U" "$PS_MOUNT_STATE" 2>/dev/null || \
echo "$_PS_U" >> "$PS_MOUNT_STATE"
else
warn "Failed to mount policystore for $_PS_U"
rmdir "$_PS_MP" 2>/dev/null || true
fi
done
unset _PS_U _PS_H _PS_MP
# Revert: unmount for users no longer in the group or group deleted.
_NEW_PS_MOUNTS=()
while IFS= read -r _OLD_PS_U; do
[[ -z "$_OLD_PS_U" ]] && continue
_OLD_PS_HOME=$(getent passwd "$_OLD_PS_U" | cut -d: -f6 2>/dev/null) || continue
_OLD_PS_MP="$_OLD_PS_HOME/policystore"
if _ps_member "$_OLD_PS_U"; then
_NEW_PS_MOUNTS+=("$_OLD_PS_U")
else
umount -l "$_OLD_PS_MP" 2>/dev/null || true
rmdir "$_OLD_PS_MP" 2>/dev/null || true
log "Unmounted policystore for $_OLD_PS_U (no longer in usr_smb_adm_policystore)"
fi
done < "$PS_MOUNT_STATE"
unset _OLD_PS_U _OLD_PS_HOME _OLD_PS_MP
if [[ ${#_NEW_PS_MOUNTS[@]} -gt 0 ]]; then
printf '%s\n' "${_NEW_PS_MOUNTS[@]}" | sort -u > "$PS_MOUNT_STATE"
else
> "$PS_MOUNT_STATE"
fi
unset _NEW_PS_MOUNTS _PS_SESS _PS_HOST _PS_SUSER _PS_SPASS _PS_CRED
rm -f "$PS_CREDS_FILE" 2>/dev/null || true
fi
else
# Group deleted — unmount for any previously-tracked users.
if [[ -s "$PS_MOUNT_STATE" ]]; then
while IFS= read -r _OLD_PS_U; do
[[ -z "$_OLD_PS_U" ]] && continue
_OLD_PS_HOME=$(getent passwd "$_OLD_PS_U" | cut -d: -f6 2>/dev/null) || continue
umount -l "$_OLD_PS_HOME/policystore" 2>/dev/null || true
rmdir "$_OLD_PS_HOME/policystore" 2>/dev/null || true
log "Unmounted policystore for $_OLD_PS_U (usr_smb_adm_policystore group deleted)"
done < "$PS_MOUNT_STATE"
> "$PS_MOUNT_STATE"
unset _OLD_PS_U _OLD_PS_HOME
fi
fi
unset _ps_grp_exists