3

At the moment I'm working on a solution to prevent all admins users (except one particular) from running sudo. I can add a specific user to sudoers by running:

sudo -i
echo '$username  ALL=(ALL:ALL) ALL' >> /etc/sudoers

Then I'd like to remove %admin ALL = (ALL) ALL within sudoers file which would just leave the above admin as the only sudo admin. However I cannot seem to find a way on how to remove/replace a particular string within sudoers.

I'd like to make this into a script hence using visudo and manually adjusting won't work for me. If there a way to run visudo from script and adjust a particular line within sudoers that would be ideal, but I couldn't find anything when researching on the Web.

I've seen a solution here:

which works in Linux. Is it possible to make it work in macOS?

  • At first glance the solution on the linked page should also work in macOS. Can you add some details on where/how exactly it fails? Also, as this is basically a "how do I delete a specific line from a text file with a script" type of question, what other kind of research have you already done – nohillside Jun 2 at 8:27
  • PS: I won't go on to list the various ways how any admin user not part of sudoers can easily get their sudo rights back... – nohillside Jun 2 at 8:28
  • PPS: But you may want to use double quotes instead of single quotes in your echo statement above :-) – nohillside Jun 2 at 8:29
2

Here's an alternate method. Lines are not added or deleted from the sudoers file. The line giving admin root rights is commented out and we create a separate file with mac_admin's rights in the directory /etc/sudoers.d. And as a bonus, the original sudoers file is backed up.

printf '%s\n' 'mac_admin  ALL=(ALL:ALL) ALL' > /tmp/99-macadmin

visudo -c -f /tmp/99-macadmin &&
install -o 0 -g 0 -m 440 /tmp/99-macadmin /etc/sudoers.d

sed $'s/%admin\t/# %admin/' /etc/sudoers > /tmp/sudoers

visudo -c -f /tmp/sudoers &&
install -B .orig -b -o 0 -g 0 -m 440 /tmp/sudoers /etc/sudoers

rm /tmp/sudoers /tmp/99-macadmin
  • Impressive! I was not aware that's an option as my bash skills are incredibly lacking. I'll test this and let you know if it works - very interested to implement this solution as it sounds much safer than editing the actual sudoers like you said. Many thanks for your time! – merkeesox Jun 2 at 16:10
  • That worked as you described - I was just thinking however, what would a script look like to reverse this change. Would it include renaming the edited script to .orig and .orig to default? Apologies as I am just doing my best learning bash, however there might be a time when there might be a need to revert to original without doing a file any direct intervention and using Jamf Pro policy instead. I would imagine a policy for applying this change with the script you have so kindly written and a reversal policy which would could be scoped to appropriate machines and undo changes. – merkeesox Jun 2 at 19:28
  • 1
    I've just realised I can just delete the edited script and rename the .orig back to default instead, sorry! That was silly of me. – merkeesox Jun 2 at 19:51
3

For what it's worth, you can use

printf '/^%%admin ALL = (ALL) ALL$/d\nw\nq\n' | ed -s sudoers

or, if you want to catch the line independent of the number of space characters, tabs etc used

printf '/^%%admin[[:blank:]]*ALL[[:blank:]]*=[[:blank:]]*(ALL)[[:blank:]]*ALL$/d\nw\nq\n' | ed sudoers 

in bash to remove the admin line (the double %% are required to prevent printf from interpreting them as formatting instructions).

The usual caveats about editing sudoers without relying on the syntax checks done by visudo apply. So it might be safer to run the following, or at least have another root shell running so you can fix any issues without getting locked out)

cp /etc/sudoers /tmp
chmod +w /tmp/sudoers
printf '/^%%admin[[:blank:]]*ALL[[:blank:]]*=[[:blank:]]*(ALL)[[:blank:]]*ALL$/d\nw\nq\n' \
    | ed /tmp/sudoers
if visudo -c -f /tmp/sudoers; then
    echo "All well"
    mv -f /tmp/sudoers /etc/sudoers
    chmod -w /etc/sudoers
else
    echo "Uups, something went wrong"
fi

(Script untested, because I don't want to mess with my sudoers file)

  • I've tested the above script and it may indeed work with some adjustment as the echo returns "All well" however, I believe it isn't removing that particular line still as I've checked sudoers file and %admin is still present. The return code is Running script Test - edit sudoers... Script exit code: 0 Script result: 2111 ? /tmp/sudoers: parsed OK All well – merkeesox Jun 2 at 9:29
  • @merkeesox Please add your sudoers file to the question then, so it‘s easier to verify what is going wrong. – nohillside Jun 2 at 10:01
  • 1
    @merkeesox Try again. BUT: currently no additional users besides root are enabled for sudo, so make sure you don’t lock yourself out! – nohillside Jun 2 at 10:50
  • That's okay, I've got the root account enabled and when I log in I can edit it back to its original values without affecting ownership and permissions of sudoers file. I'll try that now. – merkeesox Jun 2 at 10:54
1

Amazing! It worked! Thank you very much! @nohillside

I'll add a line above that to add a user mac_admin before the script executes so the final version should look like this.

echo 'mac_admin  ALL=(ALL:ALL) ALL' >> /etc/sudoers

cp /etc/sudoers /tmp
chmod +w /tmp/sudoers
printf '/^%%admin.*ALL = (ALL) ALL$/d\nw\nq\n' | ed /tmp/sudoers
if visudo -c -f /tmp/sudoers; then
    echo "All well"
    mv -f /tmp/sudoers /etc/sudoers
    chmod -w /etc/sudoers
else
    echo "Uups, something went wrong"
fi

Just FYI I am running this script by scoping it to my machine on Jamf Pro so it excecutes via a recurring check-in policy.

You must log in to answer this question.

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