How do I use tags with qubes-rpc?

I would like to modify some Qubes RPC policies, especially those using the “ask” action, so that the amount of VMs displayed as potential targets is reduced.

I understand that this list displays all VMs that are either set to “allow” or “ask”. VMs with an action of “deny” are not listed.

In particular, I want to modify qubes.OpenURL so that whenever I click on a hyperlink (e.g., in an email), only some of my persistent VMs, as well as some of the disposable VMs are shown.

I figured that the best way would be to use a tag “hyperlink-target” for these VMs.
How do I configure the RPC policy so that both existing and to-be-created disposable VMs are listed, but not the disp templates themselves?
I tried configuring the policy with “type” instead of “tag” but did not find a list of all types supported by this command (e.g., specifying the type “disposable” seems to be without effect).
I then gave a dispVM template the tag “hyperlink-target”. This made both the template and dispVMs derived from it appear in the drop down.
I further tried to exclude the template by specifying a “deny” policy for it, but it seems that it appears in the lost once it is matched by one of the allow policies.

Does anyone know how to configure such setup? Might there even be a good documentation on RPC policies regarding tags and types? The official documentation only briefly covers this aspect.

Edit: After writing this I thought about the policy file like a firewall. Putting the “deny” rule above the “ask” rules works as intended and removes the disp templates from the drop-down. However, I would still like to know if the same could be achieved by using types instead of tags.

These documents answer at least some of your questions:

1 Like

Thanks @adw. I had already consulted both documents. The first one is actually quite helpful regarding the use of “tags” and ultimately helped me to better understand the concept.
Interestingly, none of the two documents explain how to set tags using the command line tool qvm-tags (this is in fact documented somewhere, but I don’t recall the exact location).

Specifying qubes by their “type” is not well-documented. The “qrexec” doc page says

There are severals methods for specifying source/target VMs in RPC policies.

  • @tag:some-tag - meaning a VM with tag some-tag
  • @type:type - meaning a VM of type (like AppVM , TemplateVM etc)

The “etc” in parantheses lead me to the conclusion that there would be more VM types one could use in policy files, which imho would be quite nice and helpful (I was imagining types like “DispTemplate”, “DispVM”, NetVM", …).

To find an answer to this question I ended up consulting the source code for the qrexec tools and found that there are no special types defined for use in policy files. Instead the “type” argument is based on a Qube’s “system info”, which, as far as I understand it, holds the same values that are also shown in the output of qvm-ls or qvm-prefs <vmname>. There, the field holding this information is called “class”.

The output on my Qubes system shows the following different values for the class attribute: TemplateVM (obviously used for templates), AppVM (used for most interesting VMs: NetVMs, FirewallVMs, regular AppVMs, disposableVM templates, …), DispVM (apparently used by currently running disposable VMs), StandaloneVM (obvious), AdminVM (only for dom0 as far as I can see).

Based on this observation it should be possible to use these names in policy files, e.g. @anyvm @type:DispVM ask.

Ultimately, I find that for my particular case, using tags to include only certain disposableVMs while excluding others (e.g., there is no need to open a hyperlink in a disposable VM used exclusively for printing) is more useful than specifying "type"s. For reference and in case it might help others, the “qubes.OpenURL” policy I ended up with looks like this:

# Excplicitely exclude disposable templates.
# Requires to manually set the tag 'qvm-tags <vm-name> add disp-template' for each disposable template.
@anyvm   @tag:disp-template  deny

# Ecplicitely specify valid targets to fill the dropdown menu.
# Requires to set 'qvm-tags <vm-name> add hyperlink-target' to every VM which hyperlinks should be sent to.
# For disposable VMs, specify the tag at the parent (dispVM template). It is inherited to the DispVM instances.
@anyvm  @tag:hyperlink-target  ask

# Explicitely include new disposableVMs that can be launched from this action
@anyvm  @dispvm:fedora-dvm  ask
@anyvm  @dispvm:whonix-ws-15-dvm  ask

# Make sure that the popup is shown whenever this option is called from the GUI
@anyvm  @default  ask

Aaaand it’s not working after reboot. Because obviously, not only is the tag “hyperlink-target” inherited to DispVMs but also the tag “disp-template” (could have seen that coming).

I guess the only option (for now) is to live with a broader approach that allows opening of URLs in any running DispVM, no matter the type. Alternatively, one could come up with a way to dynamically tag disposable VMs after they start up, but that seems like a lot of work that could easily break once you change anything.

You are overthinking this.
You can remove the disposable templates fairy easily.

What you want is some variant on:

qubes.OpenInVM	*	@anyvm	personal		deny
qubes.OpenInVM	*	@anyvm	@dispvm:personal	ask
qubes.OpenInVM	*	@anyvm	@tag:tagger		ask

where personal is the disposable template, and you have tagged it
with tagger
This will prompt for new and existing disposables based on personal.

If you are using custom policies with arguments, you can fine tune the
pop-up options, to use only existing or only new disposables, and display
them as appropriate.

The Classes are available (e.g.) from qvm-create --help-classes for
those who prefer not to scan source code.
AdminVM is an interesting case, since it allows you to control your
Qubes system from other than dom0, and circumscribe, using policies,
what control that other qube has. This allows for remote management

1 Like

I would have preferred to have only one deny rule for all kinds of disposable VM templates. However, you are right that I was overthinking stuff.

I got so caught up in the usage of tags that I forgot I could also explicitly mention all DVM templates in the policy’s deny rules.

I would have preferred to have only one deny rule for all kinds of disposable VM templates. However, you are right that I was overthinking stuff.

You could, of course, prepend

qubes.OpenInVM	*	@anyvm	@type:AppVM		deny

and explicitly include qubes (non-disposable) above that line that you wanted to use.

This apparently only works if “personal” is the default DVM temple. If it isn’t you must also include:

qubes.OpenInVM * @anyvm @dispvm:whatever-your-default-dvm-template-is ask

So you end up with a useless listing in your dropdown.

Other than that the key insight here finally helped me solve this problem…tag the DVM template so any DVM created from it will have the tag. The third condition does that. But then, because the DVM template has the tag, you have to specifically exclude it prior to that or it will show up in the list. You have to explicitly give the name of the template (as a disposable, not as the template) in step 2 or it won’t show up because apparently it doesn’t manifest the tag. (@dispvm:personal by itself won’t cause its descendant DVMs to show up.)

This probably goes without saying, but you also need a blanket @anyvm @anyvm deny at the end or you see a LOT of VMs (all AppVMs including dvm templates) in your menu, rather than just the ones you explicitly allowed.

1 Like