Don't do this.
You're giving the
sudo-user the ability to run any commands as any user. That includes the ability to modify
/etc/sudoers using any tool that does not require executing sub-processes. You may be thinking that excludes
visudo, but strictly speaking, you don't need
visudo to edit
Like, for example:
sudo-user$ sudo sed --in-place -e '/^sudo-user/s/NOEXEC://' /etc/sudoers
...and the user has just removed the
A restriction that the user can remove at will is not a true restriction.
NOEXEC: may cause problems. It does not just prevent shell escapes: it prevents the program executed with
sudo from directly starting any other programs. This can have a lot of consequences.
For example, if your
sudo-user stops and later restarts the
cron daemon (e.g. to stop scheduled jobs for the duration of some maintenance), the restarted
cron daemon will be unable to actually execute any scheduled jobs because of the
NOEXEC: exists so that the sysadmin can apply it to carefully selected programs that are found to be able to perform their task without
exec()ing any sub-processes. Applying it blindly to everything is going to cause problems.
But if you absolutely must, here's how.
sudoers(5) man page:
User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \
(':' Host_List '=' Cmnd_Spec_List)*
Cmnd_Spec_List ::= Cmnd_Spec |
Cmnd_Spec ',' Cmnd_Spec_List
Cmnd_Spec ::= Runas_Spec? SELinux_Spec? Tag_Spec* Cmnd
Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'
SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')
Tag_Spec ::= ('EXEC:' | 'NOEXEC:' | 'FOLLOW:' | 'NOFOLLOW' |
'LOG_INPUT:' | 'NOLOG_INPUT:' | 'LOG_OUTPUT:' |
'NOLOG_OUTPUT:' | 'MAIL:' | 'NOMAIL:' | 'PASSWD:' |
'NOPASSWD:' | 'SETENV:' | 'NOSETENV:')
This is a detailed description on how to construct a user specification line for the
sudoers file. It may be a little tedious to read, but it does hold the information you need.
Let's work it out using your example line:
sudo-user ALL=(ALL) NOEXEC: NOPASSWD: ALL
The entire line is known as the user specification, or
It breaks down as follows:
User_List has just one user in your example:
Host_List has just one entry,
Cmnd_Spec_List in your example is
(ALL) NOEXEC: NOPASSWD: ALL
- there are no further
: Host_List = Cmnd_Spec_List units on this line (the asterisk after parentheses suggests there might be zero or more additional units like this.)
Cmnd_Spec_List has no commas, so it has just one
Cmnd_Spec breaks down into:
Runas_Spec: in your case,
SELinux_Spec, which does not exist in your example
- zero or more
Tag_Specs, which is the part you want to know about
Cmnd, the command, which is
ALL in your case.
And a single
Tag_Spec is just one of the listed keywords with a colon at the end, with no comma, space or other delimiter explicitly listed. The
Cmnd_Spec ::= line tells us exactly where to put spaces on that line. Since there is no instruction to put spaces or any other delimiters between tags, don't do that.
So, just put the tags one after the other, like this:
sudo-user ALL=(ALL) NOEXEC:NOPASSWD: ALL