Changing user in bash script - bash

I wanted to create an installation script for my raspberry pi which secures the default installation by configuring/hardening ssh, installing a firewall and fail2ban and finally to get rid off the default user of Raspbian. All other parts work but the final part always shows me an error.
The new user is created and added to the sudo group. After that I want to delete the old user 'pi'. As the script runs with sudo in the user context of 'pi' I thought I could solve this by switching to 'su' but I just get an error that the user couldn't be deleted as it is used by a process:
echo "Enter the new user name? Only lower case letters allowed!"
read user
sudo adduser $user && adduser $user sudo
echo "default user 'pi' will now be deleted"
su -c "deluser -remove-home pi"
If I check with 'users' the user 'pi' is gone but I can still log in with this account. How can I solve this problem inside the script?
I tried the answers I found here: How do I use su to execute the rest of the bash script as that user? and here: https://unix.stackexchange.com/questions/361327/how-to-login-as-different-user-inside-shell-script-and-execute-a-set-of-commands but nothing seem to work. I searched Google but I can't find any solution that works. Is it even possible what I'm trying to?

I usually add set -eux at the beginning of the bash script. This allows to debug and find typos and errors.
Try to switch user inside the script with
sudo -i -u ${user} $(command to delete pi here)

Think i found the cause of the problem. 'set -eux' was a great help:
deluser pi
Removing user `pi' ...
Warning: group `pi' has no more members.
userdel: user pi is currently used by process 445
/usr/sbin/deluser: `/usr/sbin/userdel pi' returned error code 8. Exiting.
I tried ps -fu pi to find the process which causes the trouble: it's /lib/systemd/systemd --user Is there a way to stop this process inside the script?

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.

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.)

Running interactive Bash commands over ssh

I am trying to automate my server provisioning process using chef. Since I don't want to run chef as root, I need a chef/deployer user. But I don't want to create this user manually. Instead, I want to automate this step. So I took a shot at scripting it but ran into an issue:
The problem is that if I run
>ssh root#123.345.345.567 '/bin/bash -e' < ./add_user.sh
where add_user contains
//..if the username doesnt exist already
adduser $USERNAME --gecos ''
I never see the output or the prompts of the command.
Is there a way to run interactive commands in this way?
Is there a better way to add users in an automated fashion?
Try this:
ssh -t root#<ipaddress> adduser $USERNAME --gecos
Not sure why you have a $ in the IP address in your original example - that's likely to cause ssh to fail to connect, but since you didn't indicate that sort of failure, I'm assuming that's just a typo.
Since add_user.sh is just a simple command, there's no need for the added complexity of explicitly running bash or the redirection, just run the adduser command via ssh.
And lastly, since $USERNAME is likely defined on the local end, and not on the remote end, even if you could get your original command to "do what you said", you'd end up running adduser --gecos on the remote end, which isn't what you intended.
Try using :
ssh -t root#$123.345.345.567 '/bin/bash -e' < ./add_user.sh
instead.

In a bash script executed on boot, how do I get the username of the user just logged-in?

I need to execute a bash script on boot.
To do so I created a file
/etc/init.d/blah
I edited it and added the following lines
#! /bin/sh
# /etc/init.d/blah
touch '/var/lock/blah'
username1=$(id -n -u)
username2=$(whoami)
touch '/var/lock/1'${username1}
touch '/var/lock/2'${username2}
exit 0
The script is execute with root privileges (which is what I need because I have to use mount inside this script) .. but the problem is that I also need to know the username of the user who has just logged-in beacuse my goal is to mount a certain folder to a certain mount-point depending on the username, like
mount -o bind /home/USERNAME/mount-point /media/data/home/USERNAME/to-be-mounted
Going back to the boot script, if I do
sudo update-rc.d blah defaults
and then reboot and log-in with my username (let's say john) both ways to get username in my script produce root in fact I've got 3 files
/var/lock/blah
/var/lock/1root
/var/lock/2root
So, how can I get the username of the user who just logged-in? (john in my example)
EDITED:
I solved in this way:
1. I created a .desktop file for each user I need to perform automount on boot to autostart a script on boot (I'm on LXDE) and put it on /home/{username}/.config/autostart
[Desktop Entry]
Type=Application
Exec=bash "/path/to/mount-bind.sh"
2. I stored in that path a bash script called mount-bind.sh and made it executable:
#!/bin/bash
_username=$1
if [[ -z "${_username}" ]]; then
_username="$(id -u -n)"
fi
mkdir -p "/home/${_username}/mount-folder"
sudo mount -o bind "/media/data/home/${_username}/mount-folder" "/home/${_username}/mount-folder"
exit 0
3. I added the following line to /etc/sudoers
%nopwd ALL=(ALL) NOPASSWD: /bin/mount
4. I created the nopwd group and added to it all the users I need
In his way after login I can mount the path under the user home.
Problem with this method is that I have to create the desktop file for each new user and add him/her to nopwd, but it works.
Any further improvement is welcome! :)
I think you should move from a boot time init script to a script executed at login time under the logged-in user. To allow this, you should look into ways to allow your users to execute the mount command you need. Depending on what you are trying to achieve, one of the following methods may help you:
Assuming you are on Linux or some other UNIX with a similar feature, add the mountpoint to /etc/fstab with the user option, allowing normal users to mount the entry.
Execute mount through sudo with a suitably narrow sudoers configuration as to not allow users to execute any mount commands.
Write a suid-root program in c which executes the required mount commands when called. This however is very tricky to get right without creating gaping security holes.
Login does not happen at boot time. You cannot foretell which user is going to log in when booting.
Try Exporting the logindetails and use it.
export username2=$(whoami)

Resources