Home > Mobile >  Shell scripting - authenticate once for many privilege escalations
Shell scripting - authenticate once for many privilege escalations

Time:09-03

Suppose I have a script commands.sh that looks something like the following:

command1 # Must be run as root
command2 # Absolutely cannot be run as root
command3 # Should be run as unprivileged user, but can be run as root
... 
...

If we run commands.sh, then command1 will complain. If we run sudo commands.sh, then command2 will complain. We could edit commands.sh to look like the following,

sudo command1 
command2 
command3 
... 
...

That is, inserting sudos in the appropriate places. With the default sudo config (15 minute authentication persistence), this works great (assuming the script takes less than 15 minutes to run). However, if the script is longer, or we have authentication persistence disabled, then I feel there's not an obvious way forward. Additionally, some systems might not even use sudo to authenticate - they may use doas or something else instead.

Is there any (POSIX-y?) way of creating a script, authenticating once at the start, and then persisting that authentication through the script when necessary, without the use of sudo's persistence?

CodePudding user response:

One possibility is to require the script to be run via sudo, but then use sudo -u within the script to revert (/demote) to the original user for commands that shouldn't be run as root. It'd probably be a good idea to include some sanity-checking at the beginning of the script to make sure it's being run from the right environment:

#!/bin/bash

if [[ "$EUID" != 0 ]]; then
    # The script is not running as root
    echo "This script must be run via sudo (as root)" >&2
    exit 1
    # Optional: replace exit 1 with:
    # exec sudo "$0" "$@"    # Re-run this script via sudo
    # exit $?    # In case the exec fails

elif [[ -z "$SUDO_USER" ]]; then
    # The script is running as root, but doesn't have $SUDO_USER
    # (the original user who ran sudo) to revert back to for
    # unprivileged operations
    echo "This script must be run via sudo, not directly as root" >&2
    exit 1

elif [[ "$SUDO_USER" = root || "$SUDO_UID" = 0 ]]; then
    # The script is running as root via sudo, but $SUDO_USER is
    # *also* root, so is not suitable to revert back to for
    # unprivileged operations
    echo "This script must be run via sudo, from a regular (non-root) account" >&2
    exit 1
fi

command1 # Must be run as root
sudo -u "$SUDO_USER" command2 # Absolutely cannot be run as root
sudo -u "$SUDO_USER" command3 # Should be run as unprivileged user, but can be run as root
  • Related