Create sudo users from script? [duplicate] - linux

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>

Related

(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

Bash read -p doesnt work [duplicate]

This question already has answers here:
': not a valid identifier [duplicate]
(4 answers)
Why would a correct shell script give a wrapped/truncated/corrupted error message? [duplicate]
(1 answer)
Closed 5 years ago.
When running my shell script I get this error:
': not a valid identifiere 17: read: `
Here is my shell script:
#!/usr/bin/env bash
# Mr. Robot Install Wordpress Script
# Script is used for the following:
# add user to server
# change to new user home directory
# download latest version of wordpress
# unzip wordpress
# move all files up a directory level
# move up a directory level
# delete wordpress.zip
# remove wordpress folder
echo "/*****************************************************/"
echo "/************** HELLO MR. ROBOT **********************/"
echo "/*****************************************************/"
echo ".."
echo ".."
echo "Website URL"
echo 'url: \r'
read -p $website
echo 'User: \r'
read -p $newuser
echo 'Pass: \r'
read -p $password
echo "creating account......"
/scripts/wwwacct $website $newuser $password 0 x3 n n n 0 0 0 0 0 0
echo "Changing Directory....."
cd ~/home/$newuser/
echo "Getting Latest Version of Wordpress!"
curl -O http://wordpress.org/latest.tar.gz
echo "Tarball Incoming!!"
tar xvzf latest.tar.gz
echo "removing tar file"
rm latest.tar.gz
echo "moving wordpress folders!"
cp -a ~/home/$newuser/public_html/wordpress/. ~/home/$newuser/public_html/
cd /home/$newuser/public_html/
echo "Part 01 Complete!!"
exit
I've tried to use different versions of the read line with -p or -e. Any help would be appreciated. I've even tried adding it on a separate line with input.
EDIT: Updated file to where it takes inputs, but issue is that the inputs are not being used through the rest of the script. Thus causing errors for directories not being found.
Don't quote the variables names. read needs the name of the variable to assign to, not its value, which is what you get if you have a dollar sign $.
read -p 'website url: ' website
read -p 'Username: ' newuser
read -p 'Password: ' password
It looks like one of the variables holds \r, a carriage return. The error message that bash is trying to print is something like:
bash: ./script: line 17: read: `\r': not a valid identifier
But \r causes the cursor to go back to the beginning of the line, causing ': not a valid identifier to overwrite the beginning of the message.
As mentioned above by John Kugelman, in case you have to check if you Input_file is having carriage returns then you could run following command:
cat -v Input_file
In case you find them then try to remove them from either of following cmmands:
tr -d '\r' < Input_file
OR
awk '{gsub(/\r/,"")} 1' Input_file
Or check if your system(box) has dos2unix utility you could use that also for removing these carriage returns.

Script to check if user belongs to sudo group

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.

Why can't this script execute the other script

This script looks for all users that have the string RECHERCHE inside them. I tried running it in sudo and it worked, but then stopped at line 8 (permission denied). Even when removing the sudo from the script, this issue still happens.
#!/bin/bash
#challenge : user search and permission rewriting
echo -n "Enter string to search : "
read RECHERCHE
echo $(cat /etc/passwd | grep "/home" | cut -d: -f5 | grep -i "$RECHERCHE" | sed s/,//g)
echo "Changing permissions"
export RECHERCHE
sudo ./challenge2 $(/etc/passwd) &
The second script then changes permissions of each file belonging to each user that RECHERCHE found, in the background. If you could help me figure out what this isn't doing right, it would be of great service. I
#!/bin/bash
while read line
do
if [-z "$(grep "/home" | cut -d: -f5 | grep -i "$RECHERCHE")" ]
then
user=$(cut -f: -f1)
file=$(find / -user $(user))
if [$(stat -c %a file) >= 700]
then
chmod 700 file 2>> /home/$(user)/challenge.log
fi
if [$(stat -c %a file) < 600]
then
chmod 600 file 2>> /home/$(user)/challenge.log
fi
umask 177 2>> /home/$(user)/challenge.log
fi
done
I have to idea what I'm doing.
the $(...) syntax means command substitution, that is: it will be replaced by the output of the command within the paranthesis.
since /etc/passwd is no command but just a text-file, you cannot execute it.
so if you want to pass the contents of /etc/passwd to your script, you would just call it:
./challenge2 < /etc/passwd
or, if you need special permissions to read the file, something like
sudo cat /etc/passwd | ./challenge2
also in your challenge2 script, you are using $(user) which is wrong as you really only want to expand the user variable: use curly braces for this, like ${user}
/etc/passwd?
not what you were asking, but you probably should not read /etc/passwd directly anyhow.
if you want to get a list of users, use the following command:
$ getent passwd
this will probably give you more users than those stored in /etc/passwd, as your system might use other PAM backends (ldap,...)

Write script to create multiple users with pre-defined passwords

So I would like to make a script that create users from users.txt running
useradd -m -s /bin/false users_in_the_users.txt
and fill the password from passwords.txt twice (to confirm the passwords)
This is the script
#!/bin/bash
# Assign file descriptors to users and passwords files
exec 3< users.txt
exec 4< passwords.txt
exec 5< passwords.txt
# Read user and password
while read iuser <&3 && read ipasswd <&4 ; do
# Just print this for debugging
printf "\tCreating user: %s with password: %s\n" $iuser $ipasswd
# Create the user with adduser (you can add whichever option you like)
useradd -m -s /bin/false $iuser
# Assign the password to the user, passwd must read it from stdin
passwd $iuser
done
The problem is, it does not fill the passwords. And 1 more thing, I want the script to fill the passwords twice.
Any suggestions?
You have to supply the password on stdin. Replace:
passwd $iuser
with:
passwd "$iuser" <<<"$ipasswd
$ipasswd"
or, as suggested by mklement0:
passwd "$iuser" <<<"$ipasswd"$'\n'"$ipasswd"
The incantation <<< creates a here-string. The string that follows the <<< is provided as standard in to the command which precedes the <<<. In this case we provide the two copies of the password that the passwd command wants.
(The script reads these passwords from a plain text file. I will assume that your situation is some special case for which this is not as dangerous as it normally would be.)
John1024's answer is the correct one - his warning about reading passwords from plain-text files bears repeating.
Let me show the solution in context, without the file-descriptor acrobatics (exec 3<, ...):
#!/bin/bash
# NOTE: Be sure to run this script with `sudo`.
# Read user and password
while read iuser ipasswd; do
# Just print this for debugging.
printf "\tCreating user: %s with password: %s\n" $iuser $ipasswd
# Create the user with adduser (you can add whichever option you like).
useradd -m -s /bin/false $iuser
# Assign the password to the user.
# Password is passed via stdin, *twice* (for confirmation).
passwd $iuser <<< "$ipasswd"$'\n'"$ipasswd"
done < <(paste users.txt passwords.txt)
paste users.txt passwords.txt reads corresponding lines from the two files and puts them on a single line, separated with \t.
The result is piped to stdin via a process substitution (<(...)).
This allows read to read from a single source.
$\n is an ANSI C-quoted string that produces a (literal) newline.
#! /bin/bash
for i in {1..100}
do
`sudo mkdir -p /root/Desktop/userm$i`
`sudo useradd -m -d /root/Desktop/userm$i -s /bin/bash userm$i`
echo "userm$i:userm$i" | chpasswd
done
this will create 100 users. user name will be (userm1-userm100). home directory will be /root/Desktop/(userm1-user100)
password will be (userm1-userm100)
Instead of using this line:
useradd -m -s /bin/false $iuser
Try this one:
useradd -m -s /bin/false -p $ipasswd $iuser
You don't actually need this:
passwd $iuser <<< "$ipasswd"$'\n'"$ipasswd"
Kindly run the below script.
#!/bin/bash
#purpose: bash script to create multiple users with pre-defined passwords at once.
#Read_Me: The import file should be in two columns, first users name and second passwords.
#author: Bablish Jaiswal
#contact: linux.cnf#gmail.com
read -p "Kindly import/type Users Name-password file with location:- " creation_info
cat $creation_info |while read i p
do
( useradd $i && echo -e "${p}\n${p}" | passwd $i ) > /dev/null 2>&1 && echo $user ${i} created and password is ${p} || echo ${i} failed
done

Resources