mirror of
https://github.com/Rudd-O/ansible-qubes.git
synced 2025-03-01 14:22:33 +01:00
177 lines
7.6 KiB
Markdown
177 lines
7.6 KiB
Markdown
Qubes OS DevOps automation toolkit: Ansible example
|
|
==================================================
|
|
|
|
This is an example of Ansible automation that leverages this toolkit to
|
|
let you manage Qubes VMs. These instructions assume that you have already:
|
|
|
|
1. cloned this entire project into directory `/home/user/ansible-qubes`
|
|
2. installed Ansible (`yum install ansible`) in the TemplateVM of that AppVM
|
|
3. opened a terminal window and changed to the directory containing this file
|
|
|
|
They also assume a bit of familiarity with Ansible as well. If you would like
|
|
to get an introduction on Ansible concepts, this examples directory is ripe
|
|
for a compare-and-contrast exercise with the
|
|
[Ansible introduction](https://docs.ansible.com/ansible/intro_getting_started.html).
|
|
|
|
Now, let's do a quick walkthrough of these files.
|
|
|
|
Ansible configuration
|
|
---------------------
|
|
|
|
The starting point is the file [`ansible.cfg`](./ansible.cfg). This file tells Ansible where
|
|
to find the requisite components to make the Qubes automation work. As
|
|
you can see, it's composed mostly of paths, and it points you to the
|
|
[`hosts`](./hosts) file.
|
|
|
|
Importantly, because Ansible will look for the [`ansible.cfg`](./ansible.cfg) file
|
|
on your current directory first, that means you will be running your
|
|
Ansible commands on the directory containing [`ansible.cfg`](./ansible.cfg). Later, you can
|
|
deploy aliases, symlinks or helpers to help you work around that.
|
|
|
|
Inventory
|
|
---------
|
|
|
|
The [`hosts`](./hosts) file is your machine inventory -- the VMs (and also physical
|
|
machines) that you own, and how they group together. The included inventory
|
|
is almost certainly guaranteed not to match the machines you have, nor how
|
|
you've grouped them conceptually, so feel free to edit it how you see fit. To
|
|
learn more about managing the inventory, check out [the relevant Ansible
|
|
documentation](https://docs.ansible.com/ansible/intro_inventory.html).
|
|
|
|
Two key things to note about the inventory:
|
|
|
|
1. You denote which machines are Qubes VMs by setting the `ansible_connection`
|
|
property to `qubes` on the configuration line specifying the inventory
|
|
entry. Instead of a host name, you use the VM name to refer to the
|
|
machine.
|
|
2. You can (of course, if the VM holding these files has network
|
|
connectivity) mix and match hosts you can manage via SSH into your
|
|
inventory.
|
|
|
|
How Ansible knows to connect to your Qubes VMs
|
|
----------------------------------------------
|
|
|
|
Importantly, nothing about this is magic. `qubes` in the `ansible_connection`
|
|
parameter merely tells Ansible to use the
|
|
[Qubes connection plugin](../../ansible/connection_plugins/qubes.py)
|
|
as pointed to by the [`ansible.cfg`](./ansible.cfg) file. That file automatically enlists
|
|
the `bombshell-client` technology to connect you to your VMs via Ansible.
|
|
|
|
When `bombshell-client` starts, it attempts to connect to the target VM's
|
|
`qubes.VMShell` service. This is a small Qubes RPC stub that allows a calling
|
|
VM to execute any command on the target VM. Of course, all of this is
|
|
always subject to the Qubes authorization mechanism, so it's secure.
|
|
|
|
Time to test drive it!
|
|
----------------------
|
|
|
|
Add some of your VMs to your inventory now. Let's assume you've added your
|
|
`work` VM to the inventory, and that you are running this from a `manager`
|
|
VM you've created for the purpose.
|
|
|
|
Ready?
|
|
|
|
OK, let's try the following. On the terminal window, type:
|
|
|
|
ansible work -m shell -a whoami
|
|
|
|
Qubes OS will ask you for permission to run several shell commands from the
|
|
`manager` VM to the `work` VM. Accept those prompts, and you'll see
|
|
something like this:
|
|
|
|
[user@manager ansible]$ ansible work -m shell -a whoami
|
|
work | success | rc=0 >>
|
|
user
|
|
|
|
That's your `work` VM responding with `I am logged in as user`, which
|
|
happens to be the user that Ansible logged into your VM as. The above
|
|
command line makes the `shell` module (specified in the command line as
|
|
`-m shell`) execute its arguments (specified with `-a`). Ansible has a ton
|
|
of execution modules, and they are all documented here:
|
|
|
|
* [Intro to modules](https://docs.ansible.com/ansible/modules.html)
|
|
* [Module index](https://docs.ansible.com/ansible/modules_by_category.html)
|
|
|
|
Connecting to dom0
|
|
------------------
|
|
|
|
If you're running a bit ahead of these instructions, you may have noticed
|
|
that running `ansible dom0 -m shell whoami` actually results in an error.
|
|
|
|
This is by design from the Qubes team -- the `qubes.VMShell` service does
|
|
not ship in the `dom0` VM at all. If you'd lik to be able to manage `dom0`
|
|
from your configuration management system, all you need to do is deploy
|
|
the necessary configuration to `dom0`.
|
|
|
|
See the heading *Enabling bombshell-client access to dom0* in the top-level
|
|
`README.md` file of this toolkit for instructions on how to do that.
|
|
|
|
Running modules as root
|
|
-----------------------
|
|
|
|
You can, however, demand to execute commands as `root` wih the parameter `-s`:
|
|
|
|
[user@manager ansible]$ ansible work -s -m shell -a whoami
|
|
work | success | rc=0 >>
|
|
root
|
|
|
|
`-s` makes the `shell` module execute its arguments as root. In fact, it
|
|
makes any Ansible module run as root. Ansible has a ton of execution modules, and they
|
|
are all documented here:
|
|
|
|
* [Intro to modules](https://docs.ansible.com/ansible/modules.html)
|
|
* [Module index](https://docs.ansible.com/ansible/modules_by_category.html)
|
|
|
|
Note that running as root may require the `sudo` package to be installed
|
|
first. If you encounter problems getting to root, then please install
|
|
the `sudo` package on the VM you're targeting (or, more appropriately,
|
|
in its template, if it is a template-based VM).
|
|
|
|
Targeting multiple machines
|
|
---------------------------
|
|
|
|
So far, we've targeted only the `work` VM, but technically you can target any
|
|
machine or group of machines in your inventory. Based on the (entirely
|
|
fictional) inventory shipped in this example:
|
|
|
|
* `ansible work:netvm ...` targets two VMs
|
|
* `ansible appvms ...` targets all VMs in a group `appvms`.
|
|
* `ansible 'all:!nonqubes' ...` targets all inventory machines minus the
|
|
non-Qubes ones.
|
|
|
|
Playbooks
|
|
---------
|
|
|
|
Everything you've seen so far applies to simple `ansible` runs. But the real
|
|
worth of Ansible is the possiblity to weave repeatable, idempotent scripts
|
|
that involve multiple machines, so you're not constantly repeating yourself.
|
|
Enter [`ansible-playbook`](https://docs.ansible.com/ansible/playbooks.html),
|
|
generously documented there, and exemplified here.
|
|
|
|
For a quick primer on how to run playbooks, here are the essentials:
|
|
|
|
ansible-playbook -v <playbook YML file> [-l <only these hosts>]
|
|
|
|
This would tell `ansible-playbook` to run every step of the playbook file
|
|
in order, on all the hosts it targets on each `hosts` stanza. Should you
|
|
want to limit your run to a subset of the hosts, you can use the `-l` argument
|
|
and pass those hosts, which are in the exact same format as the one
|
|
taken by the `ansible` command on its hosts specification list.
|
|
|
|
We ship several different sample playbooks:
|
|
|
|
* `test-nofacts.yml`: logs into the specified machines and retrieves
|
|
variables, but without the fact gathering process, leaving the collected
|
|
environment in a `/tmp/` directory.
|
|
* `test-facts.yml`: does the same thing, but collects facts about the targeted
|
|
hosts before dumping the variables.
|
|
* `editors.yml`: deploys some text editors on your template VMs (assumed
|
|
to be Fedora).
|
|
* `qubes-service.yml`: deploys a Qubes service to your template VM, which
|
|
can later be turned on via the Services tab of the properties window of
|
|
VMs based on the template. In the example, the service is named
|
|
`qubes-helloworld`, so that would be the name of the service to
|
|
add and enable on the Services tab.
|
|
|
|
More will come as time goes by. For now, that's all. Happy hacking!
|