Simple Bash question about "sudo -u <user>"

Guys, this has been driving me crazy: As far as I know, sudo -u <user> can be used in a script that is being run as sudo in order to “cancel out” the sudo, hence run the line that follows as the regular user <user>. Only it doesn’t seem to me to be working like this, at least not in the context below: it’s as if sudo -u <user> doesn’t do anything!

Here’s the context: I got two small Bash scripts, a master.sh script, and a slave.sh script:

master.sh:

#!/bin/bash

# Run as root/sudo.
if [ ! $(id -u) == 0 ]
then
  echo "This script should be run as root! Exiting ..."
  exit
fi

sudo -u dad /home/dad/Downloads/slave.sh

slave.sh:

#!/bin/bash

if [[ ! -v DOTNET_ROOT ]] # If variable is not set ...
then
  echo "DOTNET_ROOT needs to be set ..."
else
  echo "No need to set DOTNET_ROOT."
fi

Here’s what happens:

dad@DadsGram~/Downloads $ echo $DOTNET_ROOT
/home/dad/.dotnet
dad@DadsGram~/Downloads $ ./slave.sh 
No need to set DOTNET_ROOT.
dad@DadsGram~/Downloads $ sudo ./master.sh 
DOTNET_ROOT needs to be set ...
dad@DadsGram~/Downloads $ sudo ./slave.sh 
DOTNET_ROOT needs to be set ...

What am I doing wrong please?

dad@DadsGram~/Downloads $ echo $DOTNET_ROOT
/home/dad/.dotnet
dad@DadsGram~/Downloads $ ./slave.sh
No need to set DOTNET_ROOT.
dad@DadsGram~/Downloads $ sudo ./master.sh
DOTNET_ROOT needs to be set …
dad@DadsGram~/Downloads $ sudo ./slave.sh
DOTNET_ROOT needs to be set …

What am I doing wrong please?

This is a security policy from sudo, please try:

sudo mkdir /etc/sudoers.d
echo “Defaults env_keep += "DOTNET_ROOT"” | sudo tee /etc/sudoers.d/env_keep-DOTNET_ROOT.conf

To add your DOTNET_ROOT environment variable to env_keep.

2 Likes

There is the sudo --preserve-env option. I have seen the -E option used recently and checked the man page.

-E, -‐preserve‐env
        Indicates to the security policy that the user wishes  to  pre‐
        serve  their existing environment variables.  The security pol‐
        icy may return an error if the user does not have permission to
        preserve the environment.

--preserve‐env=list
        Indicates to the security policy that the user  wishes  to  add
        the comma‐separated list of environment variables to those pre‐
        served  from  the  user’s environment.  The security policy may
        return an error if the user does not have  permission  to  pre‐
        serve  the  environment.  This option may be specified multiple
        times.

Testing:

$ export HI=there
$ sudo --preserve-env sh -c 'echo $HI'
there
$ sudo --preserve-env=HI sh -c 'echo $HI'
there

Something like this in the master script.

sudo --preserve-env=DOTNET_ROOT -u dad /home/dad/Downloads/slave.sh
1 Like

Looks like this isn’t working for me:

dad@DadsGram~/Downloads $ cat master.sh 
#!/bin/bash

# Run as root/sudo.
if [ ! $(id -u) == 0 ]
then
  echo "This script should be run as root! Exiting ..."
  exit
fi

sudo --preserve-env=DOTNET_ROOT -u dad /home/dad/Downloads/slave.sh
dad@DadsGram~/Downloads $ echo $DOTNET_ROOT
/home/dad/.dotnet
dad@DadsGram~/Downloads $ sudo ./master.sh 
DOTNET_ROOT needs to be set ...

Try also, -E or --preserve-env=VAR option with the initial sudo command.

$ sudo -E /tmp/master.sh 
No need to set DOTNET_ROOT.

master.sh

#!/bin/bash

# Run as root/sudo.
if [ ! $(id -u) == 0 ]
then
  echo "This script should be run as root! Exiting ..."
  exit
fi

sudo --preserve-env=DOTNET_ROOT -u dad /home/dad/Downloads/slave.sh
1 Like

Thanks, will try the -E option. However, if I run master with the -E option, will I still need to run slave with —preserve-env?

Yes, necessary to preserve the DOTNET_ROOT environment variable.

1 Like

Thanks, that works. To recap, both changes need to be made: slave needs to be run with the --preserve-env=DOTNET_ROOT prefix, and master needs to be run with the -E option.

Otherwise, I am sure that @miguelinux’s solution works fine as well, but I was hoping to not have to mess with the sudoers.d file, as I am hoping to keep my interventions in the bowels of CL rather limited.

Concerning the sudoers file in /usr/share/defaults/sudo…
If you want, create the folder /etc/sudoers.d/ and just cp /usr/share/defaults/sudo/sudoers file to that new folder. Then you can make changes to sudoers in the /etc/ stage which is not part of the stateless Clear Linux stuff.

2 Likes

Just to be super clear, you need either -E or --preserve-env=DOTNET_ROOT, but for both. -E means “preserve all my environment variables” (potential security risk), while --preserve-env=DOTNET_ROOT means “only preserve $DOTNET_ROOT”, which is all you actually need to preserve. Just use the same option for both scripts.

2 Likes

Has anyone tried @miguelinux solution? It does not work on Clear Linux, even though /usr/share/defaults/sudo/sudoers has @includedir /etc/sudoers.d.

I have not :blush: : I’m entirely happy with the sudo --preserve-env solution. I don’t really want to force my luck. :grin: