3

I have made a shell script to write /etc/sudoers.d/aptget -file but it is breaking the sudo if an alias is already defined in /etc/sudoers or in any file in /etc/sudoers.d/. I am using visudo to edit the files but it does not catch the error as it seems to check only the file currently being edited.

Previously I added following manually into /etc/sudoers

Cmnd_Alias APTGETUPDATE = /usr/bin/apt-get update *
Cmnd_Alias APTGETINSTALL = /usr/bin/apt-get -y --force-yes install *

%aptgroup ALL = (root) NOPASSWD: APTGETUPDATE, APTGETINSTALL
Defaults!APTGETUPDATE !requiretty
Defaults!APTGETINSTALL !requiretty

Everything worked great. Making a script to write a into /etc/sudoers.d/aptget or adding above manually into it passes visudo check but causes sudo to not function.

script.sh:

#!/bin/bash

updaterSudoers="$(cat <<EOF
Cmnd_Alias APTGETUPDATE = /usr/bin/apt-get update *
Cmnd_Alias APTGETINSTALL = /usr/bin/apt-get -y --force-yes install *

%aptgroup ALL = (root) NOPASSWD: APTGETUPDATE, APTGETINSTALL
Defaults!APTGETUPDATE !requiretty
Defaults!APTGETINSTALL !requiretty
EOF
)"

echo "$updaterSudoers" | (EDITOR="tee -a" visudo -f /etc/sudoers.d/aptget)

error:

>>> /etc/sudoers: Alias `APTGETUPDATE' already defined near line 31 <<<
>>> /etc/sudoers: Alias `APTGETINSTALL' already defined near line 31 <<<
sudo: parse error in /etc/sudoers near line 31
sudo: no valid sudoers sources found, quitting
sudo: unable to initialize policy plugin

Lines from 31 onwards in sudoers:

31  Cmnd_Alias APTGETUPDATE = /usr/bin/apt-get update *
32  Cmnd_Alias APTGETINSTALL = /usr/bin/apt-get -y --force-yes install *
33  
34  %aptgroup ALL = (root) NOPASSWD: APTGETUPDATE, APTGETINSTALL
35  Defaults!APTGETUPDATE !requiretty
36  Defaults!APTGETINSTALL !requiretty
  • You need to check if APTGETUPDATE is defined in /etc/sudoers file before writing (ex: using grep APTGETUPDATE /etc/sudoers and check output) also for /etc/sudoers.d/*. – F.Igor Oct 5 '16 at 13:25
1

Temporarily including the original sudoers file and clearing the old file seemd to do the trick.

includeCurrent=$'#include /etc/sudoers\n'
echo "$includeCurrent$updaterSudoers" | visudo -c -q -f -

Whole sudoers.sh I ended up having.

#!/bin/bash

#Clear the current file if it exsists 
#Warning: this might break stuff if you edit current user visudo rights
if [[ -f "/etc/sudoers.d/aptget" ]]
then
  echo -n > "/etc/sudoers.d/aptget"
fi

#New settings to be added
updaterSudoers="$(cat <<EOF
Cmnd_Alias APTGETUPDATE = /usr/bin/apt-get update *
Cmnd_Alias APTGETINSTALL = /usr/bin/apt-get -y --force-yes install *

%aptgroup ALL = (root) NOPASSWD: APTGETUPDATE, APTGETINSTALL
Defaults!APTGETUPDATE !requiretty
Defaults!APTGETINSTALL !requiretty
EOF
)"

#Include current sudoers file
includeCurrent=$'#include /etc/sudoers\n'

#Validate new settings with current settings
echo "$includeCurrent$updaterSudoers" | visudo -c -q -f -
if [ "$?" -eq 0 ]
then
  #Write /etc/sudoers.d/aptget with updateSudoers value
  echo "$updaterSudoers" | (EDITOR="tee" visudo -f /etc/sudoers.d/aptget) &> /dev/null
else
  #Yell and exit in case of error
  echo "ERROR CHECKING SUDOERS FILE:"
  echo "$includeCurrent$updaterSudoers" | visudo -c -f -
  exit 1
fi

#If sudoers.d or sudoers.d/aptget is not included include only sudoers.d/aptget
grep -xq "#includedir /etc/sudoers\.d/\?" /etc/sudoers || grep -xq "#include /etc/sudoers\.d/aptget" /etc/sudoers
if [ "$?" -eq 1 ]
then
  echo "#include /etc/sudoers.d/aptget" | (EDITOR="tee -a" visudo -f /etc/sudoers) &> /dev/null
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.