Sudoers NOPASSWD option not working

The command in your sudoers file is:

/usr/bin/systemctl stop vdr.service

but, at the command line, you are attempting to execute:

/usr/bin/systemctl stop vdr

A solution: Add both variations to your sudoers file:

martin  ALL=(ALL)       NOPASSWD: /usr/bin/systemctl stop vdr
martin  ALL=(ALL)       NOPASSWD: /usr/bin/systemctl stop vdr.service

BTW, a good practice it to place custom sudoders rules into files created in /etc/sudoers.d directory. Such a file can be created with one of the following commands:

sudo visudo -f /etc/sudoers.d/martin-vdr-service
sudo visudo /etc/sudoers.d/martin-vdr-service # [1]

[1] “As of version 1.8.27, the sudoers path can be specified without using the -f option.” – man page for visudo

That means it works fine. If you execute it without sudo, you are getting prompted by polkit to elevate privileges and i am nut sure but apparently, it doesn’t read /etc/sudoers file.

created the custom sudoers rule as mentioned in /etc/sudoers.d directory, but it still asks for the password.

the following sudoers rules are read from the /etc/sudoers file:

[martin@fc36 ~]$ sudo -l -U martin
Matching Defaults entries for martin on fc36:
    !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE",
    env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/var/lib/snapd/snap/bin

User martin may run the following commands on fc36:
    (ALL) ALL
    (ALL) NOPASSWD: /usr/bin/systemctl stop vdr
    (ALL) NOPASSWD: /usr/bin/systemctl stop vdr.service

password request as user martin:

[martin@fc36 ~]$ /usr/bin/systemctl stop vdr
Failed to stop vdr.service: Access denied
See system logs and 'systemctl status vdr.service' for details.

In any case, nopasswd or not, you have to use sudo. Isn’t it?
sudo systemctl stop vdr

1 Like

yes, it works now as user martin, i have to use this command and the password is no longer requested.

[martin@fc36 ~]$ sudo systemctl stop vdr.service

2 Likes

If you don’t want to prepend sudo to the command, you should consider to use polkit instead of the old style sudo.

I’m not an expert, but it seems to work.
Create a file like /etc/polkit-1/rules.d/10-vdr.rules containing this stuff:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units") {
        polkit.log("action=" + action)
        polkit.log("subject=" + subject)
        polkit.log("unit="+action.lookup("unit"))
        if (action.lookup("unit") == "vdr.service") {
            polkit.log("verb="+action.lookup("verb"))
            var verb = action.lookup("verb");
            if (verb == "start" || verb == "stop" || verb == "restart") {
                return polkit.Result.YES;
            }
        }
    }
});

Now, systemctl {start|stop|restart} vdr (even without sudo) shouldn’t ask for a password anymore.

Yes, polkit is way more complicated than sudo, but it is where the world is going today. However, as you could imagine, it allows to assign more fine grained authorizations in the modern world.

1 Like

You could also add a check if the user is in the wheel group

...
            if (verb == "start" || verb == "stop" || verb == "restart") {
                if (subject.isInGroup("wheel")) {
                    return polkit.Result.YES;
                }
            }
...

or limit the policy to a specific user

            if (subject.user == "martin") {
                if (verb == "start" || verb == "stop" || verb == "restart") {
                    return polkit.Result.YES;
                }
            }
...
2 Likes

the polkit rules sounds reasonable.
The reason for my request is that I want to wake up my Video Disk Recorder (VDR) from sleep (suspend mode) via a desktop script.
For this I made the desktop icons visible again under Fedora 36 and created 2 desktop scripts (Start\ VDR.desktop + Stop\ VDR.desktop) and another script (vdr_start_stop). If I now want to control the call via polkit then it will probably be very long or what do you think ?

[martin@fc36 ~]$ cat -v /home/martin/Desktop/Start\ VDR.desktop 
[desktop entry]
Version=1.0
Encoding=UTF-8
Name=vdr_attach
Exec=/home/martin/scripts/vdr/vdr_start_stop start + deta
Exec=/home/martin/scripts/vdr/vdr_start_stop start + atta
Icon=/home/martin/scripts/vdr/softhddevice.png
Type=Application
Name[en]=VDR on
Name[en_DE]=VDR on
Comment[en_DE]=attach vdr
[martin@fc36 ~]$ cat -v /home/martin/desktop/stop\ VDR.desktop 
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Name=vdr_dettach
Exec=/home/martin/scripts/vdr/vdr_start_stop stop + deta
Icon=/home/martin/scripts/vdr/softhddevice.png
Type=Application
Name[en]=VDR off
Name[en_DE]=VDR off
Comment[en_DE]=vdr dettachen
StartupNotify=true
[martin@fc36 ~]$ cat -v /home/martin/scripts/vdr/vdr_start_stop 
#!/bin/sh
sudo systemctl $1 vdr.service
xhost $2
svdrpsend plug softhddevice $3

With the main polkit rule you mentioned the commands are working on console, but not with
the desktop icons.

running the commands on console, all is working

/home/martin/scripts/vdr/vdr_start_stop start + deta
/home/martin/scripts/vdr/vdr_start_stop start + atta

but when selecting the desktop icons the plugin is not dettached and no X-Window opens.
see journalctl -b

Jun 18 16:29:27 fc36 polkitd[715]: <no filename>:3: action=[Action id='org.freedesktop.systemd1.manage-units' verb='start' unit='vdr.service' polkit.message='Authentication is required to start '$(unit)'.' polkit.gettext_domain='systemd']
Jun 18 16:29:27 fc36 polkitd[715]: <no filename>:4: subject=[Subject pid=8087 user='martin' groups=martin,root,wheel,video,audio seat=null session=null local=true active=true]
Jun 18 16:29:27 fc36 polkitd[715]: <no filename>:5: unit=vdr.service
Jun 18 16:29:27 fc36 polkitd[715]: <no filename>:7: verb=start
Jun 18 16:29:27 fc36 nemo-autostart-with-gnome.desktop[8088]: access control disabled, clients can connect from any host
Jun 18 16:29:27 fc36 vdr[5302]: [5322] SVDRP fc36 < 127.0.0.1:51010 client connection accepted
Jun 18 16:29:27 fc36 vdr[5302]: [5322] SVDRP fc36 > 127.0.0.1:51010 server created
Jun 18 16:29:27 fc36 nemo-autostart-with-gnome.desktop[8089]: 220 fc36 SVDRP VideoDiskRecorder 2.6.1; Sat Jun 18 16:29:27 2022; UTF-8
Jun 18 16:29:27 fc36 nemo-autostart-with-gnome.desktop[8089]:900 can't attach SoftHdDevice not detached
Jun 18 16:29:27 fc36 nemo-autostart-with-gnome.desktop[8089]: 221 fc36 closing connection
Jun 18 16:29:27 fc36 vdr[5302]: [5322] SVDRP fc36 < 127.0.0.1:51010 connection closed
Jun 18 16:29:27 fc36 vdr[5302]: [5322] SVDRP fc36 < 127.0.0.1:51010 server destroyed

@alciregi Thanks for your great Solution with the polkit rules. :+1:

2 Likes

I found an even simpler way, this example is for making virt-manager work without password prompt:

printf """polkit.addRule(function(action, subject) {
  if (action.id == "org.libvirt.unix.manage" && subject.local && subject.active && subject.isInGroup("wheel")) {
      return polkit.Result.YES;
  }
});""" | sudo tee /etc/polkit-1/rules.d/80-libvirt-manage.rules

This should do a good and secure policy change, only wheel is allowed. I think this should be standard behavior, as well as with other things like mounting LUKS drives. It is very annoying how it currently is.

There is a built-in policy that only requires relevant group membership:

sudo usermod -a -G libvirt ${USER}
1 Like

Is martin a member of the wheel group? That line above seems to indicate the possibility.

If so then any command that does not ‘exactly’ match the specialized command for that user will fall over to the next available option and since a wheel member is required to enter the password now the password is required.

This one shows what I suspect to be the ‘wheel’ entry before the custom entries, so it would always require the password. The permission is granted at the first entry to match.

I always allow wheel members to use the entry in the sudoers file and put specialized entries for other users in /etc/sudoers.d/ This avoids conflicts between the config for the wheel group and for individual users. The individual users should not be a member of the wheel group. As you can see, privileges may conflict.

are both things needed? the Group and the polkit rule?

The group should be created automatically by the package libvirt-daemon.

Yes the group is created, but the user has to be added to it. It had no effect on the password prompt for me though. So I wonder if just allowing the commands for all wheel users would be enough to avoid them.

A new group membership requires to terminate all active user processes or just reboot:

sudo loginctl terminate-user ${USER}
sudo pkill -9 -u ${USER}
sudo reboot

Logout is often not enough as it only sends a graceful termination signal ignored by some processes unless the option KillUserProcesses is enabled.

1 Like

I made a small script automatically creating Polkit rules, as the process is tedious. What do you think of it?

You can optimize the code to look like this:
Fedora 37 - Can't have wifi properly working - Realtek 8821CE - #7 by vgaetera