mirror of
https://github.com/Rudd-O/ansible-qubes.git
synced 2025-03-01 14:22:33 +01:00
add example of qubesformation technology
This commit is contained in:
parent
ff34ab7725
commit
0369485fab
@ -164,6 +164,12 @@ and fourth parameters `--management-proxy <M>`, then it is assumed
|
||||
that you want to connect to the VM through the IP address of the
|
||||
management proxy `<M>`.
|
||||
|
||||
How to use the Salt management interface for Qubes in Ansible
|
||||
-------------------------------------------------------------
|
||||
|
||||
Documentation is a bit sparse at the moment, so the best bet is
|
||||
to follow [the tutorial contained in the corresponding example](./examples/qubesformation/).
|
||||
|
||||
Bug bounties
|
||||
------------
|
||||
|
||||
|
@ -5,4 +5,6 @@ This is the examples directory. Each example within this directory has a
|
||||
`README.md` file that explains it further. Feel free to use these examples
|
||||
as templates to get your own automation started.
|
||||
|
||||
* [ansible/](ansible/) contains an example Ansible setup.
|
||||
* [ansible/](ansible/) contains a basic example Ansible setup.
|
||||
* [qubesformation/](qubesformation/) details how to use the Qubes formation
|
||||
Ansible module, used to provision VMs and enforce state on those VMs.
|
||||
|
168
examples/qubesformation/README.md
Normal file
168
examples/qubesformation/README.md
Normal file
@ -0,0 +1,168 @@
|
||||
Qubes OS DevOps automation toolkit: Provisioning example
|
||||
========================================================
|
||||
|
||||
This example shows how to use the `qubesformation` and `qubessls`
|
||||
action plugins to:
|
||||
|
||||
* automatically provision a number of VMs entirely based on your Ansible
|
||||
inventory, as well as
|
||||
* alter and enforce settings on your provisioned VMs over time.
|
||||
|
||||
These Ansible plugins leverage the newly-added
|
||||
[Salt management stack in Qubes 3.1](https://www.qubes-os.org/news/2015/12/14/mgmt-stack/)
|
||||
in a very simple way: they use your inventory information to generate
|
||||
a Salt formula (a "top"), and then use the `qubesctl` command to realize
|
||||
said formula.
|
||||
|
||||
This example assumes you are familiar with:
|
||||
|
||||
* [the previous example](../ansible/)
|
||||
* Ansible concepts like the inventory, host vars, group vars, and the like
|
||||
* the [Salt management stack in Qubes](https://www.qubes-os.org/news/2015/12/14/mgmt-stack/).
|
||||
|
||||
Additionally, we assume that you are running this sample Ansible setup within
|
||||
an AppVM on your Qubes OS machine -- similar to what we did in the basic
|
||||
example mentioned before.
|
||||
|
||||
Defining the inventory
|
||||
----------------------
|
||||
|
||||
Let's start by examining the [inventory file](./hosts). What do we
|
||||
see?
|
||||
|
||||
1. Our targets under `# Hosts defined here`. For the purposes of this example,
|
||||
these will be the VMs we will configure, as well as the templates we will
|
||||
rely on, and finally the `dom0` machine where the magic will happen.
|
||||
2. A list of `[groups]` that identify VMs based on the type. You can group
|
||||
your own VMs however you like. The key characteristic of these groups,
|
||||
however, is that the all the groups are listed under `[vms:children]`,
|
||||
which tells Ansible there's a "group of groups" called `vms`, that
|
||||
includes all VMs we will manage in this example.
|
||||
3. A configuration variable applied to *all*hosts under the stanza
|
||||
`[all:vars]`. This tells Ansible that all of the hosts it knows about,
|
||||
it must contact via the [Qubes connection plug-in for Ansible](../../ansible/connection_plugins/qubes.py).
|
||||
|
||||
Defining the requisite variables for the creation of the formula
|
||||
----------------------------------------------------------------
|
||||
|
||||
At this point, we need to assign a few variables to each VM we want
|
||||
to provision. Let's start by defining which inventory host will be
|
||||
the `dom0` for all of the VMs (yes, this system is compatible
|
||||
with it being used on multiple Qubes OS machines, so we cannot just
|
||||
assume that there's a single `dom0`).
|
||||
|
||||
Look at the [group vars file for the group `vms`](group_vars/vms.yml).
|
||||
This vars file contains one dictionary `qubes`, with a sole attribute
|
||||
`dom0_vm`. Since this attribute will be inherited (as per Ansible variable
|
||||
precedence) by all VMs in the super-group `vms`, we've effectively told
|
||||
Ansible that all VMs have `dom0` as their `dom0_vm`.
|
||||
|
||||
Now let's direct our attention to [host vars](host_vars/). You'll note there
|
||||
are a few notable attributes we are defining per hosts:
|
||||
|
||||
* `qubes.template_vm`: designates which VM will be used as a template
|
||||
for the VM in question. Note how most VMs have `app-template`
|
||||
as their template, except for `app-template` itself, which has `fedora-23`
|
||||
as template -- this will tell the formula to clone `app-template` from
|
||||
`fedora-23` if it doesn't exist already. Also note that `fedora-23` itself
|
||||
has no template -- this tells the formula to simply expect its existence.
|
||||
As `fedora-23` is generally a built-in template of Qubes, that should
|
||||
work as we expected.
|
||||
* `qubes.vm_type`: this assigns the VM type we expect to instantiate.
|
||||
There are several types: TemplateVM, StandaloneVM, NetVM, ProxyVM
|
||||
and AppVM. Depending on the type, the formula will perform a
|
||||
different action to bring the VM into existence. Note that we could have
|
||||
set the attribute `vm_type` in a `group_vars` file for its type -- but,
|
||||
since this is a small example, we set the attribute directly in each
|
||||
`host_vars` file.
|
||||
* `qubes.netvm_vm`: this assigns the NetVM to which the VM
|
||||
will be attached. It's not mandatory to assign one -- in which case
|
||||
the system will automatically assign the default NetVM to the
|
||||
created VM. To explicitly demand no NetVM, you can always say
|
||||
`netvm_vm: None`. In our example, the VM we want to use as
|
||||
NetVM is almost always `firewall`, except in the case of `firewall`
|
||||
itself, in which case we use `wired-netvm`.
|
||||
* `qubes.label`: sets the color label you're already familiar with.
|
||||
* `qubes.pcidevs` and `qubes.services` set the PCI devices to
|
||||
attach to the VM, and the services to enable or disable. `pcidevs`
|
||||
is a list of strings denoting PCI IDs in their short form (without the
|
||||
leading `0000`, as expected by `qvm-prefs`). `services` is a
|
||||
dictionary of `{service_name: value}`, where the value is
|
||||
always one of `True` for enabled, `False` for disabled, or `None`
|
||||
for explicitly setting the service to its default value. You'll note
|
||||
that we use these in the NetVM to attach a single PCI device,
|
||||
and to disable the memory balancing service (dangerous to
|
||||
use on a NetVM or any other VM with a PCI device on it).
|
||||
|
||||
This is all we really need to get on with it. Of course, you can add
|
||||
additional properties to each VM. This system supports listing,
|
||||
within the `qubes` dictionary of each VM, pretty much all properties
|
||||
that `qvm-prefs` supports.
|
||||
|
||||
Ansible playbook
|
||||
----------------
|
||||
|
||||
Now look at [the playbook](./realize-inventory). It targets your
|
||||
`dom0`, which is precisely what you want.
|
||||
|
||||
There are four main plays in it:
|
||||
|
||||
1. Use the Salt subsystem in your dom0 to create the `/srv/user_salt`
|
||||
directory, which happens the first time that `qubesctl` is used to apply
|
||||
the highstate of the system.
|
||||
2. Create the provisioning formula. This formula is stored in
|
||||
`/srv/user_salt/myprovisionedvms.sls` and
|
||||
`/srv/user_salt/myprovisionedvms.top`.
|
||||
3. Tell the Salt subsystem to activate the formula. This won't actually
|
||||
realize the formula, but it will tell Salt that, from now on, every time
|
||||
a `qubesctl state.highstate` is applied, the formula must be
|
||||
enforced.
|
||||
4. Finally, realize the formula.
|
||||
|
||||
Let's discuss steps 2 and 4, unique to this software project:
|
||||
|
||||
In step 2, we invoke the [`qubesformation` action plugin](../../ansible/action_plugins/qubesformation.py]). This plugin will:
|
||||
|
||||
* identify the targeted dom0,
|
||||
* collect all inventory hosts that have been declared to be in that dom0
|
||||
(via `qubes.dom0_vm`),
|
||||
* identify their types, preferences, and other attributes as declared
|
||||
in the `qubes` variable for each inventory host,
|
||||
* generate a SaltStack formula (the `.sls` file) that uses the Qubes
|
||||
Salt modules `qvm.*` to realize and enforce state,
|
||||
* generate a SaltStack Qubes top file, that will let you activate
|
||||
or deactivate the formula as a single unit.
|
||||
|
||||
This formula is clever enough to know in which order to create and
|
||||
reconfigure hosts, because you've provided it with all the necessary
|
||||
information to make those determinations.
|
||||
|
||||
In step 4, all we do is simply tell the [`qubessls` action plugin](../../ansible/action_plugins/qubessls.py) to look for the `myprovisionedvms.sls`
|
||||
and the `myprovisionedvms.top` files we created in step 2, then
|
||||
actually realize them by executing them. It is the equivalent of running
|
||||
`qubesctl state.sls myprovisionedvms saltenv=user` on the
|
||||
dom0 as root.
|
||||
|
||||
Testing the playbook
|
||||
--------------------
|
||||
|
||||
Assuming you've modified the inventory and vars files to suit your
|
||||
testing needs, you can now run the playbook:
|
||||
|
||||
ansible-playbook -v realize-inventory.yml -t create
|
||||
|
||||
creates the `/srv/user_salt/myprovisionedvms.sls`. Now take
|
||||
a look at that file -- it should describe your infrastructure as you'd like
|
||||
it to be (or perhaps even how it already is).
|
||||
|
||||
ansible-playbook -v realize-inventory.yml -t realize
|
||||
|
||||
does the work to activate and realize the infrastructure as it was
|
||||
described in `myprovisionedvms.sls`.
|
||||
|
||||
From this point on, every time you want to change properties in
|
||||
your VMs, all you must do is run the playbook after changing
|
||||
the appropriate variables. The playbook will ensure that your
|
||||
system remains compliant with what you've specified for it.
|
||||
|
||||
More will come as time goes by. For now, that's all. Happy hacking!
|
9
examples/qubesformation/ansible.cfg
Normal file
9
examples/qubesformation/ansible.cfg
Normal file
@ -0,0 +1,9 @@
|
||||
[defaults]
|
||||
connection_plugins = ../../ansible/connection_plugins
|
||||
action_plugins = ../../ansible/action_plugins
|
||||
library = ../../ansible
|
||||
hostfile = ./hosts
|
||||
hash_behaviour = merge
|
||||
|
||||
[ssh_connection]
|
||||
pipelining = True
|
3
examples/qubesformation/group_vars/vms.yml
Normal file
3
examples/qubesformation/group_vars/vms.yml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
qubes:
|
||||
dom0_vm: dom0
|
4
examples/qubesformation/host_vars/app-template.yml
Normal file
4
examples/qubesformation/host_vars/app-template.yml
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
qubes:
|
||||
vm_type: TemplateVM
|
||||
template_vm: fedora-23
|
6
examples/qubesformation/host_vars/builder.yml
Normal file
6
examples/qubesformation/host_vars/builder.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
qubes:
|
||||
vm_type: StandaloneVM
|
||||
template_vm: app-template
|
||||
netvm_vm: firewall
|
||||
label: green
|
3
examples/qubesformation/host_vars/fedora-23.yml
Normal file
3
examples/qubesformation/host_vars/fedora-23.yml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
qubes:
|
||||
vm_type: TemplateVM
|
5
examples/qubesformation/host_vars/firewall.yml
Normal file
5
examples/qubesformation/host_vars/firewall.yml
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
qubes:
|
||||
vm_type: ProxyVM
|
||||
template_vm: app-template
|
||||
netvm_vm: wired-netvm
|
6
examples/qubesformation/host_vars/testnode.yml
Normal file
6
examples/qubesformation/host_vars/testnode.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
qubes:
|
||||
vm_type: AppVM
|
||||
template_vm: app-template
|
||||
netvm_vm: firewall
|
||||
label: blue
|
8
examples/qubesformation/host_vars/wired-netvm.yml
Normal file
8
examples/qubesformation/host_vars/wired-netvm.yml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
qubes:
|
||||
vm_type: NetVM
|
||||
template_vm: app-template
|
||||
pcidevs:
|
||||
- 00:05.0
|
||||
services:
|
||||
meminfo-writer: False
|
34
examples/qubesformation/hosts
Normal file
34
examples/qubesformation/hosts
Normal file
@ -0,0 +1,34 @@
|
||||
# Hosts defined here.
|
||||
dom0
|
||||
fedora-23
|
||||
app-template
|
||||
wired-netvm
|
||||
firewall
|
||||
builder
|
||||
testnode
|
||||
|
||||
[templatevms]
|
||||
fedora-23
|
||||
app-template
|
||||
|
||||
[standalonevms]
|
||||
builder
|
||||
|
||||
[appvms]
|
||||
testnode
|
||||
|
||||
[netvms]
|
||||
wired-netvm
|
||||
|
||||
[proxyvms]
|
||||
firewall
|
||||
|
||||
[vms:children]
|
||||
templatevms
|
||||
standalonevms
|
||||
appvms
|
||||
netvms
|
||||
proxyvms
|
||||
|
||||
[all:vars]
|
||||
ansible_connection=qubes
|
31
examples/qubesformation/realize-inventory.yml
Normal file
31
examples/qubesformation/realize-inventory.yml
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
- hosts: dom0
|
||||
sudo: True
|
||||
gather_facts: False
|
||||
tasks:
|
||||
- name: ensure that Salt /srv/user_salt directory exists
|
||||
shell: test -d /srv/user_salt || { qubesctl state.highstate || exit $? ; echo CHANGED ; }
|
||||
register: saltdirs
|
||||
changed_when: "'CHANGED' in saltdirs.stdout"
|
||||
tags:
|
||||
- create
|
||||
|
||||
- name: configure Qubes formation and its top file
|
||||
qubesformation:
|
||||
dest: /srv/user_salt/myprovisionedvms.sls
|
||||
tags:
|
||||
- create
|
||||
|
||||
- name: enable Qubes formation
|
||||
shell: qubesctl top.enabled | grep myprovisionedvms.top || { qubesctl top.enable myprovisionedvms && echo CHANGED || exit 1 ; }
|
||||
register: enableformation
|
||||
changed_when: "'CHANGED' in enableformation.stdout"
|
||||
tags:
|
||||
- realize
|
||||
|
||||
- name: realize Qubes formation
|
||||
qubessls:
|
||||
sls: myprovisionedvms
|
||||
env: user
|
||||
tags:
|
||||
- realize
|
Loading…
x
Reference in New Issue
Block a user