Skip to content

Add qubes_shell_rpc option#5

Closed
bcduggan wants to merge 3 commits into
QubesOS:mainfrom
bcduggan:qubes_shell_rpc-option
Closed

Add qubes_shell_rpc option#5
bcduggan wants to merge 3 commits into
QubesOS:mainfrom
bcduggan:qubes_shell_rpc-option

Conversation

@bcduggan

@bcduggan bcduggan commented Apr 20, 2025

Copy link
Copy Markdown

This PR replaces the ansible_user option with the qubes_shell_rpc option, which defaults to qubes.VMShell. The plugin always uses the qubes_shell_rpc value instead of trying other RPCs.

Combined with the updated qubes.VMRootShell policy in the README in PR https://github.com/fepitre/qubes-ansible/pull/4, this fixes running privileged tasks on qubes without passwordless root, like minimal qubes. It also enables other functionalities.

Root connections to minimal qubes

There was no way to run tasks as root on qubes without the qubes-core-agent-passwordless-root package installed. Plays that use become: true fail on minimal qubes because the default user can't assume root privileges at all.

This fix depends on the updated qubes.VMRootShell policy described in PR https://github.com/fepitre/qubes-ansible/pull/4:

qubes.VMRootShell    * mgmtvm @tag:created-by-mgmtvm allow user=root

This change enables connecting to minimal qubes as the default user by default:

---
- name: Connect to minimal qube as default user
  hosts: fedora-41-minimal
  connection: qubes
  tasks:
    ...

As well as root:

---
- name: Connect to minimal qube as root
  hosts: fedora-41-minimal
  connection: qubes
  vars:
    qubes_shell_rpc: qubes.VMRootShell
  tasks:
    ...

become: true still works on qubes with qubes-core-agent-passwordless-root installed:

---
- name: Connect to regular qube as root through "become: true"
  hosts: fedora-41
  connection: qubes
  become: true
  tasks:
    ...

become: true will still fail on minimal qubes, as expected.

qubes_shell_rpc: qubes.VMRootShell also works on regular qubes:

---
- name: Connect to regular qube as root through qubes.VMRootShell
  hosts: fedora-41
  connection: qubes
  vars:
    qubes_shell_rpc: qubes.VMRootShell
  tasks:
    ...

Shell predictability

This change makes the connection plugin always use the value of qubes_shell_rpc to connect to remote qubes. This option defaults to qubes.VMShell.

Previously, the connection plugin tried qubes.VMRootShell to transfer files and only used qubes.VMShell if qubes.VMRootShell failed.

The qubes.VMRootShell policy in the README doesn't set the user parameter to root. With this configuration, qubes.VMRootShell is the same as qubes.VMShell, anyway.

I'm not sure why elevating privileges in the put_file method was necessary. In my limited testing, using a shell with default user privileges hasn't caused any obvious problems.

Custom users and shells

This change also enables connecting to qubes as arbitrary users through policy parameters and arbitrary shells through custom RPCs.

With qubes.VMAliceShell symlinked to qubes.VMShell, this policy allows Ansible to connect as alice:

qubes.VMAliceShell * mgmtvm @tag:created-by-mgmtvm allow user=alice

Users can define their own RPCs to run non-Bourne shells (see ansible_shell_type) or even shells in containers.

Unified interface between dom0 and domUs

The ansible_user option is unusable on domUs like the mgmtvm described in the README. This option is only usable on dom0. The qvm-run command's -u option is disallowed on VMs:

mgmtvm$ qvm-run --pass-io --service -u user workvm qubes.VMShell
...
ValueError: non-default user not possible for calls from VM

Instead of providing two methods of configuring the remote user, one of which only works on dom0, this change removes the half-functional ansible_user option.

Closes QubesOS/qubes-issues#9934
Closes QubesOS/qubes-issues#9938

The human user should be able to predict which qube user each play will
use to connect to the remote qube.
Allow the user to select the qubes shell RPC the task should use to
connect to the remote qube with the `qubes_shell_rpc` option. Default
to `qubes.VMShell`. For example:

```yaml
- name: Example
  vars:
    qubes_shell_rpc: qubes.VMRootShell
  tasks:
    - name: Run whoami
      ansible.builtins.command:
        cmd: whoami
```
The README describes running Ansible from mgmtvm instead of dom0, but
the `-u` option is disallowed from domUs:

```console
mgmtvm$ qvm-run --pass-io --service -u user workvm qubes.VMShell
...
ValueError: non-default user not possible for calls from VM
```

This change unifies the interface for running tasks as non-default users
on dom0 and domUs under the qubes_shell_rpc option.
@marmarek

Copy link
Copy Markdown
Member

Can the become: true be mapped to qubes_shell_rpc: qubes.VMRootShell ?

@andrewdavidwong

Copy link
Copy Markdown
Member

Suggestion: If you intend for this pull request to resolve the associated issue and would like for it to be linked to the issue automatically, you can put Closes QubesOS/qubes-issues#XXXX in the PR message (where XXXX is the issue number). Closes is one of several special keywords that GitHub will recognize. If and when the PR is merged, GitHub will automatically close the associated issue.

@bcduggan

bcduggan commented May 1, 2025

Copy link
Copy Markdown
Author

Can the become: true be mapped to qubes_shell_rpc: qubes.VMRootShell ?

It might be possible, but I think it would be messy. The become option belongs to the active "become" action plugin. become plugins enable methods of assuming other users after getting a shell on the remote host. They are things likerunas,su, sudo, etc. A become plugin for minimal qubes would be a no-op.

The user would need to enable the no-op become plugin on specific hosts or groups with the become_method option. Then the existing qubes connection plugin would need to read the become option itself (if possible) and execute qubes.VMRootShell, again only for specific hosts or groups.

An alternative could be restoring the remote_user/ansible_user option in this PR, but modify it so that it only accepts root and user. Instead of passing --user root to qvm-run, it would run qubes.VMRootShell without the --user option. It would need to error out on any other values. But if we could maintain the qubes_shell_rpc option, users would still be able to connect with arbitrary shells and users through policy.

Is it worth pursuing become: true even if it could be messy? Would restoring ansible_user with those modifications be an OK alternative?

Edit: If the user can use remote_user/ansible_user to login as root, they can use become_user to assume any other user from there. Maybe it's OK to drop qubes_shell_rpc then?

@marmarek

marmarek commented May 1, 2025

Copy link
Copy Markdown
Member

Edit: If the user can use remote_user/ansible_user to login as root, they can use become_user to assume any other user from there. Maybe it's OK to drop qubes_shell_rpc then?

Yes, this makes sense. And implementing remote_user/ ansible_user (with limited allowed values) as switching to qubes.VMRootShell would also avoid issues like QubesOS/qubes-issues#9938

@bcduggan

bcduggan commented May 7, 2025

Copy link
Copy Markdown
Author

Closing in favor of PR #8

@bcduggan bcduggan closed this May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Qubes-Ansible - remote_user option fails on management qube Qubes-Ansible - become: true fails on minimal qubes

3 participants