You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ublinux-init/ublinux/rc.halt.pre/25-accounts-sync

278 lines
17 KiB

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/bash
#
# Author: Dmitry Razumov <asmeron@ublinux.com>
# Copyright (c) 2021-2025 UBLinux <support@ublinux.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Extended pattern matching: https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html#Pattern-Matching
shopt -s extglob
ENABLED=yes
[[ ${ENABLED} == "yes" ]] || { return 0 2>/dev/null && return 0 || exit 0; }
DEBUGMODE=no
unset ROOTFS; [[ -d /usr/lib/ublinux ]] || ROOTFS=.
SOURCE=${ROOTFS}/usr/lib/ublinux/functions; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null || exit 0
SOURCE=${ROOTFS}/usr/lib/ublinux/default; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null || exit 0
debug_mode "$0" "$@"
SYSCONF="${ROOTFS}${SYSCONF}"
SOURCE=${SYSCONF}/config; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
SOURCE=${SYSCONF}/users; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
## Синхронизация пользователей системы /etc/passwd и их параметры /etc/shadow с глобальной конфигурацией
## USERADD_SYNC='boot,shutdown,shutdown@all,shutdown@users,shutdown@systems,shutdown@<min>-<max>,shutdown@<uid>'
## boot # При загрузке системы принудительно применить глобальную конфигурацию на пользователя
## shutdown # Аналогичен shutdown@users + shutdown@systems
## shutdown@all # При завершении работы системы синхронизировать всех пользователей в системе с глобальной конфигурацией
## shutdown@users # При завершении работы системы синхронизировать пользователей 1000<=UID<=6000 в системе с глобальной конфигурацией
## shutdown@systems # При завершении работы системы синхронизировать системных пользователей 500<=UID<=999 в системе с глобальной конфигурацией
## shutdown@<min>-<max> # При завершении работы системы синхронизировать диапазон UID пользователей в системе с глобальной конфигурацией
## shutdown@<uid> # При завершении работы системы синхронизировать UID пользователя в системе с глобальной конфигурацией
## USERADD_SYNC=boot,shutdown
##
## USERADD_SYNC[<user_name>]='boot,shutdown'
## <user_name> # Имя пользователя, необязательное поле. Если не указано, то применяется для всех пользователей
## boot # При загрузке системы принудительно применить глобальную конфигурацию на пользователя
## shutdown # При завершении работы системы синхронизировать указанного пользователя в системе с глобальной конфигурацией
## USERADD_SYNC[superadmin]=boot,shutdown
exec_01_useradd_sync(){
remove_ubconfig(){
# Удалить пользователей из глобальной конфигурации
local PARAM="$1"
local FILE_LOGINDEFS="${ROOTFS}/etc/login.defs"
if [[ ${PARAM} == '@all' ]]; then
# Удалить всех пользователей из глобальной конфигурации
${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] USERADD[*] USERSHADOW[*]
elif [[ ${PARAM} == '@users' ]]; then
# Удалить пользователей 1000<=UID<=6000 из глобальной конфигурации
# Все пользователи кроме системных
local UID_MIN=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*UID_MIN[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}")
local UID_MAX=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*UID_MAX[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}")
local STR_REMOVE_USERS=()
[[ -n ${!USERADD[@]} ]] && while IFS= read -u3 SELECT_USER; do
IFS=':' read -u4 SELECT_GECOS SELECT_UID NULL 4<<< ${USERADD[${SELECT_USER}]}
if [[ ${SELECT_UID} == @(""|"x"|"X") ]] || [[ ${SELECT_UID} -ge ${UID_MIN} && ${SELECT_UID} -le ${UID_MAX} ]]; then
STR_REMOVE_USERS+=("USERADD[${SELECT_USER}]")
STR_REMOVE_USERS+=("USERSHADOW[${SELECT_USER}]")
fi
done 3< <(printf "%s\n" "${!USERADD[@]}")
[[ ${#STR_REMOVE_USERS[@]} -ge 0 ]] && ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] "${STR_REMOVE_USERS[@]}"
elif [[ ${PARAM} == '@systems' ]]; then
# Удалить пользователей 500<=UID<=999 из глобальной конфигурации
# Пользователи системные
local UID_MIN_SYS=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*SYS_UID_MIN[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}")
local UID_MAX_SYS=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*SYS_UID_MAX[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}")
local STR_REMOVE_USERS=()
[[ -n ${!USERADD[@]} ]] && while IFS= read -u3 SELECT_USER; do
IFS=':' read -u4 SELECT_GECOS SELECT_UID NULL 4<<< ${USERADD[${SELECT_USER}]}
if [[ ${SELECT_UID} != @(""|"x"|"X") && ${SELECT_UID} -ge ${UID_MIN_SYS} && ${SELECT_UID} -le ${UID_MAX_SYS} ]]; then
STR_REMOVE_USERS+=("USERADD[${SELECT_USER}]")
STR_REMOVE_USERS+=("USERSHADOW[${SELECT_USER}]")
fi
done 3< <(printf "%s\n" "${!USERADD[@]}")
[[ ${#STR_REMOVE_USERS[@]} -ge 0 ]] && ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] "${STR_REMOVE_USERS[@]}"
elif [[ ${PARAM} =~ ^([[:digit:]]+)'-'*([[:digit:]]*)$ ]]; then
# Удалить пользователей X<=UID<=Y из глобальной конфигурации
local UID_MIN=${BASH_REMATCH[1]}
local UID_MAX=${BASH_REMATCH[2]}
local STR_REMOVE_USERS=()
[[ -n ${UID_MAX} ]] || UID_MAX=${UID_MIN}
[[ -n ${!USERADD[@]} ]] && while IFS= read -u3 SELECT_USER; do
IFS=':' read -u4 SELECT_GECOS SELECT_UID NULL 4<<< ${USERADD[${SELECT_USER}]}
if [[ ${SELECT_UID} != @(""|"x"|"X") && ${SELECT_UID} -ge ${UID_MIN} && ${SELECT_UID} -le ${UID_MAX} ]]; then
STR_REMOVE_USERS+=("USERADD[${SELECT_USER}]")
STR_REMOVE_USERS+=("USERSHADOW[${SELECT_USER}]")
fi
done 3< <(printf "%s\n" "${!USERADD[@]}")
[[ ${#STR_REMOVE_USERS[@]} -ge 0 ]] && ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] "${STR_REMOVE_USERS[@]}"
else
# Входящий параметр - имя пользователя
${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] USERADD[${PARAM}] USERSHADOW[${PARAM}]
fi
}
set_ubconfig(){
local PARAM="$1"
local GET_USERADD=$(get_conf_useradd_from_system "${PARAM}")
if [[ ${GET_USERADD} != "" ]]; then
eval ${ROOTFS}/usr/bin/ubconfig --quiet --target global set [users] ${GET_USERADD}
local GET_USERSHADOW=$(get_conf_usershadow_from_system ${PARAM})
# TODO: Если задан диапазон пользователей, пример 0-999, то GET_USERSHADOW будет содержать всех пользователей в этом диапазоте
# А нужно выбрать только пользователей которые содержатся в GET_USERADD
if [[ ${GET_USERSHADOW} != "" ]]; then
eval ${ROOTFS}/usr/bin/ubconfig --quiet --target global set [users] ${GET_USERSHADOW}
fi
fi
}
set_ubconfig_global_allsync(){
# Если в системной конфигурации заданы USERADD_SYNC= то установить в глобальной конфигурации
[[ -n ${USERADD_SYNC} ]] && ${ROOTFS}/usr/bin/ubconfig --quiet --target global set [users] USERADD_SYNC="${USERADD_SYNC}"
}
set_ubconfig_global_selectsync(){
local PARAM="$1"
# Если в системной конфигурации заданы USERADD_SYNC[${PARAM}]= то установить в глобальной конфигурации
[[ -n ${PARAM} && "$(declare -p USERADD_SYNC 2>/dev/null)" == "declare -A"* && -n ${USERADD_SYNC[${PARAM}]} ]] \
&& ${ROOTFS}/usr/bin/ubconfig --quiet --target global set [users] USERADD_SYNC["${PARAM}"]="${USERADD_SYNC[${PARAM}]}"
}
[[ $1 == @("set="|"set+="|"set++="|"set-="|"set--="|"remove") ]] && COMMAND=$1 && shift
[[ -n ${COMMAND} ]] || COMMAND="set="
local PARAM="$@"
if [[ -n ${PARAM} ]]; then
# Параметр вида USERADD_SYNC=
if [[ ${PARAM} =~ ^[^'[']+'=' ]]; then
USERADD_SYNC=
else
# Параметр вида USERADD_SYNC[*]=
local USERADD_SYNC=
declare -A USERADD_SYNC=()
fi
[[ ${PARAM} =~ ^[[:alnum:]_]+("="|"[".*"]=") ]] && eval "${PARAM%%=*}=\${PARAM#*=}"
fi
if [[ ${COMMAND} == @("set="|"set+="|"set++=") ]]; then
# Обработка всех пользователей параметр USERADD_SYNC=...
while IFS= read -u3 SELECT_USERADD_SYNC; do
if [[ ${SELECT_USERADD_SYNC} == 'shutdown@all' ]]; then
remove_ubconfig "@all"
set_ubconfig "@all"
elif [[ ${SELECT_USERADD_SYNC} == 'shutdown@users' ]]; then
remove_ubconfig "@users"
set_ubconfig "@users"
elif [[ ${SELECT_USERADD_SYNC} == 'shutdown@systems' ]]; then
remove_ubconfig "@systems"
set_ubconfig "@systems"
elif [[ ${SELECT_USERADD_SYNC} == 'shutdown' ]]; then
remove_ubconfig "@users"
remove_ubconfig "@systems"
set_ubconfig
elif [[ ${SELECT_USERADD_SYNC} =~ ^'shutdown@'(([[:digit:]]+)'-'*([[:digit:]]*))$ ]]; then
local LIST_USERS="${BASH_REMATCH[1]}"
remove_ubconfig "${LIST_USERS}"
set_ubconfig "${LIST_USERS}"
fi
set_ubconfig_global_allsync
done 3<<< "${USERADD_SYNC//@(,|;)/$'\n'}"
# Обработка выбранних пользователей параметр USERADD_SYNC[...]=...
if [[ "$(declare -p USERADD_SYNC 2>/dev/null)" == "declare -A"* ]]; then
[[ -n ${!USERADD_SYNC[@]} ]] && while IFS= read -u3 SELECT_USER; do
# В массиве 0 запись игнорируем, т.к. это параметр не ассоциативного массива
if [[ ${SELECT_USER} != 0 && ${USERADD_SYNC[${SELECT_USER}]} =~ 'shutdown' ]]; then
# Если все пользователи уже были синхронизироаны, то пропустить
if [[ ! ${USERADD_SYNC} =~ (^|,)('shutdown@all'|'shutdown')(,|$) ]]; then
remove_ubconfig "${SELECT_USER}"
set_ubconfig "${SELECT_USER}"
fi
set_ubconfig_global_selectsync "${SELECT_USER}"
fi
done 3< <(printf "%s\n" "${!USERADD_SYNC[@]}")
fi
elif [[ ${COMMAND} == @("set-="|"set--="|"remove") ]]; then
true
fi
}
## Синхронизация группы системы /etc/groups и их параметры /etc/gshadow с глобальной конфигурацией
## GROUPADD_SYNC='shutdown,shutdown@all,shutdown@users,shutdown@systems,shutdown@<min>-<max>,shutdown@<gid>'
## shutdown # Аналогичен shutdown@users + shutdown@systems
## shutdown@all # При завершении работы системы синхронизировать все группы в системе с глобальной конфигурацией
## shutdown@groups # При завершении работы системы синхронизировать группы 1000<=GID<=6000 в системе с глобальной конфигурацией
## shutdown@systems # При завершении работы системы синхронизировать системные группы 500<=GID<=999 в системе с глобальной конфигурацией
## shutdown@<min>-<max> # При завершении работы системы синхронизировать диапазон GID групп в системе с глобальной конфигурацией
## shutdown@<gid> # При завершении работы системы синхронизировать GID группы в системе с глобальной конфигурацией
## GROUPADD_SYNC=shutdown
##
## GROUPADD_SYNC[group_name]='shutdown'
## group_name # Имя группы, необязательное поле. Если не указано, то применяется для всех групп
## shutdown # При завершении работы системы синхронизировать указанную группу в системе с глобальной конфигурацией
## GROUPADD_SYNC[users]='shutdown'
exec_02_groupadd_sync(){
set_ubconfig(){
local PARAM="$1"
local GET_GROUPADD=$(get_conf_groupadd_from_system "${PARAM}")
if [[ ${GET_GROUPADD} != "" ]]; then
eval ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] ${GET_GROUPADD}
eval ${ROOTFS}/usr/bin/ubconfig --quiet --target global set [users] ${GET_GROUPADD}
fi
}
set_ubconfig_global_allsync(){
# Если в системной конфигурации заданы GROUPADD_SYNC= то установить в глобальной конфигурации
[[ -n ${GROUPADD_SYNC} ]] && ${ROOTFS}/usr/bin/ubconfig --quiet --target global set [users] GROUPADD_SYNC="${GROUPADD_SYNC}"
}
set_ubconfig_global_selectsync(){
local PARAM="$1"
# Если в системной конфигурации заданы GROUPADD_SYNC[${PARAM}]= то установить в глобальной конфигурации
[[ -n ${PARAM} && "$(declare -p GROUPADD_SYNC 2>/dev/null)" == "declare -A"* && -n ${GROUPADD_SYNC[${PARAM}]} ]] \
&& ${ROOTFS}/usr/bin/ubconfig --quiet --target global set [users] GROUPADD_SYNC["${PARAM}"]="${GROUPADD_SYNC[${PARAM}]}"
}
[[ $1 == @("set="|"set+="|"set++="|"set-="|"set--="|"remove") ]] && COMMAND=$1 && shift
[[ -n ${COMMAND} ]] || COMMAND="set="
local PARAM="$@"
if [[ -n ${PARAM} ]]; then
# Параметр вида GROUPADD_SYNC=
if [[ ${PARAM} =~ ^[^'[']+'=' ]]; then
GROUPADD_SYNC=
else
# Параметр вида GROUPADD_SYNC[*]=
local GROUPADD_SYNC=
declare -A GROUPADD_SYNC=()
fi
[[ ${PARAM} =~ ^[[:alnum:]_]+("="|"[".*"]=") ]] && eval "${PARAM%%=*}=\${PARAM#*=}"
fi
if [[ ${COMMAND} == @("set="|"set+="|"set++=") ]]; then
# Обработка всех групп, параметр GROUPADD_SYNC=...
# Если синхронизируем группы по шаблону, то удалим все группы из глобальной конфигурации
if [[ ${USERADD_SYNC} =~ 'shutdown' ]]; then
${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] GROUPADD[*]
fi
while IFS= read -u3 SELECT_GROUPADD_SYNC; do
if [[ ${SELECT_GROUPADD_SYNC} == 'shutdown@all' ]]; then
set_ubconfig "@all"
elif [[ ${SELECT_GROUPADD_SYNC} == 'shutdown@groups' ]]; then
set_ubconfig "@groups"
elif [[ ${SELECT_GROUPADD_SYNC} == 'shutdown@systems' ]]; then
set_ubconfig "@systems"
elif [[ ${SELECT_GROUPADD_SYNC} =~ ^'shutdown@'(([[:digit:]]+)'-'*([[:digit:]]*))$ ]]; then
set_ubconfig "${BASH_REMATCH[1]}"
elif [[ ${SELECT_GROUPADD_SYNC} == 'shutdown' ]]; then
set_ubconfig
fi
set_ubconfig_global_allsync
done 3<<< "${GROUPADD_SYNC//@(,|;)/$'\n'}"
# Обработка выбранних групп параметр GROUPADD_SYNC[...]=...
if [[ "$(declare -p GROUPADD_SYNC 2>/dev/null)" == "declare -A"* ]]; then
while IFS= read -u3 SELECT_GROUP; do
# В массиве 0 запись игнорируем, т.к. это параметр не ассоциативного массива
if [[ ${SELECT_GROUP} != 0 && ${GROUPADD_SYNC[${SELECT_GROUP}]} =~ 'shutdown' ]]; then
# Если все пользователи уже были синхронизироаны, то пропустить
if [[ ! ${GROUPADD_SYNC} =~ (^|,)('shutdown@all'|'shutdown')(,|$) ]]; then
set_ubconfig "${SELECT_GROUP}"
fi
set_ubconfig_global_selectsync "${SELECT_GROUP}"
fi
done 3< <(printf "%s\n" "${!GROUPADD_SYNC[@]}")
fi
elif [[ ${COMMAND} == @("set-="|"set--="|"remove") ]]; then
true
fi
}
################
##### MAIN #####
################
# Если файл подключен как ресурс с функциями, то выйти
return 0 2>/dev/null && return 0
if [[ -z $@ ]]; then
while read -r FUNCTION; do
$"${FUNCTION##* }"
done < <(declare -F | grep "declare -f exec_")
else
FUNCTION=
while [[ $# -gt 0 ]]; do
[[ -z ${1} ]] || { declare -f "${1}" &>/dev/null && FUNCTION+="; ${1}" || FUNCTION+=" '${1//\'/}'"; }
shift
done
eval ${FUNCTION#*; }
fi