Automate server setup with Ansible SSH keypairs fails without sshpass - ansible

I'm am using Ansible and want to automate my VPS & Homelab setups. I'm running into an issue, which is the initial connection.
If I have a fresh VPS that has never been used or logged into, how can I remotely configure the node from my laptop?
ansible.cfg
[defaults]
inventory = ./inventory
remote_user = root
host_key_checking = false
ansible_ssh_common_args = "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
inventory
[homelab]
0.0.0.0 <--- actual IP here
./playbooks/add_pub_keys.yaml
---
- hosts: all
become: yes
tasks:
- name: Install public key on remote node
authorized_key:
state: present
user: root
key: "{{lookup('file','~/.ssh/homelab.pub')}}"
Command
ansible-playbook playbooks/add_public_keys.yaml
Now, this fails with permission denied, which makes sense because there is nothing that would allow connection to the remote node.
I tried adding -ask-pass to the command:
ansible-playbook playbooks/add_public_keys.yaml -ask-pass
and typing in the root password, but that fails and says I need sshpass, which is not recommended and not readily available to install on Mac due to security. How should I think about this initial setup process?

When I get issues like this I try and replicate the problem using ansible ad-hoc commands and go back to basics. It helps to prove where the issue is located.
Are you able to run ansible ad-hoc commands against your remote server using the password?
ansible -i ip, all -m shell -a 'uptime' -u root -k
If you can't, something is up with the password or possible in the ansible.cfg.

Related

How to deploy Consul on AWS EC2 instance over Ansible

Note: This is not the Consul by HashiCorp it is a different project: http://consulproject.org/
I'm not sure if this is a specific problem to the consul project or if anyone with knowledge of Ansible and EC2 would be able to solve it.
I am trying to deploy a Consul instance to an Amazon EC2 instance via the Installer. I've followed the instructions found here: https://github.com/consul/installer
I'm doing this from a Mac running macOS Sierra 10.12.6 which has Python 2.7 installed on it.
I downloaded the .pem file from AWS which is a Private Key for SSH authentication. I can SSH into the server via ssh -i [path to .pem file] ec2-user#[ip address of EC2 instance]
I've installed Ansible. When I run:
sudo ansible-playbook -v consul.yml -i hosts
"Please login as the user \"ec2-user\" rather than the user
\"root\".\r\n\r\n"
However, I have edit my group_vars/all file to include root_access: false so I'm not really sure what else needs to be done.
My git diff looks like this from the repository:
diff --git a/group_vars/all b/group_vars/all
index 85bf74d..cb3db37 100644
--- a/group_vars/all
+++ b/group_vars/all
## -10,10 +10,10 ## locale: en_US.UTF-8
# General settings
env: production
-root_access: true
-deploy_user: deploy
+root_access: false
+deploy_user: ec2-user
home_dir: "/home/{{ deploy_user }}"
-deploy_password: test
+deploy_password: <some really great password>
deploy_app_name: test
deploy_server_hostname: 127.0.0.1
consul_dir: "{{ home_dir }}/consul"
## -27,7 +27,7 ## shared_public_dirs:
- "system"
- "ckeditor_assets"
-ssh_public_key_path: "~/.ssh/id_rsa.pub"
+ssh_public_key_path: "[path to .pem file]"
# Ruby
ruby_version: 2.4.9
Do not run the ansible-playbook command with sudo. If the tasks in the playbook need root access (on the remote/managed host), then add become: true where necessary (i.e. either at a task level, play level, or in your Ansible config)
I needed to update the ansible_user.
To do this in this case, I added this line to the group_vars/all file
ansible_user: ec2-user

How to make ansible only ask for become password when required

I am using ansible 2.0.2.0 to update my static website from any computer. My playbook runs on localhost only and essentially has two parts:
Privileged part: Ensure packages are installed, essentially apt tasks with become: true
Unprivileged part: Fill in templates, minify and sync with web hosting service, essentially command tasks without become.
I would prefer having these two parts in the same playbook so that I do not need to worry about dependencies when switching computers. Ideally, I would like ansible to check if the apt packages are installed and only ask for the become password if it needs to install any.
Other, less satisfactory alternatives that I have explored so far and their drawbacks are highlighted below:
sudo ansible-playbook ...: Runs the unprivileged part as root, asks sudo password when not required;
ansible-playbook --ask-become-pass ...: Always asks sudo password, even if no new packages need to be installed;
ansible-playbook ...: Fails with sudo: a password is required.
Is there any way to keep the privileged and unprivileged parts in the same playbook without needlessly typing the sudo password nor giving needless privileges to the unprivileged part?
If you run ansible-playbook with the --ask-sudo-pass parameter, then your second option will ask you for the password once, and will reuse that each time, where needed.
If do run as sudo as in your first case, then you can use become within the script, to lose your privilege status, as you need it.
However, you can setup ansible.cfg to do remote installs to localhost. Hence you can setup an unprivileged ansible user (I use centos), which is setup to sudo without needing a password. Then I setup my local user in the authorized_keys for the centos user.
Hence you run unprivileged (as centos), but when you need to sudo, you can use become_method: sudo to become root.
Using this method I do bare metal installs with the same ansible playbook, as I do remote AWS installs.
Looking at my ansible.cfg I have:-
[defaults]
hostfile = inventory
# use local centos account, and ask for sudo password
remote_user = centos
#ask_pass = true
#private_key_file = ~/packer/ec2_amazon-ebs.pem
My inventory.yml contains:-
[webservers]
localhost
my setup.sh contains:-
ansible-playbook playbook.yml -vvv
#ansible-playbook --ask-sudo-pass playbook.yml
Hence all password asking statements are off. Remember as I don't specify a private_key_file in the defaults, it assumes the running user has authority to ssh to centos#localhost without requiring a password

Running Ansible against host group

When I try running this Ansible command - ansible testserver -m ping it works just fine, but when I try this command - ansible webservers -m ping I get the following error - ERROR! Specified hosts options do not match any hosts.
My host file looks like this -
[webservers]
testserver ansible_ssh_host=127.0.0.1 ansible_ssh_port=2222
What could be the problem? Why can ansible recognize the host in question and not the host group?
I've tried changing the file to make sure ansible is reading from this file specifically, and made sure this is the case, so this is not a problem of reading configurations from another file I am not aware of.
I've also tried using the solutions specified in Why Ansible skips hosts group and does nothing but it seems like a different problem with a different solution.
EDIT - added my anisble.cfg file, to point out I've already made all the vagrant specific configurations.
[defaults]
inventory = ./ansible_hosts
roles_path = ./ansible_roles
remote_user = vagrant
private_key_file = .vagrant/machine/default/virtualbox/private_key
host_key_checking = False
I think you are working with the vagrant and you need to ping like this:
ansible -i your-inventory-file webservers -m ping -u vagrant -k
Why your ping fail prevously:
ansible try to connect to vagrant machine using local login user and it doesn't exist on the vagrant machine
it also need password for the vagrant user which is also vagrant.
Hope that help you.

Ansible execute command locally and then on remote server

I am trying to start a server using ansible shell module with ipmitools and then do configuration change on that server once its up.
Server with ansible installed also has ipmitools.
On server with ansible i need to execute ipmitools to start target server and then execute playbooks on it.
Is there a way to execute local ipmi commands on server running ansible to start target server through ansible and then execute all playbooks over ssh on target server.
You can run any command locally by providing the delegate_to parameter.
- shell: ipmitools ...
delegate_to: localhost
If ansible complains about connecting to localhost via ssh, you need to add an entry in your inventory like this:
localhost ansible_connection=local
or in host_vars/localhost:
ansible_connection: local
See behavioral parameters.
Next, you're going to need to wait until the server is booted and accessible though ssh. Here is an article from Ansible covering this topic and this is the task they have listed:
- name: Wait for Server to Restart
local_action:
wait_for
host={{ inventory_hostname }}
port=22
delay=15
timeout=300
sudo: false
If that doesn't work (since it is an older article and I think I previously had issues with this solution) you can look into the answers of this SO question.

Ansible : Not able to switch user from remote machine

I am new to Ansible. Trying to copy some files to remote machine.
I am able to copy to remote server's tmp folder, but not able to copy to a particular users folder.
I think it is possible if we can switch to that particular user. But I am not able to do so using playbook.
Please help me on this.
Regards,
KP
This is a permission issue. The user which you use to connect to the host does not have permissions to write to that other users folder.
If you have access to that users account (e.g. your ssh key is accepted) you can simply define the user per task through remote_user:
- copy: src=...
dest=...
remote_user: <SET_OWNER_HERE>
If you do not have access, you can use the sudo flag to execute a task with root permissions. But make sure you set the permissions correctly or the user might not be able to read/write those files:
- copy: src=...
dest=...
owner=<SET_OWNER_HERE>
group=<SET_GROUP_HERE>
mode=0644
sudo: yes
Also, you can define the username as which the sudo command is executed with sudo_user:
- copy: src=...
dest=...
sudo: yes
sudo_user: <SET_OWNER_HERE>
If sudo requires a password from you, you have to provide it or the task will hang forever without any error message.
You can define this globally in the ansible.cfg:
ask_sudo_pass=True
Or pass the option when you call your playbook:
ansible-playbook ... --ask-sudo-pass

Resources