Ansible Server Configuration

Fixing Ansible Become Sudo Password Errors and Permission Denied Failures

I’ll never forget that 11: PM page after a routine patching playbook stalled out across 300 servers; it just sat there without throwing any errors or timing out, with nothing but a blinking cursor staring at me. So I killed it and re‑ran it with verbose logging, only to find that all of the tasks were missing sudo passwords. The most frustrating aspect of this situation was that the same servers ran just fine the week before, because someone modified the SSH configuration file, and now the cached credentials are no longer valid. I spent the entire night SSHing into all of the boxes and manually executing updates while my coffee was getting cold.

That experience really made me learn about how Ansible’s privilege escalation actually works at a low level. The fixes themselves are not complicated, but the Ansible documentation can be very confusing when you are already stressed out. The following outlines everything that I know about how to stop these password prompts, and the various situations that continue to cause confusion for others.

Quick Summary

  • When the node doesn’t have sudo rights on the target, the JSON response will show an error that contains the phrase “Missing sudo password”.
  • If the become_method is incorrect, it could go silent when trying to prompt for the password.
  • This can be remedied by using passwordless sudo, adding a CLI flag, or using an encrypted variable.
  • Both requiretty and SSH multiplexing can result in an interactive shell hanging even if the username, password, and any other credentials are valid.
  • To prevent this from happening, treat ansible_become_pass like a production secret, and restrict inventory permissions.

Understanding Privilege Escalation Failures

Ansible uses the privilege escalation feature to allow a playbook to change its SSH user to another specified account (usually root). When this fails, the error is rather odd; usually, the remote connection will terminate without returning a useful exit code.

Missing Sudo Privileges on the Target Node

The most often occurring failure is that remote users do not have permission to execute sudo commands. The playbook calls for sudo -u root, but the sudo policy denies the request due to a non-zero response from Ansible. In the task output, you may see the following:

fatal: [db01]: FAILED! => {
    "msg": "Missing sudo password",
    "rc": 1
}  <-- This line is the core error

This output might lead you to believe the problem is that the user has no password set, but rather it indicates that the user does not have permission even to request a password. In the case where the user is not part of the sudoer group or does not possess a NOPASSWD parameter, the sudo command will prompt for a password that Ansible does not have, which will either time out or return an empty string.

Invalid become_method Configurations

If you try to use a method that is not available on the remote user/subsystem or is restricted from being used, the method fails in an alternate fashion. The following is a snippet of my .ansible.cfg configuration file that would produce an error on a standard Linux system:

[privilege_escalation]
become = True
become_method = su
become_user = root
become_ask_pass = False

Unless you configure your ansible.cfg for different OS configurations, su commands should prompt by default for the target user’s password. Therefore, SSH can not provide this password interactively when running the ansible module. Consequently when the ansible module requests the user’s password via su, it hangs until the SSH session times out.

What didn’t work for me

When trying to bypass a misconfigured sudo configuration, I set the become_method: su in ansible.cfg and thought it would work. But it only caused the SSH session to hang until the session timed out due ControlPersist. I also tried providing the become password with --ask-become-pass to su, but it requires the root password and we did not provide those passwords to the team. Therefore, I ended up fixing the sudo configuration instead.

Core Prerequisites for the Right Security Context

Before you begin to troubleshoot your problems, it is important to determine what the remote host thinks about the environment where it is expected to run with the security context you want to use. Knowing this allows you to eliminate a good part of the guessing that takes a lot of time.

Verifying the become_user Account

Use an ad-hoc command as shown below to see which user has been elevated to by the remote host. Use the --become flag as it will force the same escalation path as will be used by the playbook:

ansible all -m command -a "whoami" --become -K

Notice the -K flag will prompt you for the become password. If the output returns root on every host, then end-to-end escalation of privileges is functioning properly. If the result is a grid of fail, this indicates the misconfiguration lies within the target group and not in the logic of the playbook.

The Ultimate ansible sudo password prompt error fix

Here are three great methods for avoiding having the password prompt ruin your playbooks. I use Method 1 in CI Pipelines and Static Infrastructure environments.

Method 1: Configuring nopasswd sudoers

By configuring your sudoers file to allow the Ansible user to run commands without entering a password, you prevent Ansible’s become plugin from ever prompting for a password. Simply edit your sudoers file using visudo and add a line similar to this:

ansible ALL=(ALL) NOPASSWD: ALL

Since Ansible never prompts for a password, any ansible sudo password prompt errors will be solely caused by the host configuration. This is ideal for fully automated environments where you have tightly controlled the Ansible user.

Method 2: Passing Passwords via CLI Flags

If you need to use Ansible in one-offs or cannot edit your sudoers file, you can use the –ask-become-pass (or -K) CLI flag to prompt you once per session for your become password and reuse that password:

ansible-playbook site.yml --ask-become-pass

Ansible caches the become password in memory and passes it to the sudo process for each command you execute on a remote host. Additionally, you may also set ansible_become_pass as a prompt variable. However, using a CLI flag is quick and easy to use when typing at the keyboard.

Method 3: Utilizing Ansible Vault for Credentials

If you need to store your ansible_become_pass but do not want to have it in plaintext, you can encrypt it using Ansible Vault. First create a vault file like group_vars/all/vault.yml:

ansible_become_pass: "S3cretP@ss"

After creating the vault file, encrypt the entire contents of the file:

ansible-vault encrypt group_vars/all/vault.yml

When running the playbook, provide the vault password to Ansible using –ask-vault-pass, and Ansible will use the decrypted password automatically. The Ansible Vault documentation provides all the details necessary to manage these encrypted values.

Edge Case: Interactive Shell Hanging During Execution

Even with proper credentials, if the remote TTY has a misconfigured terminal, or if SSH connection multiplexing interferes, your playbook may hang indefinitely.

Resolving “Requiretty” Sudoers Conflicts

Many security policies include a Defaults requiretty setting in /etc/sudoers, which requires sudo to run only from a true terminal. As Ansible employs a non-interactive SSH session, it often does not allocate a terminal session for Command execution. The workaround is to disable requiretty for the Ansible user.

Defaults:ansible !requiretty

Alternatively, -tt can be specified as an argument to the SSH command defined in your ansible.cfg file, but the approach above is cleaner and does not lower security for other users. The sudoers manual specifies all the Defaults options available.

Handling SSH Multiplexing Disconnects

When attempting to achieve faster SSH connection times via ControlMaster and ControlPersist commands, having a master connection socket dropped can also lead to hanging operations when trying to elevate privileges. My ~/.ssh/config file is configured as follows:

Host *
  ControlMaster auto
  ControlPath ~/.ssh/controlmasters/%r@%h:%p
  ControlPersist 10m

Because of the ControlPersist 10m command, the SSH client will keep the master SSH connection open in the background for 10 minutes after disconnecting from it. This prevents connection timeout errors while running playbooks that may take a long time to complete, especially if a handler fires just before finishing and the handler requires a new prompt for elevated privileges.

Best Practices for Managing ansible_become_pass

Think of your become password as an API Key. It’s important to never hard code passwords in a playbook and to restrict access to sensitive files by limiting who has access to read them.

Defining Variables in Group Vars

For example, rather than storing the Become variable in your playbook, store it in a separate group-vars file. I have my directory structure set up as follows:

group_vars/
└── all/
    ├── vars.yml
    └── vault.yml   # ansible_become_pass lives here

With this setup, you can use encryption on only the sensitive variables and keep the other group variables in plain text so they are easier to edit. Per Ansible privilege escalation documentation, the recommended pattern for using group-vars with vault is to use this approach.

Restricting Permissions on Inventory Files

It’s also important to set appropriate permission on your inventory files. If a user accidentally commits an unencrypted Become password to source control, you will have a larger issue to deal with. I always restrict permissions on the entire inventory directory right after creating it:

chmod 600 inventory/production/group_vars/all/vault.yml

When I run an ls -l command on that file, here is what I get:

-rw------- 1 ansible ansible 512 Mar 15 08:00 vault.yml

This one simple step prevents the leaking of passwords from being copied via a improperly configured backup script or through a user’s curiosity.

Frequently Asked Questions

The FAQ here will help you test whether or not Ansible Become is functioning before running a full playbook.

How do I test if Ansible become is working before running a full playbook?

To test if Ansible Become is working prior to running a full playbook, you can use the ad-hoc command that I’ve referenced before:

ansible all -m command -a "whoami" --become -K

If the ad-hoc command returns root for each target system, then you are good to go. You do not need to run a full playbook to verify the security context in this instance.

Why does Ansible say “Missing sudo password” when I didn’t set one?

The “Missing Sudo Password” error generally means that the remote user does not have a valid sudoers entry or the sudoers entry requires a password that Ansible has no way to prompt for. Be sure to check to see if the user is allowed to run sudo and, if you would like to avoid passwords entirely, include the NOPASSWD option on their sudoers entry.

Can I use a different become method like su or pbrun instead of sudo?

Yes, you can specify a different become method such as su or pbrun in either your playbook or your configuration. You need to be aware of the additional requirements for using each of these methods: su requires the target user password, and pbrun requires using the PowerBroker client. I would recommend sticking with sudo unless your organization requires otherwise since it is the best-supported route in Ansible.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button