0

I am making a desktop application for Linux that interacts with some Ubuntu system files. As such, during the end-user's installation of my software, I need to generate a file in /etc/sudoers.d/ giving a number of scripts access to the system files without knowing the password. The user will input there password during the installation, but after that they shouldn't have to. During the installation, they will run give-sudo.sh which contains the following lines of Bash code:

echo '$USER ALL=(ALL) NOPASSWD: power_off.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: reboot.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: timeout_moss.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: timeout_default.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: set_next_os.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: boot_os_1.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: boot_os_2.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: give_sudo.sh' >> /etc/sudoers.d/moss-priv

It is supposed to create a file called moss-priv, and append the lines necessary to make my scripts run without requiring a password. I have 8 scripts, so I append 8 lines of code. The echo commands work fine, moss-priv is generated and its contents read:

$USER ALL=(ALL) NOPASSWD: power_off.sh
$USER ALL=(ALL) NOPASSWD: reboot.sh
$USER ALL=(ALL) NOPASSWD: timeout_moss.sh
$USER ALL=(ALL) NOPASSWD: timeout_default.sh
$USER ALL=(ALL) NOPASSWD: set_next_os.sh
$USER ALL=(ALL) NOPASSWD: boot_os_1.sh
$USER ALL=(ALL) NOPASSWD: boot_os_2.sh
$USER ALL=(ALL) NOPASSWD: give_sudo.sh

This is when the issue occurs. Instead of giving password-less sudo to the scripts, it prints a stack trace saying an error occurred at each line (1-8). Not only that, but if I try to call sudo for any reason, it says "authorization failed" and stack traces. As such, I completely lost sudo access and couldn't even go back to delete the file that was causing this issue. I ended up having to re-install the whole operating system just to get it back to normal.

Now that I have sudo back, I am ready to try it again as soon as I figure out what is wrong with the moss-priv file. I can't figure it out though, I think it looks good. Help?

I would be happy with a solution to this problem or a good alternative method.


Error:

\>>> /etc/sudoers.d/moss-priv: syntax error near line 1 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 2 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 3 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 4 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 5 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 6 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 7 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 8 <<<
\sudo: parse error in /etc/sudoers.d/moss-priv near line 1
\sudo: no valid sudoers sources found, quitting
\sudo: unable to initialize policy plugin1\\

UPDATE: Going off of the suggested fixes, I have a file give_sudo.sh:

echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/power_off.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/reboot.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/timeout_moss.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/timeout_default.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/set_next_os.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/boot_os_1.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/boot_os_2.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/give_sudo" >> /etc/sudoers.d/moss-priv

And one of the scripts, say timeout_moss.sh:

sudo sed -i 's/GRUB_HIDDEN_TIMEOUT=10/GRUB_HIDDEN_TIMEOUT=0.01/g' /etc/default/grub

When I run it, with bash timeout_moss.sh (when I am in the current directory) it still asks for my password... why?

5
  • 1
    For future reference: I think one can use Ubuntu installer as a live system ("Try Ubuntu" or so). From inside the live system it's possible to mount the disk and remove the troublesome file. This emergency solution should be faster than installing from scratch. Feb 10, 2020 at 6:28
  • There is no sudo in bash timeout_moss.sh. The relevant line you added allows to run sudo ./timeout_moss.sh … (or equivalent with e.g. full path). Does it work? Neither sudo sed … nor sudo bash … matches. This is a separate issue. The original question was about parse errors and IMO it was solved. The new issue is different and if my comment is not enough then you should ask a new question (and rollback the current one to a form without the extra issue). From the new question you can link to this one to provide context, still the new one should be standalone. One issue – one question. Feb 11, 2020 at 5:17
  • But if sudo /home/jeremiahdgage/Desktop/MOSS/timeout_moss.sh still asks for password then the original issue is not solved and we should fix it first. Maybe unless it turns out this is not (or never was) what you wanted. Compare this dilemma: Should I use sudo in a script or sudo an entire script? Feb 11, 2020 at 5:22
  • My original question was not about parse errors, someone else edited the title. MY original issue was figuring out how do I give a script sudo access without requiring a password. Your answer did not fix this. I will start a new question, because the focus I think has went off the original issue. With the title change and focus delineation, I think your question is a sufficient solution. Not the solution I was looking for, but still super helpful. Thanks. Feb 11, 2020 at 16:01
  • The title was changed to help other users with similar problems find your question. To test if you have given "a script sudo access without requiring a password", run sudo -k /home/jeremiahdgage/Desktop/MOSS/timeout_moss.sh. I realized there may be other conditions. One of them is if the script is executable. See the edited answer (first hint). A feedback from you saying that sudo /home/jeremiahdgage/Desktop/MOSS/timeout_moss.sh still requires a password would make me investigate further. But the feedback included sudo sed and bash timeout_moss.sh, these are off the original issue. Feb 11, 2020 at 19:07

2 Answers 2

4
echo '$USER ALL=(ALL) NOPASSWD: power_off.sh' >> /etc/sudoers.d/moss-priv

After this the file does not look fine. You need to provide the fully qualified file name (below I assume /sbin/power_off.sh). In addition $USER in single quotes is not expanded, it gets to the file as literal $USER; I guess this is not what you want. Use double quotes and specify the full path:

echo "$USER ALL=(ALL) NOPASSWD: /sbin/power_off.sh" >> /etc/sudoers.d/moss-priv

The line in the file will look like:

kamil ALL=(ALL) NOPASSWD: /sbin/power_off.sh

Hints:

  • This will not work if /sbin/power_off.sh is not executable. Make it executable with chmod.
  • Make sure $USER expands as you expect. If your installation script is run with sudo then you will probably need $SUDO_USER (see man 8 sudo). In any case it's advised to check if the expanded value looks sane before you write to the file.
  • Use here document (with unquoted word because you want $SUDO_USER expanded) to write to the file in a more elegant manner. This example will create the file anew:

    cat >/etc/sudoers.d/moss-priv <<EOF
    $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/power_off.sh
    $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/reboot.sh
    $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/timeout_moss.sh
    $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/timeout_default.sh
    $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/set_next_os.sh
    $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/boot_os_1.sh
    $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/boot_os_2.sh
    $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/give_sudo.sh
    EOF
    
  • Note sudoers allows you to specify an entire directory (by its full path, it should begin with / and end with /). Move the scripts to a dedicated directory and you will need to add just one line to /etc/sudoers.d/moss-priv. But then if you need your tools to be reachable via PATH, remember sudo can use a separate PATH.
  • In your tests open an elevated shell first (e.g. sudo su -) and keep it open all the time. Test in a regular shell if sudo works after changes. If you lose sudo access, use the elevated shell to fix the problem (in your case removing /etc/sudoers.d/moss-priv should do).
  • If working remotely, in your tests use tmux or screen as a regular user and open the elevated shell from there. This way even if you temporarily lose connection in the most critical moment when you're going to fix the sudo access, the shell will survive. You will be able to jump into the elevated shell without sudo just by reattaching to tmux/screen.
3
  • Yes, the path is wrong...I had the files in the same folder as give_sudo.sh, so I thought that was the full path. I wasn't considering that when I write the file, the path needs to be read from the new location. I am going to try out your solution and see how it goes. Feb 10, 2020 at 6:12
  • No errors, but it still asks for my password. Any ideas why? ill edit my post with the new file/data Feb 10, 2020 at 23:47
  • Thanks for the comments so far, I added an update. Feb 10, 2020 at 23:52
-2

Try with double quotes:

echo "$USER ALL=(ALL) NOPASSWD: power_off.sh" >> /etc/sudoers.d/moss-priv

So that $USER variable will be replaced with its contents. Single quotes prevent variables from being interpreted.

1
  • This is not the reason the OP lost sudo access. Fixing the quotes alone will not help at all; the OP will get parse error again. Fixing the other problem (see my answer to know it) alone won't do what the OP wants but sudo will stay operable. I have tested these cases. Feb 10, 2020 at 6:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .