Ansible SSH as one user and Sudo as another

I am having trouble with configuring Ansible and sudo to allow me to SSH into a server and run a command as another user.
I have gone through the questions / answers below and the Ansible documentation here: http://docs.ansible.com/intro_inventory.html

But I still can not get it to work. Please can someone put me on the right track.

References:
http://stackoverflow.com/questions/24743085/ansible-ssh-as-one-user-and-sudo-as-another
http://serverfault.com/questions/559154/ansible-using-different-sudo-user-for-different-hosts

I am trying to do this:

server-01 client-01


foo ----> ssh —> foo
bar - sudo as root user

Using Ansible,
connect from: server-01

using the user foo
and then use sudo to run a command as user bar

User bar is setup to be able to run any command.

However, I am not sure where the problem is, with sudo or Ansible.
I think the problem is with sudo but I am not sure where.

This ansible command works:

[foo@server-01 ~]$ ansible client-01 -m raw -a “touch /var/tmp/testfile” --ask-sudo-pass

sudo password: ********* ( password for foo user )
client-01 | success | rc=0 >>

This one does not:
ansible client-01 -m raw -a “touch /etc/testfile” --ask-sudo-pass

sudo password: ********* ( password for foo user )
client-01 | FAILED | rc=1 >>
touch: cannot touch `/etc/testfile’: Permission denied

I have SSH authentication without a password setup between server-01 and client-01 for user foo and it works OK.

[foo@server-01 ~]$ id
uid=96(foo) gid=96(foo) groups=96(foo)
[foo@server-01 ~]$ su - foo
Password:
[foo@server-01 ~]$
[foo@server-01 ~]$
[foo@server-01 ~]$ ssh client-01
Last login: Thu Jan 15 16:32:05 2015 from server-01.voodooit.co.uk
[foo@client-01 ~]$

This is my setup:

server-01: /etc/ansible/hosts

first, the following line shows you should not need a password for
doing sudo as 'foo'

foo ALL=(bar) NOPASSWD: ALL

In your command you are implying a double sudo while ansible only does one.

ansible can connect as a remote user 'foo' and then use sudo to run a
command as another user 'bar', to have that command also be sudo, you
need to add that yourself, or allow 'foo' to sudo as root.

for example, i believe this is what you want (with your inventory
configured for remote user being 'foo' and sudo user being 'bar':

ansible client-01 -m raw -a "sudo touch /etc/testfile"

except it won't work, as ansible won't prompt you for the sudo
password for 'bar' only for 'foo', which does not need one, but the
reverse would work.

foo ALL=(bar) ALL
bar ALL=(ALL) NOPASSWD: ALL

with this ansible can use the password prompt for 'foo' and then you
can sudo to root from bar w/o a password.

Hi

Thanks for the reply. Sorry though, I do not understand. Perhaps I am just being thick.
I have read the documentation here: http://docs.ansible.com/intro_inventory.html
but can not get it to work.

I can setup Ansible to perform tasks using the root user account to SSH directly as root and then run commands on a remote server using the root user.
I can setup Ansible to perform tasks using a non-root user account to SSH directly and then run commands on the remote server as the same user if sudo is setup to run as root either with a password or without.

However, I do not understand how to use Ansible to run commands on a remote server if the account used for SSH and the account with sudo as root on the remote server are different.

For example, this is the setup,
User foo can ssh to server1 without a password
User bar is setup in sudo to run root commands on server1 but does not allow ssh from the Ansible server.

Ansible Server server1


foo ----> ssh —> foo
bar - sudo as root user

Configuration: server1 - /etc/sudoers

On the remote server client-01

If I log in as user foo I can see that sudo is not giving me access to create file /etc/testfile and that user bar does.

This looks like a configuration issue with sudo for user foo.

[root@client-01 ~]# su - foo
[foo@client-01 ~]$ sudo -l
[sudo] password for foo:
User foo may run the following commands on this host:
(bar) ALL
[foo@client-01 ~]$ sudo touch /etc/testfile
Sorry, user foo is not allowed to execute ‘/bin/touch /etc/testfile’ as root on client-01.
[foo@client-01 ~]$ exit
logout
[root@client-01 ~]# su - bar
[bar@client-01 ~]$ sudo -l
User bar may run the following commands on this host:
(ALL) NOPASSWD: ALL
[bar@client-01 ~]$ sudo touch /etc/testfile
[bar@client-01 ~]$ sudo rm /etc/testfile
[bar@client-01 ~]$ exit
logout

So, user bar can run commands as the root user and user foo can not.
But, I can not connect as user bar because the only account with SSH keys setup is user foo.

How do other people handle the SSH user and the user with root sudo access being different?

Does everyone use the same user account on remote servers for the SSH connection and the sudo as root user?

Thanking you for your time.

The normal pattern is having an remote user that can sudo, in your
case you need to chain 2 sudos, this is not the normal pattern.

Hi Brian
I appreciate your reply. Thank you.

To clarify, the “usual” set-up for an Ansible environment of servers would be to use a non-root user account on the remote servers that has the ability to accept SSH connections from the Ansible server and the ability to run commands as the root user via sudo.

If that is the case then I will go back to my client and ask for the SSH user to be provided with sudo root access, the same as their other servers.

Thanks for your reply. This is new to me and I do not want to do anything “silly” but also, do not want to make things more difficult than they should be.

That does mean though that the user specified using the parameters ansible_ssh_user and ansible_sudo_user must always be the same if performing something that requires root privileges against a remote system.

no, ansible_ssh_user/remote_user is the user you log in as,
ansible_sudo_user is the user you become through sudo.

Sorry, I do not understand again.

If this is true below
ansible_ssh_user /remote_user is the user you log in as.
ansible_sudo_user is the user you become through sudo.

Then why can I not use one user account to connect to a remote servers using SSH and another, separate account to use sudo on the remote machine.

ansible_ssh_user=foo ( use foo to connect from local server to remote using SSH )
ansible_sudo_user=bar ( sudo to use bar on the remote server and run command as the root user )

Am I getting my local and remote sudo mixed up?
Is the ansible_sudo_user parameter for the local server and not the remote server?

no, it is for the remote server, but you are there as the user you
loged in as 'foo', ansible_sudo_user is the user you want to become
from the logged in user, so you can run stuff as bar, but then you
want to sudo again (this is the unsupported part) to run commands as
root.

so ansible supports this:

foo => bar
or
foo => root

but not

foo => bar => root

Thank you for the reply. Very helpful. I have been trying to figure this out for over a week but just been reading and re-reading the documentation and books without getting anywhere.

Is the below correct please and would I need to initiate the ansible command as user foo on the local server or can I use the root user.
At the moment I use account foo to initiate Ansible using a sudo entry for the Ansible commands.

ansible_ssh_user=foo Remote SSH user
ansible_sudo_user=bar Remote sudo user

foo => bar (Run commands as user bar on remote server)
ansible_ssh_user=foo
ansible_sudo_user=bar

foo => root (Run commands as user root on remote server)
ansible_ssh_user=foo
ansible_sudo_user=foo

No, sudo_user is not the user allowed to sudo, but the user you are
allowed to sudo as.

logs in as foo and runs command as bar (uses foo's privlege to sudo to bar)
ansible_ssh_user=foo
ansible_sudo_user=bar

logs in as foo and runs commands as foo user (this is actually a sudo noop)
ansible_ssh_user=foo
ansible_sudo_user=foo

logs in as foo and runs commands as root user (for this you need to
modify the sudoers)
ansible_ssh_user=foo
ansible_sudo_user=root

Thanks for your reply, taking the first example,

first example

I do not think that this is right. The sudo does not work for the first example.

Is there any documentation please for basic Ansible user configuration for initiating Ansible instructions between a local and remote server using several different user examples.

This is not something that I have been able to find. It is easy if using the same user accounts and particularly just root but confusing if using several accounts.

I do not think that this is right. The sudo does not work for the first
example.

Is there any documentation please for basic Ansible user configuration for
initiating Ansible instructions between a local and remote server using
several different user examples.

This is not something that I have been able to find. It is easy if using the
same user accounts and particularly just root but confusing if using several
accounts.

I had a couple replies in this thread that I think eventually helped
explain this: https://groups.google.com/forum/#!search/toshio$20rew$20sudo/ansible-project/LkNe-hZKbwg/ZZ4NfZ9wFm4J

Let me see if I can help out here with the same sort of information.
The concepts aren't very complex but if you've already spent some time
on it and gotten confused then chances are that you've got some ideas
of how it works that aren't matching with what's really happening and
that's why the confusion exists. Get rid of those extraneous concepts
and then hopefully will become clear :slight_smile:

Thanks for your reply, taking the first example,

The first thing to understand is that when doing ansible --sudo
ansible is dealing with three accounts:

(1) The local user
(2) The remote user that you ssh into the box as
(3) The user that you sudo to on the remote box

Ansible does not natively deal with more than these three accounts.
As I go through your examples, I'll comment on which of these three
users are being used in your examples. In some cases, I think that
you'll see that you were assuming that ansible had a fourth user in
addition to these three and that's what's leading to the confusion.

first example

logs in as foo and runs command as bar (uses foo's privlege to sudo to
bar)
ansible_ssh_user=foo
ansible_sudo_user=bar

ansible server server1
--------------------- -----------
foo --> ssh --> foo
                                        bar

Up to here, what your specifying is something that ansible handles.

(1) Local user running /usr/bin/ansible is foo
(2) Remote user is an account on the remote box which is also named foo
(3) sudoing to a third account which is named bar in order to run your commands

So far so good :slight_smile:

The Ansible session is initiated on the Ansible server as user root. ( or
should I use foo ? )

Here you try to bring in a fourh account, though. You're trying to
bring in the root account on the remote machine. This is not one of
the three accounts we listed in the first section. So it's not an
account that you're telling ansible to deal with. If you want the
root account to be used on the remote machine, you need to substitute
it for account (2) or account (3) above. The most common case of
using ansible with sudo is to have root be the account used for (3).

Ansible uses user foo for the SSH session between the Ansible server and
the remote server, server1

This is both correct and an over simplification. When talking about
the connection between the two servers we're really talking about two
accounts. One the local server, we have account (1) which is named
foo. On the remote server we have account(2) which is also named foo.
Despite these two accounts having the same name, they are separate
accounts. The local account (1) has an ssh public key/private key
pair. The public key in this pair has to be in the remote
account(2)'s ~/.ssh/authorized_keys file. So in this example, it's
more accurate to say:

"Ansible uses local user foo on the Ansible server to create an SSH
conenction to the remote user foo on the remote server, server1."

On server1, user foo is given access to run commands as user bar via the
/etc/suders file

/etc/sudoers
-----------------------------------------------
foo ALL=(bar) NOPASSWD: ALL

<nod> So the setup you talk about in this example means that when
ansible runs commands on server1 using --sudo, those commands are run
as the bar user on server1. If things were setup this way, I'd expect
that you'd see the following:

<foo@ansible-server> $ ansible server1 --sudo -m command -a 'whoami'
server1 | success | rc=0 >>
bar

Second example

logs in as foo and runs commands as foo user (this is actually a sudo
noop)
ansible_ssh_user=foo
ansible_sudo_user=foo

ansible server server1
--------------------- -----------
foo --> ssh --> foo

So in this example:
(1) Local user running /usr/bin/ansible is foo
(2) Remote user is an account on the remote box which is also named foo
(3) sudoing will sudo to the remote account foo. Which as you say is a no-op.

The Ansible session is initiated on the Ansible server as user root.
Ansible uses user foo for the SSH session between the Ansible server and
the remote server, server1

Same two comments about these statements as in Example 1.

On server1, user foo runs commands on server1

Correct.

No changed to the /etc/suders file are required.

This may not be correct depending on how /etc/sudoers is setup to
begin with and what you're actually doing with ansible. At least on
my Fedora21 system, sudo has to be configured to allow sudo execution
of a command:

<badger@roan.lan> $ sudo -u testuser /bin/bash
<testuser@roan.lan> $ sudo -u testuser whoami
testuser is not in the sudoers file. This incident will be reported.

testuser hasn't been configured in the /etc/sudoers file so testuser
isn't allowed to use sudo *even though it's sudo'ing to its own
account*.

So if your server1 is similarly configured, I'd expect the following
ansible command to return an error: ansible server1 --sudo -m command
-a 'whoami'

OTOH, as you say, this is a sudo no-op. So you can achieve the same
thing without ansible attempting to use sudo. So I'd expect that this
equivalent command would work: ansible server1 -m command -a 'whoami'

Third example

logs in as foo and runs commands as root user (for this you need to modify
the sudoers)
ansible_ssh_user=foo
ansible_sudo_user=root

ansible server server1
--------------------- -----------
foo --> ssh --> foo
                                        root

So in this case we have:
(1) Local user running /usr/bin/ansible is foo
(2) Remote user is an account on the remote box which is also named foo
(3) sudoing will sudo to the remote account root. Which is user 0 and
has all privileges

Note that this is the most common way that people run ansible with sudo.

The Ansible session is initiated on the Ansible server as user root.
Ansible uses user foo for the SSH session between the Ansible server and
the remote server, server1

Same comments for these two as the previous examples.

On server1, user foo runs commands on server1 as the root user.

/etc/sudoers
-----------------------------------------------
foo ALL=(ALL) NOPASSWD: ALL

Do I have this right now?

yep, this is correct.

Is this documented anywhere. I have looked for something like this but can
not find it.

I don't believe so. The reason is likely that none of this is
terribly ansible-specific. It's just a simple automating of ssh and
sudo. ie: if you don't modify ansible.cfg or otherwise set an
ansible_sudo_user or ansible_ssh_user, ansible is basically
automating the following:

<foo@ansible-server> $ ssh foo@server1

Welcome to server1

<foo@server1> $ sudo -u root whoami
root
<foo@server1> $ exit

(equivalent to ansible server1 -m command -a 'whoami' --sudo )

Hope that helps you understand things.
-Toshio

Thank you Brian and Toshio for your replies.
Thanks Toshio for your detailed reply.

I did not realise that it is the ansible command can be run from the Ansible server as a non-root user.
I had been setting up a sudo entry for the Ansible commands.

However, that is not where my confusion with the use of sudo.
Thanks.

Ans thanks tkuratomi

I still do not understand this.

Example 1:

Ansible Local Server Remote server
local-01 remote-01


Local user foo → ssh → Remote user foo

I do not understand how Ansible knows what user account to use on the local and remote servers for the purposes of the SSH connection if no user account is specified within the command line ( ansible_ssh_user=foo ) or /etc/ansible/hosts file.

I will ask a new separate question.

Example 2:

Ansible Local Server Remote server
local-01 remote-01


Local user foo → ssh → Remote user foo
bar (foo user uses sudo to run command as bar)

I still can not get this to work. The SSH connection is working fine for user foo and if the foo user uses sudo to run a command as user bar on the remote server it works fine but I still can not get Ansible to glue it together.

I will ask a separate question about this.
This was my main question really. I have one non-root user that allows SSH, but can not use sudo for root access.
So I can not use the same example as above.

I still do not understand this.

Example 1:

Ansible Local Server Remote server
local-01 remote-01
------------------- --------------------
Local user foo --> ssh --> Remote user foo

I do not understand how Ansible knows what user account to use on the local
and remote servers for the purposes of the SSH connection if no user account
is specified within the command line ( ansible_ssh_user=foo ) or
/etc/ansible/hosts file.

Ansible (and the ssh commandline) defaults to using the same username
on the remote server as you are logged into on the local server.

So if nothing is specified, If you invoke ansible from the local user
foo account, ansible will attempt to connect to a remote user foo
account.

I will ask a new separate question.

Example 2:

Ansible Local Server Remote server
local-01 remote-01
------------------- --------------------
Local user foo --> ssh --> Remote user foo
                                                bar
(foo user uses sudo to run command as bar)

I still can not get this to work. The SSH connection is working fine for
user foo and if the foo user uses sudo to run a command as user bar on the
remote server it works fine but I still can not get Ansible to glue it
together.

This should work. Try something like this:

$ ansible rhel7-test --sudo -K -a 'whoami'
sudo password:
rhel7-test | success | rc=0 >>
root

$ sudo vim /etc/ansible/ansible.cfg
$ # Edit the sudo_user config so that: sudo_user = ansibletest1
$ ansible rhel7-test --sudo -K -a 'whoami'
sudo password:
rhel7-test | success | rc=0 >>
ansibletest1

I will ask a separate question about this.
This was my main question really. I have one non-root user that allows SSH,
but can not use sudo for root access.
So I can not use the same example as above.

This sounds slightly problematic
* To be able to administrate this box at all you'll need a chain of
accounts from the account you ssh in as to an account that has all of
the privileges that you need (usually the root account so that you can
do anything you need).
* To be able to run ansible efficiently you should have an account
that can ssh in and either has the privileges you need or be one sudo
or su login away from the account that has all the privileges you
need.

However all is not lost because:
* You can be more than one sudo login away (as bcoca's explanation was
showing) but that is harder to achieve, has many caveats, and is much
harder to explain clearly :slight_smile:
* If you have an account that can sudo to root you should be able to
either add the account you can ssh in as to /etc/sudoers or add SSH
keys to the account that you can sudo to root from so that you can SSH
into the box as the aaccount that's only one sudo step away from root.

-Toshio

Thank you for the full reply Toshio

I don’t understand the comments regarding example 2 and can not get it to work.
I will answer a separate question reference example 2 as I did for example 1

Thank you.