Installing package via Ansible using a user with limited sudo rights [duplicate] - ansible

I have a playbook that performs some prechecks on the database as the Oracle user. The remote node is an AIX server and so I created a shell script that is ran via the playbook.
---
- hosts: db
var_files:
- ansible_var.yml
tasks:
- name: "DB Checks"
become: True
become_user: oracle
script: "{ db_prechk }"
On the AIX server, I added the below entry to the sudoers file
ansible ALL=(oracle) NOPASSWD: /tmp/ansible-tmp-*/db_prechecks.sh
But the playbook fails with the error that it's waiting for the privilege escalation prompt.
This runs fine if it is ran as root. However we do not want passwordless root between the Ansible controller and the remote nodes. So we created ansible user on the controller and remote nodes and exchanged the SSH keys.
This also runs if the sudoers entry is just
ansible ALL=(oracle) NOPASSWD: ALL
We do not want to provide full access to the oracle userid via the ansible user id too.
I ran the playbook in the verbose mode and can see that Ansible is copying the script to the remote_tmp dir and is executing it as the oracle userid. In that case the sudoers line should've allowed it to run?

If you look at the verbose mode output, you will see that the actual command differs from the one you specified in the sudoers file:
<127.0.0.1> SSH: EXEC ssh -o ForwardAgent=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=2202 -o 'IdentityFile="/Users/techraf/devops/testground/debian/.vagrant/machines/debian/virtualbox/private_key"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=ansible -o ConnectTimeout=120 -o ControlPath=/Users/techraf/.ansible/cp/ansible-ssh-%h-%p-%r -tt 127.0.0.1 '/bin/sh -c '"'"'sudo -H -S -n -u oracle /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-xoamupogqwtteubvedoscaghzmfascsr; /tmp/ansible-tmp-1488508771.72-271591203197790/db_prechecks.sh '"'"'"'"'"'"'"'"' && sleep 0'"'"''
So what is executed after sudo -u oracle starts actually with /bin/sh -c.
I managed to filter a working string to:
ansible ALL=(oracle) NOPASSWD: /bin/sh -c echo BECOME-SUCCESS*; * /tmp/ansible-tmp-*/db_prechecks.sh*
But it is based on trial-and-error. I'm not sure yet why * is required between ; and /tmp/... and at the end, but otherwise it does not work.
In both places Ansible added superfluous space characters and it seems to be the reason, as adding a space to a shell command (specified in the sudoers file) does affect the ability to sudo.
You might try with ? instead of *, I will test later

Q: "This also runs if the sudoers entry is just ansible ALL=(oracle) NOPASSWD: ALL"
A: Quoting from Privilege escalation must be general:
"You cannot limit privilege escalation permissions to certain commands..."

Replying to #techraf's answer: sudo seems to truncate the extra space and you can see it with sudo -l. I was able to get around this by escaping the spaces with \ as instructed in sudo's man page:
\x For any character ‘x’, evaluates to ‘x’.

Related

What does sleep 0 do in a shell script and what does it do if it used in the ansible SSH config to append after each command?

What does sleep 0 do in a shell script? I read the man page for sleep and it says "delay for a specified amount of time" And the argument NUMBER specifies this time in SECONDS (by default).
But I see ansible using sh -c 'echo ~ec2-user && sleep 0' to start with each task.
Also, it uses this at the end of each remote command it is firing.
I didn't find any special case mention of sleep 0 on the man page and based on the functionality of the sleep command it doesn't make any sense to have sleep 0.
The sleep command on my server is from GNU coreutils 8.22
After looking into this for some more time, here are few things that I have learned,
this is a SSH configuration given to the ansible,
each time ansible using SSH to execute a task it is running SSH with -C with multiple options. These are not part of playbook or task.
I looked for ansible configuration on ansible page here. Checked all files and Env variables but found nothing related to ssh
Checked the /etc/ssh/ssh_config there are not all the parameters/arguments that I see in the SSH that ansible is doing
In the inventory as well the host is mentioned just like this
ansible_host=localhost ansible_user=ec2-user
e.g. log lines at the beginning when ansible executes any task:
<localhost> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="ec2-user"' -o C
onnectTimeout=120 -o ControlPath=/home/ec2-user/.ansible/cp/6bc5a26ee4 localhost '/bin/sh -c '"'"'echo ~ec2-user && sleep 0'"'"''
<localhost> (0, '/home/ec2-user\n', '')
<localhost> ESTABLISH SSH CONNECTION FOR USER: ec2-user
I'm executing an ansible playbook written by one team, there is no one in that team I can talk to. I'm struggling to find where Ansible is taking all these arguments it is using in each SSH and why is it using this sleep 0

Ansible privilege escalation become without -u flag

How is it possible to become a certain user without the -u flag (sudo su test_user instead of sudo su -u test_user)
Inventory (hosts)
[example]
test0001.example.org ansible_become_user=test_user ansible_become=true
ansible.cfg:
[defaults]
timeout=30
[privilege_escalation]
become_method="sudo"
become_flags="su"
And on the target machine:
$ sudo -l
User foo may run the following commands on test0001:
(root) NOPASSWD: /bin/su test_user
Running the playbook now fails with:
<test0001> (0, b'', b'')
<test0001> ESTABLISH SSH CONNECTION FOR USER: None
<test0001> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=30 -o ControlPath=/home/foo/.ansible/cp/c7eeb339b6 -tt test0001 '/bin/sh -c '"'"'sudo su -u test_user /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-geolooxawvydfclkjnetjajadmffqjvz ; /usr/bin/python /var/tmp/ansible-tmp-1578410709.7699296-180938533114945/AnsiballZ_setup.py'"'"'"'"'"'"'"'"' && sleep 0'"'"''
fatal: [test0001]: FAILED! => {
"msg": "Timeout (32s) waiting for privilege escalation prompt: \r\nWe trust you have received the usual lecture from the local System\r\nAdministrator. It usually boils down to these three things:\r\n\r\n #1) Respect the privacy of others.\r\n #2) Think before you type.\r\n #3) With great power comes great responsibility.\r\n\r\n"
}
And that is because it tries to become test_user with sudo su -u test_user. I actually want it to become test_user with sudo su test_user (so without the -u flag). How would it be possible to tell ansible not to include the -u flag?
Note that I am not able to change the sudoers files.

Restrict Ansible script module using sudoers on the remote node

I have a playbook that performs some prechecks on the database as the Oracle user. The remote node is an AIX server and so I created a shell script that is ran via the playbook.
---
- hosts: db
var_files:
- ansible_var.yml
tasks:
- name: "DB Checks"
become: True
become_user: oracle
script: "{ db_prechk }"
On the AIX server, I added the below entry to the sudoers file
ansible ALL=(oracle) NOPASSWD: /tmp/ansible-tmp-*/db_prechecks.sh
But the playbook fails with the error that it's waiting for the privilege escalation prompt.
This runs fine if it is ran as root. However we do not want passwordless root between the Ansible controller and the remote nodes. So we created ansible user on the controller and remote nodes and exchanged the SSH keys.
This also runs if the sudoers entry is just
ansible ALL=(oracle) NOPASSWD: ALL
We do not want to provide full access to the oracle userid via the ansible user id too.
I ran the playbook in the verbose mode and can see that Ansible is copying the script to the remote_tmp dir and is executing it as the oracle userid. In that case the sudoers line should've allowed it to run?
If you look at the verbose mode output, you will see that the actual command differs from the one you specified in the sudoers file:
<127.0.0.1> SSH: EXEC ssh -o ForwardAgent=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=2202 -o 'IdentityFile="/Users/techraf/devops/testground/debian/.vagrant/machines/debian/virtualbox/private_key"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=ansible -o ConnectTimeout=120 -o ControlPath=/Users/techraf/.ansible/cp/ansible-ssh-%h-%p-%r -tt 127.0.0.1 '/bin/sh -c '"'"'sudo -H -S -n -u oracle /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-xoamupogqwtteubvedoscaghzmfascsr; /tmp/ansible-tmp-1488508771.72-271591203197790/db_prechecks.sh '"'"'"'"'"'"'"'"' && sleep 0'"'"''
So what is executed after sudo -u oracle starts actually with /bin/sh -c.
I managed to filter a working string to:
ansible ALL=(oracle) NOPASSWD: /bin/sh -c echo BECOME-SUCCESS*; * /tmp/ansible-tmp-*/db_prechecks.sh*
But it is based on trial-and-error. I'm not sure yet why * is required between ; and /tmp/... and at the end, but otherwise it does not work.
In both places Ansible added superfluous space characters and it seems to be the reason, as adding a space to a shell command (specified in the sudoers file) does affect the ability to sudo.
You might try with ? instead of *, I will test later
Q: "This also runs if the sudoers entry is just ansible ALL=(oracle) NOPASSWD: ALL"
A: Quoting from Privilege escalation must be general:
"You cannot limit privilege escalation permissions to certain commands..."
Replying to #techraf's answer: sudo seems to truncate the extra space and you can see it with sudo -l. I was able to get around this by escaping the spaces with \ as instructed in sudo's man page:
\x For any character ‘x’, evaluates to ‘x’.

Remote Machine unreachable while trying to ping through ansible

This is my hosts file :
[openstack]
ec2-54-152-162-0.compute-1.amazonaws.com
I am trying to ping it using the following command :
ansible openstack -u redhat -m ping -vvvv
I got the following response :
Loaded callback minimal of type stdout, v2.0
Using module file /usr/lib/python2.7/site-packages/ansible-2.2.0-py2.7.egg/ansible/modules/core/system/ping.py
<ec2-54-152-162-0.compute-1.amazonaws.com> ESTABLISH SSH CONNECTION FOR USER: redhat
<ec2-54-152-162-0.compute-1.amazonaws.com> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o Port=22 -o 'IdentityFile="/home/centos/AnsibleKeyPair.pem"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=redhat -o ConnectTimeout=10 -o ControlPath=/home/centos/.ansible/cp/ansible-ssh-%h-%p-%r ec2-54-152-162-0.compute-1.amazonaws.com '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1480529571.83-128837972481874 `" && echo ansible-tmp-1480529571.83-128837972481874="` echo $HOME/.ansible/tmp/ansible-tmp-1480529571.83-128837972481874 `" ) && sleep 0'"'"''
ec2-54-152-162-0.compute-1.amazonaws.com | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh.",
"unreachable": true
}
NOTE : I am able to connect to centos machines properly. But, I can't ping Ubuntu and Redhat machines. My controller machine is Centos. What might the problem be?
I solved it finally by using the following command :
ansible openstack -u ec2-user -m ping
I have been typing -u redhat but AWS has already given a name to it automatically ec2-user
"ESTABLISH SSH CONNECTION FOR USER: None" - this means that it is trying to ssh this host using a blank username which will not work.
Two solutions:
Edit the hosts file to include ansible_user=ubuntu (or whatever user your flavor uses, i.e. ec2-user for amazon linux)
[openstack]
ec2-54-204-230-203.compute-1.amazonaws.com ansibler_user=ubuntu
Just call it with the -u ubuntu when calling the playbook (or again whatever your flavor uses).
ansible openstack -u ubuntu -m ping -vvvv
Hope this helps!
--Edit--
(this is what helped me do it)
1.) Add your ssh key to the ~/.ssh directory
touch ~/.ssh/mykey.pem
2.) Enter ssh-agent bash mode
ssh-agent bash
3.) Ehange its permissionschmod
chmod 600 ~/.ssh/mykey.pem
4.) Make a path for ansible to use the permission
ssh-add ~/.ssh/mykey.pem
In your command line, use argument -k to ask ssh passwork:
ansible openstack -u redhat -m ping -k

sudo -i doesn't work anymore with specific permissions through sudoers file

I had a bash script which called sudo -i -u user /bin/bla/whatever. That worked fine until the last update to CentOS 5.8.
That's the corresponding entry in the sudoers file:
Runas_Alias TEST = user1, user2
Defaults:test always_set_home
test ALL=(TEST) NOPASSWD: /bin/bash -c /bin/bla/whatever, /bin/bla/whatever
If I used sudo -i it seems it called the command
"/bin/bash -c /bin/bla/whatever"
(regarding the secure log). Now, since the update, it seems to call
"/bin/bash -c \/bin\/bla\/whatever"
and therefore is not allowed to. I tried to change the line in the sudoers file to
test ALL=(TEST) NOPASSWD: /bin/bash -c /bin/bla/whatever, /bin/bla/whatever, /bin/bash -c \/bin\/bla\/whatever
but thats not allowed syntax, so I tried:
test ALL=(TEST) NOPASSWD: /bin/bash -c /bin/bla/whatever, /bin/bla/whatever, /bin/bash -c \\/bin\\/bla\\/whatever
That's valid syntax but doesn't work either.
If I use sudo -H -u user /bin/bla/whatever it works fine. Even if I allow /bin/bash in the sudoers file, but that would allow anything.....
Any ideas?
Erik
Just checked the sudo man page on my fedora 16 system and it says:
-i [command]
The -i (simulate initial login) option runs the shell specified by the password database entry of the target user as a login shell. This means
that login-specific resource files such as .profile or .login will be read by the shell. If a command is specified, it is passed to the shell
for execution via the shell's -c option.
So it does not appear to be necessary to specify bash -c in your sudoers command definition.
If you call the command as sudo -i /bin/bla/whatever you should need nothing more than the following in your sudoers file:
test ALL=(TEST) NOPASSWD: /bin/bla/whatever
I can reproduce the problem on my fedora 16 system, no changes to the sudoers file I tried had any effect. I cannot find any other configuration required to make this work. All I can say is to use '-H -u ...'.
Were you running sudo -i -u user /bin/bla/whatever with arguments? From man sudoers:
A simple file name allows the user to run the command with any arguments he/she wishes. However, you may also specify command line arguments (including wildcards). Alternately, you can specify "" to indicate that the command may only be run without command line arguments.
So once you add in the /bin/bash -c you are now specifying arguments and they must match exactly.
Here's an example sudoers line:
test ALL=(ALL) NOPASSWD: /bin/bash -c /bin/true, /bin/bash -c /bin/true *, /bin/true *
With that I can do:
sudo /bin/true
sudo /bin/true foo
sudo -u /bin/true
sudo -u /bin/true foo
But not sudo true because that becomes bash -c true which does not match bash -c /bin/true.

Resources