#!/bin/bash # # Author: Georg Voell - georg.voell@standby.cloud # Version: @(#)group-management 3.2.0 12.08.2024 (c)2024 Standby.cloud # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ # # This script can be used free of charge. Use it as is or customize as needed. It is not guaranteed to be # error free and you will not be reimbursed for any damage it may cause. # #@ Manages groups within Linux. #@ #@Usage: group-management [options] [action] groupname #@ Options: #@ -h, --help : Displays helptext. #@ -v, --version : Displays the version of the script. #@ -a, --all : Display all groups. #@ -g, --gid : Group ID. #@ -n, --new-name : New groupname. #@ #@ Action: #@ show : Show groups. #@ check : Check if group exists and has the given attributes - otherwise create or change. #@ delete: Delete group. #@ #@Examples: #@ group-management check dba -g 1005 #@ Create group 'dba' (if it doesn't exist) with group id '1005'. #@ group-management delete dba #@ Delete group 'dba'. # # Exit codes: # 01: Unknown or wrong parameter and only LINUX supported and script needs to be executed with ROOT privileges. # 02: Unknown action. # 03: No groupname specified. # 99: User interrupt. # # See also: # **bootstrap**(1), **disk-management**(1), **key-management**(1), **install-scripts**(1) # # ToDo: # # Known bugs: # # Update history: # # V 3.0.0 23.05.2021 New version # V 3.1.0 05.06.2023 New copyright # V 3.2.0 12.08.2024 New minor version # # Find executable bash library and source it lib=`which lib.bash 2>/dev/null | sed 's|^no 'lib.bash' in .*||'` if [ "$lib" != "" ]; then source "$lib" else progdir=`dirname "$0"` if [ -r "${progdir}/lib.bash" ]; then source "${progdir}/lib.bash" else echo "Unexpected error: Unable to locate bash library 'lib.bash'." exit 1 fi fi # Read configuration for users function ReadConfig() { local config="/etc/login.defs" if [ -r "$config" ]; then cat $config | tr -s ' ' ' ' | tr -s ' ' ' ' > $scratchfile gid_min=`grep "^GID_MIN " $scratchfile | cut -d' ' -f2` gid_max=`grep "^GID_MAX " $scratchfile | cut -d' ' -f2` fi } # Display all regular groups function DisplayGroups() { local groupname="" local pass="" local gid=0 local member="" local result="" local pass="" local user="" local agroups="" if [ -r "$groupfile" ]; then printf "groupname\tpassword\tgid\tmember\n" > $scratchfile while IFS=':' read -r groupname pass gid member; do if [ "$showall" = true -o $gid -ge $gid_min -a $gid -le $gid_max ]; then if [ "$pass" = " " -o "$pass" = "" ]; then pass="None" elif [ "$pass" = "*" ]; then pass="Nopasswd" elif [ "$pass" != "x" ]; then result=`grep "^!.*"` if [ "$result" != "" ]; then pass="Locked" else pass="Set" fi else pass="Unknown" if [ -r "$gshadowfile" ]; then result=`grep "^${groupname}:" $gshadowfile` if [ "$result" != "" ]; then pass=`echo "$result" | cut -d':' -f2` if [ "$pass" = '!' ]; then pass="None" elif [ "$pass" = '' ]; then pass="Nopasswd" else result=`echo "$pass" | grep "^!.*"` if [ "$result" != "" ]; then pass="Locked" else pass="Set" fi fi fi fi fi user=`grep "^.*:.*:.*:$gid:" $passwdfile | cut -d':' -f1` user=`printf "$user" | tr '\n' ','` if [ "$member" = "" ]; then if [ "$user" = "" ]; then agroups="" else agroups="($user)" fi else if [ "$user" = "" ]; then agroups="$member" else agroups="(${user}),$member" fi fi # echo "groupname: '$groupname' - user: '$user' - member: '$member'." printf "%s\t%s\t%s\t%s\n" "$groupname" "$pass" "$gid" "$agroups" >> $scratchfile fi done < <(cat "$groupfile" | stripcomment | grep .) if [ "$showall" = true ]; then printf "\nAll groups:\n\n" else printf "\nRegular groups:\n\n" fi print-table --import $scratchfile fi } function CreateGroup() { local groupname=${1} local stat=0 if [ "$groupname" != "" ]; then # Create the group groupadd "$groupname" 2>/dev/null stat=$? if [ $stat -gt 0 ]; then errormsg 0 "Unable to create group '$groupname'." else # Modify if [ "$gid" != "" ]; then groupmod -g "$gid" "$groupname" 2>/dev/null stat=$? if [ $stat -gt 0 ]; then errormsg 0 "Unable to set GID to '$gid' for group '$groupname'. Using default." fi fi if [ "$newname" != "" ]; then if [ "$newname" != "$groupname" ]; then groupmod -n "$newname" "$groupname" 2>/dev/null stat=$? if [ $stat -gt 0 ]; then errormsg 0 "Unable to change name to '$newname' for group '$groupname'." fi fi fi fi else errormsg 0 "Unexpected: Empty groupname." fi } function DeleteGroup() { local groupname=${1} local groupstr="" local stat=0 if [ -r "$groupfile" -a "$groupname" != "" ]; then groupstr=`cat "$groupfile" | stripcomment | grep "^${groupname}:"` if [ "$groupstr" != "" ]; then groupdel -f "$groupname" 2>/dev/null stat=$? if [ $stat -gt 0 ]; then errormsg 0 "Unable to delete group '$groupname'." fi else errormsg 0 "Group '$groupname' does not exist." fi fi } function CheckGroup() { local groupname=${1} local groupstr="" local oldgid="" local stat=0 if [ -r "$groupfile" -a "$groupname" != "" ]; then groupstr=`cat "$groupfile" | stripcomment | grep "^${groupname}:"` if [ "$groupstr" != "" ]; then # group exists # groupname pass gid member oldgid=`echo "$groupstr" | cut -d':' -f3` if [ "$gid" != "" ]; then if [ "$oldgid" != "$gid" ]; then groupmod -g "$gid" "$groupname" 2>/dev/null stat=$? if [ $stat -gt 0 ]; then errormsg 0 "Unable to change GID from '$oldgid' to '$gid' for group '$groupname'." fi fi fi if [ "$newname" != "" ]; then if [ "$newname" != "$groupname" ]; then groupmod -n "$newname" "$groupname" 2>/dev/null stat=$? if [ $stat -gt 0 ]; then errormsg 0 "Unable to change name to '$newname' for group '$groupname'." fi fi fi else # group does not exist yet # Create group CreateGroup "$groupname" fi fi } # Check if we are running on Linux and have root privileges. if [ "$OS" != "Linux" ]; then errstr="This script only supports LINUX." elif [ "$USER" != "root" ]; then # Try sudo check-sudo stat=$? if [ $stat -eq 0 ]; then printf 'sudo -n "%s"' "$script" > $scratchfile while [ $# -gt 0 ]; do pname=${1} printf ' "%s"' "$pname" >> $scratchfile shift done # Execute script chmod 700 $scratchfile $scratchfile stat=$? # Cleanup rm -f $scratchfile exit $stat else # Need root privileges errstr="Root privileges needed to continue." fi fi # Preset action="" param1="" gid="" newname="" showall=false gid_min=1000 gid_max=60000 # Check parameters: Loop until all parameters are used up while [ $# -gt 0 ]; do pname=${1} case "$pname" in -v | --version) shift showversion=true ;; -h | --help) shift showhelp=true ;; -a | --all) shift showall=true ;; -g | --gid) shift if [ "$1" != "" ]; then gid=${1} result=`echo "$gid" | grep '^[0123456789]*$'` if [ "$result" = "" ]; then errstr="Id has to be a number." fi shift else errstr="Please specify an id after parameter '$pname'." fi ;; -n | --new-name) shift if [ "$1" != "" ]; then newname=${1} shift else errstr="Please specify a name after parameter '$pname'." fi ;; *) shift paramck=`echo "$pname" | grep '^-'` # Keys don't begin with '-' if [ "$paramck" != "" ]; then errstr="Unknown option '$pname'." else if [ "$action" = "" ]; then action=`echo "$pname" | tolower` elif [ "$param1" = "" ]; then param1="$pname" else errstr="Unknown additional parameter: '$pname'." fi fi esac done # Display help or error message DisplayHelp # Plausibilty check if [ "$action" = "" ]; then action="show" fi # Main passwdfile="/etc/passwd" shadowfile="/etc/shadow" gshadowfile="/etc/gshadow" groupfile="/etc/group" keyfile=".ssh/authorized_keys" if [ "$USER" = "root" ]; then ReadConfig case "$action" in show) DisplayGroups ;; check) if [ "$param1" = "" ]; then exitcode=3 errormsg $exitcode "No groupname specified." else CheckGroup "$param1" fi ;; delete) if [ "$param1" = "" ]; then exitcode=3 errormsg $exitcode "No groupname specified." else DeleteGroup "$param1" fi ;; *) exitcode=2 errormsg $exitcode "Unknown action: '$action'." esac fi # Cleanup and exit Cleanup exit $exitcode