Stackvora.tech

Sudo Without a Password for a Specific Command Only

Granting elevated privileges is a core task for any system administrator. While full NOPASSWD access to sudo is convenient, it poses a significant…

Granting elevated privileges is a core task for any system administrator. While full NOPASSWD access to sudo is convenient, it poses a significant security risk. A more granular approach is often required, particularly in automated environments like CI/CD pipelines or for specific operational tasks. This article details how to configure sudo to allow a user or group to execute a specific command, or a set of specific commands, without requiring a password, thereby minimizing the attack surface while enabling necessary automation.

The primary tool for managing sudo policies is visudo, which safely edits the /etc/sudoers file or files within the /etc/sudoers.d/ directory. Directly editing /etc/sudoers without visudo risks syntax errors that can render sudo unusable and potentially lock out administrative access.

Understanding sudoers Syntax

The sudoers file follows a specific syntax for defining rules. Each rule typically consists of four main fields:

  • User/Group: The user or group to whom the rule applies. Groups are prefixed with a % (e.g., %admin).
  • Host: The host(s) from which the user can run commands. Usually ALL for local systems.
  • RunAsUser/Group: The user or group as whom the command can be run. Typically (ALL:ALL) for any user and group.
  • Commands: The command(s) that can be executed. This is where granularity is applied.

The format is generally: user HOST=(RUNAS_USER:RUNAS_GROUP) COMMANDS

The NOPASSWD Tag

To disable password prompting for specific commands, the NOPASSWD: tag is placed before the command list. Conversely, PASSWD: explicitly requires a password.

Creating a Specific NOPASSWD Rule

The recommended practice is to create separate files in the /etc/sudoers.d/ directory for custom rules. This modular approach simplifies management and prevents merge conflicts during package upgrades that might modify the main /etc/sudoers file. These files must have strict permissions (0440) and contain no . or ~ characters in their filenames.

Example: Granting a CI/CD User Service Restart Permissions

Consider a scenario where a CI/CD system runs as the deploy user and needs to restart a specific application service named myapp.service. We want this user to be able to execute systemctl restart myapp without a password.

  1. Access visudo: Open a terminal and run:
    sudo visudo -f /etc/sudoers.d/deploy
    This command creates and opens a new file named deploy in the /etc/sudoers.d/ directory using your default editor (usually vi or nano).
  2. Add the rule: Inside the editor, add the following line:
    deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp.service
    Let's break this down:
    • deploy: This is the username. If you want to apply this to a group, use %deploygroup.
    • ALL=(ALL): The user deploy can run commands as any user and any group. This is common but can be restricted further if needed (e.g., (root:root)).
    • NOPASSWD:: Specifies that no password is required for the subsequent commands.
    • /usr/bin/systemctl restart myapp.service: This is the exact command allowed. Always specify the full path to the executable. This prevents malicious users from creating their own systemctl in /tmp or other user-writeable paths that might be in PATH and exploiting the rule.
  3. Save and exit: Save the file and exit the editor. visudo will automatically check for syntax errors before saving. If an error is detected, it will prompt you to correct it.

Now, the deploy user can run:

sudo systemctl restart myapp.service

...without being prompted for a password.

Granting Multiple Specific Commands

If the user needs to execute several specific commands without a password, you can list them separated by commas on the same line:

deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp.service, /usr/bin/systemctl status myapp.service

Alternatively, for better readability with many commands, you can define an alias:

  1. Define a Command Alias:
    Cmnd_Alias MYAPP_SVC_CMDS = /usr/bin/systemctl restart myapp.service, /usr/bin/systemctl status myapp.service, /usr/bin/journalctl -u myapp.service
  2. Reference the Alias in the Rule:
    deploy ALL=(ALL) NOPASSWD: MYAPP_SVC_CMDS

This approach makes the sudoers file cleaner and easier to manage, especially when applying similar sets of permissions to different users or groups.

Wildcards and Their Risks

While sudoers supports wildcards, their use, especially with NOPASSWD, should be approached with extreme caution. For instance, allowing /usr/bin/systemctl * myapp.service might seem convenient, but it opens up access to stop, disable, mask, or even daemon-reload, which could have unintended consequences.

A slightly safer, but still risky, approach for arguments might be specific arguments using regex-like patterns, but this is highly complex and error-prone in sudoers. For example, to allow restart or reload for myapp.service:

deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl (restart|reload) myapp.service

Note: The parentheses and pipe | are interpreted literally by sudoers as part of the command string to match, not as regex operators. This means the above would not work as intended; you would need two separate entries or a more complex external script to wrap the command. The sudoers file does not support regular expressions for command matching. Always specify exact commands.

Permissions and Security Considerations

The files within /etc/sudoers.d/ must have file permissions set to 0440 (read-only for owner and group, no access for others). visudo automatically enforces this. If you manually create or move files into this directory, ensure the permissions are correct:

sudo chmod 0440 /etc/sudoers.d/deploy

Ownership should typically be root:root.

It's crucial to understand that even with specific command rules, there are potential bypasses if the command itself allows arbitrary execution or file manipulation. For instance:

  • Allowing sudo /usr/bin/apt install * could be exploited if an attacker can manipulate package sources.
  • Allowing sudo /usr/bin/vi /etc/shadow allows editing of critical system files.
  • Even seemingly innocuous commands like sudo /bin/find . -exec ... \; can be leveraged for privilege escalation if -exec is allowed.

Always consider the capabilities of the allowed command. If the command allows shelling out, arbitrary file writes, or execution of other programs, the NOPASSWD grant can be circumvented.

Verifying sudoers Configuration

After making changes, it's good practice to verify the configuration for the affected user. You can test by attempting to run the permitted command:

# Switch to the user for testing (optional, but good practice)
sudo -iu deploy
# Attempt the command
sudo systemctl restart myapp.service
# If no password prompt appears and the command executes, it's working.
# Attempt a forbidden command
sudo systemctl stop myapp.service
# This should prompt for a password or deny access with an error.
exit

You can also use sudo -l to list the privileges for the current user (or a specified user with sudo -U <user> -l):

sudo -U deploy -l

This command will display the sudo rules applicable to the deploy user. You should see an entry similar to:

User deploy may run the following commands on this host:
    (ALL) NOPASSWD: /usr/bin/systemctl restart myapp.service

Common Pitfalls

  • Not using visudo: Editing /etc/sudoers directly is the most common cause of locked-out systems. Always use visudo.
  • Incorrect file permissions in /etc/sudoers.d/: Files must be 0440. Incorrect permissions will cause sudo to ignore the file.
  • Not using full paths: Omitting the full path (e.g., systemctl instead of /usr/bin/systemctl) is a major security vulnerability, as it allows an attacker to place a malicious executable earlier in the user's PATH.
  • Syntax errors: Missing commas, incorrect capitalization, or typos in sudoers syntax can lead to rules not applying or sudo failing. visudo helps catch many of these.
  • Over-permissioning: Granting overly broad commands (e.g., wildcards) or commands that can be abused (e.g., commands that allow arbitrary code execution or file editing).
  • Forgetting .service suffix: For systemctl commands, ensure you include the .service suffix if that's the full unit name you intend to restart.
  • Defaults requiretty interfering with scripts: If your sudoers file contains Defaults requiretty, automated scripts might fail because they don't have a TTY. You can add a rule to disable this for specific users or commands:
    Defaults:deploy !requiretty
    Place this on a separate line, ideally above the command-specific rules.

Back to the knowledge base · Ask the AI assistant