2018-04-22

Ansible Week - Part 2

We have previously added a service account with a new SSH key to a target host. With that key, we can start using our Ansible setup on it to make administrative changes.

Remember that Ansible is agentless. The service account and SSH key you created are the only elements needed to authenticate your changes against your target host from a central command machine. Because this machine literally holds the keys to your proverbial kingdom, you want to take extra-special precaution that it doesn't fall into the wrong hands. I would run my Ansible node in a dedicated VM, and I'd use full disk encryption on it so its data is protected when not in use.

First thing to do when you're setting up your Ansible config is test that you can remote into your machines. Start with a simple hosts file to describe your environment. Ansible calls this an "inventory":

cat ./hosts.my
[mymachines]
10.0.0.5

[mymachines:vars]
ansible_become_method=doas
ansible_ssh_user=ansible
ansible_ssh_port=22
ansible_ssh_private_key_file=/home/master/ansible/keys/id_ed25519.mymachines

You can see that there is a "[mymachines]" section with an IP address listed, and a "[mymachines:vars]" section with some values defined for it. The IP address is my first target host, and the vars are how I'd set up ansible: using the "ansible" user, connecting via SSH to port 22/tcp, and using a specific SSH key called "id_ed25519.mymachines". This "id_ed25519.mymachines" key was created on the target host in the last post; its corresponding public key will be on the target machine in "~ansible/.ssh/authorized_keys".

You can tell that this box is an OpenBSD machine because the "become" method is "doas", which is a system-specific replacement for "sudo". When the "ansible_ssh_user" account needs root permissions, it supports a number of builtin privilege escalation options, including "doas" and "sudo". It considers this the designated "become method". In other words, this variable answers the question "Which method do I use to become root?"

Now we test:

ansible --inventory=./hosts.my --module-name=ping mymachines

Run ansible, with the inventory file that defines your own target host and which credentials to use to remote to it. We are using the "ping" module, and we are defining the "mymachines" section of the inventory. You can infer from this that an inventory file can be enormous and you can have multiple sections within one file that you can then reference in specific lines as needed, like so:

$ cat ./hosts.full-inventory
[mail]
10.0.0.9
10.0.0.10
10.0.0.11

[dns]
ns1.mydns.host
ns2.mydns.host

[web]
webserver.cloudapp.net

If we just wanted to do something with our [web] machine among the full inventory, we could single it out:

$ ansible --inventory=./hosts.full-inventory -m ping web

Or just the [dns] hosts:

$ ansible --inventory=./hosts.full-inventory -m ping dns

The module we're using, "ping", is the Ansible version of a network test. Can you remote into your targets? Ansible-ping them. The results should be simple:

ansible --inventory=./hosts.my --module-name=ping mymachines
10.0.0.5 | SUCCESS => {
  "changed": false,
  "ping": "pong"
}

Ansible reports back (1) the host it reached, (2) success or failure on the operation, and (3) the result, which was no changes made to the target machine and the response to "ping" was "pong". You're all set to manage this machine with Ansible now.

But just pinging machines is boring. You want to add software, add and remove users, and make configuration changes. Ansible is good for setting up new machines and pushing changes to existing boxes. And the art of crafting a new Ansible configuration exists in how well you write a "playbook", which is a sequence of instructions you define, which are run against one or more hosts in your inventory.

Are you getting a sense of how powerful Ansible can be now?

Next time: Yet Another Yet Another Markup Language post.

No comments: