17

When writing a shell script, in which some but not all commands in it need superuser privileges, shall I

  • add sudo to those commands which need superuser privileges, and run the shell script without sudo, or

  • don't add sudo to those commands which need superuser privileges, but run the shell script with sudo?

In the second way I will only need to provide my password once, but all the commands in the script will be run with superuser privilleges, including those commands which don't need.

In the first way I may need to provide my password multiple times for different sudo commands, while the superuser privileges are granted only to those commands which need them.

From security concern, the first way is better. For convenience, the second way is better.

  1. I have been thinking of adopting the first way. So I have to deal with the inconvenience of providing my passwords to multiple sudo commands in the shell script.

  2. Stephen Harris wrote:

    A well written script would detect if it was running with the right permissions and not call sudo at all, but there's a lot of bad scripts

    So should I use the second way? If so,

    • how can I write "script would detect if it was running with the right permissions and not call sudo at all"?

    • how can I improve its security to avoid the problem of giving superuser privileges to commands which don't need them when running the script with sudo?

  3. Would this simple approach have the best of of both approach: add sudo to commands which only need it, and run the script with or without sudo depending on whether I want convenience or security? Does this approach have some problem?

Thanks.

Tim
  • 101,790

2 Answers2

17

To address your first issue:

how can I write "script would detect if it was running with the right permissions and not call sudo at all"?

There is a simple and POSIX check for root:

#!/bin/sh
is_user_root ()
{
    [ "$(id -u)" -eq 0 ]
}

Alternatively, in Bash, more performance-driven coders might want to use:

#!/bin/bash
is_user_root ()
{
    [ "${EUID:-$(id -u)}" -eq 0 ]
}

Note that I intentionally wrapped the code in functions for re-use.

To address your second issue:

how can I improve its security to avoid the problem of giving superuser privileges to commands which don't need them when running the script with sudo?

You can't do much about this. At least nothing comes to my mind. If I saw the script, I might have suggestions. But since you did not include it in your question... If you run the whole script with sudo or as root, I see no way to control this.

To address the comment:

What do you think of "use sudo inside it vs run it with sudo"

In my scripts, I usually proceed with the latter approach, but that does not necessarily mean I recommend it to you. Because it depends on who the script is meant for - for root only; for user mostly with the exception of having some users having sudo rights; you would have to literally include your script into the question for me to be able to answer with any value.

  • sudo -u "$SUDO_USER" command...? – Michael Homer Nov 01 '18 at 06:10
  • Thanks. What do you think of "use sudo inside it vs run it with sudo"? – Tim Nov 01 '18 at 11:21
  • Thanks. Would this simple approach have the best of of both approaches: add sudo to commands which only need it, and run the script with or without sudo depending on whether I want convenience or security? Does this approach have some problem? – Tim Nov 01 '18 at 12:58
  • @MichaelHomer I was wondering what sudo -u "$SUDO_USER" command is supposed to mean here? – Tim Nov 01 '18 at 13:00
  • @Tim Though I don't find any problem with that approach, someone might object with reasonable arguments. This is really out of the scope of your original question. I need to do my monthly M-Disc backup now, so I don't think to be available yet today, sorry for that. I hope I did answer the main point at least. See you tomorrow. – Vlastimil Burián Nov 01 '18 at 13:10
  • Or the more readable one would be [ "$(whoami)" == "root" ]... . Unless anything wrong with it? – aderchox Nov 12 '21 at 08:59
  • 1
    @aderchox Actually there is something wrong with what you mentioned. I cannot put it inside a comment, so if interested, please read up or below my answer here on SO – Vlastimil Burián Nov 12 '21 at 11:17
-4

I think I can answer this.

So should I use the second way?

There is no reason why you should have a problem here, this is why:

If there is only one command that needs to be run as root, then run your program as root or sudo because sudo inside your script is the longer road. Have you forgotten that programmers are lazy?

If you need many commands run as root then run it as root or sudo.

how can I improve its security to avoid the problem of giving superuser privileges to commands which don't need them when running the script with sudo?

If other users need to run your program then setup sudo for those because sudo is a lot customizable and will fulfill your needs.

Here's an example with sudo:

Always use visudo when editing the sudoers file.....

kate ALL=(ALL) NOPASSWD: /usr/local/bin/script ARG1 ARG2

sudo is also great for changing users inside your program/script here's a line from one of mine scripts:

sudo -i -u "$user" user="$user" CURRENTDIR="$CURRENTDIR" BASHRC="$BASHRC" bash <<'EOF'

how can I write "script would detect if it was running with the right permissions and not call sudo at all"?

https://www.cyberciti.biz/tips/shell-root-user-check-script.html
how-do-i-determine-if-a-shell-script-is-running-with-root-permissions

bash/sh:

#!/bin/bash
# (Use #!/bin/sh for sh)
if [ `id -u` = 0 ] 
then
        echo "I AM ROOT, HEAR ME ROAR"
fi

csh:

#!/bin/csh
if ( `id -u` == "0" ) 
then
        echo "I AM ROOT, HEAR ME ROAR"
endif

#!/bin/bash
if [[ $EUID -ne 0 ]]; then
  echo "You must be a root user" 2>&1
  exit 1
else
  mount /dev/sdb1 /mnt/disk2
fi

EDIT by request from the gentleman @terdon:

Think of your script this way....

Is it a public script(other people than you will use it) What does the script do? Does it tell you the time? Or does it update iptables on 200 systems? If only you use it, is it work/professional related or is it for personal use?

You just have to know in advance what your user-group consists of, that's it.

If it is written to give or sell to admins, even then, why shouldn't the script be allowed to run as root?? What harm can it do?

Real scripts/programs run often as the privileged user and no one mentions that thats no problem, but when programmers, mostly novices like me talk about these things, then it's a real security threat..... what the guy in your post you refer to is trying to say while not elegantly is that some people look at the control you have of the system and your code.... do you set files to more permissions than you are going to use, do you have all the checks in your logic or is talented programmer going to see dangers in your code just glancing at it?

If your code needs root, use sudo, and if there are many just run it as root....... my answer ends here phew

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
  • 2
    @somethingSomething could you explain why you are recommending always running the script as root, even when there is only a single command that needs root privileges? You give two possibilities in your answer (one command requiring root privileges or multiple) but you suggest the same thing for both of them. – terdon Nov 01 '18 at 09:26
  • 2
    I have thought about this issue and read other similar discussions. This answer just confuses me. (But, you have enough down votes already.) – Joe Nov 03 '18 at 09:43