I'm a beginner with Ansible, and I need to run some basic tasks on a remote server.
The procedure is as follows:
I log as some user (osadmin)
I run su - to become root
I then do the tasks I need to.
So, I wrote my playbook as follows:
---
- hosts: qualif
vars:
- ansible_user: osadmin
- ansible_password: H1g2.D6#
tasks:
- name: Copy stuff from here to over there
copy:
src: /home/osadmin/file.txt
dest: /home/osadmin/file-changed.txt
owner: osadmin
group: osadmin
mode: 0777
Also, I have the following in vars/main.yml:
ansible_user: osadmin
ansible_password: password1
ansible_become_password: password2
[ some other values ]
However, when running my tasks, Ansible / the hosts returns me the following:
"Incorrect sudo password"
I then changed my tasks so that instead of becoming sudo and copy the file in some place my osadmin doesn't have access, I just copy the file on /home/osadmin. So, theorically, no need to become sudo for just a simple copy.
The problem now is that not only it keeps saying "wrong sudo password", but if I remove it, Ansible asks for it.
I then decided to run the command and added -vvv at the end, and it showed me the following:
ESTABLISH SSH CONNECTION FOR USER: osadmin
SSH: EXEC sshpass -d10 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o User=osadmin -o ConnectTimeout=10 -o ControlPath=/home/osadmin/.ansible/cp/b9489e2193 -tt HOST-ADDRESS '/bin/sh -c '"'"'sudo -H -S -n -u
root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-ewujwywrqhcqfdrkaglvrouhmuiefwlj; /usr/bin/python /home/osadmin/.ansible/tmp/ansible-tmp-1550076004.1888492-11284794413477/AnsiballZ_setup.py'"'"'"'"'"'"'"'"' && sleep 0'"'"''
(1, b'sudo: a password is required\r\n', b'Shared connection to HOST-ADDRESS closed.\r\n')
As you can see, it somehow uses root, while I never told him to.
Does anyone know why Ansible keeps trying to be sudo, and how can I disable this?
Thank you in advance
There is a difference between 'su' and 'sudo'. If you have 'su' access, that means, that you can log as root (may be not, but it looks like). Use ansible_ssh_user=root, ansible_password=password2.
If this doesn't work, try to configure sudo on a server. You should be able to run sudo whoami and to get answer root. After that your code should run.
One more thing: you are using 'copy' module incorrectly. It uses src as path on local machine (where ansible is run), and dst as path on remote machine.
Related
In our organization, we have strict policies on our Linux users. We, in our case have a user that can execute sudo su - myuser without a password. But as soon as we add -c behind the su command that is not allowed.
The problem is Ansible adds the -c when executing the "become" command in order to set the environment variables.
My becomes variables:
become: yes
become_user: myuser
become_method: sudo
become_flags: 'su - '
Ansible executes the following:
sudo su - myuser -c '"'"'"'"'"'"'"'"'/bin/sh -c '"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-lksjasdhksldjfhsdklhfshsklhkljsh; /usr/bin/python /tmp/ansible-tmp-1602838989.23-135651442029159/setup.py
And this error is caused:
fatal: [xbi407cl03vm01.dbaas.ing.net]: FAILED! => {
"msg": "Timeout (32s) waiting for privilege escalation prompt: "
}
This causes a timeout because the -c is not allowed.
Is there a way to force Ansible to only run the command after the become command was successful?
Or is there an alternative way of changing user for a playbook?
I have written a simple play for installing pip and expect on my clients using ansible. However, the execution is stuck in the TASK part.
My code-
---
- hosts: mygroup
tasks:
- name: Install packages
yum: name= {{ item }} state=installed
with_items:
- pip
- expect
Debug- [only the Task part where the execution is stuck]
TASK [Install packages] ********************************************************
task path: /home/netman/lab7/prsh1271_play.yaml:4
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/packaging/os/yum.py
<192.168.1.2> ESTABLISH SSH CONNECTION FOR USER: None
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/packaging/os/yum.py
<172.16.1.2> ESTABLISH SSH CONNECTION FOR USER: None
<192.168.1.2> SSH: EXEC sshpass -d12 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o ConnectTimeout=10 -o ControlPath=/home/netman/.ansible/cp/61004433e3 192.168.1.2 '/bin/sh -c '"'"'/usr/bin/python && sleep 0'"'"''
<172.16.1.2> SSH: EXEC sshpass -d12 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o ConnectTimeout=10 -o ControlPath=/home/netman/.ansible/cp/3e78e2ce1a 172.16.1.2 '/bin/sh -c '"'"'/usr/bin/python && sleep 0'"'"''
Please help resolve.
Package installation requires root user or root like user. Can you add the user in the sudoers file and try again if not added
Also re run the playbook using -vvvv for verbose logging and entry the verbose logs - which would be helpful for debugging.
you could add a "become: true", so it runs as the root user.
so you have:
---
- hosts: mygroup
become: true
tasks:
- name: Install packages
yum: name= {{ item }} state=installed
with_items:
- pip
- expect
The playbook might be stuck because the command you run in the stuck task issues an input prompt, which you don't see when you run the playbook.
Since no input is ever supplied to the prompt, it just sits there and waits forever.
The solution (if this is indeed the problem):
Change your tasks such that you provide any necessary inputs directly in your Ansible tasks, thus avoiding input prompts.
I need to be able to login into a remote server, switch user and then, do whatever it is required.
I played with ansible and found the "become" tool, so I tried it, after all... it allows dzdo.
My playbook became something like this:
- name: Create empty file
file: path=touchedFile.txt state=touch
become: true
become_method: dzdo
become_user: userid
I ran it and got:
"Sorry, user someuser is not allowed to execute '/bin/sh -c echo BECOME-SUCCESS-xklihidlmxpfvxxnbquvsqrgfjlyrsah; /usr/bin/python /tmp/ansible-tmp-1513185770.1-52571838933499/command.py'
Mmm... I thought that maybe it is trying to execute something like this:
dzdo touch touchedFile.txt
Unfortunately, it doesn't work like that in my company. The policy forces us to log in as ourselves and then switch to the required user like this:
dzdo su - userid
I did a bit of research and tried running several commands in a single block, my logic thought that if I switched users first, then everything else would be executed as the other user. My playbook was updated to look like this:
- name: Create empty file
shell: |
dzdo su - userid
touch touchedFile.txt
It failed and I tried this then:
- name: Create empty file
command: "{{ item }}"
with_items:
- dzdo su - userid
- touch touchedFile.txt
And failed again... both approaches create touchedFile.txt but as my user and not the one they should...
Is there a way to do what I need directly with Ansible? Or do I need to start looking for more complex alternatives?
In the past I achieved what I'm trying to do now with a script that mainly used "expect", but it was prone to errors... that's why I'm looking for better alternatives.
EDIT 2018-01-08:
I can now use "sudo su - userid" without the need of a password; but somehow Ansible always expect input from the user, a timeout occurs and my play fails:
fatal: [240]: FAILED! => {
"failed": true,
"msg": "Timeout (12s) waiting for privilege escalation prompt: "
}
One thing I noticed is that Ansible is doing the following:
EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no
-o 'IdentityFile="./.ssh/fatCamel"' -o KbdInteractiveAuthentication=no
-o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey
-o PasswordAuthentication=no -o User=login_userid -o ConnectTimeout=10
-o ControlPath=/Users/local_userid/.ansible/cp/446eee77f4
-tt server_url '/bin/sh -c '"'"'sudo su - sudo_userid -u root /bin/sh
-c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-hsyxhtaoxiepyjexaffecfiblmjezopu;
/usr/bin/python /u/users/login_userid/.ansible/tmp/ansible-tmp-1515438271.05-219108659465262/command.py;
rm -rf "/u/users/login_userid/.ansible/tmp/ansible-tmp-1515438271.05-219108659465262/"
> /dev/null 2>&1'"'"'"'"'"'"'"'"' && sleep 0'"'"''
This part is what I caught my attention sudo su - sudo_userid -u root
If I try to run it in the server (copy&paste) it also fails... Why is Ansible adding the "-u root" and is there a way to prevent it from doing so? I will never be granted ROOT access to any server.
Also, I am setting the ansible_become_pass variable to the correct value... but it still fails.
By the way, I check several bugs reported to Ansible (like https://github.com/ansible/ansible/issues/23921), and my error is similar, but their work-arounds don't work with my case.
Any help will be much appreciated!!
I have finally found a work-around for my problem, and I'm sharing this answer in case someone finds it useful.
Ansible become module is great, but for my company it is not working. As I explained in the question, it is adding a "-u root" at the end of the sudo, which makes the whole command to fail.
I was able to make it work with the following snippet:
- name: Create empty file as sudo_userid
command: "sudo su - sudo_userid -c 'touch touchedFile.txt'"
I did several tests, and all of them worked! I didn't even got an Ansible warning!
So, cheers everyone!
This playbook works for me in ansible 2.4 for your limited test case, I'm not sure how well it would work against larger / more complex tasks or modules. It basically just works around your site's dzdo/sudo limitations.
---
- hosts: 127.0.0.1
become: yes
become_method: dzdo
become_flags: "su - root -c"
gather_facts: no
tasks:
- name: Create empty file
file: path=touchedFile.txt state=touch
I would like to use ansible in a full automated context, where I cannot manually type passwords. To deal with this, I connect the servers with SSH public key, and I whitelisted severals commands such as apt-get install * in my sudoers configuration so I do not need a password to run them. For instance sudo apt-get install git.
However if the setting become is True in a playbook, ansible asks me for a password it does not need.
How can I tell ansible to run a command as sudo, without asking me a password?
Do you know another way to install apt packages without password?
Should I use another become method?
sudoers conf
myuser ALL = NOPASSWD: /usr/bin/apt-get install *
ansible
- name: install the latest version of ntpdate
package:
name: ntpdate
state: latest
become: True
Produces this output:
failed: [x.x.x.x] (item=ntpdate) => {"failed": true, "item": "python3-dev", "module_stderr": "", "module_stdout": "sudo: a password is required\r\n", "msg": "MODULE FAILURE", "rc": 1}
The simple answer is that you cannot do it without enabling all commands (or at least python).
Ansible does not run the commands as you expect it to run. It runs Python scripts. You can see the exact command when you execute ansible-playbook with -vvv. They are much more complex and to enable them you would have to add them to sudoers, for example:
sudo -H -S -n -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-xxxxxx;
/usr/bin/python /var/www/.ansible/tmp/ansible-tmp-xxxxxxxx/apt.py;
rm -rf "/var/www/.ansible/tmp/ansible-tmp-xxxxxxxx/" > /dev/null 2>&1'"'"'
&& sleep 0
The tricky part is that all spaces, quotes, and other special characters are relevant and until you get the correct command pattern by trial and error, replacing characters with wildcards, the system will not allow the command to run with elevated privileges. Effectively you won't be able to whitelist all the commands Ansible runs.
The only exception is raw module which runs the given command intact.
In all the Ansible playbooks I have worked on, I had to do only 2 things so that tasks run with become:True
Create file /etc/sudoers.d/demo on the target hosts with below content:
demo ALL=(ALL) NOPASSWD:ALL
Copy ssh id from Ansible host to target host using ssh-copy-id
template/without_sudo
%sudo ALL=(ALL) NOPASSWD: ALL
%sudo ALL=(ALL) NOPASSWD: /sbin/poweroff, /sbin/reboot, /sbin/shutdown
tasks/main.yml
- name: Sudoers no password
raw: echo '{{ user_password }}' | sudo -S sh -c 'echo "{{ lookup('file', 'templates/without_sudo') }}" > /etc/sudoers.d/without_sudo'
no sudo for the rest of the ansible command
You can use the ansible 'command' module with sudo as part of the command, instead of 'become: yes'
- name: install the latest version of ntpdate
command: 'sudo apt-get update ntpdate'
The downside is that this is much less portable. The upside is, it works... and you only need to whitelist the specific command.
in my opinion, if you set your node with =(ALL) NOPASSWD:ALL. then anybody: including the hackers can access your nodes.
so what I can suggest ,
ansible-playbook <name>.yml --ask-sudo-pass
this will ask your node sudo password. and u can execute ur operation, as I guess you know ur node's credential.
I am trying to run a "folder creation" command with my ansible playbook. (Code is below)
The creation requires sudo login to execute.
I run the playbook as follows:
ansible-playbook myfile.yml --ask-pass
This prompts for user account password of remote machine.
The ssh connection gets established, but commands fail with permission denied since its not taking super user password.
How can I fix my issue?
hosts: GSP
tasks:
- name: "make build directory"
command: mkdir -p /home/build/
become: true
become_user: root
- name: "change permissions on the directory"
command: chmod 777 -R /home/
become: true
become_user: root
There's also --ask-become-pass switch for ansible-playbook cli to query user for sudo password.
You can add the ansible_become_pass variable to specify the become password in your playbook.
More details can be found here:
http://docs.ansible.com/ansible/latest/become.html