Last active
August 17, 2023 10:20
-
-
Save muety/eedbc7f6aa5d618e53142cfbd7caf6bc to your computer and use it in GitHub Desktop.
Script to determine the next available subuid on Linux
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Author: Ferdinand Mütsch <[email protected]> | |
# Script to determine the next subuid / subgid for a user. | |
# It will consider (a) all already existing subuid / subgid ranges and (b) all "real" user ids. | |
# | |
# Note: When using LDAP login (e.g. with SSSD), /etc/passwd won't contain those external users. | |
# In the case of SSSD, you will have to enable enumeration (https://access.redhat.com/solutions/500433) to make "getent passwd" all local AD / LDAP users. | |
# However, on the other hand, enabling recommendation is not recommended, because it will cause high load on server and client (https://docs.pagure.org/sssd.sssd/users/faq.html#when-should-i-enable-enumeration-in-sssd-or-why-is-enumeration-disabled-by-default). | |
# | |
# Limitations: | |
# This script is not guaranteed to work with external user authentication like LDAP / AD, because the ID of a future LDAP user might be as high as to conflict with previously assigned subuid ranges. | |
# To reduce the likelihood of such conflicts, it is recommended to add a large offset to the currently highest ID (as returned by this script) when allocating a new range. | |
# | |
# Example 1 (get largest UID): | |
# ./next_subuid.sh uid | |
# | |
# Example 2 (get largest GID): | |
# ./next_subuid.sh gid | |
# | |
# Example 3 (use in combination with usermod): | |
# export next="$(./next_subuid.sh)"; sudo usermod --add-subuids "$next-$(($next+65536-1))" some-user | |
uid_file='/etc/subuid' | |
if [ "$1" = "gid" ]; then | |
uid_file='/etc/subuid' | |
fi | |
pattern='([0-9a-zA-Z_\-]+):([0-9]+):([0-9]+)' | |
# read file line by line into array | |
readarray -t subuids < <(cat $uid_file) | |
# parse file and find highest next available id | |
max_uid=0 | |
for uid in "${subuids[@]}"; do | |
[[ $uid =~ $pattern ]] | |
uid_start="${BASH_REMATCH[2]}" | |
uid_range="${BASH_REMATCH[3]}" | |
uid_end=$(($uid_start+$uid_range+1)) | |
((uid_end > max_uid)) && max_uid=$uid_end | |
done | |
# read all user ids | |
if [ "$1" = "gid" ]; then | |
readarray -t ids < <(getent passwd | cut -d: -f3) | |
else | |
readarray -t ids < <(getent passwd | cut -d: -f4) | |
fi | |
# find highest user / group id | |
max_id=0 | |
for id in "${ids[@]}"; do | |
((id > max_id)) && max_id=$id | |
done | |
own_id=$(id -u) | |
all_ids=($own_id $max_id $max_uid) | |
max=$(printf '%s\n' "${all_ids[@]}" | sort -n -r | head -n 1) | |
echo "$max" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment