Script to check if user belongs to sudo group - linux

I think I'm fairly close to checking if a user belongs to the sudo group in Ubuntu, then add a line to the sudoers file. Except when I look in the sudoers file, I see:
$IDUSER ALL=NOPASSWD: /usr/local/sbin/myscript
instead of that users name, eg.
bob ALL=NOPASSWD: /usr/local/sbin/myscript
Here is what I have:
#! /bin/sh
set -e
IDUSER=$(grep -Po '^sudo.+:\K.*$' /etc/group)
if [ `id -u $IDUSER 2>/dev/null || echo -1` -ge 0 ]; then
echo '$IDUSER ALL=NOPASSWD: /usr/local/sbin/myscript' >> /etc/sudoers
else
echo "Script failed..."
fi
Ideally, I'd like to add all users in the sudo group to the sudoers file.
Thank you.

In single quotes ', bash variables don't get expanded. Use double quotes " instead in the line with echo.
If you're just trying to let users in the group sudo run this command, though, just add the line:
%sudo ALL=NOPASSWD: /usr/local/sbin/myscript
to the /etc/sudoers file. The % sign denotes a group, here.

Related

Create sudo users from script? [duplicate]

This question already has answers here:
How do I edit /etc/sudoers from a script?
(14 answers)
Closed 2 years ago.
Normally one uses visudo to edit /etc/sudoers and perhaps add a line similar to this one
kirk ALL=(spock) NOPASSWD: ALL
which will allow the kirk user to become spock.
Question
I need to create a non-interactive Bash script that will allow user1, user2, user3 to become spock.
Does anyone knows how to do that?
visudo honors EDITOR env var which defines the editor program to use.
Thus, you can use sed as editor, tell sed to read commands from STDIN (-f-) and pass the changes to the whole visudo/sed pipline via STDIN.
Example:
echo '$ a # comment' | EDITOR="sed -f- -i" visudo
This will add '# comment' line to the end of sudoers file.
($ instructs sed to append the line to the end of file, 'a' is the command to append followed by the line).
In order to add a sudoer, you will need something like
echo '$ a kirk ALL=(spock) NOPASSWD: ALL' | EDITOR="sed -f- -i" visudo
Note that visudo also does syntax check so it will fail if the command produces broken sudoers file:
root#chi:~# echo '$ a broken directive' | EDITOR="sed -f- -i" visudo
>>> /etc/sudoers: syntax error near line 44 <<<
P.S. Tested with GNU sed 4.2.2. There may be problems with e.g. Busybox sed.
Since you want to allow multiple users to be able to sudo as spock , I'd recommend adding User_Alias in you sudoers file (/etc/sudoers) for all users who can become spock
Please note, I'm using a dummy file sudoers.test in place of my /etc/sudoers for this example, it should work fine with /etc/sudoers as well.
$ cat sudoers.test
User_Alias USERS_SPOCK = kirk,bob
USERS_SPOCK ALL=(spock) NOPASSWD: ALL
Once that is done you can use something like the add_users bash script below to add users to this file.
$ cat add_users
#!/bin/env bash
#
# Usage:
# add_users User_Alias users [users]
#
# change it to /etc/sudoers
SUDOERS_FILE=sudoers.test
# read args to an array
IFS=', ' read -r -a arg_array <<< "$#"
# alias to add users to
alias_name=${arg_array[0]}
# array of users to add to the list
new_users=${arg_array[#]:1}
# Find the specified alias and the users associated with that alias
IFS=', ' read -r -a current_users <<< $(grep "User_Alias $alias_name" $SUDOERS_FILE | sed -e "s/User_Alias $alias_name = //g")
[ "${#current_users[#]}" = "0" ] && echo "ERR: No Users found for User_Alias: $alias_name" && exit 1
echo "== LOG.INFO Users currently in User_Alias $alias_name: ${current_users[#]} -- (${#current_users[#]} users)"
echo "== LOG.INFO New Users to be added to User_Alias $alias_name: ${new_users[#]} -- (${#new_users[#]} users)"
# All only users not currenltly there in sudoers file.
for user in ${new_users[#]}; do
if [[ ! " ${current_users[#]} " =~ " $user " ]]; then
current_users+=($user)
echo "== LOG.DEBUG Adding user '$user' to User_Alias $alias_name"
else
echo "== LOG.WARN Skipping user '$user': already part of User_Alias $alias_name"
fi
done
echo "== LOG.INFO After update Users in User_Alias $alias_name: ${current_users[#]} -- (${#current_users[#]} users)"
all_users=$(echo ${current_users[#]} | tr ' ' ',')
# Update the current sudoers file
sed -i "s/User_Alias $alias_name = .*$/User_Alias $alias_name = $all_users/g" $SUDOERS_FILE
[ "$?" = "0" ] && echo "== LOG.INFO Sudoers updated successfully." || echo "== LOG.ERR Some error occured while updating Sudoers."
echo "== LOG.INFO Verifying sudoers file post edit"
visudo -c $SUDOERS_FILE
$ ./add_users USERS_SPOCK alice andrew
== LOG.INFO Users currently in User_Alias USERS_SPOCK: kirk bob -- (2 users)
== LOG.INFO New Users to be added to User_Alias USERS_SPOCK: alice andrew -- (1 users)
== LOG.DEBUG Adding user 'alice' to User_Alias USERS_SPOCK
== LOG.DEBUG Adding user 'andrew' to User_Alias USERS_SPOCK
== LOG.INFO After update Users in User_Alias USERS_SPOCK: kirk bob alice andrew -- (4 users)
== LOG.INFO Sudoers updated successfully.
== LOG.INFO Verifying sudoers file post edit
sudoers.test: parsed OK
$
$ cat sudoers.test
User_Alias USERS_SPOCK = kirk,bob,alice,andrew
USERS_SPOCK ALL=(spock) NOPASSWD: ALL
$
After these changes are made in /etc/sudoers as root.
Any of the member of User Alias USERS_SPOCK can run any command as spock
alice$ sudo -u spock <random command>
alice$ sudo -u spock <my awesome script>

(Linux-Bash) Create an account for each user and add the user to its group from a text file [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have a username.txt which contains their username and specific group. As of right now i'm trying to create a bash script which allows me to create an account for each user and add the user to its group in one command.
this is currently my failed bash script(i know pretty much everything is wrong but i hope you guys got a clear idea on it):
#!/bin/bash
sudo addgroup staff
sudo addgroup visitors
username="username.txt"
while read line; do
sudo useradd $-Eo '^[^,]+' $username;
if [grep staff $username]; then
sudo usermod -a -G staff
else
sudo usermod -a -G visitors
done < $username
This is what is inside my username.txt file:
ellipsiscoterie,visitor
magnetcommonest,visitor
belateddefensive,staff
bobstercaramelize,staff
Let's go through your script.
#!/bin/bash
sudo addgroup staff
sudo addgroup visitors
username="username.txt"
OK. There is some debate about using sudo in scripts, but I'm not against it.
while read line; do
You read the line from STDIN, which is your input file. The variable line contains ellipsiscoterie,visitor in the first iteration.
sudo useradd $-Eo '^[^,]+' $username;
$- prints The current set of options in your current shell. It will produce something like himBH. The next argument seems a regular expression, and the last argument is the filename that you use. So the command here is:
sudo useradd himBHEo '^[^,]+' username.txt
Hint: if you are unsure of the arguments, check with an echo (echo $-Eo '^[^,]+' $username) before you add them to a sudo-ed command.
This is not what you want. First, you probably want to use the variable line instead of username. Why would you otherwise loop through that file?
Second, read-up on variable expansion in bash. For now, try:
line=ellipsiscoterie,visitor
echo ${line%,*}
echo ${line#*,}
So the line would probably need to be:
sudo useradd ${line%,*}
if [grep staff $username]; then
This is wrong in almost everything.
the [ and ] require spaces to set them apart
but you dont want to do a test, you want to see if the grep succeeds, so the [ and ] are not needed anyway
you are again using the complete file. So the grep succeeds if there is any line with staff in it; even if the username would be johnfalstaff
What you really want to know is if the second column in your line is staff, so:
if [ "${line#*,}" = "staff" ] ; then
sudo usermod -a -G staff
else
sudo usermod -a -G visitors
So, where is the fi that closes the if statement?
done < $username
Also, quote the filename: done < "$username"
You can use awk to write it in one line. In this case, awk splits each row into different columns and you can access each field separately.
awk -F "," '{ if(system("grep -q -E "$2" /etc/group") != 0 ){system("groupadd "$2)}; system("useradd "$1" -G "$2)}' username.txt
The first argument (-F ",") defines the field-separator, but it could be also something else e.g. ";" or "/"
The part if(system("grep -q -E "$2" /etc/group") != 0 ) verifies if the group exist and if not, the part {system("groupadd "$2)} creates the group before the next command system("useradd "$1" -G "$2) creates the user and adds it to the group $2.
It's possible to simplify the command to remove the if part, but then you will get a warning message that the user already exists.
awk -F "," '{ system("groupadd "$2); system("useradd "$1" -G "$2)}' username.txt
groupadd: group 'visitor' already exists
groupadd: group 'staff' already exists
btw: the part system executes just an operating system command
The newusers command allows you to configure users from a file in batch:
https://www.man7.org/linux/man-pages/man8/newusers.8.html

Unix: 'su user' not working and remains root inside SSH if condition [duplicate]

I've written a script that takes, as an argument, a string that is a concatenation of a username and a project. The script is supposed to switch (su) to the username, cd to a specific directory based upon the project string.
I basically want to do:
su $USERNAME;
cd /home/$USERNAME/$PROJECT;
svn update;
The problem is that once I do an su... it just waits there. Which makes sense since the flow of execution has passed to switching to the user. Once I exit, then the rest of the things execute but it doesn't work as desired.
I prepended su to the svn command but the command failed (i.e. it didn't update svn in the directory desired).
How do I write a script that allows the user to switch user and invoke svn (among other things)?
Much simpler: use sudo to run a shell and use a heredoc to feed it commands.
#!/usr/bin/env bash
whoami
sudo -i -u someuser bash << EOF
echo "In"
whoami
EOF
echo "Out"
whoami
(answer originally on SuperUser)
The trick is to use "sudo" command instead of "su"
You may need to add this
username1 ALL=(username2) NOPASSWD: /path/to/svn
to your /etc/sudoers file
and change your script to:
sudo -u username2 -H sh -c "cd /home/$USERNAME/$PROJECT; svn update"
Where username2 is the user you want to run the SVN command as and username1 is the user running the script.
If you need multiple users to run this script, use a %groupname instead of the username1
You need to execute all the different-user commands as their own script. If it's just one, or a few commands, then inline should work. If it's lots of commands then it's probably best to move them to their own file.
su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME"
Here is yet another approach, which was more convenient in my case (I just wanted to drop root privileges and do the rest of my script from restricted user): you can make the script restart itself from the correct user. This approach is more readable than using sudo or su -c with a "nested script". Let's suppose it is started as root initially. Then the code will look like this:
#!/bin/bash
if [ $UID -eq 0 ]; then
user=$1
dir=$2
shift 2 # if you need some other parameters
cd "$dir"
exec su "$user" "$0" -- "$#"
# nothing will be executed beyond that line,
# because exec replaces running process with the new one
fi
echo "This will be run from user $UID"
...
Use a script like the following to execute the rest or part of the script under another user:
#!/bin/sh
id
exec sudo -u transmission /bin/sh - << eof
id
eof
Use sudo instead
EDIT: As Douglas pointed out, you can not use cd in sudo since it is not an external command. You have to run the commands in a subshell to make the cd work.
sudo -u $USERNAME -H sh -c "cd ~/$PROJECT; svn update"
sudo -u $USERNAME -H cd ~/$PROJECT
sudo -u $USERNAME svn update
You may be asked to input that user's password, but only once.
It's not possible to change user within a shell script. Workarounds using sudo described in other answers are probably your best bet.
If you're mad enough to run perl scripts as root, you can do this with the $< $( $> $) variables which hold real/effective uid/gid, e.g.:
#!/usr/bin/perl -w
$user = shift;
if (!$<) {
$> = getpwnam $user;
$) = getgrnam $user;
} else {
die 'must be root to change uid';
}
system('whoami');
This worked for me
I split out my "provisioning" from my "startup".
# Configure everything else ready to run
config.vm.provision :shell, path: "provision.sh"
config.vm.provision :shell, path: "start_env.sh", run: "always"
then in my start_env.sh
#!/usr/bin/env bash
echo "Starting Server Env"
#java -jar /usr/lib/node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-2.40.0.jar &
#(cd /vagrant_projects/myproj && sudo -u vagrant -H sh -c "nohup npm install 0<&- &>/dev/null &;bower install 0<&- &>/dev/null &")
cd /vagrant_projects/myproj
nohup grunt connect:server:keepalive 0<&- &>/dev/null &
nohup apimocker -c /vagrant_projects/myproj/mock_api_data/config.json 0<&- &>/dev/null &
Inspired by the idea from #MarSoft but I changed the lines like the following:
USERNAME='desireduser'
COMMAND=$0
COMMANDARGS="$(printf " %q" "${#}")"
if [ $(whoami) != "$USERNAME" ]; then
exec sudo -E su $USERNAME -c "/usr/bin/bash -l $COMMAND $COMMANDARGS"
exit
fi
I have used sudo to allow a password less execution of the script. If you want to enter a password for the user, remove the sudo. If you do not need the environment variables, remove -E from sudo.
The /usr/bin/bash -l ensures, that the profile.d scripts are executed for an initialized environment.

How to correctly secure this Bash Script? (Sudo)

I wanted to make this Script kinda Secure, so it cannot be direct exploited.
I have a Bash file called Test.sh, I gave a User Sudo rights on it:
user ALL=(root) NOPASSWD: /home/user/Test.sh
So the User has full Sudo permission to this file.
Next Step was to ensure that the User cannot edit this file with:
chown root:root /home/user/Test.sh
chmod u=rwx,g=rwx,o=rx /home/user/Test.sh
The File for example contains this Command
if [ "$1" = "run" ]; then
sudo -u ${2} ${3};
fi
OR
`sudo cp -R /home/test/test/${2}/* /home/${3}/test/
useradd ${2} -r -d /home/${2} -s /bin/bash
userdel -r ${2}
Basically the User could even Login as root and fuck things up.
So my first thought was, lets check if the Home folder exists like that:
if [ -d "/home/$2" ] && [ "$2" != "" ]; then
Which would prevent such things like run crap as root and only let them log into th other users like i want. Or do i think wrong?
I would also check that the Command begins with /home/....
grep '^/home/....' $3
So, is that enought? or Not? I guess I should filter also ;

How to make a script run commands as root

I'm new to Ubuntu and bash scripts, but I just made runUpdates.sh and added this to my .profile to run it:
if [ -f "$HOME/bin/runUpdates.sh" ]; then
. "$HOME/bin/runUpdates.sh"
fi
The problem I'm having is, I want the script to run as if root is running it (because I don't want to type my sudo password)
I found a few places that I should be able to do sudo chown root.root <my script> and sudo chmod 4755 <my script> and when I run it, it should run as root. But it's not...
The script looks good to me. What am I missing? -rwxr-xr-x 1 root root 851 Mar 23 21:14 runUpdates.sh*
Can you please help me run the commands in this script as root? I don't really want to change the sudors file, I really just want to run the commands in this script at root (if possible).
#!/bin/sh
echo "user is ${USER}"
#check for updates
update=`cat /var/lib/update-notifier/updates-available | head -c 2 | tail -c 1`;
if [ "$update" = "0" ]; then
echo -e "No updates found.\n";
else
read -p "Do you wish to install updates? [yN] " yn
if [ "$yn" != "y" ] && [ "$yn" != "Y" ]; then
echo -e 'No\n';
else
echo "Please wait...";
echo `sudo apt-get update`;
echo `sudo apt-get upgrade`;
echo `sudo apt-get dist-upgrade`;
echo -e "Done!\n";
fi
fi
#check for restart
restartFile=`/usr/lib/update-notifier/update-motd-reboot-required`;
if [ ! -z "$restartFile" ]; then
echo "$restartFile";
read -p "Do you wish to REBOOT? [yN] " yn
if [ "$yn" != "y" ] && [ "$yn" != "Y" ]; then
echo -e 'No\n';
else
echo `sudo shutdown -r now`;
fi
fi
I added the user is to debug, it always outputs my user not root, and prompts for the sudo password (since I'm calling the commands with sudo) or tells me are you root? (if I remove sudo)
Also, is there a way to output the update commands stdout in real time, not just one block when they finish?
(I also tried with the shebang as #!/bin/bash)
setuid does not work on shell scripts for security reasons. If you want to run a script as root without a password, you can edit /etc/sudoers to allow it to be run with sudo without a password.
To "update in real time", you would run the command directly instead of using echo.
Its not safe to do, you should probably use sudoers but if you really need/want to, you can do it with something like this:
echo <root password> | sudo -S echo -n 2>/dev/random 1>/dev/random
sudo <command>
This works because sudo doesn't require a password for a brief window after successfully being used.
SUID root scripts were phased out many years ago if you really want to run scripts as root you need to wrap them in an executable, you can see an example on how to do this on my blog:
http://scriptsandoneliners.blogspot.com/2015/01/sanitizing-dangerous-yet-useful-commands.html
The example is how to change executable permissions and place a filter around other executables using a shell script but the concept of wrapping a shell script works for SUID as well, the resulting executable file from the shell script can be made SUID.
https://help.ubuntu.com/community/Sudoers

Resources