120 lines
5.1 KiB
Bash
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
|