Allow user to run a command with arguments (which contains spaces)

I want to allow one user to run grep (through sudo), and to grep for one specific string in one specific file. I don’t want to allow this user to be able to run grep on all files. The user doesn’t have read access to the file, hence the requirement to use sudo. I am trying to write a nagios check which greps the log file of another service on the machine.

However it doesn’t work, sudo keeps asking for a password.

My command is: sudo grep "string I want (" /var/log/thefilename.log (yes, there is a raw ( and some spaces in the string I want to grep)

/etc/sudoers.d/user-can-grep has this content:

user ALL=(root) NOPASSWD: /bin/grep "string I want (" /var/log/thefilename.log

This sudoers file is owned by root:root and has permissions -r--r-----

The server is Ubuntu trusty 14.04.3 LTS.

How can I make this work?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

  1. Write a script (writeable only by root)
  2. In that script, execute the grep you need
  3. In the sudoers config, allow only access to that script
  4. Configure whatever tool or advise whichever user to just run the script via sudo

Much easier to debug, easier to lock down specific access to a specific file, and much harder to exploit.

Solution 2

Apparently, sudo flattens the command into a string before comparing it to a specification in the sudoers file. So, in your case, you don’t need to use quotes or any other form of escaping:

user ALL=(root) NOPASSWD: /bin/grep string I want ( /var/log/thefilename.log

Edit: As @user23013 points out in the comments, this can be exploited to grep for “string I want” in any file (and, by extension, also for “string I” and “string”.) Please make a careful consideration before using sudo’s argument checking!


Also note that the following invocations are equivalent, i.e. you won’t be able to restrict users to one specific representation:

sudo grep "string I want (" /var/log/thefilename.log
sudo grep 'string I want (' /var/log/thefilename.log
sudo grep string\ I\ want\ \( /var/log/thefilename.log

This is due to the fact that quotes and escaping is handled by the shell and never reach sudo.

Solution 3

Since you only need root for the file access, consider using cat, tee or something similar and piping that to grep or whatever program you need to run. E.g. sudo cat /file/path | grep … This way you restrict root to where you absolutely need it.

Solution 4

sudo is great, but sometimes it is not the best fit. For this I like to use super. super also allows elevated permissions, however it assumes command aliases, which is convenient when allowing complicated command lines, because they are used as simple command lines.

your super.tab would look like:

grepcmd "grep 'string I want (' /var/log/thefilename.log" user

and would be invoked as super grepcmd.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply