Remember root password throughout script using Bash - bash

Background
I have a long bash script which setup a large environment of interconnected software, taking several hours to complete. A few of the tasks it performs need to be run as root, for which I use sudo .... The whole process is then paused until the user notices and types in the root password. I seek some way for the user to type in the root password only at the beginning of the script, and then automatically supply it when required by sudo later.
My thoughts on possible (bad) solutions
I could store the password directly in a variable and then supply it using
echo "${root_password}" | sudo -S ...
but something tells me that this is bad practice.
Another workaround would be to force the user to run the entire script as root, but wouldn't that lead to different permissions for all of the files generated without the use of sudo?

You can prompt it at the start of your script, so it is not plain text hard saved.
Example:
#!/bin/bash
read -s -p "[sudo] sudo password for $(whoami): " pass
echo $pass | sudo -S apt-get update
help read:
-r do not allow backslashes to escape any characters
-s do not echo input coming from a terminal

I suggest you figure out all of the commands you need the script to run using SUDO, ensure the script is run by a special unprivileged user (e.g. scriptuser), and then edit /etc/sudoers to permit scriptuser to run those commands with NOPASSWD
As an example:
scriptuser ALL = NOPASSWD: /bin/kill, /usr/bin/othercommand, etc.
If you know the complete commands, including arguments, that's ideal (it means that an attacker that compromises the scriptuser account can only run those specific commands as root)
Sudo has a lot of options configurable in /etc/sudoers. If you man sudoers , you should see all of them. Forewarning: This man page is very hard to understand. Find examples. Test them. Ask on StackExchange.

Related

Running sudo in shell script

I am just creating a little script which changes mac address. Everytime I run it i have to enter sudo password. How to allow script to enter password or skip sudo verification?
OR is there another way to create this script?Maybe use python?
So here is my script:
#!/bin/bash
nmcli radio wifi off
sudo macchanger wlp6s0 -a
nmcli radio wifi on
What you want to do is modify the sudoers file to allow the user running the script access to a specific command without having to enter a password.
See this answer for more information: https://askubuntu.com/questions/334318/sudoers-file-enable-nopasswd-for-user-all-commands
In short, call visudo and add the following entry:
your_user ALL=(ALL) NOPASSWD:/path/to/the/binary/macchanger wlp6s0 -a
Of course, exchange /path/to/the/binary/macchanger with the true path, found by running which macchanger.
Now the user your_user can run that single command with those exact arguments via sudo without password.
Also, as Cyrus pointed out, man is your friend. It's a good idea to always check the manpages first. More often than not you're going to find the answer to your question by reading it and trying some ideas. In this case: man visudo and man sudo.conf.
Instead of playing around with sudo and risking giving full root
access to programs that may act irresponsibly you can set
cap_net_admin on the binary:
sudo setcap cap_net_admin+ep "$(command -v macchanger)"
It's just one-time operation. Now you can remove sudo from your
script and it will work.
Maybe use python?
No, that wouldn't help. Language doesn't matter. It's kernel that
allows or forbids performing certain operations.

How to run command as another user

I have a shell script that makes a few calls to Asterisk at some point and shows some output. Calling Asterisk is the first thing I have tried that seems not to work. I determined the user I setup to run the script didn't have the permissions to run Asterisk, so I looked at ways to run it as root which would get around that (the only other user on the system).
I tried using su with no luck. For the past two hours, I've been messing with sudo and sudoers and not been able to get it working.
For example, here is some code called in my script, run by the user com:
printf "\n"
calls=`sudo "asterisk -rx 'core show channels'" | grep "active call"`
lastinboundcaller=`cat /var/log/asterisk/lastcaller.txt`
printf '%s\n' "Current Call Count: $calls"
printf '%s\n' "Last Inbound Caller: $lastinboundcaller"
Output:
[sudo] password for com:
sudo: asterisk -rx 'core show channels': command not found
Current Call Count:
Last Inbound Caller: Unknown
There are two problems here,
It's prompting for a password. Why it's prompting for the current user's password rather than the root password, I have no idea, but it shouldn't prompt for any password at all.
The Asterisk command asterisk -rx "command" is still not working — in other words, it's still failing to run the Asterisk shell, though it should have permission.
I tried updating my sudoers file and creating a new file in /etc/sudoers.d titled asterisk as well and putting my command in there.
My latest modification to that file was:
com ALL = (ALL:ALL) NOPASSWD: /usr/sbin/asterisk
Before that, I tried:
com ALL = (root) NOPASSWD: /usr/sbin/asterisk
My understanding is this should allow the user com to execute asterisk as sudo without a password. Clearly, something is not working.
I have followed the answers to numerous similar SO posts, like:
Use sudo without password INSIDE a script
https://unix.stackexchange.com/questions/18877/what-is-the-proper-sudoers-syntax-to-add-a-user
Unfortunately, despite following all the answers I've been able to find on this issue, none have worked for me.
Can anyone point me in the right direction here or suggest an alternative? I already consulted a Linux expert and this seems to be the right approach. This is all super easy to do in Windows and I'm surprised it's all this convoluted in Linux.
Don't quote the argument to sudo. It expects the first argument to be the name of the command, so it thinks the whole command line is the program name.
It should be
calls=`sudo asterisk -rx 'core show channels' | grep "active call"`
Why it's prompting for the current user's password rather than the root password, I have no idea, but it shouldn't prompt for any password at all.
That's how sudo works. It prompts for the current user's password, and checks /etc/sudoers to see if they're allowed to run the command. You're thinking of su, which prompts for the root password.

Disable sudo password for specific user login

I have a bash script that executes some PostgreSQL as
sudo -i -u postgres psql <<EOF > /dev/null
--SQL CODE
EOF
The sudo asks me for a password for the current user and I'd like to disable that. I don't want to provide a password inside the script through sudo -S. I know I can disable the password for sudo using visudo, however I need to specify the command for which to disable it (I don't want to disable it globally). How do I disable the sudo password for sudo -i -u postgres ?
You probably like a line in the sudoers file as follows:
script_user ALL = (postgres) NOPASSWD: /usr/bin/psql
The individual items in the line are as follows:
script_user: the (standard) user which uses the bash script (i.e., your user account)
ALL: special variable, here at the position where it indicates all hosts. You could try and limit this to e.g. localhost if you want
(postgres): user to run the command(s) as. That is, the user specified by the -u option
NOPASSWD: special variable indicating that the following command does not require a password (for this combination of user, sudo user and host, of course)
/usr/bin/psql: the specific command allowed. This could also be a comma-separated lists of commands, or ALL. (Obviously the path may be different on your machine.)
Related questions and answers on StackOverflow are a bit scattered and don't appear to fully answer your specific question, but I've come across an overall nice write-up on this topic by Abhijit Menon-Sen, which I found clearer to read than the various man pages on sudo & friends.

Login to su and take the password from the same script

I'm trying to automate the build process which is done on linux server.
to do that first i need to login to the su and then perform the tasks for stopping and starting the server. I've written shell script to do that but there are some problems I'm facing,
1) even though I'm providing password from script using expect & send it tasks for password on terminal.
2) doing echo'password' | sudo -S su takes password automatically but says wrong even if it is right.
3) and when i put the password through terminal manually using su I get logged in to the su but the rest of the commands in script does not gets executed unless i do exit.
The script I've tried is,
echo 'password\n' | sudo -S su ##it says wrong password for su
commands to be performed after logging to su
exit
I've tried expect and send too,
su expect"Password" send "password\n";
and rest of the code here
but it's not fetching password from send automatically, I've to put it manually.
I would really appreciate if someone can help me with this!!
sudo requires the password of the user calling it, not the password of the superuser (or the user specified by the -u option). That may seem backwards, but the idea is that sudo can be configured to provide fine-grained control over what you are actually allowed to run as the superuser, rather than giving you access to the superuser account itself. Also, sudo keeps a log of who does what for auditing purposes.
If you used the wrong password, use the right password instead. Like others have already commented, sudo requires your password, not root's.
Additionally, your script is wrong. The sequence su; echo hello; exit will run a root shell with su, then when that shell exits, run echo hello and exit in your current shell.
You want this instead:
sudo -S sh -c 'echo hello'
The su is completely superfluous because sudo already takes care of switching to the root user, and offers a more convenient syntax for running commands as another user to boot. The sh -c '...' isn't strictly required in this example, but will probably be useful if you have more than one command which you wish to execute using elevated privileges. (Make sure you understand the implications. A useful commandment is to try to run even less code as sudo than you currently do. Always.)

Writing a bash script that performs operations that require root permissions

I'm trying to write a bash script that sets up my web development environment in ubuntu. As part of the process of setting up the script, it needs to edit files that are owned by root. It also needs to create fields in the public_html directory of the user that runs the script.
Should I therefore require that the script be run as the superuser? If it should, then how do I get it to access the current user's username? I would normally use the $USER variable, but I can't do that if the script is being run as the superuser. If I'm not the superuser, how can I get the script to request super user privileges for certain operations, while not requiring the user to type in a password for every operation that requires super user privileges.
Thanks
You can use the -E flag for sudo to preserve the environment variables, or, you can set up sudoers to preserve the environment on a per-command basis.
You can also set up the sudoers file to not ask for a password on a per-command basis, for example, to allow user xy to use smbmount without asking for a password:
xy ALL=NOPASSWD: /usr/bin/smbmount
In your case, it would be enough to just store the current user in a variable before invoking sudo, and use the already saved username:
CURRENT_USER=$USER
sudo yourscript.sh $CURRENT_USER
Then read the username from $1.
You can also use the SUDO_USER env variable, which is set to the user who is invoking sudo.
Insert a check at the top of the script:
# Make sure only root can run this script
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2
exit 1
fi
In this way when you run it without the root privileges you will be prompted, then you can simply rerun it the right way with:
sudo yourscript.sh
More infos at http://www.cyberciti.biz/tips/shell-root-user-check-script.html
There's a command named sudo for this purpose. It lets you specify that certain users can run certain commands as root (or another user).
If your users have root access anyway, you could just write a script that must be run as root and takes an username as parameter, instead of picking up the username.
Alternatively, one way of picking up the login username in an interactive shell is:
stat -Lc %U /proc/self/fd/0
This retrieves the ovner of the tty associated with stdin.
Just make it a setuid file. Or use sudo which is probably safer, since you can limit who gets to run it.
chmod 4755 script.sh
In Ubuntu, there's the SUDO_USER environment variable.
So, you can just run your script sudo somescript.sh and have it pull the invoking user's username $SUDO_USER.
Not sure on other dists, though.

Resources