Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upImprove qrexec policy syntax for $dispvm to be more expressive and less confusing #3048
Comments
rootkovska
added
bug
C: core
P: critical
labels
Aug 23, 2017
rootkovska
added this to the Release 4.0 milestone
Aug 23, 2017
rootkovska
assigned
marmarek and
woju
Aug 23, 2017
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
woju
Aug 23, 2017
Member
Arguably this is relevant only when one has more than one MgmtVM. This is already complicated situation, since R4.0 out of the box supports only one MgmtVM, namely dom0 which also doubles as GuiVM. Situation when one needs another MgmtVM is an "enterprise" situation. With that in mind, I'd suggest at minimum to reschedule this for R4.1.
Ad rem: IMO this needlessly complicates policy syntax (and consequently parser). This can already be implemented using extensions by forbidding setting dispvm_allowed (or #3047) property to unwanted values.
Example extension (maybe add this to documentation?):
import qubes.api
import qubes.ext
class MyCorporateExtension(qubes.ext.Extension):
@qubes.ext.handler('admin-permission:admin.vm.property.Set')
def on_vm_property_set(self, subject, event, dest, arg, newvalue):
if dest.name in ('secretvm1', 'secretvm2') \
and arg == 'default_dispvm':
try:
newvalue = self.app.domains[newvalue]
except KeyError:
raise qubes.api.PermissionDenied()
if 'managed-by-corpo' not in newvalue.tags:
raise qubes.api.PermissionDenied()|
Arguably this is relevant only when one has more than one MgmtVM. This is already complicated situation, since R4.0 out of the box supports only one MgmtVM, namely dom0 which also doubles as GuiVM. Situation when one needs another MgmtVM is an "enterprise" situation. With that in mind, I'd suggest at minimum to reschedule this for R4.1. Ad rem: IMO this needlessly complicates policy syntax (and consequently parser). This can already be implemented using extensions by forbidding setting Example extension (maybe add this to documentation?): import qubes.api
import qubes.ext
class MyCorporateExtension(qubes.ext.Extension):
@qubes.ext.handler('admin-permission:admin.vm.property.Set')
def on_vm_property_set(self, subject, event, dest, arg, newvalue):
if dest.name in ('secretvm1', 'secretvm2') \
and arg == 'default_dispvm':
try:
newvalue = self.app.domains[newvalue]
except KeyError:
raise qubes.api.PermissionDenied()
if 'managed-by-corpo' not in newvalue.tags:
raise qubes.api.PermissionDenied() |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
rootkovska
Aug 23, 2017
Member
The problem with deferring this to a later time, e.g. 4.1, is that large part of the solution I proposed requires changing of the syntax for the policy definition, and this is something we should do now (i.e. still at an early rc1 stage, rather than later). How are we going to implement it actually (extension or core logic) is of secondary importance.
|
The problem with deferring this to a later time, e.g. 4.1, is that large part of the solution I proposed requires changing of the syntax for the policy definition, and this is something we should do now (i.e. still at an early rc1 stage, rather than later). How are we going to implement it actually (extension or core logic) is of secondary importance. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
marmarek
Aug 25, 2017
Member
Adding explicit $dispvm_system_default, to mean system-default DispVM (as set/reported by qubes-prefs),
Adding explicit $dispvm_appvm_default, to mean per-AppVM default DispVM (as set/reported by qvm-prefs for the particular calling VM, defaults to system default).
The distinction between $dispvm_system_default and $dispvm_appvm_default is an important one, because otherwise users are likely to fall into the trap of thinking of $dispvm_default as "system default", so e.g. a benign DispVM based on some empty template, overlooking the possibility that a malcious mgmt VM might override the default_dispvm for its own VMs, as discussed above.
There is no such thing as "system default" and "appvm default" DispVM. There is only one: "appvm default" (using your terminology). This property happen to default to global property, but that's a mere convenience for simplest use case (when user have just one DispVM template for everything). If you want to prevent usage of some particular DispVM by others it's better to express that explicitly in the policy (using "deny" rule, before others), instead of looking for all possible ways leading to that place (carefully manually evaluating all "allow" rules). Also, we have some preliminary version of a tool to help with policy validation.
If you still want to have some DispVM available for anyone, and state that in "allow" rule, better use that VM characteristic itself (tag for example), not the fact that it is set as default (either global one, or per-VM). Otherwise you'll fall into exactly the same "trap" when one (either user, or corporate admin) is allowed to change the global default.
- The new keyword $dispvm_tagged:XYZ meaning: a DispVM created from an AppVM which has tag XYZ,
I agree this is useful, but I don't like the underscore here. Personally I like the initial version (from email thread): $dispvm:$tag:XYZ. I think it's more logical, even if that's the only special word allowed after $dispvm:.
- The change of the meaning of $dispvm. Currently it means "a DispVM based on the AppVM pointed by default_dispvm property", and I think this is confusing to those users who might interpret this as "any DispVM". The consequence of this mistaken interpretation might be fatal. Thus I postulate that we change the meaning of $dispvm to mean "any AppVM", and this is how it was used in the example above,
Actually, the current approach is the safe one, and yours may lead to fatal mistakes. Allowing access to $dispvm allow only to one DispVM, dedicated to this VM (in most cases: global default), not all of them - including some corporate one, and the one with printing credentials. You may say that one may write $anyvm $dispvm deny rule to selectively deny DispVM usage (allowing everything else), but it's always better to selectively allow things, than to selectively deny them (when it comes to writing policy).
On the other hand, there is currently no syntax for "any DispVM" (but it is possible to express it using multiple rules). Maybe add $dispvm:$anyvm? But this may be confusing, because it will really mean "DispVM based on any AppVM with dispvm_allowed (or #3047) set to True", so not exactly the same as $anyvm in other context.
Related: what tags new DispVM should have? This is important for writing rules what DispVM can do.
I see a few sensible options:
- Just one,
started-by-some-vm- based on what VM have created it (or maybe even usecreated-by-some-vm?). - Same as AppVM the DispVM is based on (this is the current version) - based on assumption that AppVM being base for DispVM control how DispVM behave.
- Something based on all tags of calling VM - either full copy, or the same with some prefix (
caller-?). So DispVM started by VM with tagcreated-by-corpo-mgmtwill get a tagcaller-created-by-corpo-mgmt.
There is no such thing as "system default" and "appvm default" DispVM. There is only one: "appvm default" (using your terminology). This property happen to default to global property, but that's a mere convenience for simplest use case (when user have just one DispVM template for everything). If you want to prevent usage of some particular DispVM by others it's better to express that explicitly in the policy (using "deny" rule, before others), instead of looking for all possible ways leading to that place (carefully manually evaluating all "allow" rules). Also, we have some preliminary version of a tool to help with policy validation.
I agree this is useful, but I don't like the underscore here. Personally I like the initial version (from email thread):
Actually, the current approach is the safe one, and yours may lead to fatal mistakes. Allowing access to On the other hand, there is currently no syntax for "any DispVM" (but it is possible to express it using multiple rules). Maybe add Related: what tags new DispVM should have? This is important for writing rules what DispVM can do.
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
rootkovska
Aug 26, 2017
Member
I suggest the best way to keep this discussion, is that everyone who proposes a different syntax, provides also their own version of the qrexec policy that solves the examples I've given above. We could then compare which solution offers the least-confusing expression of polices. Additionally, extra examples might be given, e.g. to illustrate how the proposed solution is better than other proposed solutions (or current implementation).
|
I suggest the best way to keep this discussion, is that everyone who proposes a different syntax, provides also their own version of the qrexec policy that solves the examples I've given above. We could then compare which solution offers the least-confusing expression of polices. Additionally, extra examples might be given, e.g. to illustrate how the proposed solution is better than other proposed solutions (or current implementation). |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
marmarek
Aug 27, 2017
Member
The problem with deferring this to a later time, e.g. 4.1, is that large part of the solution I proposed requires changing of the syntax for the policy definition, and this is something we should do now (i.e. still at an early rc1 stage, rather than later).
This repeatedly come during rc1 stage. Some choices turns out to be not so good only at broader testing phase. In our current workflow, only bugfixes are allowed after releasing rc1. Specifically, new features or API changes are not allowed. While in practice we make exceptions to this rule, it is not the right thing to do. Maybe we need to bring alpha/beta stages back (or just one beta)?
Back to the topic:
- Mark
fedora-25-dvmwithglobally-available-dispvmtag (or any other sensible name). - Use this policy:
# Allow any VM to use standard DispVMs:
$anyvm $dispvm:$tag:globally-available-dispvm allow
# Allow personal VMs to start DispVMs created by the user via guidom:
$tag:created-by-guidom $dispvm:$tag:created-by-guidom allow
# Allow corpo-managed VMs to start DispVMs based on corpo-owned AppVMs:
$tag:created-by-mgmt-corpo $dispvm:$tag:created-by-mgmt-corpo allow
# Forbid any other combinations (redundant, but for completeness)
$anyvm $anyvm deny
The above will enforce the right policy, regardless of default_dispvm property (either AppVM or global).
Note that I haven't used here neither $dispvm:$anyvm, nor bare $dispvm.
This repeatedly come during rc1 stage. Some choices turns out to be not so good only at broader testing phase. In our current workflow, only bugfixes are allowed after releasing rc1. Specifically, new features or API changes are not allowed. While in practice we make exceptions to this rule, it is not the right thing to do. Maybe we need to bring alpha/beta stages back (or just one beta)? Back to the topic:
The above will enforce the right policy, regardless of |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
rootkovska
Sep 2, 2017
Member
So, we agree that we want to add ability for DispVM specification via tags and that we want to do that before rc2.
Even thought I originally proposed the $dispvm:$tag syntax (in the original email thread), I was somehow convinced by Wojtek that it would be trickier in implementation than the "flat" syntax of $dispvm_tagged (or $dispvm$tag maybe?) But I won't fight too hard for this ;)
I agree it's desirable to try to use tags instead of what I proposed above as $dispvm_{system,appvm}_default. So, we need to agree on the policy on tags inheritance for the DispVMs. From what Marek proposed, I'm inclined to say #2 (inherit from the AppVM template), as this is the simplest and most static case. Also this is what Marek used in the snipped above.
|
So, we agree that we want to add ability for DispVM specification via tags and that we want to do that before rc2. Even thought I originally proposed the $dispvm:$tag syntax (in the original email thread), I was somehow convinced by Wojtek that it would be trickier in implementation than the "flat" syntax of $dispvm_tagged (or $dispvm$tag maybe?) But I won't fight too hard for this ;) I agree it's desirable to try to use tags instead of what I proposed above as $dispvm_{system,appvm}_default. So, we need to agree on the policy on tags inheritance for the DispVMs. From what Marek proposed, I'm inclined to say #2 (inherit from the AppVM template), as this is the simplest and most static case. Also this is what Marek used in the snipped above. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
marmarek
Sep 2, 2017
Member
Even thought I originally proposed the $dispvm:$tag syntax (in the original email thread), I was somehow convinced by Wojtek that it would be trickier in implementation than the "flat" syntax of $dispvm_tagged (or $dispvm$tag maybe?) But I won't fight too hard for this ;)
I've just implemented $dispvm:$tag. The code treats $dispvm:$tag: as yet another prefix (there is no nested parsing of content of $dispvm: tag) - specifically to avoid what Wojtek feared. Changing this to $dispvm_tagged: would be a simple find&replace, but IMO $dispvm:$tag: is nicer logically and visually.
I've checked (using our test suite) that this change do not break any existing syntax. As it should be.
I've just implemented I've checked (using our test suite) that this change do not break any existing syntax. As it should be. |
added a commit
to marmarek/qubes-core-admin
that referenced
this issue
Sep 4, 2017
added a commit
to marmarek/qubes-core-admin
that referenced
this issue
Sep 5, 2017
marmarek
referenced this issue
in QubesOS/qubes-core-admin
Sep 5, 2017
Merged
Policy related changed for DispVM #148
marmarek
closed this
in
QubesOS/qubes-core-admin#148
Sep 13, 2017
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
qubesos-bot
Sep 14, 2017
Automated announcement from builder-github
The package qubes-core-dom0-4.0.7-1.fc25 has been pushed to the r4.0 testing repository for dom0.
To test this update, please install it with the following command:
sudo qubes-dom0-update --enablerepo=qubes-dom0-current-testing
qubesos-bot
commented
Sep 14, 2017
|
Automated announcement from builder-github The package
|
qubesos-bot
added
the
r4.0-dom0-cur-test
label
Sep 14, 2017
qubesos-bot
referenced this issue
in QubesOS/updates-status
Sep 14, 2017
Closed
core-admin v4.0.7 (r4.0) #204
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
qubesos-bot
Oct 30, 2017
Automated announcement from builder-github
The package qubes-core-dom0-4.0.11-1.fc25 has been pushed to the r4.0 stable repository for dom0.
To install this update, please use the standard update command:
sudo qubes-dom0-update
Or update dom0 via Qubes Manager.
qubesos-bot
commented
Oct 30, 2017
|
Automated announcement from builder-github The package
Or update dom0 via Qubes Manager. |
rootkovska commentedAug 23, 2017
There are a few problems with the new syntax with regards to DispVMs (introduced in 4.0-rc1).
In scenarios where we will have more than one mgmt VM in the system (e.g. GUI domain and corporate mgmt VM), we would like to be able to state something like this via the policy (for whatever service):
This is because we would like to (generically) avoid a situation where one of the mgmt VMs (say the
guidom) will request to start a DispVM based on some AppVM belonging to the "corpo world".The above exemplary snippet contains a few proposed extensions to the policy:
The new keyword
$dispvm_tagged:XYZmeaning: a DispVM created from an AppVM which has tag XYZ,The change of the meaning of
$dispvm. Currently it means "a DispVM based on the AppVM pointed bydefault_dispvmproperty", and I think this is confusing to those users who might interpret this as "any DispVM". The consequence of this mistaken interpretation might be fatal. Thus I postulate that we change the meaning of$dispvmto mean "any AppVM", and this is how it was used in the example above,Adding explicit
$dispvm_system_default, to mean system-default DispVM (as set/reported byqubes-prefs),Adding explicit
$dispvm_appvm_default, to mean per-AppVM default DispVM (as set/reported by qvm-prefs for the particular calling VM, defaults to system default).The distinction between
$dispvm_system_defaultand$dispvm_appvm_defaultis an important one, because otherwise users are likely to fall into the trap of thinking of$dispvm_defaultas "system default", so e.g. a benign DispVM based on some empty template, overlooking the possibility that a malcious mgmt VM might override thedefault_dispvmfor its own VMs, as discussed above.