aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxen/include/xen/api/xen_vif.h14
-rw-r--r--tools/libxen/src/xen_vif.c39
-rw-r--r--tools/python/xen/util/security.py48
-rw-r--r--tools/python/xen/xend/XendAPI.py19
-rw-r--r--tools/python/xen/xend/XendConfig.py10
-rw-r--r--tools/python/xen/xend/XendDomain.py23
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py2
-rw-r--r--tools/python/xen/xend/XendXSPolicyAdmin.py12
-rw-r--r--tools/python/xen/xend/server/netif.py43
-rw-r--r--tools/python/xen/xm/addlabel.py41
-rw-r--r--tools/python/xen/xm/create.dtd3
-rw-r--r--tools/python/xen/xm/create.py3
-rw-r--r--tools/python/xen/xm/getlabel.py26
-rw-r--r--tools/python/xen/xm/rmlabel.py38
-rw-r--r--tools/python/xen/xm/xenapi_create.py13
15 files changed, 312 insertions, 22 deletions
diff --git a/tools/libxen/include/xen/api/xen_vif.h b/tools/libxen/include/xen/api/xen_vif.h
index 26608f0af9..3fb8d7128e 100644
--- a/tools/libxen/include/xen/api/xen_vif.h
+++ b/tools/libxen/include/xen/api/xen_vif.h
@@ -362,4 +362,18 @@ extern bool
xen_vif_get_all(xen_session *session, struct xen_vif_set **result);
+/**
+ * Set the security label of a VIF.
+ */
+extern bool
+xen_vif_set_security_label(xen_session *session, int64_t *result, xen_vif vif,
+ char *label, char *oldlabel);
+
+
+/**
+ * Get the security label of a VIF.
+ */
+extern bool
+xen_vif_get_security_label(xen_session *session, char **result, xen_vif vif);
+
#endif
diff --git a/tools/libxen/src/xen_vif.c b/tools/libxen/src/xen_vif.c
index bc9dd0dd2f..ac6147ff4f 100644
--- a/tools/libxen/src/xen_vif.c
+++ b/tools/libxen/src/xen_vif.c
@@ -575,3 +575,42 @@ xen_vif_get_uuid(xen_session *session, char **result, xen_vif vif)
XEN_CALL_("VIF.get_uuid");
return session->ok;
}
+
+
+bool
+xen_vif_set_security_label(xen_session *session, int64_t *result, xen_vif vif,
+ char *label, char *oldlabel)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vif },
+ { .type = &abstract_type_string,
+ .u.string_val = label },
+ { .type = &abstract_type_string,
+ .u.string_val = oldlabel },
+ };
+
+ abstract_type result_type = abstract_type_int;
+
+ *result = 0;
+ XEN_CALL_("VIF.set_security_label");
+ return session->ok;
+}
+
+
+bool
+xen_vif_get_security_label(xen_session *session, char **result, xen_vif vif)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vif },
+ };
+
+ abstract_type result_type = abstract_type_string;
+
+ *result = NULL;
+ XEN_CALL_("VIF.get_security_label");
+ return session->ok;
+}
diff --git a/tools/python/xen/util/security.py b/tools/python/xen/util/security.py
index 608ed463f2..5183ed2c98 100644
--- a/tools/python/xen/util/security.py
+++ b/tools/python/xen/util/security.py
@@ -831,7 +831,7 @@ def get_domain_resources(dominfo):
Entries are strored in the following formats:
tap:qcow:/path/xyz.qcow
"""
- resources = { 'vbd' : [], 'tap' : []}
+ resources = { 'vbd' : [], 'tap' : [], 'vif' : []}
devs = dominfo.info['devices']
uuids = devs.keys()
for uuid in uuids:
@@ -839,6 +839,15 @@ def get_domain_resources(dominfo):
typ = dev[0]
if typ in [ 'vbd', 'tap' ]:
resources[typ].append(dev[1]['uname'])
+ if typ in [ 'vif' ]:
+ sec_lab = dev[1].get('security_label')
+ if sec_lab:
+ resources[typ].append(sec_lab)
+ else:
+ resources[typ].append("%s:%s:%s" %
+ (xsconstants.ACM_POLICY_ID,
+ active_policy,
+ "unlabeled"))
return resources
@@ -874,23 +883,36 @@ def __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel,
dictionary of the resource name to resource label mappings
under which the evaluation should be done.
"""
+ def collect_labels(reslabels, s_label, polname):
+ if len(s_label) != 3 or polname != s_label[1]:
+ return False
+ label = s_label[2]
+ if not label in reslabels:
+ reslabels.append(label)
+ return True
+
resources = get_domain_resources(dominfo)
reslabels = [] # all resource labels
+
polname = xspol.get_name()
- for key in resources.keys():
- for res in resources[key]:
- try:
- tmp = access_control[res]
- if len(tmp) != 3:
+ for key, value in resources.items():
+ if key in [ 'vbd', 'tap' ]:
+ for res in resources[key]:
+ try:
+ label = access_control[res]
+ if not collect_labels(reslabels, label, polname):
+ return False
+ except:
return False
-
- if polname != tmp[1]:
+ elif key in [ 'vif' ]:
+ for xapi_label in value:
+ label = xapi_label.split(":")
+ if not collect_labels(reslabels, label, polname):
return False
- label = tmp[2]
- if not label in reslabels:
- reslabels.append(label)
- except:
- return False
+ else:
+ log.error("Unhandled device type: %s" % key)
+ return False
+
# Check that all resource labes have a common STE type with the
# vmlabel
rc = xspol.policy_check_vmlabel_against_reslabels(vmlabel, reslabels)
diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py
index 3d890e7c44..2192d334b5 100644
--- a/tools/python/xen/xend/XendAPI.py
+++ b/tools/python/xen/xend/XendAPI.py
@@ -2084,6 +2084,25 @@ class XendAPI(object):
def VIF_get_security_label(self, session, vif_ref):
return self._VIF_get(vif_ref, 'security_label')
+ def _VIF_set(self, ref, prop, val, old_val):
+ return XendDomain.instance().set_dev_property_by_uuid(
+ 'vif', ref, prop, val, old_val)
+
+ def VIF_set_security_label(self, session, vif_ref, sec_lab, old_lab):
+ xendom = XendDomain.instance()
+ dom = xendom.get_vm_with_dev_uuid('vif', vif_ref)
+ if not dom:
+ return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
+
+ if dom._stateGet() == XEN_API_VM_POWER_STATE_RUNNING:
+ raise SecurityError(-xsconstants.XSERR_RESOURCE_IN_USE)
+
+ rc = self._VIF_set(vif_ref, 'security_label', sec_lab, old_lab)
+ if rc == False:
+ raise SecurityError(-xsconstants.XSERR_BAD_LABEL)
+ return xen_api_success(xsconstants.XSERR_SUCCESS)
+
+
# Xen API: Class VIF_metrics
# ----------------------------------------------------------------
diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py
index 4dac85061b..5bc40a5dfb 100644
--- a/tools/python/xen/xend/XendConfig.py
+++ b/tools/python/xen/xend/XendConfig.py
@@ -1085,6 +1085,12 @@ class XendConfig(dict):
self.device_duplicate_check(dev_type, dev_info, target)
+ if dev_type == 'vif':
+ if dev_info.get('policy') and dev_info.get('label'):
+ dev_info['security_label'] = "%s:%s:%s" % \
+ (xsconstants.ACM_POLICY_ID,
+ dev_info['policy'],dev_info['label'])
+
# create uuid if it doesn't exist
dev_uuid = dev_info.get('uuid', None)
if not dev_uuid:
@@ -1159,6 +1165,10 @@ class XendConfig(dict):
network = XendAPIStore.get(
cfg_xenapi.get('network'), 'network')
dev_info['bridge'] = network.get_name_label()
+
+ if cfg_xenapi.get('security_label'):
+ dev_info['security_label'] = \
+ cfg_xenapi.get('security_label')
dev_uuid = cfg_xenapi.get('uuid', None)
if not dev_uuid:
diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py
index c951dc6af8..3d48365571 100644
--- a/tools/python/xen/xend/XendDomain.py
+++ b/tools/python/xen/xend/XendDomain.py
@@ -688,6 +688,29 @@ class XendDomain:
return value
+ def set_dev_property_by_uuid(self, klass, dev_uuid, field, value,
+ old_val = None):
+ rc = True
+ self.domains_lock.acquire()
+
+ try:
+ try:
+ dom = self.get_vm_with_dev_uuid(klass, dev_uuid)
+ if dom:
+ o_val = dom.get_dev_property(klass, dev_uuid, field)
+ log.info("o_val=%s, old_val=%s" % (o_val, old_val))
+ if old_val and old_val != o_val:
+ return False
+
+ dom.set_dev_property(klass, dev_uuid, field, value)
+ self.managed_config_save(dom)
+ except ValueError, e:
+ pass
+ finally:
+ self.domains_lock.release()
+
+ return rc
+
def is_valid_vm(self, vm_ref):
return (self.get_vm_by_uuid(vm_ref) != None)
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index a69211d32b..94a02049a6 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -2420,6 +2420,8 @@ class XendDomainInfo:
config['io_read_kbs'] = 0.0
config['io_write_kbs'] = 0.0
+ config['security_label'] = config.get('security_label', '')
+
if dev_class == 'vbd':
if self._stateGet() not in (XEN_API_VM_POWER_STATE_HALTED,):
diff --git a/tools/python/xen/xend/XendXSPolicyAdmin.py b/tools/python/xen/xend/XendXSPolicyAdmin.py
index 727cae664a..b3d7c2a9f1 100644
--- a/tools/python/xen/xend/XendXSPolicyAdmin.py
+++ b/tools/python/xen/xend/XendXSPolicyAdmin.py
@@ -312,6 +312,18 @@ class XSPolicyAdmin:
vmlabel = pol.policy_get_domain_label_by_ssidref_formatted(ssidref)
return vmlabel
+ def get_stes_of_vmlabel(self, vmlabel_xapi):
+ """ Get the list of STEs given a VM label in XenAPI format """
+ stes = []
+ loadedpol = self.get_loaded_policy()
+ if loadedpol:
+ tmp = vmlabel_xapi.split(":")
+ if len(tmp) != 3:
+ return []
+ stes = loadedpol.policy_get_stes_of_vmlabel(tmp[2])
+ return stes
+
+
poladmin = None
def XSPolicyAdminInstance(maxpolicies=1):
diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py
index 130668428c..3d4b598b91 100644
--- a/tools/python/xen/xend/server/netif.py
+++ b/tools/python/xen/xend/server/netif.py
@@ -26,6 +26,11 @@ import re
from xen.xend import XendOptions
from xen.xend.server.DevController import DevController
+from xen.xend.XendError import VmError
+from xen.util import security
+from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
+
+from xen.xend.XendLogging import log
xoptions = XendOptions.instance()
@@ -108,6 +113,7 @@ class NetifController(DevController):
ipaddr = config.get('ip')
model = config.get('model')
accel = config.get('accel')
+ sec_lab = config.get('security_label')
if not typ:
typ = xoptions.netback_type
@@ -134,6 +140,8 @@ class NetifController(DevController):
back['model'] = model
if accel:
back['accel'] = accel
+ if sec_lab:
+ back['security_label'] = sec_lab
config_path = "device/%s/%d/" % (self.deviceClass, devid)
for x in back:
@@ -149,9 +157,34 @@ class NetifController(DevController):
front = { 'handle' : "%i" % devid,
'mac' : mac }
+ if security.on():
+ self.do_access_control(config)
+
return (devid, back, front)
+ def do_access_control(self, config):
+ """ do access control checking. Throws a VMError if access is denied """
+ domain_label = self.vm.get_security_label()
+ stes = XSPolicyAdminInstance().get_stes_of_vmlabel(domain_label)
+ res_label = config.get('security_label')
+ if len(stes) > 1 or res_label:
+ if not res_label:
+ raise VmError("'VIF' must be labeled")
+ (label, ssidref, policy) = \
+ security.security_label_to_details(res_label)
+ if domain_label:
+ rc = security.res_security_check_xapi(label, ssidref,
+ policy,
+ domain_label)
+ if rc == 0:
+ raise VmError("VM's access to network device denied. "
+ "Check labeling")
+ else:
+ raise VmError("VM must have a security label to access "
+ "network device")
+
+
def getDeviceConfiguration(self, devid):
"""@see DevController.configuration"""
@@ -160,10 +193,12 @@ class NetifController(DevController):
config_path = "device/%s/%d/" % (self.deviceClass, devid)
devinfo = ()
for x in ( 'script', 'ip', 'bridge', 'mac',
- 'type', 'vifname', 'rate', 'uuid', 'model', 'accel'):
+ 'type', 'vifname', 'rate', 'uuid', 'model', 'accel',
+ 'security_label'):
y = self.vm._readVm(config_path + x)
devinfo += (y,)
- (script, ip, bridge, mac, typ, vifname, rate, uuid, model, accel) = devinfo
+ (script, ip, bridge, mac, typ, vifname, rate, uuid,
+ model, accel, security_label) = devinfo
if script:
result['script'] = script
@@ -185,5 +220,7 @@ class NetifController(DevController):
result['model'] = model
if accel:
result['accel'] = accel
-
+ if security_label:
+ result['security_label'] = security_label
+
return result
diff --git a/tools/python/xen/xm/addlabel.py b/tools/python/xen/xm/addlabel.py
index 9e93641284..bb27d30331 100644
--- a/tools/python/xen/xm/addlabel.py
+++ b/tools/python/xen/xm/addlabel.py
@@ -34,6 +34,7 @@ def help():
Format: xm addlabel <label> dom <configfile> [<policy>]
xm addlabel <label> mgt <domain name> [<policy type>:<policy>]
xm addlabel <label> res <resource> [[<policy type>:]<policy>]
+ xm addlabel <label> vif-<idx> <domain name> [<policy type>:<policy>]
This program adds an acm_label entry into the 'configfile'
for a domain or allows to label a xend-managed domain.
@@ -162,6 +163,32 @@ def add_domain_label_xapi(label, domainname, policyref, policy_type):
print "Set the label of dormant domain '%s' to '%s'." % \
(domainname,label)
+def add_vif_label(label, vmname, idx, policyref, policy_type):
+ if xm_main.serverType != xm_main.SERVER_XEN_API:
+ raise OptionError('Need to be configure for using xen-api.')
+ vm_refs = server.xenapi.VM.get_by_name_label(vmname)
+ if len(vm_refs) == 0:
+ raise OptionError('A VM with the name %s does not exist.' %
+ vmname)
+ vif_refs = server.xenapi.VM.get_VIFs(vm_refs[0])
+ if len(vif_refs) <= idx:
+ raise OptionError("Bad VIF index.")
+ vif_ref = server.xenapi.VIF.get_by_uuid(vif_refs[idx])
+ if not vif_ref:
+ print "Internal error: VIF does not exist."
+ sec_lab = "%s:%s:%s" % (policy_type, policyref, label)
+ try:
+ old_lab = server.xenapi.VIF.get_security_label(vif_ref)
+ rc = server.xenapi.VIF.set_security_label(vif_ref,
+ sec_lab, old_lab)
+ if int(rc) != 0:
+ print "Could not label the VIF."
+ else:
+ print "Successfully labeled the VIF."
+ except Exception, e:
+ print "Could not label the VIF: %s" % str(e)
+
+
def main(argv):
policyref = None
policy_type = ""
@@ -209,6 +236,20 @@ def main(argv):
else:
raise OptionError("Policy name in wrong format.")
add_resource_label(label, resource, policyref, policy_type)
+ elif argv[2].lower().startswith("vif-"):
+ try:
+ idx = int(argv[2][4:])
+ if idx < 0:
+ raise
+ except:
+ raise OptionError("Bad VIF device index.")
+ vmname = argv[3]
+ if policy_type == "":
+ tmp = policyref.split(":")
+ if len(tmp) != 2:
+ raise OptionError("Policy name in wrong format.")
+ policy_type, policyref = tmp
+ add_vif_label(label, vmname, idx, policyref, policy_type)
else:
raise OptionError('Need to specify either "dom", "mgt" or "res" as '
'object to add label to.')
diff --git a/tools/python/xen/xm/create.dtd b/tools/python/xen/xm/create.dtd
index f9c7fe8957..efb3cbfd3e 100644
--- a/tools/python/xen/xm/create.dtd
+++ b/tools/python/xen/xm/create.dtd
@@ -74,7 +74,8 @@
mtu CDATA #REQUIRED
device CDATA #REQUIRED
qos_algorithm_type CDATA #REQUIRED
- network CDATA #IMPLIED>
+ network CDATA #IMPLIED
+ security_label CDATA #IMPLIED>
<!ELEMENT vtpm (name*)>
<!ATTLIST vtpm backend CDATA #REQUIRED>
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index bca85abbde..f4d056608b 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -704,7 +704,8 @@ def configure_vifs(config_devs, vals):
def f(k):
if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
- 'vifname', 'rate', 'model', 'accel']:
+ 'vifname', 'rate', 'model', 'accel',
+ 'policy', 'label']:
err('Invalid vif option: ' + k)
config_vif.append([k, d[k]])
diff --git a/tools/python/xen/xm/getlabel.py b/tools/python/xen/xm/getlabel.py
index 5954ca923b..cf7033d7d4 100644
--- a/tools/python/xen/xm/getlabel.py
+++ b/tools/python/xen/xm/getlabel.py
@@ -31,6 +31,7 @@ def help():
Usage: xm getlabel dom <configfile>
xm getlabel mgt <domain name>
xm getlabel res <resource>
+ xm getlabel vif-<idx> <vmname>
This program shows the label for a domain, resource or virtual network
interface of a Xend-managed domain."""
@@ -103,6 +104,22 @@ def get_domain_label(configfile):
data = data.rstrip("\']")
print "policytype=%s," % xsconstants.ACM_POLICY_ID + data
+def get_vif_label(vmname, idx):
+ if xm_main.serverType != xm_main.SERVER_XEN_API:
+ raise OptionError('xm needs to be configure to use the xen-api.')
+ vm_refs = server.xenapi.VM.get_by_name_label(vmname)
+ if len(vm_refs) == 0:
+ raise OptionError('A VM with the name %s does not exist.' %
+ vmname)
+ vif_refs = server.xenapi.VM.get_VIFs(vm_refs[0])
+ if len(vif_refs) <= idx:
+ raise OptionError("Bad VIF index.")
+ vif_ref = server.xenapi.VIF.get_by_uuid(vif_refs[idx])
+ if not vif_ref:
+ print "No VIF with this UUID."
+ sec_lab = server.xenapi.VIF.get_security_label(vif_ref)
+ print "%s" % sec_lab
+
def get_domain_label_xapi(domainname):
if xm_main.serverType != xm_main.SERVER_XEN_API:
raise OptionError('xm needs to be configure to use the xen-api.')
@@ -128,6 +145,15 @@ def main(argv):
elif argv[1].lower() == "res":
resource = argv[2]
get_resource_label(resource)
+ elif argv[1].lower().startswith("vif-"):
+ try:
+ idx = int(argv[1][4:])
+ if idx < 0:
+ raise
+ except:
+ raise OptionError("Bad VIF device index.")
+ vmname = argv[2]
+ get_vif_label(vmname, idx)
else:
raise OptionError('First subcommand argument must be "dom"'
', "mgt" or "res"')
diff --git a/tools/python/xen/xm/rmlabel.py b/tools/python/xen/xm/rmlabel.py
index 2eb9c4b6d4..c3c488fc5b 100644
--- a/tools/python/xen/xm/rmlabel.py
+++ b/tools/python/xen/xm/rmlabel.py
@@ -30,6 +30,7 @@ def help():
Example: xm rmlabel dom <configfile>
xm rmlabel res <resource>
xm rmlabel mgt <domain name>
+ xm rmlabel vif-<idx> <domain name>
This program removes an acm_label entry from the 'configfile'
for a domain, from a Xend-managed domain, from the global resource label
@@ -129,24 +130,55 @@ def rm_domain_label_xapi(domainname):
except Exception, e:
print('Could not remove label from domain: %s' % e)
+def rm_vif_label(vmname, idx):
+ if xm_main.serverType != xm_main.SERVER_XEN_API:
+ raise OptionError('Need to be configure for using xen-api.')
+ vm_refs = server.xenapi.VM.get_by_name_label(vmname)
+ if len(vm_refs) == 0:
+ raise OptionError('A VM with the name %s does not exist.' %
+ vmname)
+ vif_refs = server.xenapi.VM.get_VIFs(vm_refs[0])
+ if len(vif_refs) <= idx:
+ raise OptionError("Bad VIF index.")
+ vif_ref = server.xenapi.VIF.get_by_uuid(vif_refs[idx])
+ if not vif_ref:
+ print "A VIF with this UUID does not exist."
+ try:
+ old_lab = server.xenapi.VIF.get_security_label(vif_ref)
+ rc = server.xenapi.VIF.set_security_label(vif_ref, "", old_lab)
+ if int(rc) != 0:
+ print "Could not remove the label from the VIF."
+ else:
+ print "Successfully removed the label from the VIF."
+ except Exception, e:
+ print "Could not remove the label the VIF: %s" % str(e)
+
def main (argv):
if len(argv) != 3:
raise OptionError('Requires 2 arguments')
- if argv[1].lower() not in ('dom', 'mgt', 'res'):
- raise OptionError('Unrecognised type argument: %s' % argv[1])
-
if argv[1].lower() == "dom":
configfile = argv[2]
rm_domain_label(configfile)
elif argv[1].lower() == "mgt":
domain = argv[2]
rm_domain_label_xapi(domain)
+ elif argv[1].lower().startswith("vif-"):
+ try:
+ idx = int(argv[1][4:])
+ if idx < 0:
+ raise
+ except:
+ raise OptionError("Bad VIF device index.")
+ vmname = argv[2]
+ rm_vif_label(vmname, idx)
elif argv[1].lower() == "res":
resource = argv[2]
rm_resource_label(resource)
+ else:
+ raise OptionError('Unrecognised type argument: %s' % argv[1])
if __name__ == '__main__':
try:
diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py
index 0a2d74a209..70c91140b7 100644
--- a/tools/python/xen/xm/xenapi_create.py
+++ b/tools/python/xen/xm/xenapi_create.py
@@ -440,7 +440,9 @@ class xenapi_create:
vif.attributes["qos_algorithm_type"].value,
"qos_algorithm_params":
get_child_nodes_as_dict(vif,
- "qos_algorithm_param", "key", "value")
+ "qos_algorithm_param", "key", "value"),
+ "security_label":
+ vif.attributes["security_label"].value
}
return server.xenapi.VIF.create(vif_record)
@@ -748,6 +750,15 @@ class sxp2xml:
vif.attributes["device"] = dev
vif.attributes["qos_algorithm_type"] = ""
+ policy = get_child_by_name(vif_sxp, "policy")
+ label = get_child_by_name(vif_sxp, "label")
+
+ if label and policy:
+ vif.attributes["security_label"] \
+ = "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, policy, label)
+ else:
+ vif.attributes["security_label"] = ""
+
if get_child_by_name(vif_sxp, "bridge") is not None:
vif.attributes["network"] \
= get_child_by_name(vif_sxp, "bridge")