How to Fix Ansible 403 Forbidden on Ubuntu 22.04


Troubleshooting Guide: Resolving “Ansible 403 Forbidden” on Ubuntu 22.04

As a Senior DevOps Engineer, encountering an “Ansible 403 Forbidden” error, especially when targeting Ubuntu 22.04 hosts, can be a frustrating roadblock in your automation workflows. While “403 Forbidden” is typically an HTTP status code, in the context of Ansible’s operation, it often points to a failure in privilege escalation or execution due to security configurations on the target host. This guide will walk you through the root cause and provide direct solutions.


1. The Root Cause: Why this happens on Ubuntu 22.04

The “Ansible 403 Forbidden” error, when not related to a specific uri module call, most commonly manifests as a privilege escalation failure on the target Ubuntu 22.04 host. Specifically, it often indicates that Ansible is unable to successfully use sudo to execute commands that require elevated permissions.

The primary culprit on many modern Linux distributions, including Ubuntu 22.04, is the Defaults requiretty setting within the sudoers configuration. This setting mandates that sudo can only be used when the user is connected via an interactive terminal (TTY).

Ansible, by its nature as an automation tool, operates in a non-interactive mode. When Ansible attempts to use become: yes (its mechanism for sudo or su) on a host configured with Defaults requiretty, the sudo command fails because no TTY is allocated for the session. This failure is then reported back by Ansible, sometimes appearing as a generic “permission denied” or “forbidden” type error, preventing tasks from executing with the necessary elevated privileges.

Other potential, though less common, causes for similar privilege errors include:

  • The connecting user (ansible_user) is not part of the sudo group or does not have explicit sudo privileges configured.
  • Incorrect become_user or become_method settings in your Ansible playbook or inventory.
  • Password-related issues if become_password is required and incorrect.

However, for the specific symptom of “403 Forbidden” during task execution with become: yes, Defaults requiretty is the most frequent and specific cause on Ubuntu 22.04.


2. Quick Fix (CLI)

The most direct way to resolve this is to modify the sudoers configuration on the target Ubuntu 22.04 host to allow the Ansible user to use sudo without requiring a TTY. This is best achieved by creating a new file in the /etc/sudoers.d/ directory, which helps maintain configuration modularity and prevents direct edits to the main /etc/sudoers file.

Steps to apply the quick fix:

  1. SSH into your target Ubuntu 22.04 host:

    ssh your_ansible_user@your_ubuntu_host_ip

    (Replace your_ansible_user and your_ubuntu_host_ip with your actual login credentials.)

  2. Create a new sudoers.d file for Ansible configuration: Use visudo -f to safely edit or create a sudoers file, ensuring correct syntax and permissions.

    sudo visudo -f /etc/sudoers.d/ansible_fix
  3. Add the necessary line: Inside the editor (usually vi or nano), add the following line:

    Defaults !requiretty

    This line globally disables the requiretty setting for all users. If you prefer to disable it only for the specific user Ansible connects as, you can use:

    Defaults:your_ansible_user !requiretty

    (Replace your_ansible_user with the actual username Ansible uses to connect.)

    Save and exit the editor. For vi, press Esc, then type :wq and press Enter. For nano, press Ctrl+X, then Y to confirm save, and Enter.

  4. Verify file permissions (optional, visudo handles this, but good to know): visudo automatically sets the correct permissions (0440), but you can manually verify or set them if you created the file differently:

    sudo chmod 0440 /etc/sudoers.d/ansible_fix

After these steps, your Ubuntu 22.04 host should now allow Ansible to execute sudo commands without a TTY.


3. Configuration Check

If the quick fix doesn’t immediately resolve the issue, or if you want to understand the existing configuration, it’s crucial to inspect the sudoers files on your target Ubuntu 22.04 host.

  1. Inspect /etc/sudoers: Open the main sudoers file using visudo. This is the only safe way to edit or view it, as it performs syntax checks.

    sudo visudo

    Look for lines containing Defaults requiretty. If found and not commented out, it’s contributing to your issue. While you could comment it out here, creating a file in sudoers.d is generally preferred for manageability.

  2. Inspect /etc/sudoers.d/ directory: List all files within this directory:

    ls -l /etc/sudoers.d/

    Review each file in this directory using sudo cat /etc/sudoers.d/<filename> or sudo visudo -f /etc/sudoers.d/<filename>. Look for any conflicting Defaults requiretty settings or specific user/group configurations that might override your ansible_fix file. The last processed rule generally takes precedence, and files are typically processed in alphabetical order, though visudo handles the logical merging.

  3. Verify Ansible User’s Sudo Permissions: Ensure that the user Ansible connects as (ansible_user in your inventory) has the necessary sudo privileges.

    • Check group membership:
      groups your_ansible_user
      The output should include sudo. If not, add the user to the sudo group: sudo usermod -aG sudo your_ansible_user.
    • Check explicit sudoers entry: Look in /etc/sudoers or /etc/sudoers.d/ files for an entry explicitly granting sudo permissions to your_ansible_user, e.g.:
      your_ansible_user ALL=(ALL) NOPASSWD: ALL
      (Note: NOPASSWD means no password is required for sudo, which is common for Ansible automation but might not be desired in all security contexts.)

4. Verification

After applying the fix and checking configurations, verify that Ansible can now successfully perform tasks requiring privilege escalation on your Ubuntu 22.04 host.

  1. Ansible Ad-Hoc Command Test: From your Ansible control machine, run a simple command that requires sudo using an ad-hoc command.

    ansible <your_target_host_group> -i <path_to_inventory> -u <your_ansible_user> --private-key=<path_to_key> -b -a "whoami"
    • Replace <your_target_host_group> with the group from your inventory, or all.
    • Replace <path_to_inventory> with the path to your inventory file.
    • Replace <your_ansible_user> with the user Ansible connects as.
    • Replace <path_to_key> with the path to your SSH private key.
    • The -b (or --become) flag tells Ansible to escalate privileges.
    • The -a "whoami" module executes the whoami command.

    Expected Output: The output for the task should display root (or the user specified via become_user if you’re using a different escalated user), indicating successful privilege escalation.

    your_ubuntu_host_ip | SUCCESS | rc=0 >>
    root
  2. Simple Playbook Test: For a more comprehensive test, create a simple playbook that explicitly uses become: yes.

    Create a file named test_sudo_permissions.yml:

    ---
    - name: Verify Ansible sudo permissions on Ubuntu 22.04
      hosts: all
      gather_facts: false # Optional, but speeds up the test
      become: true        # Enable privilege escalation
    
      tasks:
        - name: Get current effective user
          command: whoami
          register: current_user_info
          changed_when: false # This command doesn't change state
    
        - name: Display current user
          debug:
            msg: "Ansible is currently running as: {{ current_user_info.stdout }}"
    
        - name: Create a test file in a root-only directory
          command: touch /root/ansible_test_file_{{ ansible_hostname }}
          when: current_user_info.stdout == 'root' # Only if we successfully became root
          args:
            creates: /root/ansible_test_file_{{ ansible_hostname }} # Idempotent check
    
        - name: Verify the test file exists
          stat:
            path: /root/ansible_test_file_{{ ansible_hostname }}
          register: test_file_status
          when: current_user_info.stdout == 'root'
    
        - name: Display test file status
          debug:
            msg: "Test file created successfully: {{ test_file_status.stat.exists }}"
          when: current_user_info.stdout == 'root'

    Run the playbook:

    ansible-playbook -i <path_to_inventory> test_sudo_permissions.yml

    Expected Output: The debug tasks should show Ansible is currently running as: root and Test file created successfully: True. You can also manually SSH into the target host and verify the existence of /root/ansible_test_file_<hostname>.

By following these steps, you should successfully resolve the “Ansible 403 Forbidden” error stemming from sudo privilege escalation issues on your Ubuntu 22.04 hosts, allowing your automation to proceed smoothly.