Skip to content

Commit 9a86cce

Browse files
committed
Hide improper qubes from selection
Improve filters of several comboboxes to show only valid options: - Templates nor disposable templates shouldn't be used: - as service qubes - have devices assigned to it - GPG key qube - Minimal template may lack some packages and services, improve filter: - "updatevm" requires "supported-rpc.qube.TemplateDownload" - "split-gpg" requires "supported-rpc.qube.Gpg" - every model using VMSubsetPolicyHandler will check "service_name"
1 parent a89069d commit 9a86cce

7 files changed

Lines changed: 106 additions & 9 deletions

File tree

qubes_config/global_config/basics_handler.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,11 @@ def __init__(self, gtk_builder: Gtk.Builder, qapp: qubesadmin.Qubes):
740740

741741
@staticmethod
742742
def _clock_vm_filter(vm) -> bool:
743-
return vm.klass != "TemplateVM"
743+
return (
744+
vm.klass != "TemplateVM"
745+
and not getattr(vm, "template_for_dispvms", False)
746+
and (vm.klass == "AdminVM" or vm.is_networked())
747+
)
744748

745749
@staticmethod
746750
def _default_template_filter(vm) -> bool:

qubes_config/global_config/device_attachments.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ def __init__(
122122
self.qapp,
123123
"edit_device",
124124
[],
125-
filter_function=lambda vm: vm.klass != "AdminVM",
125+
filter_function=lambda vm: vm.klass not in ["AdminVM", "TemplateVM"]
126+
and not getattr(vm, "template_for_dispvms", False),
126127
)
127128

128129
self.backend_vm: Optional[qubesadmin.vm.QubesVM] = None
@@ -398,7 +399,8 @@ def __init__(
398399
self.qapp,
399400
"required_device",
400401
[],
401-
filter_function=lambda vm: vm.klass != "AdminVM",
402+
filter_function=lambda vm: vm.klass not in ["AdminVM", "TemplateVM"]
403+
and not getattr(vm, "template_for_dispvms", False),
402404
)
403405

404406
self.dev_modeler = self.fill_combo_with_devices(

qubes_config/global_config/global_config.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,11 @@ def perform_setup(self):
434434
service_name="qubes.Gpg",
435435
policy_file_name="50-config-splitgpg",
436436
default_policy="",
437+
filter_function=lambda vm: vm.klass not in ["AdminVM", "TemplateVM"]
438+
and not getattr(vm, "template_for_dispvms", False)
439+
and not vm.features.get("service.guivm")
440+
and not vm.features.get("service.audiovm")
441+
and not getattr(vm, "provides_network", False),
437442
main_rule_class=RuleSimpleNoAllow,
438443
main_verb_description=SimpleVerbDescription(
439444
{

qubes_config/global_config/policy_handler.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
import qubesadmin
4646
import qubesadmin.vm
47-
from ..widgets.utils import compare_rule_lists
47+
from ..widgets.utils import compare_rule_lists, get_boolean_feature
4848

4949
gi.require_version("Gtk", "3.0")
5050
from gi.repository import Gtk
@@ -562,6 +562,7 @@ def __init__(
562562
main_rule_class: Type[AbstractRuleWrapper],
563563
exception_verb_description: AbstractVerbDescription,
564564
exception_rule_class: Type[AbstractRuleWrapper],
565+
filter_function: Callable[[qubesadmin.vm.QubesVM], bool] | None = None,
565566
):
566567
"""
567568
:param qapp: Qubes object
@@ -619,7 +620,22 @@ def __init__(
619620

620621
# populate combo
621622
self.select_qube_model = VMListModeler(
622-
combobox=self.select_qube_combo, qapp=self.qapp
623+
combobox=self.select_qube_combo,
624+
qapp=self.qapp,
625+
filter_function=(
626+
(
627+
lambda vm: filter_function(vm)
628+
and get_boolean_feature(
629+
vm, "supported-rpc." + service_name, recurse_template=True
630+
)
631+
)
632+
if filter_function
633+
else (
634+
lambda vm: get_boolean_feature(
635+
vm, "supported-rpc." + service_name, recurse_template=True
636+
)
637+
)
638+
),
623639
)
624640

625641
# connect events

qubes_config/global_config/updates_handler.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,10 @@ def __init__(
686686
lambda vm: vm.klass != "TemplateVM"
687687
and vm.klass != "AdminVM"
688688
and vm.is_networked()
689+
and not getattr(vm, "template_for_dispvms", False)
690+
and get_boolean_feature(
691+
vm, "supported-rpc.qubes.TemplateDownload", recurse_template=True
692+
)
689693
),
690694
current_value=self.qapp.updatevm,
691695
additional_options=NONE_CATEGORY,

qubes_config/tests/test_policy_handler.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,16 @@ def test_subset_handler(test_builder, test_qapp, test_policy_manager: PolicyMana
886886
default_policy = """
887887
TestService * @anyvm test-blue allow"""
888888

889+
for qube in test_qapp.domains:
890+
test_qapp.expected_calls[
891+
(
892+
qube,
893+
"admin.vm.feature.CheckWithTemplate",
894+
"supported-rpc.TestService",
895+
None,
896+
)
897+
] = b"0\x001"
898+
889899
handler = VMSubsetPolicyHandler(
890900
qapp=test_qapp,
891901
gtk_builder=test_builder,
@@ -973,6 +983,16 @@ def test_subset_handler_limited_choice(
973983
TestService * @anyvm test-blue allow
974984
TestService * @anyvm test-red allow"""
975985

986+
for qube in test_qapp.domains:
987+
test_qapp.expected_calls[
988+
(
989+
qube,
990+
"admin.vm.feature.CheckWithTemplate",
991+
"supported-rpc.TestService",
992+
None,
993+
)
994+
] = b"0\x001"
995+
976996
handler = VMSubsetPolicyHandler(
977997
qapp=test_qapp,
978998
gtk_builder=test_builder,
@@ -1066,6 +1086,16 @@ def test_subset_handler_remove_choice(
10661086
TestService * @anyvm test-blue allow
10671087
TestService * @anyvm vault ask"""
10681088

1089+
for qube in test_qapp.domains:
1090+
test_qapp.expected_calls[
1091+
(
1092+
qube,
1093+
"admin.vm.feature.CheckWithTemplate",
1094+
"supported-rpc.TestService",
1095+
None,
1096+
)
1097+
] = b"0\x001"
1098+
10691099
handler = VMSubsetPolicyHandler(
10701100
qapp=test_qapp,
10711101
gtk_builder=test_builder,
@@ -1122,6 +1152,16 @@ def test_subset_handler_duplicates(
11221152
default_policy = """
11231153
TestService * @anyvm vault ask"""
11241154

1155+
for qube in test_qapp.domains:
1156+
test_qapp.expected_calls[
1157+
(
1158+
qube,
1159+
"admin.vm.feature.CheckWithTemplate",
1160+
"supported-rpc.TestService",
1161+
None,
1162+
)
1163+
] = b"0\x001"
1164+
11251165
handler = VMSubsetPolicyHandler(
11261166
qapp=test_qapp,
11271167
gtk_builder=test_builder,
@@ -1161,6 +1201,16 @@ def test_subset_handler_duplicates_load(
11611201
TestService * @anyvm vault ask
11621202
"""
11631203

1204+
for qube in test_qapp.domains:
1205+
test_qapp.expected_calls[
1206+
(
1207+
qube,
1208+
"admin.vm.feature.CheckWithTemplate",
1209+
"supported-rpc.TestService",
1210+
None,
1211+
)
1212+
] = b"0\x001"
1213+
11641214
handler = VMSubsetPolicyHandler(
11651215
qapp=test_qapp,
11661216
gtk_builder=test_builder,
@@ -1191,6 +1241,16 @@ def test_subset_handler_unsupported(
11911241
TestService * @anyvm vault allow target=test-blue
11921242
"""
11931243

1244+
for qube in test_qapp.domains:
1245+
test_qapp.expected_calls[
1246+
(
1247+
qube,
1248+
"admin.vm.feature.CheckWithTemplate",
1249+
"supported-rpc.TestService",
1250+
None,
1251+
)
1252+
] = b"0\x001"
1253+
11941254
test_policy_manager.policy_client.policy_replace("c-test", current_policy, "any")
11951255

11961256
handler = VMSubsetPolicyHandler(

qubes_config/widgets/utils.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,25 @@
3333
_ = t.gettext
3434

3535

36-
def get_feature(vm, feature_name, default_value=None):
36+
def get_feature(vm, feature_name, default_value=None, recurse_template=False):
3737
"""Get feature, with a working default_value."""
38+
if recurse_template:
39+
feat = vm.features.check_with_template
40+
else:
41+
feat = vm.features.get
3842
try:
39-
return vm.features.get(feature_name, default_value)
43+
return feat(feature_name, default_value)
4044
except qubesadmin.exc.QubesDaemonAccessError:
4145
return default_value
4246

4347

44-
def get_boolean_feature(vm, feature_name, default=False):
48+
def get_boolean_feature(vm, feature_name, default=False, recurse_template=False):
4549
"""helper function to get a feature converted to a Bool if it does exist.
4650
Necessary because of the true/false in features being coded as 1/empty
4751
string."""
48-
result = get_feature(vm, feature_name, None)
52+
result = get_feature(
53+
vm, feature_name, default_value=None, recurse_template=recurse_template
54+
)
4955
if result is not None:
5056
result = bool(result)
5157
else:

0 commit comments

Comments
 (0)