Ansible 2.0.0.2: ansible doesn't respect the "- u" switch - ansible

I'm probing a freshly installed Archlinux installation on a Raspberry PI 2 like so:
ansible -i PI2 arch -m setup -c paramiko -k -u alarm -vvvv
This reads to me: Fire the setup module against the IP connecting with the user "alarm" asking for the password of this specific user. However the user that eventually attempts to connect is "root".
Here's the debug response:
Loaded callback minimal of type stdout, v2.0
<192.168.1.18> ESTABLISH CONNECTION FOR USER: root on PORT 22 TO 192.168.1.18
192.168.1.18 | UNREACHABLE! => {
"changed": false,
"msg": "ERROR! Authentication failed.",
"unreachable": true
}
The inventory looks like this:
[arch]
192.168.1.18
Some things that may or may not be relevant are the following:
ssh logins via root are not permitted
sudo is not installed
default user and pass are "alarm" : "alarm"
no ssh key being copied to the machine hence the paramiko connection attempt
What is NOT ignored and leads to a successful connection is adding ansible_user=alarm to the IP line in the inventory file.
EDIT
Found this interesting passage in the official docs: http://docs.ansible.com/ansible/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable which states:
Another important thing to consider (for all versions) is that connection specific variables override config, command line and play specific options and directives. For example:
ansible_user will override-u andremote_user: `
The original question seems to remain though. Without any mention of ansible_user in the inventory, why is root being used instead of the explicitly mentioned user via - u?
EDIT_END
Is this expected behaviour?
Thanks

You don't need to specify paramiko as the connection type, Ansible will figure that part out. You may have a group_vars directory with an ansible_user or ansible_ssh_user variable defined for this host which could be overriding the alarm user.
I was able to replicate your test on ansible 2.0.0.2 without any issues against a raspberry pi 2 running Raspian:
➜ ansible ansible -i PI2 arch -m setup -u alarm -vvvv -k
Using /etc/ansible/ansible.cfg as config file
SSH password:
Loaded callback minimal of type stdout, v2.0
<192.168.1.84> ESTABLISH CONNECTION FOR USER: alarm on PORT 22 TO 192.168.1.84
CONNECTION: pid 78534 waiting for lock on 9
CONNECTION: pid 78534 acquired lock on 9
paramiko: The authenticity of host '192.168.1.84' can't be established.
The ssh-rsa key fingerprint is 54e12e8153e0319f450934d606dca7df.
Are you sure you want to continue connecting (yes/no)?
yes
CONNECTION: pid 78534 released lock on 9
<192.168.1.84> EXEC ( umask 22 && mkdir -p "$( echo $HOME/.ansible/tmp/ansible-tmp-1454502995.07-263327298967895 )" && echo "$( echo $HOME/.ansible/tmp/ansible-tmp-1454502995.07-263327298967895 )" )
<192.168.1.84> PUT /var/folders/39/t0dm88q50dbcshd5nc5m5c640000gn/T/tmp5DqywL TO /home/alarm/.ansible/tmp/ansible- tmp-1454502995.07-263327298967895/setup
<192.168.1.84> EXEC LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/alarm/.ansible/ tmp/ansible-tmp-1454502995.07-263327298967895/setup; rm -rf "/home/alarm/.ansible/tmp/ansible-tmp-1454502995. 07-263327298967895/" > /dev/null 2>&1
192.168.1.84 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.1.84"
],

I virtualenv'd myself a Ansible 1.9.4 sandbox, copied over the ansible.cfg and the inventory and ran the command again. Kinda worked as expected:
⤷ ansible --version
ansible 1.9.4
configured module search path = None
(ANS19TEST)~/Documents/Code/VENVS/ANS19TEST
⤷ ansible -i PI2 arch -m setup -c paramiko -k -u alarm -vvvv
SSH password:
<192.168.1.18> ESTABLISH CONNECTION FOR USER: alarm on PORT 22 TO 192.168.1.18
<192.168.1.18> REMOTE_MODULE setup
From where I'm standing I'd say this is a bug. Maybe somebody can confirm?! This goes to the bugtracker then...
Cheers
EDIT
For brevity I omitted a important part of my inventory file, which ultimately is responsible for the behavior. It looks like this:
[hypriot]
192.168.1.18 ansible_user=root
[arch]
192.168.1.18
Quote from the Ansible bugtracker:
The names used in the inventory is the key in a dictionary. So everything you put in there as host-specific variables will be merged into one big dictionary. That means that in some conflicting cases variables are superseded by other values.
You can prevent this by using different names for the same host (e.g. using IP address and hostname, or an alias or DNS-alias) and in that case you can still do what you like to do.
So my inventory looks like this now:
[hypriot]
hypriot_local ansible_host=192.168.1.18 ansible_user=root
[archlinux]
arch_local ansible_host=192.168.1.18
This works fine. The corresponding issue on the Ansible tracker is here: https://github.com/ansible/ansible/issues/14268

Related

Ansible :execute playbook from localhost through bastion host

I am newbie to the ansible
We are doing our deployments via ansible and a bastion host is provisioned for the deployments.
The current approach I am using is to clone the ansible repo in bastion host and run the commands from that folder
My question is it possible to run the ansible code through the local machine through bastion??
(basically, avoid the repo in bastion host)
Let's say you want to provision a couple of VMs 172.20.0.10 and 172.20.0.11 in your development environment going through your 172.20.0.1 bastion. Your inventory looks a bit like this
[development]
172.20.0.10
172.20.0.11
Then you can edit your ~/.ssh/config and add
Host bastion
Hostname 172.20.0.1
User youruser
Host 172.20.*
ProxyJump bastion
User youruser
Then you can test a ssh 172.20.0.10 that should land you in your first VM. If it works for SSH, Ansible should work the same.
Note, you can run ansible with -vvv (or is it one more v, not sure atm), you'll see the SSH commands Ansible is running.
Note 2, ProxyJump requires a recent OpenSSH, 6.7 at least if I remember correctly
Using this data
host remoto : 10.0.1.121
user remoto : application_user
ssh key : app_ssh_key
host bastian : 212.34.345.12
user bastian : bastian_user
ssh key: bastian_ssh_key
and using key to access with ssh (you have to store keys in a secure storage, not with ansible playbook).
In a ssh single command
$ ssh application_user#10.0.1.121 -i path/to/app_ssh_key \
-o ProxyCommand="ssh -q bastian_user#212.34.345.12 -i path/to/bastian_ssh_key -W %h:%p"
In ansible
you can use two method:
Method 1
Use variables for inventory machine/group, in order to have different connection option for different machine/group.
Add to inventory file:
[remote-vm]
10.0.1.121
[remote-vm:vars]
ansible_ssh_user=application_user
ansible_ssh_private_key_file=path/to/app_ssh_key
ansible_ssh_common_args= -o ProxyCommand="ssh -q bastian_user#212.34.345.12 -i path/to/bastian_ssh_key -W %h:%p"
Method 2
Single configuration valid for all inventory machines.
Add to/replace in ansible.cfg:
[defaults]
remote_user = application_user
[ssh_connection]
ssh_args=-i path/to/app_ssh_key -o ProxyCommand="ssh -q bastian_user#212.34.345.12 -i path/to/bastian_ssh_key -W %h:%p"

Ansible root/password login

I'm trying to use Ansible to provision a server and the first thing I want to do is test the ssh access. If I use ssh directly I can log in fine...
ssh root#server
root#backups's password:
If I use Ansible I can't...
user#ansible:~$ ansible backups -m ping --user root --ask-pass
SSH password:
backups | UNREACHABLE! => {
"changed": false,
"msg": "Invalid/incorrect password: Permission denied, please try again.",
"unreachable": true
}
The password I'm using is correct - 100%.
Before anyone suggests using SSH keys - that's what part of what I'm looking to automate.
The issue was caused by the getting started documentation setting a trap.
It instructs you to create an inventory file with servers, use ansible all -m ping to ping those servers and to use the -u switch to change the remote user.
What it doesn't tell you is that if like me not all you servers have the same user, the advised way to specify a user per server is in the inventory file...
server1 ansible_connection=ssh ansible_user=user1
server2 ansible_connection=ssh ansible_user=user2
server3 ansible_connection=ssh ansible_user=user3
I was provisioning a server, and the only user I had available to me at the time was root. But trying to do ansible server3 -user root --ask-pass failed to authenticate. After a couple of wasted hours I discovered the -user switch is only effective if the inventory file doesn't have a user. This is intended precedence behaviour. There are a few gripes about this in GitHub issues but a firm 'intended behaviour' mantra is the response you get if you challenge it. It seems to go against the grain to me.
I subsequently discovered that you can specify -e 'ansible_ssh_user=root' to override the inventory user - I will see about creating a pull request to improve the docs.
While you're here, I might be able to save you some time with some further gotchas. This behaviour is the same if you use playbooks. In there you can specify a remote_user but this isn't honoured - presumably also because of precedence. Again you can override the inventory user with -e 'ansible_ssh_user=root'
Finally, until I realised Linode could provision a server with an SSH key deployed, I was trying to specify the root password to an ad-hoc command. You have to encrypt the password and this gives you a long string and this is almost certainly going to include $ in it which bash will treat as substitutions. Make sure you escape these.
The lineinfile module behaviour isn't intuitive either.
Write your hosts file like this. It will work.
192.168.2.4
192.168.1.4
[all:vars]
ansible_user=azureuser
Then execute the following command: ansible-playbook --ask-pass -i hosts main.yml --check to check before configuration.
Also create a ansible.cfg file. Then paste the following contents there:
[defaults]
inventory = hosts
host_key_checking = False
Note: All the 3 files namely, main.yml,ansible.cfg & hosts must be in the same folder.
Also, the code is tested for devices connected to a private network using Private IPs. I haven't checked using Public IPs. If using Azure/AWS, create a test VM and connect it to the VPN of the other devices.
Note: You need to install the SSHPass package to be able to authenticate with Password.
For Ubuntu: apt-get install sshpass

Ansible Module Failure – Unknown Cause

SYNOPSIS
I was getting the following error when trying to run both the standard ansible all -m ping and ansible all -a "pwd" (The second command is just in the case the ping module was the issue):
..."module_stdout": " File \"/tmp/ansible_C2IrV6/ansible_module_command.py\", line 183\r\n out = b''\r\n ^\r\nSyntaxError: invalid syntax\r\n",...
My issue was that I was somehow running an unreleased Ansible version (2.4.0) due to installation via pip. This was conflicting with my yum installation (2.3.1.0), compounded by an incompatibility with my current Python version (2.6.6).
My solution was to uninstall both versions to ensure I no longer had ansible on my system. From there, I used yum to reinstall ansible to a version that I knew was compatible (2.3.1.0). I have also read that it's possible to use pip to specify the version:
pip install ansible==<version>
There are more details on installing different versions here
ORIGINAL POST
I've seen many instances where people seem to have my exact issue, but it always ends up being something slightly different. Regardless, I attempt the solutions to no avail.
I'm running Ansible 2.4.0 on what I believe is RHEL6:
$ uname -a
Linux <server address> 2.6.32-642.11.1.el6.x86_64 #1 SMP Wed Oct 26 10:25:23 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux
The host I'm communicating with is running RHEL5.
When I run this command:
$ sudo ansible all -a "pwd" -vvvv
I get the following result:
Verbose Ansible Output
Extracting the ssh command from the above output:
$ ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o 'IdentityFile="/root/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath=~/.ansible/cp' user#hostDestination '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
Result:
Extracted Ansible SSH Command Output
Based on the result above, it seems like the command makes a successful connection, so I don't see why Ansible is giving me the Permission Denied
EDIT: Thanks to #KonstantinSuvorov, I was able to more precisely pin down my issue – I seem to have attributed a module failure to the command's result of Permission Denied because I got the best response using sudo. See his post for why that was an issue.
Some Additional Information
On the server with Ansible installed, I have super user privileges. On the destination host I do not.
Normal SSHing into the destination host works perfectly fine and vice versa.
The following is what we see upon successfully logging in to any of our servers here at work, so don't be alarmed when it isn't familiar:
***************************************************************
* *
* Do not attempt to log on unless you are an authorized user. *
* *
* You must have a valid Network account. *
* *
***************************************************************
If it's necessary, I'll provide my ansible.cfg when I get back to the office tomorrow.
Forgive me if this belongs in SuperUser, ServerFault, or somewhere else.
UPDATE
Running the command without sudo:
ansible all -a "/bin/pwd" -vvvv
Result:
Verbose Ansible Command Without Sudo
UPDATE 2
After placing ssh_args= under [ssh_connection] in my ansible.cfg:
ansible all -a "pwd"
Result:
hostDestination | FAILED! => {
"changed": false,
"failed": true,
"module_stderr": "\n***************************************************************\n* *\n* Do not attempt to log on unless you are an authorized user. *\n* *\n* You must have a valid Network account. *\n* *\n***************************************************************\n\nConnection to hostDestination closed.\r\n",
"module_stdout": " File \"/tmp/ansible_C2IrV6/ansible_module_command.py\", line 183\r\n out = b''\r\n ^\r\nSyntaxError: invalid syntax\r\n",
"msg": "MODULE FAILURE",
"rc": 0
}
NOTE: Running the command with Ansible's raw module is successful:
ansible all -m raw -a "pwd"
Result:
hostDestination | SUCCESS | rc=0 >>
/home/user
***************************************************************
* *
* Do not attempt to log on unless you are an authorized user. *
* *
* You must have a valid Network account. *
* *
***************************************************************
Shared connection to hostDestination closed.
When I look at the verbose output (-vvvv) of the regular command I see the following modules being used:
Using module_utils file /usr/lib/python2.6/site-packages/ansible-2.4.0-py2.6.egg/ansible/module_utils/basic.py
Using module_utils file /usr/lib/python2.6/site-packages/ansible-2.4.0-py2.6.egg/ansible/module_utils/_text.py
Using module_utils file /usr/lib/python2.6/site-packages/ansible-2.4.0-py2.6.egg/ansible/module_utils/parsing/convert_bool.py
Using module_utils file /usr/lib/python2.6/site-packages/ansible-2.4.0-py2.6.egg/ansible/module_utils/parsing/__init__.py
Using module_utils file /usr/lib/python2.6/site-packages/ansible-2.4.0-py2.6.egg/ansible/module_utils/pycompat24.py
Using module_utils file /usr/lib/python2.6/site-packages/ansible-2.4.0-py2.6.egg/ansible/module_utils/six/__init__.py
Using module file /usr/lib/python2.6/site-packages/ansible-2.4.0-py2.6.egg/ansible/modules/commands/command.py
I feel like one or more modules may be the issue seeing as the last line in the output above is similar to the following line in the failed command's output:
... /tmp/ansible_C2IrV6/ansible_module_command.py\ ...
It looks as if the Python interpreter is having an issue with the syntax of the empty binary string in this file. Unfortunantely, Ansible deletes the file immediately after running the command – preventing me from looking at line 183 to make my own assessment.
You run ansible with sudo under root account and it tries to use ssh-keys from root account (which are absent?).
When you try ssh command, you run it under your current user account and use another access key.
I believe you have no reasons to use sudo here.

needrestart behaves differently when run by ansible instead of a manual ssh connection

I am trying to run the needrestart tool by ansible to check for processes with outdated libraries.
When I run needstart with the command or shell modules from ansible it says that I need to restart my ssh daemon. When I run needrestart manually it says that there are no processes with outdated libraries.
When I restart the ssh daemon it does not make a difference. But after rebooting the remote server the ssh daemon is not listed as a service I should restart anymore.
So I really do not understand the difference between the ssh connection from ansible and my manual ssh connection that causes the different behavior of needrestart.
Any help would be appreciated!
Thank you in advance and best regards
Max
My local machine
$ python -V
Python 2.7.13
$ ansible --version
ansible 2.2.0.0
$ cat ansible.cfg
[defaults]
inventory = hosts
ask_vault_pass = True
retry_files_enabled = False
I am using a ssh proxy to connect to the server:
ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q user#jumphost.example.com"'
The remote server
$ cat /etc/debian_version
8.6
$ python -V
Python 2.7.9
Using ansible
$ ansible example.com -m command -a 'needrestart -b -l -r l'
Vault password:
example.com | SUCCESS | rc=0 >>
NEEDRESTART-VER: 1.2
NEEDRESTART-SVC: ssh.service
$ ansible example.com -m shell -a 'needrestart -b -l -r l'
Vault password:
example.com | SUCCESS | rc=0 >>
NEEDRESTART-VER: 1.2
NEEDRESTART-SVC: ssh.service
Using SSH
$ ssh example.com 'needrestart -b -l -r l'
NEEDRESTART-VER: 1.2
Killed by signal 1.
It looks like you have an active connection with older version of ssh process. When ssh restarts it does not terminate current copies which keeps active connections. If it would do this, than ssh servers sudo service ssh restart would kill active connection and you'll have a broken server.
So, when you do systemctl restart sshd, you restart only ssh-part, which accepts new connection. All existing connections are served by old ssh.
Why do ansible keep ssh old ssh connection between runs? Because of the ControlMaster feature. It keeps active ssh connection between runs to speed up new runs.
What to do? Close active ssh connections on your machine. Try ps aux|grep ssh and you'll see a process which serves as ControlMaster. Kill it, and outdated connection should be closed.

Ansible Timeout (12s) waiting for privilege escalation prompt

I'm having trouble running my Ansible playbook on AWS instance. Here is my version:
$ ansible --version
ansible 2.0.0.2
I created an inventory file as:
[my_ec2_instance]
default ansible_host=MY_EC2_ADDRESS ansible_user='ubuntu' ansible_ssh_private_key_file='/home/MY_USER/MY_KEYS/MY_KEY.pem'
Testing connection to my server:
$ ansible -i provisioner/inventory my_ec2_instance -m ping
default | SUCCESS => {
"changed": false,
"ping": "pong"
}
Now when running my playbook on this inventory I get the error Timeout (12s) waiting for privilege escalation prompt as follows:
$ ansible-playbook -i provisioner/inventory -l my_ec2_instance provisioner/playbook.yml
PLAY [Ubuntu14/Python3/Postgres/Nginx/Gunicorn/Django stack] *****
TASK [setup] *******************************************************************
fatal: [default]: FAILED! => {"failed": true, "msg": "ERROR! Timeout (12s) waiting for privilege escalation prompt: "}
NO MORE HOSTS LEFT *************************************************************
PLAY RECAP *********************************************************************
default : ok=0 changed=0 unreachable=0 failed=1
If I run the same playbook using the .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory as the inventory parameter it works perfectly on my Vagrant instance.(I believe, proving there is nothing wrong in the playbook/roles itself)
Also, if I run it with an -vvvv, copy the exec ssh line and run it manually it indeed connects to AWS without problems.
Do I need to add any other parameter on my inventory file to connect an EC2 instance? What am I missing?
$ vim /etc/ansible/ansible.cfg
SSH timeout
[defaults]
timeout = 10 ( change to 60 )
There is a git issue about this error that affect various versions of Ansible 2.x in here https://github.com/ansible/ansible/issues/13278#issuecomment-216307695
My solution was simply to add timeout=30 to /etc/ansible/ansible.cfg.
This is not a "task" or "role" timeout and was enough to solve the error (I do have some roles/tasks that take much longer than that).
In my case, the root cause was an incorrect entry in /etc/hosts for the localhost, causing a 20s delay for any sudo command.
127.0.0.1 wronghostname
Changed it to the correct hostname to fix it. No more delay for sudo/privileged commands.
In my case it was because my playbook had
become_method: su
become_flags: "-"
which prompts a password request on the host.
Adding ansible-playbooks … --ask-become-pass and passing the password solved the issue.
I ran the command like follows & it works :
command:
ansible-playbook -c paramiko httpd.yml
As the issue is related to the openssl implementation, the usage of paramiko dodges it.
Ansible defaults ssh_args setting, as documented here https://docs.ansible.com/ansible/latest/reference_appendices/config.html#ansible-ssh-args, is
-C -o ControlMaster=auto -o ControlPersist=60s
and by changing ControlMaster to either yes (or no) resolved the issue for me (somehow):
ansible.cfg:
[ssh_connection]
ssh_args = -C -o ControlMaster=yes -o ControlPersist=60s
I had the same issue. I was able to solve it adding become_exe: sudo su -
- hosts: "{{ host | default('webservers')}}"
become: yes
become_user: someuser
become_method: su
become_exe: sudo su -
The thread is old but the varied solutions keep coming.
In my case, the issue was that the ansible script had modified the sudoers file in the vagrant vm to add an entry for the vagrant group (%vagrant) after the existing entry for the vagrant user.
That was enough to cause the ansible script to timeout waiting for privilege escalation.
The solution was to force the sudoers entry for the vagrant group to be above the entry for the vagrant user.
Sometime setup phase takes more time for ec2 instances, you need to change timeout value in ansible.cfg to something like timeout=40 . This will set the timeout value to 40 seconds.
I fixed this error for my system because I forgot I had altered the ansible config file:
sudo vim /etc/ansible/ansible.cfg
Try commenting the priviledge parameters that could be trying to sudo to root.
like so:
[privilege_escalation]
#become=True
#become_method=su
#become_user=root
#become_ask_pass=False
#become_exe="sudo su -"
The account I was trying to ssh as did not have permission to become root.
I am building secure VM images for AWS, QEMU and VBox on an isolated network, with limited DNS support. Increasing the SSH Timeout to 40 sec had limited effect in my situation.
I am using Packer v1.5.5, Ansible v2.9.2 and OpenSSH v7.4p1
My solution was to change the UseDNS parameter in /etc/ssh/ssd_config to no.
I added the following lines in my RHEL/CentOS kickstart configuration, with great result.
%post
# Disable DNS lookups by sshd to address Ansible timeouts
perl -npe 's/^#UseDNS yes/UseDNS no/g' -i /etc/ssh/sshd_config
%end
Check if it is a problem with an old version of sudo at destination server. Some old sudo versions does not have the -n option ansible uses.

Resources