How to Use Ansible to SSH as Non-Privileged User and Execute Commands as Root (su Method)


2 views

In enterprise environments with strict security policies, we often encounter servers where:

  • Only non-privileged users (e.g., 'foo') have SSH access
  • No sudo privileges are granted to these users
  • Root access requires manual su authentication

While expect scripts work, Ansible provides a more maintainable solution through its become system and su method.

Your inventory file or host vars need these parameters:

[webservers]
server1 ansible_user=foo ansible_become=yes ansible_become_method=su ansible_become_user=root

Or in YAML format:

webservers:
  hosts:
    server1:
      ansible_user: foo
      ansible_become: yes
      ansible_become_method: su
      ansible_become_user: root

For security, never store passwords in plaintext. Use Ansible Vault:

# Create encrypted variable
ansible-vault encrypt_string 'your_root_password' --name 'ansible_become_password'

Store the output in your inventory or group_vars:

webservers:
  hosts:
    server1:
      ansible_become_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          663864396537363962316266...

Here's a complete playbook to demonstrate privileged package installation:

---
- name: Install security updates
  hosts: webservers
  tasks:
    - name: Update package cache
      ansible.builtin.apt:
        update_cache: yes

    - name: Upgrade all packages
      ansible.builtin.apt:
        upgrade: dist
        autoremove: yes

For quick tasks without playbooks:

ansible server1 -m shell -a "whoami" --become --become-method=su --become-user=root

If you must interact with password prompts (not recommended):

- name: Example with explicit become
  ansible.builtin.command: /usr/bin/privileged_command
  become: yes
  become_method: su
  become_user: root
  vars:
    ansible_become_pass: "{{ root_password }}"
  • Always use Ansible Vault for password storage
  • Consider implementing SSH certificate authentication
  • Regularly rotate root passwords
  • Log all privilege escalations

Common issues and fixes:

# Enable verbose mode for debugging
ANSIBLE_DEBUG=1 ansible-playbook playbook.yml

# Check connection parameters
ansible -m ping server1 --user=foo

In enterprise environments, we often encounter systems where direct SSH access as root is disabled for security reasons, and the available user account lacks sudo privileges. The standard workaround involves:

  1. SSH login as restricted user (foo)
  2. Using su - root with password authentication
  3. Executing privileged commands

While Ansible typically expects either:

  • SSH as root directly
  • SSH with sudo privileges

Our situation requires a different approach since neither option is available.

Ansible's become system supports this exact use case through the su method. Here's how to configure it:

# ansible.cfg
[privilege_escalation]
become=True
become_method=su
become_user=root
become_ask_pass=True

Configure your inventory file with connection details:

[webservers]
web1.example.com ansible_user=foo ansible_become_pass=rootpassword
web2.example.com ansible_user=foo ansible_become_pass=rootpassword

Example playbook to demonstrate privilege escalation:

---
- name: Update system packages
  hosts: webservers
  tasks:
    - name: Update all packages
      yum:
        name: '*'
        state: latest
      become: yes
      become_method: su

For quick tasks without playbooks:

ansible webservers -m yum -a "name=httpd state=latest" --become --become-method=su --become-user=root -u foo -K
  • Store passwords in Ansible Vault instead of plaintext
  • Consider setting up SSH key-based authentication for the foo user
  • Eventually migrate to proper sudo configuration

For environments requiring interactive password entry (like TTY restrictions):

# Using ansible expect module
- name: Privileged command with expect
  expect:
    command: su - root -c "yum update -y"
    responses:
      'Password:': "{{ root_password }}"