Giter Club home page Giter Club logo

ansible-qubes's Introduction

Qubes OS DevOps automation toolkit

This software helps you automate development operations on Qubes OS through industry-standard configuration management solutions.

Do you learn better by example? Then jump to the directory examples/ to get started right away.

The software in this kit includes the following:

  1. A computer program bombshell-client that can run in dom0 or in any domU, which uses the qubes.VMShell Qubes RPC service to provide an interactive session with a shell interpreter (or any program of your choice) from a VM to any other VM.
  2. A connection plug-in for Ansible that uses bombshell-client to make the full power of Ansible automation available to Qubes OS administrators and users.
  3. A set of commands for SaltStack salt-ssh that fake SSH and SCP using bombshell-client to enable SaltStack management of Qubes OS VMs.
  4. A set of action plugins for Ansible that interface with the new Qubes OS 3.1 Salt management stack.
  5. A set of DevOps automation skeletons / examples to get you up and running without having to construct everything yourself.
  6. A lookup plugin for qubes-pass to get you to look up passwords for your infrastructure stored in separate VMs.
  7. A module and action plugin for qubes-pass to get you to store passwords needed to manage your infrastructure in separate VMs.

bombshell-client and the other programs in this toolkit that depend on it, can be used to run operations from one VM to another, in the following combinations:

  • Qubes VM -> Qubes VM
  • Qubes VM -> Qubes dom0 (see below for enablement instructions)
  • Qubes dom0 -> Qubes VM
  • Qubes VM -> network (SSH) -> Qubes VM on another Qubes host (see below)
  • normal desktop Linux -> network (SSH) -> Qubes VM on another Qubes host

What this means for you is quite simple. With this toolkit, you can completely script the setup and maintenance of an entire network of Qubes OS machines.

Contributions always welcome.

Security notes:

  1. Please be absolutely sure you have reviewed this code before using it.
  2. These programs are stdin / stdout / stderr proxies over qubes.VMShell that allow the calling VM to create interactive and batch sessions in another VM. Treat the resulting output from the called programs with the appropriate security precautions involving parsing untrusted input.

Bombshell remote shell technology

Bombshell is a way to run commands in other VMs, that employs the bombshell-client script from this repository. Said method is now integrated in these programs and will only work with Qubes OS 3.

Direct (non-Ansible and non-SaltStack) usage instructions:

./bombshell-client <vmname> command-to-run [arguments...]

The command above spawns a command-to-run on vmname, interactively. Standard input, output, and error work as you would expect them to work -- you can type or pipe data, and said data will be fed to the remote end as standard input, with the remote end's standard output and standard error coming to your terminal's standard output and standard error. Several signals sent to the local bombshell client will be relayed to the command-to-run program in the vmname.

./bombshell-client -d <vmname> command-to-run [arguments...]

Spawns the command-to-run on the vmname, interactively, printing communication channel interaction behavior into the standard error of the invoker, and into the root journal of the vmname.

Fairly simple:

./bombshell-client vmname bash

starts an interactive bash shell (without a prompt, as there is no tty) on the machine vmname. Any program can be run in this way. For example:

./bombshell-client vmname hostname

should give you the host name of the VM vmname.

The rsync manpage documents the use of a special form of rsh to connect to remote hosts -- this option can be used with bombshell-client to run rsync against other VMs as if they were normal SSH hosts.

Enabling bombshell-client access to dom0

dom0 needs its qubes.VMShell service activated. As root in dom0, create a file /etc/qubes-rpc/qubes.VMshell with mode 0755 and make sure its contents say /bin/bash.

You will then create a file /etc/qubes/policy.d/80-ansible-qubes.policy with mode 0664, owned by root and group qubes. Add a policy line towards the top of the file:

qubes.VMShell           *           controller          *     allow

Where controller represents the name of the VM you will be executing bombshell-client against dom0 from.

That's it -- bombshell-client should work against dom0 now. Of course, you can adjust the policy to have it not ask โ€” do the security math on what that implies.

How to use the connection technology with automation tools like Ansible

See [Enhance your Ansible with Ansible Qubes](doc/Enhance your Ansible with Ansible Qubes.md).

Enabling bombshell-client remote access to VMs in other machines

See [Remote management of Qubes OS servers](doc/Remote management of Qubes OS servers.md).

How to use the connection technology with SaltStack

You can also integrate this plugin with SaltStack's salt-ssh program, by:

  1. placing the bombshell-client, qrun and qssh commands in some directory of your path, then
  2. symlinking ssh to qssh and scp to qssh again, then
  3. adding the host: attribute to the roster entry of each one of your VMs as follows: <VM name>.__qubes__.

These fake ssh and scp commands will transparently attempt to SSH into a host unless the host name ends with .__qubes__, in which case they will assume it's a VM and fall back to using the bombshell-client to communicate with said presumed VM. SaltStack's SSH-based salt-ssh automator will pick these fake SSH and SCP clients based on the path, and they will work transparently.

If the program qssh or qscp get a first and second parameters --vmname <VM>, then it is assumed that the host name passed to the command is irrelevant, and that you want to connect to the VM specified by <VM>. If, in addition to that, you specify third 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.

Bug bounties

The bounties that were published have been collected. Sorry! Open source works!

Enjoy!

License

This code is available to you under the terms of the GNU LGPL version 2 or later. The license terms are available on the FSF's Web site.

ansible-qubes's People

Contributors

holmboe avatar professormanhattan avatar rudd-o avatar ypid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ansible-qubes's Issues

Can ansible-qubes be used in R4?

Hello, your ansible-qubes idea sounds great

Considering #7 and the commits I wonder if this project can be safely and easily used in R4. I'd like to try it but I don't have much time for troubleshooting

Example does not work. Bug in qubes.py in hack [with workaround/fix]

Following the example, the ansible work -m shell -a whoami command fails to run with the following error:

The full traceback is:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/ansible/executor/task_executor.py", line 140, in run
    res = self._execute()
  File "/usr/lib/python3/dist-packages/ansible/executor/task_executor.py", line 559, in _execute
    self._set_connection_options(variables, templar)
  File "/usr/lib/python3/dist-packages/ansible/executor/task_executor.py", line 896, in _set_connection_options
    self._connection.set_options(var_options=options)
  File "/home/user/ansible-qubes/connection_plugins/qubes.py", line 255, in set_options
    if task_keys['delegate_to'] and 'management_proxy' in self._options:
TypeError: 'NoneType' object is not subscriptable

work | FAILED | rc=-1 >>
Unexpected failure during module execution.

This is caused by this line

if task_keys['delegate_to'] and 'management_proxy' in self._options:

Changing the line to the following solves the issue.

if task_keys is not None and task_keys['delegate_to'] and 'management_proxy' in self._options

Unable to run qubesformation

Hey, I'm trying to run the qubesformation plugin but I'm getting the following error:

TASK [Configure Qubes Salt formula and the top file] ***************************
task path: /etc/ansible/qubes.yml:32
Sunday 11 September 2022  00:09:03 -0400 (0:00:03.668)       0:00:04.172 ****** 
The full traceback is:
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/ansible/executor/task_executor.py", line 147, in run
    res = self._execute()
  File "/usr/lib/python3.8/site-packages/ansible/executor/task_executor.py", line 665, in _execute
    result = self._handler.run(task_vars=variables)
  File "/usr/share/ansible/plugins/action/qubesformation.py", line 102, in run
    x.write(contents)
  File "/usr/lib64/python3.8/tempfile.py", line 473, in func_wrapper
    return func(*args, **kwargs)
TypeError: a bytes-like object is required, not 'str'
fatal: [dom0]: FAILED! => {
    "msg": "Unexpected failure during module execution.",
    "stdout": ""
}

When I do print(contents) on line 102 I get something like {{ vms | print_yml }}.

Any idea on what is not working?

I'm using the following config: https://gitlab.com/megabyte-labs/gas-station/-/blob/master/ansible.cfg

All the plugins etc. are placed in the recommended Ansible locations using this script: https://gitlab.com/megabyte-labs/gas-station/-/blob/master/scripts/qubes.sh

When I try to run the first example, I get the following error which is similar:

TASK [Configure Qubes Salt formula and the top file] ***************************
task path: /etc/ansible/qubes.yml:32
Sunday 11 September 2022  00:09:03 -0400 (0:00:03.668)       0:00:04.172 ****** 
The full traceback is:
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/ansible/executor/task_executor.py", line 147, in run
    res = self._execute()
  File "/usr/lib/python3.8/site-packages/ansible/executor/task_executor.py", line 665, in _execute
    result = self._handler.run(task_vars=variables)
  File "/usr/share/ansible/plugins/action/qubesformation.py", line 102, in run
    x.write(contents)
  File "/usr/lib64/python3.8/tempfile.py", line 473, in func_wrapper
    return func(*args, **kwargs)
TypeError: a bytes-like object is required, not 'str'
fatal: [dom0]: FAILED! => {
    "msg": "Unexpected failure during module execution.",
    "stdout": ""
}

Any idea on what I'm doing wrong?

dom0 accessibility issue with SomeVM In qubes OS 4.1

[user@controller ansible-qubes]$ qrun dom0 shell
2022-04-22 17:04:22.094 qrexec-client-vm[2278]: process_io.c:36:handle_vchan_error: Error while vchan send(handle_input stdout), exiting

journalctl -b -a
Apr 22 17:31:19 dom0 qrexec-policy-daemon[2158]: qrexec: qubes.VMShell+: controller -> @adminvm: allowed to dom0 Apr 22 17:31:19 dom0 qrexec-policy-daemon[37787]: 2022-04-22 17:31:19.827 qrexec-client[37787]: exec.c:511:execute_parsed_qubes_rpc_command: Unknown service > Apr 22 17:31:19 dom0 qrexec-policy-daemon[37787]: 2022-04-22 17:31:19.847 qrexec-client[37787]: qrexec-client.c:278:handle_failed_exec: failed to spawn proce> Apr 22 17:31:19 dom0 qrexec-policy-daemon[2158]: qrexec: qubes.VMShell: controller -> dom0: error while executing: qrexec-client failed: ['/usr/lib/qubes/qre> lines 10121-10161/10161 (END)

To solve this problem, you need to make the file /etc/qubes-rpc/qubes.VMShell executable

In Dom0:

sudo chmod +x /etc/qubes-rpc/qubes.VMShell

Problems accessing templates

Following the documentation, I have successfully setup a management vm and can use it to access dom0, where I am running an update play and proceed to read out what vms are present, which are templates and running, firing them up as appropriate. I proceed with dynamically adding the detected vms to the inventory

- add_host:
  name:                       "{{ item }}"
  groups:                     template_vms
  ansible_connection: qubes
  with_items:
     "{{ template_vms_present.stdout_lines }}"

When I now try to proceed with updating the templates, it becomes apparent, that I cannot access them. An exemplary error looks like

fatal: [fedora-23]: UNREACHABLE! => {"changed": false, "msg": "Authentication or permission 
failure. In some cases, you may have been able to authenticate and did not have permissions on the 
remote directory. Consider changing the remote temp path in ansible.cfg to a path rooted in \"/tmp\". 
Failed command was: ( umask 77 && mkdir -p \"` echo ~/.ansible/tmp/ansible-
tmp-1490762777.82-167116017398295 `\" && echo ansible-
tmp-1490762777.82-167116017398295=\"` echo ~/.ansible/tmp/ansible-
tmp-1490762777.82-167116017398295 `\" ), exited with result 125", "unreachable": true}

Following ansible's proposal from the error message and switching the remote_tmp variable in ansible.cfg to something like /tmp/.ansible/tmp does not remedy the situation.

Any hints on how to achieve this? Is my budding understanding of Qubes OS to blame?

Sincerely, Joh

Qubes OS 4. Switch screen background

how can I change the screen background of the official Qubes OS 4.? Please help me, I am new to the IT world. maybe someone knows how to copy in Qubes 4 directly to Dom0 or connect the USB stick directly to Dom0? ask for instructions with a detailed explanation. Thank you in advance !;)

Sent with GitHawk

Line Return Whenever qrun and command/shell are invoked

Minor issue but would love it if you knew how to fix it:

Whenever command/shell are invoked (perhaps in some other cases too), a line return is added to the Ansible output. This can cause issues for parsing the output and it doesn't look as good.

4.0-rc2: Facts gathering failing

Hi,

With the appropriate configuration in both dom0 and the management VM , ./bombshell-client dom0 hostname works just fine on my QubesOS 4.0-rc2 system.

Executing a playbook that used to work just fine, however, I now get during TASK [Gathering Facts] the following error:

TypeError: set_host_overrides() takes exactly 3 arguments (4 given)

Any clue what might be wrong?

Working with 4.0-rc1?

See subject line?
In dom0 I have a line in /etc/qubes-rpc/policy/qubes.VMChell I have a line that reads

managevm    dom0    allow

but running ./bombshell-client dom0 hostname gives nothing - just a new line on the CLI ...

Getting Non-Fatal Error Message on a lot of items

Hey, I'm trying to clean up the logging that this project outputs. I'm getting the following error but I'm unsure of how to fix it:

TypeError: a bytes-like object is required, not 'str'

This error comes from tasks that use copy with inline data. Here's an example:

- name: Save meta information about the version of AriaNG that was installed
  copy:
    dest: ~/.config/megabytelabs/ariang
    mode: 0600
    content: |
      {{ ariang_latest_release_tag.json.tag_name }}
  when: install_ariang

Any idea on how to fix this?

PATH problem

user@controller bin]$ ansible dom0 -m ping
dom0 | FAILED! => {
"msg": "qrun command not found in PATH"
}

To make qubes.py work and find qrun

You need to comment out this line.

in qubes.py
if 'transport_cmd' in kwargs: self.transport_cmd = kwargs['transport_cmd'] return self.transport_cmd = distutils.spawn.find_executable('qrun') self.transport_cmd = None if not self.transport_cmd: self.transport_cmd = os.path.join( os.path.dirname(__file__), os.path.pardir, "bin",

#self.transport_cmd = None

[Errno 2] No such file or directory: b'qvm-run'

Hello!

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: FileNotFoundError: [Errno 2] No such file or directory: b'qvm-run'
work | FAILED | rc=-1 >>
Unexpected failure during module execution.\

Did it step by step. run from directory
/home/user/ansible-qubes/examples/ansible

ansible log https://pastebin.com/mQ1X3jer

ansible work -m shell -a whoami
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not
match 'all'
[WARNING]: Could not match supplied host pattern, ignoring: work

ansible work -m shell -a whoami -i hosts -vvv
full error -vvv : https://pastebin.com/LDk3nfqV

Thank you in advance for your help!

Support Qubes OS 4.1

This issue will be closed when this program has been tested successfully working in Qubes 4.1, and best practices from said release have been adopted.

Dom0 access issue with SomeVM . Ansible

[user@controller ~]$ ansible dom0 -m ping [WARNING]: Unhandled error in Python interpreter discovery for host dom0: the remote end of the Qubes connection was not ready: /home/user/autoqubes/ansible- qubes/bin/qrun dom0 python -u -i -c ' from future import print_function import sys, os, subprocess [sys.ps](http://sys.ps/)1 = '"'"''"'"' [sys.ps](http://sys.ps/)2 = '"'"''"'"' sys.stdin = os.fdopen(sys.stdin.fileno(), '"'"'rb'"'"', 0) if hasattr(sys.stdin, '"'"'buffer'"'"') else sys.stdin sys.stdout = sys.stdout.buffer if hasattr(sys.stdout, '"'"'buffer'"'"') else sys.stdout ' yielded b'' dom0 | FAILED! => { "msg": "the remote end of the Qubes connection was not ready: /home/user/autoqubes/ansible-qubes/bin/qrun dom0 python -u -i -c '\nfrom future import print_function\nimport sys, os, subprocess\[nsys.ps](http://nsys.ps/)1 = '"'"''"'"'\[nsys.ps](http://nsys.ps/)2 = '"'"''"'"'\nsys.stdin = os.fdopen(sys.stdin.fileno(), '"'"'rb'"'"', 0) if hasattr(sys.stdin, '"'"'buffer'"'"') else sys.stdin\nsys.stdout = sys.stdout.buffer if hasattr(sys.stdout, '"'"'buffer'"'"') else sys.stdout\n' yielded b''"

qrun and bombshell clients work it

[user@controller ~]$ qrun dom0 whoami
root
[user@controller ~]$ bombshell-client dom0 whoami
root

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.