Drop from root to user preserving ALL environment variables - bash

The following bash command works to drop down to user privileges, and preserve an environment for the most part:
root#machine:/root# DOLPHIN=1 sudo -E -u someuser bash -c 'echo $DOLPHIN'
1
However, this does not work for all variables, such as PATH, and LD_LIBRARY_PATH:
root#machine:/root# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
root#machine:/root# sudo -E -u someuser bash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
Notice the PATH is different ^
Why is this happening?
Must be some bash mechanics I don't understand...

Looks like this is a workable option:
root#machine:/root# sudo PATH=$PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH -E -u someuser bash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

Related

How not to terminate after carried out commands in bash

After carrying out commands with "-c" option of bash, how can I make the terminal wait for input while preserving the environment?
Like CMD /K *** or pwsh -NoExit -Command ***.
From a comment by Cyrus:
You can achieve something similar by abusing the --rcfile option:
bash --rcfile <(echo "export PS1='> ' && ls")
From bash manpage:
--rcfile file
Execute commands from file instead of the system wide initialization file /etc/bash.bashrc and the standard personal initialization file ~/.bashrc if the shell is interactive
This is the answer I was looking for. Thank you!!
As an example of use, I use the following method to use the latest docker image with my preferred repository without building the image:
# Call bash in the container from bash
docker run --rm -it ubuntu:22.04 bash -c "bash --rcfile <(echo 'sed -i -E '\''s%^(deb(-src|)\s+)https?://(archive|security)\.ubuntu\.com/ubuntu/%\1http://mirrors.xtom.com/ubuntu/%'\'' /etc/apt/sources.list && apt update && FooBar=`date -uIs`')"
# ... from pwsh
docker run --rm -it ubuntu:22.04 bash -c "bash --rcfile <(echo 'sed -i -E '\''s%^(deb(-src|)\s+)https?://(archive|security)\.ubuntu\.com/ubuntu/%\1http://mirrors.xtom.com/ubuntu/%'\'' /etc/apt/sources.list && apt update && FooBar=``date -uIs``')"
# Call dash (BusyBox ash) in the container from bash
docker run --rm -it alpine:latest ash -c "ash -c 'export ENV=\$1;ash' -s <(echo 'sed -i -E '\''s%^https?://dl-cdn\.alpinelinux\.org/alpine/%https://ftp.udx.icscoe.jp/Linux/alpine/%'\'' /etc/apk/repositories && apk update && FooBar=`date -uIs`')"
# ... from pwsh
docker run --rm -it alpine:latest ash -c "ash -c 'export ENV=`$1;ash' -s <(echo 'sed -i -E '\''s%^https?://dl-cdn\.alpinelinux\.org/alpine/%https://ftp.udx.icscoe.jp/Linux/alpine/%'\'' /etc/apk/repositories && apk update && FooBar=``date -uIs``')"

Executing sudo command in bash script without displaying it

I'm executing a command with sudo from bash script, and I'm wondering how to prevent sudo from displaying anything on the screen
echo "mypassword" | sudo -S cp -u /scripts/.bashrc ~/ > /dev/null 2>&1
The result will be an output displaying: [sudo] password for username:
I want to hide that output..
now, before the first comment;
This isn't the safest way, since you're entering your password into the script, but this is strictly internal servers.
Run sudo --help, we can get answer from the parameter list:
-p, --prompt=prompt use the specified password prompt
Then,
echo "mypassword" | sudo -S --prompt="" cp -u /scripts/.bashrc ~/ > /dev/null 2>&1
may do the trick.

Mac terminal : trying to add to /etc/shells

This one works
$ cat /etc/shells
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.
/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
But this one does not :
sudo -s 'echo /usr/local/bin/zsh >> /etc/shells'
/bin/bash: echo /usr/local/bin/zsh >> /etc/shells: No such file or directory
sudo takes the string as complete command. You should use a shell to interpret your command like this:
sudo sh -c 'echo /usr/local/bin/zsh >> /etc/shells'
This executes sh with root privileges, and sh interprets the string as a shell command including >> as output redirection.
The only thing you really need sudo for is to open the protected file for writing. You can use the tee command to append to the file.
echo /usr/local/bin/zsh | sudo tee -a /etc/shells > /dev/null

mkdir: missing operand when doing sudo over ssh

I am trying to create directory with sudo user permission over SSH.
Here is the command i formed
some_command "ssh -t userA#host bash -c \"\'sudo -u userB bash -c \" mkdir -p /home/userB/dir_to_create \" \'\" "
here some_command is part of expect script.
I am getting this error :-
[sudo] password for userB:
mkdir: missing operand
Try `mkdir --help' for more information.
Connection to host closed.
If i run
sudo -u userB bash -c "mkdir /home/userB/dir_to_create"
it works.
ssh -t user#host "bash -c \"sudo -u otherUser bash -c 'mkdir -p /home/userB/dir_to_create'\""
should work
Based on comment from Mark Plotnick , i figured out the answer .
Here is the solution to it
spawn bash -c "ssh -t userA#host \"sudo -u userB bash -c 'mkdir -p /home/userB/perf_tools' \" "
Trick is that , single quote and double quote placements make all the magic happen in this script.

sudo -i doesn't work anymore with specific permissions through sudoers file

I had a bash script which called sudo -i -u user /bin/bla/whatever. That worked fine until the last update to CentOS 5.8.
That's the corresponding entry in the sudoers file:
Runas_Alias TEST = user1, user2
Defaults:test always_set_home
test ALL=(TEST) NOPASSWD: /bin/bash -c /bin/bla/whatever, /bin/bla/whatever
If I used sudo -i it seems it called the command
"/bin/bash -c /bin/bla/whatever"
(regarding the secure log). Now, since the update, it seems to call
"/bin/bash -c \/bin\/bla\/whatever"
and therefore is not allowed to. I tried to change the line in the sudoers file to
test ALL=(TEST) NOPASSWD: /bin/bash -c /bin/bla/whatever, /bin/bla/whatever, /bin/bash -c \/bin\/bla\/whatever
but thats not allowed syntax, so I tried:
test ALL=(TEST) NOPASSWD: /bin/bash -c /bin/bla/whatever, /bin/bla/whatever, /bin/bash -c \\/bin\\/bla\\/whatever
That's valid syntax but doesn't work either.
If I use sudo -H -u user /bin/bla/whatever it works fine. Even if I allow /bin/bash in the sudoers file, but that would allow anything.....
Any ideas?
Erik
Just checked the sudo man page on my fedora 16 system and it says:
-i [command]
The -i (simulate initial login) option runs the shell specified by the password database entry of the target user as a login shell. This means
that login-specific resource files such as .profile or .login will be read by the shell. If a command is specified, it is passed to the shell
for execution via the shell's -c option.
So it does not appear to be necessary to specify bash -c in your sudoers command definition.
If you call the command as sudo -i /bin/bla/whatever you should need nothing more than the following in your sudoers file:
test ALL=(TEST) NOPASSWD: /bin/bla/whatever
I can reproduce the problem on my fedora 16 system, no changes to the sudoers file I tried had any effect. I cannot find any other configuration required to make this work. All I can say is to use '-H -u ...'.
Were you running sudo -i -u user /bin/bla/whatever with arguments? From man sudoers:
A simple file name allows the user to run the command with any arguments he/she wishes. However, you may also specify command line arguments (including wildcards). Alternately, you can specify "" to indicate that the command may only be run without command line arguments.
So once you add in the /bin/bash -c you are now specifying arguments and they must match exactly.
Here's an example sudoers line:
test ALL=(ALL) NOPASSWD: /bin/bash -c /bin/true, /bin/bash -c /bin/true *, /bin/true *
With that I can do:
sudo /bin/true
sudo /bin/true foo
sudo -u /bin/true
sudo -u /bin/true foo
But not sudo true because that becomes bash -c true which does not match bash -c /bin/true.

Resources