|
@@ -76,7 +76,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
SOCKNAME = '/var/run/qubesd.sock'
|
|
|
|
|
|
- @qubes.api.method('admin.vmclass.List', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vmclass.List', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vmclass_list(self):
|
|
|
'''List all VM classes'''
|
|
@@ -89,7 +90,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
return ''.join('{}\n'.format(ep.name)
|
|
|
for ep in entrypoints)
|
|
|
|
|
|
- @qubes.api.method('admin.vm.List', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.List', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_list(self):
|
|
|
'''List all the domains'''
|
|
@@ -106,13 +108,15 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
vm.get_power_state())
|
|
|
for vm in sorted(domains))
|
|
|
|
|
|
- @qubes.api.method('admin.vm.property.List', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.property.List', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_property_list(self):
|
|
|
'''List all properties on a qube'''
|
|
|
return self._property_list(self.dest)
|
|
|
|
|
|
- @qubes.api.method('admin.property.List', no_payload=True)
|
|
|
+ @qubes.api.method('admin.property.List', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def property_list(self):
|
|
|
'''List all global properties'''
|
|
@@ -126,13 +130,15 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
return ''.join('{}\n'.format(prop.__name__) for prop in properties)
|
|
|
|
|
|
- @qubes.api.method('admin.vm.property.Get', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.property.Get', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_property_get(self):
|
|
|
'''Get a value of one property'''
|
|
|
return self._property_get(self.dest)
|
|
|
|
|
|
- @qubes.api.method('admin.property.Get', no_payload=True)
|
|
|
+ @qubes.api.method('admin.property.Get', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def property_get(self):
|
|
|
'''Get a value of one global property'''
|
|
@@ -168,14 +174,16 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
property_type,
|
|
|
str(value) if value is not None else '')
|
|
|
|
|
|
- @qubes.api.method('admin.vm.property.Set')
|
|
|
+ @qubes.api.method('admin.vm.property.Set',
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_property_set(self, untrusted_payload):
|
|
|
'''Set property value'''
|
|
|
return self._property_set(self.dest,
|
|
|
untrusted_payload=untrusted_payload)
|
|
|
|
|
|
- @qubes.api.method('admin.property.Set')
|
|
|
+ @qubes.api.method('admin.property.Set',
|
|
|
+ scope='global', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def property_set(self, untrusted_payload):
|
|
|
'''Set property value'''
|
|
@@ -195,13 +203,15 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
setattr(dest, self.arg, newvalue)
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.property.Help', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.property.Help', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_property_help(self):
|
|
|
'''Get help for one property'''
|
|
|
return self._property_help(self.dest)
|
|
|
|
|
|
- @qubes.api.method('admin.property.Help', no_payload=True)
|
|
|
+ @qubes.api.method('admin.property.Help', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def property_help(self):
|
|
|
'''Get help for one property'''
|
|
@@ -221,13 +231,15 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
return qubes.utils.format_doc(doc)
|
|
|
|
|
|
- @qubes.api.method('admin.vm.property.Reset', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.property.Reset', no_payload=True,
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_property_reset(self):
|
|
|
'''Reset a property to a default value'''
|
|
|
return self._property_reset(self.dest)
|
|
|
|
|
|
- @qubes.api.method('admin.property.Reset', no_payload=True)
|
|
|
+ @qubes.api.method('admin.property.Reset', no_payload=True,
|
|
|
+ scope='global', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def property_reset(self):
|
|
|
'''Reset a property to a default value'''
|
|
@@ -243,7 +255,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
delattr(dest, self.arg)
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.volume.List', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.volume.List', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_volume_list(self):
|
|
|
assert not self.arg
|
|
@@ -251,7 +264,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
volume_names = self.fire_event_for_filter(self.dest.volumes.keys())
|
|
|
return ''.join('{}\n'.format(name) for name in volume_names)
|
|
|
|
|
|
- @qubes.api.method('admin.vm.volume.Info', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.volume.Info', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_volume_info(self):
|
|
|
assert self.arg in self.dest.volumes.keys()
|
|
@@ -266,7 +280,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
return ''.join('{}={}\n'.format(key, getattr(volume, key)) for key in
|
|
|
volume_properties)
|
|
|
|
|
|
- @qubes.api.method('admin.vm.volume.ListSnapshots', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.volume.ListSnapshots', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_volume_listsnapshots(self):
|
|
|
assert self.arg in self.dest.volumes.keys()
|
|
@@ -277,7 +292,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
return ''.join('{}\n'.format(revision) for revision in revisions)
|
|
|
|
|
|
- @qubes.api.method('admin.vm.volume.Revert')
|
|
|
+ @qubes.api.method('admin.vm.volume.Revert',
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_volume_revert(self, untrusted_payload):
|
|
|
assert self.arg in self.dest.volumes.keys()
|
|
@@ -294,7 +310,10 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
self.dest.storage.get_pool(volume).revert(revision)
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.volume.CloneFrom', no_payload=True)
|
|
|
+ # write=True because this allow to clone VM - and most likely modify that
|
|
|
+ # one - still having the same data
|
|
|
+ @qubes.api.method('admin.vm.volume.CloneFrom', no_payload=True,
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_volume_clone_from(self):
|
|
|
assert self.arg in self.dest.volumes.keys()
|
|
@@ -314,7 +333,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
self.app.api_admin_pending_clone[token] = volume
|
|
|
return token
|
|
|
|
|
|
- @qubes.api.method('admin.vm.volume.CloneTo')
|
|
|
+ @qubes.api.method('admin.vm.volume.CloneTo',
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_volume_clone_to(self, untrusted_payload):
|
|
|
assert self.arg in self.dest.volumes.keys()
|
|
@@ -347,7 +367,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
self.dest.volumes[self.arg] = op_retval
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.volume.Resize')
|
|
|
+ @qubes.api.method('admin.vm.volume.Resize',
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_volume_resize(self, untrusted_payload):
|
|
|
assert self.arg in self.dest.volumes.keys()
|
|
@@ -363,7 +384,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
self.dest.storage.resize(self.arg, size)
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.volume.Import', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.volume.Import', no_payload=True,
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_volume_import(self):
|
|
|
'''Import volume data.
|
|
@@ -392,7 +414,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
return '{} {}'.format(size, path)
|
|
|
|
|
|
- @qubes.api.method('admin.vm.tag.List', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.tag.List', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_tag_list(self):
|
|
|
assert not self.arg
|
|
@@ -403,7 +426,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
return ''.join('{}\n'.format(tag) for tag in sorted(tags))
|
|
|
|
|
|
- @qubes.api.method('admin.vm.tag.Get', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.tag.Get', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_tag_get(self):
|
|
|
qubes.vm.Tags.validate_tag(self.arg)
|
|
@@ -412,7 +436,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
return '1' if self.arg in self.dest.tags else '0'
|
|
|
|
|
|
- @qubes.api.method('admin.vm.tag.Set', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.tag.Set', no_payload=True,
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_tag_set(self):
|
|
|
qubes.vm.Tags.validate_tag(self.arg)
|
|
@@ -422,7 +447,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
self.dest.tags.add(self.arg)
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.tag.Remove', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.tag.Remove', no_payload=True,
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_tag_remove(self):
|
|
|
qubes.vm.Tags.validate_tag(self.arg)
|
|
@@ -435,7 +461,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
raise qubes.exc.QubesTagNotFoundError(self.dest, self.arg)
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.pool.List', no_payload=True)
|
|
|
+ @qubes.api.method('admin.pool.List', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def pool_list(self):
|
|
|
assert not self.arg
|
|
@@ -445,7 +472,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
return ''.join('{}\n'.format(pool) for pool in pools)
|
|
|
|
|
|
- @qubes.api.method('admin.pool.ListDrivers', no_payload=True)
|
|
|
+ @qubes.api.method('admin.pool.ListDrivers', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def pool_listdrivers(self):
|
|
|
assert self.dest.name == 'dom0'
|
|
@@ -458,7 +486,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
' '.join(qubes.storage.driver_parameters(driver)))
|
|
|
for driver in drivers)
|
|
|
|
|
|
- @qubes.api.method('admin.pool.Info', no_payload=True)
|
|
|
+ @qubes.api.method('admin.pool.Info', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def pool_info(self):
|
|
|
assert self.dest.name == 'dom0'
|
|
@@ -471,7 +500,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
return ''.join('{}={}\n'.format(prop, val)
|
|
|
for prop, val in sorted(pool.config.items()))
|
|
|
|
|
|
- @qubes.api.method('admin.pool.Add')
|
|
|
+ @qubes.api.method('admin.pool.Add',
|
|
|
+ scope='global', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def pool_add(self, untrusted_payload):
|
|
|
assert self.dest.name == 'dom0'
|
|
@@ -506,7 +536,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
self.app.add_pool(name=pool_name, driver=self.arg, **pool_config)
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.pool.Remove', no_payload=True)
|
|
|
+ @qubes.api.method('admin.pool.Remove', no_payload=True,
|
|
|
+ scope='global', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def pool_remove(self):
|
|
|
assert self.dest.name == 'dom0'
|
|
@@ -517,7 +548,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
self.app.remove_pool(self.arg)
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.label.List', no_payload=True)
|
|
|
+ @qubes.api.method('admin.label.List', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def label_list(self):
|
|
|
assert self.dest.name == 'dom0'
|
|
@@ -527,7 +559,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
return ''.join('{}\n'.format(label.name) for label in labels)
|
|
|
|
|
|
- @qubes.api.method('admin.label.Get', no_payload=True)
|
|
|
+ @qubes.api.method('admin.label.Get', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def label_get(self):
|
|
|
assert self.dest.name == 'dom0'
|
|
@@ -541,7 +574,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
return label.color
|
|
|
|
|
|
- @qubes.api.method('admin.label.Index', no_payload=True)
|
|
|
+ @qubes.api.method('admin.label.Index', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def label_index(self):
|
|
|
assert self.dest.name == 'dom0'
|
|
@@ -555,7 +589,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
return str(label.index)
|
|
|
|
|
|
- @qubes.api.method('admin.label.Create')
|
|
|
+ @qubes.api.method('admin.label.Create',
|
|
|
+ scope='global', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def label_create(self, untrusted_payload):
|
|
|
assert self.dest.name == 'dom0'
|
|
@@ -591,7 +626,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
self.app.labels[new_index] = label
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.label.Remove', no_payload=True)
|
|
|
+ @qubes.api.method('admin.label.Remove', no_payload=True,
|
|
|
+ scope='global', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def label_remove(self):
|
|
|
assert self.dest.name == 'dom0'
|
|
@@ -613,7 +649,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
del self.app.labels[label.index]
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.Start', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.Start', no_payload=True,
|
|
|
+ scope='local', execute=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_start(self):
|
|
|
assert not self.arg
|
|
@@ -625,35 +662,40 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
raise qubes.exc.QubesException('Start failed: ' + str(e))
|
|
|
|
|
|
|
|
|
- @qubes.api.method('admin.vm.Shutdown', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.Shutdown', no_payload=True,
|
|
|
+ scope='local', execute=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_shutdown(self):
|
|
|
assert not self.arg
|
|
|
self.fire_event_for_permission()
|
|
|
yield from self.dest.shutdown()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.Pause', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.Pause', no_payload=True,
|
|
|
+ scope='local', execute=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_pause(self):
|
|
|
assert not self.arg
|
|
|
self.fire_event_for_permission()
|
|
|
yield from self.dest.pause()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.Unpause', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.Unpause', no_payload=True,
|
|
|
+ scope='local', execute=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_unpause(self):
|
|
|
assert not self.arg
|
|
|
self.fire_event_for_permission()
|
|
|
yield from self.dest.unpause()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.Kill', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.Kill', no_payload=True,
|
|
|
+ scope='local', execute=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_kill(self):
|
|
|
assert not self.arg
|
|
|
self.fire_event_for_permission()
|
|
|
yield from self.dest.kill()
|
|
|
|
|
|
- @qubes.api.method('admin.Events', no_payload=True)
|
|
|
+ @qubes.api.method('admin.Events', no_payload=True,
|
|
|
+ scope='global', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def events(self):
|
|
|
assert not self.arg
|
|
@@ -694,14 +736,16 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
else:
|
|
|
self.dest.remove_handler('*', dispatcher.vm_handler)
|
|
|
|
|
|
- @qubes.api.method('admin.vm.feature.List', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.feature.List', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_feature_list(self):
|
|
|
assert not self.arg
|
|
|
features = self.fire_event_for_filter(self.dest.features.keys())
|
|
|
return ''.join('{}\n'.format(feature) for feature in features)
|
|
|
|
|
|
- @qubes.api.method('admin.vm.feature.Get', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.feature.Get', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_feature_get(self):
|
|
|
# validation of self.arg done by qrexec-policy is enough
|
|
@@ -713,7 +757,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
raise qubes.exc.QubesFeatureNotFoundError(self.dest, self.arg)
|
|
|
return value
|
|
|
|
|
|
- @qubes.api.method('admin.vm.feature.CheckWithTemplate', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.feature.CheckWithTemplate', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_feature_checkwithtemplate(self):
|
|
|
# validation of self.arg done by qrexec-policy is enough
|
|
@@ -725,7 +770,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
raise qubes.exc.QubesFeatureNotFoundError(self.dest, self.arg)
|
|
|
return value
|
|
|
|
|
|
- @qubes.api.method('admin.vm.feature.Remove', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.feature.Remove', no_payload=True,
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_feature_remove(self):
|
|
|
# validation of self.arg done by qrexec-policy is enough
|
|
@@ -737,7 +783,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
raise qubes.exc.QubesFeatureNotFoundError(self.dest, self.arg)
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.feature.Set')
|
|
|
+ @qubes.api.method('admin.vm.feature.Set',
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_feature_set(self, untrusted_payload):
|
|
|
# validation of self.arg done by qrexec-policy is enough
|
|
@@ -749,14 +796,16 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
self.app.save()
|
|
|
|
|
|
@qubes.api.method('admin.vm.Create.{endpoint}', endpoints=(ep.name
|
|
|
- for ep in pkg_resources.iter_entry_points(qubes.vm.VM_ENTRY_POINT)))
|
|
|
+ for ep in pkg_resources.iter_entry_points(qubes.vm.VM_ENTRY_POINT)),
|
|
|
+ scope='global', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_create(self, endpoint, untrusted_payload=None):
|
|
|
return self._vm_create(endpoint, allow_pool=False,
|
|
|
untrusted_payload=untrusted_payload)
|
|
|
|
|
|
@qubes.api.method('admin.vm.CreateInPool.{endpoint}', endpoints=(ep.name
|
|
|
- for ep in pkg_resources.iter_entry_points(qubes.vm.VM_ENTRY_POINT)))
|
|
|
+ for ep in pkg_resources.iter_entry_points(qubes.vm.VM_ENTRY_POINT)),
|
|
|
+ scope='global', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_create_in_pool(self, endpoint, untrusted_payload=None):
|
|
|
return self._vm_create(endpoint, allow_pool=True,
|
|
@@ -846,7 +895,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
raise
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.Remove', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.Remove', no_payload=True,
|
|
|
+ scope='global', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_remove(self):
|
|
|
assert not self.arg
|
|
@@ -867,7 +917,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
@qubes.api.method('admin.vm.device.{endpoint}.Available', endpoints=(ep.name
|
|
|
for ep in pkg_resources.iter_entry_points('qubes.devices')),
|
|
|
- no_payload=True)
|
|
|
+ no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_device_available(self, endpoint):
|
|
|
devclass = endpoint
|
|
@@ -901,7 +952,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
|
|
|
@qubes.api.method('admin.vm.device.{endpoint}.List', endpoints=(ep.name
|
|
|
for ep in pkg_resources.iter_entry_points('qubes.devices')),
|
|
|
- no_payload=True)
|
|
|
+ no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_device_list(self, endpoint):
|
|
|
devclass = endpoint
|
|
@@ -932,8 +984,12 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
return ''.join('{} {}\n'.format(ident, dev_info[ident])
|
|
|
for ident in sorted(dev_info))
|
|
|
|
|
|
+ # Attach/Detach action can both modify persistent state (with
|
|
|
+ # persistent=True) and volatile state of running VM (with persistent=False).
|
|
|
+ # For this reason, write=True + execute=True
|
|
|
@qubes.api.method('admin.vm.device.{endpoint}.Attach', endpoints=(ep.name
|
|
|
- for ep in pkg_resources.iter_entry_points('qubes.devices')))
|
|
|
+ for ep in pkg_resources.iter_entry_points('qubes.devices')),
|
|
|
+ scope='local', write=True, execute=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_device_attach(self, endpoint, untrusted_payload):
|
|
|
devclass = endpoint
|
|
@@ -972,9 +1028,13 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
yield from self.dest.devices[devclass].attach(assignment)
|
|
|
self.app.save()
|
|
|
|
|
|
+ # Attach/Detach action can both modify persistent state (with
|
|
|
+ # persistent=True) and volatile state of running VM (with persistent=False).
|
|
|
+ # For this reason, write=True + execute=True
|
|
|
@qubes.api.method('admin.vm.device.{endpoint}.Detach', endpoints=(ep.name
|
|
|
for ep in pkg_resources.iter_entry_points('qubes.devices')),
|
|
|
- no_payload=True)
|
|
|
+ no_payload=True,
|
|
|
+ scope='local', write=True, execute=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_device_detach(self, endpoint):
|
|
|
devclass = endpoint
|
|
@@ -994,7 +1054,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
yield from self.dest.devices[devclass].detach(assignment)
|
|
|
self.app.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.firewall.Get', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.firewall.Get', no_payload=True,
|
|
|
+ scope='local', read=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_firewall_get(self):
|
|
|
assert not self.arg
|
|
@@ -1004,7 +1065,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
return ''.join('{}\n'.format(rule.api_rule)
|
|
|
for rule in self.dest.firewall.rules)
|
|
|
|
|
|
- @qubes.api.method('admin.vm.firewall.Set')
|
|
|
+ @qubes.api.method('admin.vm.firewall.Set',
|
|
|
+ scope='local', write=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_firewall_set(self, untrusted_payload):
|
|
|
assert not self.arg
|
|
@@ -1020,7 +1082,8 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|
|
self.dest.firewall.rules = rules
|
|
|
self.dest.firewall.save()
|
|
|
|
|
|
- @qubes.api.method('admin.vm.firewall.Reload', no_payload=True)
|
|
|
+ @qubes.api.method('admin.vm.firewall.Reload', no_payload=True,
|
|
|
+ scope='local', execute=True)
|
|
|
@asyncio.coroutine
|
|
|
def vm_firewall_reload(self):
|
|
|
assert not self.arg
|