[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XM] Tools support for extensions of the Xen-API for managing security policies
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1184147383 -3600 # Node ID 73b6733e4bb1d83bd7c8e11958c274874243a535 # Parent 637ff26be6ff820d185d8cdc5cc344aea6b5c9e2 [XM] Tools support for extensions of the Xen-API for managing security policies This patch adds a couple of new commands for using the Xen-API extensions for security policies. Older tools are converted to support going through the Xen-API for their operations rather than doing the operations directly in their own code. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx> --- tools/python/xen/xm/activatepolicy.py | 86 +++++++++++++++++++++ tools/python/xen/xm/addlabel.py | 135 +++++++++++++++++++++++++--------- tools/python/xen/xm/cfgbootpolicy.py | 76 ++++++++++++++----- tools/python/xen/xm/create.dtd | 7 + tools/python/xen/xm/create.py | 22 +---- tools/python/xen/xm/getlabel.py | 45 ++++++++--- tools/python/xen/xm/getpolicy.py | 94 +++++++++++++++++++++++ tools/python/xen/xm/labels.py | 37 ++++++++- tools/python/xen/xm/loadpolicy.py | 32 +++++++- tools/python/xen/xm/main.py | 72 ++++++++++++------ tools/python/xen/xm/makepolicy.py | 14 ++- tools/python/xen/xm/resources.py | 33 ++++++-- tools/python/xen/xm/rmlabel.py | 65 ++++++++++++---- tools/python/xen/xm/setpolicy.py | 117 +++++++++++++++++++++++++++++ tools/python/xen/xm/xenapi_create.py | 55 +++++++++++++ 15 files changed, 754 insertions(+), 136 deletions(-) diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/activatepolicy.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xm/activatepolicy.py Wed Jul 11 10:49:43 2007 +0100 @@ -0,0 +1,86 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2007 International Business Machines Corp. +# Author: Stefan Berger <stefanb@xxxxxxxxxx> +#============================================================================ + +"""Activate the managed policy of the system. +""" + +import sys +from xen.util import xsconstants +from xml.dom import minidom +from xen.xm.opts import OptionError +from xen.xm import getpolicy +from xen.xm import main as xm_main +from xen.xm.main import server + +def help(): + return """ + Usage: xm activatepolicy [options] + + Activate the xend-managed policy. + + The following options are defined: + --load Load the policy into the hypervisor. + --boot Have the system boot with the policy. Changes the default + title in grub.conf. + --noboot Remove the policy from the default entry in grub.conf. + """ + +def activate_policy(flags): + policystate = server.xenapi.XSPolicy.get_xspolicy() + xs_ref = policystate['xs_ref'] + if int(policystate['type']) == 0 or xs_ref == "": + print "No policy is installed." + return + rc = int(server.xenapi.XSPolicy.activate_xspolicy(xs_ref, flags)) + if rc == flags: + print "Successfully activated the policy." + else: + print "An error occurred trying to activate the policy: %s" % \ + xsconstants.xserr2string(rc) + +def remove_bootpolicy(): + server.xenapi.XSPolicy.rm_xsbootpolicy() + +def main(argv): + if xm_main.serverType != xm_main.SERVER_XEN_API: + raise OptionError('xm needs to be configured to use the xen-api.') + flags = 0 + c = 1 + + while c < len(argv): + if '--boot' == argv[c]: + flags |= xsconstants.XS_INST_BOOT + elif '--load' == argv[c]: + flags |= xsconstants.XS_INST_LOAD + elif '--noboot' == argv[c]: + remove_bootpolicy() + else: + raise OptionError("Unknown command line option '%s'" % argv[c]) + c += 1 + + if flags != 0: + activate_policy(flags) + + getpolicy.getpolicy(False) + +if __name__ == '__main__': + try: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) + sys.exit(-1) diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/addlabel.py --- a/tools/python/xen/xm/addlabel.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/addlabel.py Wed Jul 11 10:49:43 2007 +0100 @@ -25,17 +25,29 @@ from xen.util import dictio from xen.util import dictio from xen.util import security from xen.xm.opts import OptionError +from xen.util import xsconstants +from xen.xm import main as xm_main +from xen.xm.main import server def help(): return """ Format: xm addlabel <label> dom <configfile> [<policy>] - xm addlabel <label> res <resource> [<policy>] + xm addlabel <label> mgt <domain name> [<policy type>:<policy>] + xm addlabel <label> res <resource> [[<policy type>:]<policy>] This program adds an acm_label entry into the 'configfile' - for a domain or to the global resource label file for a - resource. It derives the policy from the running hypervisor + for a domain or allows to label a xend-managed domain. + The global resource label file for is extended with labels for + resources. It derives the policy from the running hypervisor if it is not given (optional parameter). If a label already - exists for the given domain or resource, then addlabel fails.""" + exists for the given domain or resource, then addlabel fails. + + For xend-managed domains, the 'mgt' parameter should be used and + the 'xm' tool must have been configured to use the xen-api for + communication with xen. If a policy is provided as last parameter, + its type must also be given. Currently only one type of policy is + supported and identified as 'ACM'. An example for a valid string + is 'ACM:xm-test'. """ def validate_config_file(configfile): @@ -66,32 +78,47 @@ def validate_config_file(configfile): return 1 -def add_resource_label(label, resource, policyref): +def add_resource_label(label, resource, policyref, policy_type): """Adds a resource label to the global resource label file. """ - # sanity check: make sure this label can be instantiated later on - ssidref = security.label2ssidref(label, policyref, 'res') - - #build canonical resource name - resource = security.unify_resname(resource) - - # see if this resource is already in the file - access_control = {} - file = security.res_label_filename - try: - access_control = dictio.dict_read("resources", file) - except: - print "Resource file not found, creating new file at:" - print "%s" % (file) - - if access_control.has_key(resource): - security.err("This resource is already labeled.") - - # write the data to file - new_entry = { resource : tuple([policyref, label]) } - access_control.update(new_entry) - dictio.dict_write(access_control, "resources", file) - + + if xm_main.serverType != xm_main.SERVER_XEN_API: + + # sanity check: make sure this label can be instantiated later on + ssidref = security.label2ssidref(label, policyref, 'res') + + #build canonical resource name + resource = security.unify_resname(resource,mustexist=False) + + # see if this resource is already in the file + access_control = {} + fil = security.res_label_filename + try: + access_control = dictio.dict_read("resources", fil) + except: + print "Resource file not found, creating new file at:" + print "%s" % (fil) + + if access_control.has_key(resource): + security.err("This resource is already labeled.") + + # write the data to file + new_entry = { resource : tuple([policy_type, policyref, label]) } + access_control.update(new_entry) + dictio.dict_write(access_control, "resources", fil) + else: + res = [ policy_type, policyref, label ] + res_xapi = security.format_resource_label(res) + old = server.xenapi.XSPolicy.get_resource_label(resource) + if old == "": + try: + server.xenapi.XSPolicy.set_resource_label(resource, + res_xapi, + "") + except Exception, e: + security.err("Could not label this resource: %s" % e) + else: + security.err("'%s' is already labeled with '%s'" % (resource,old)) def add_domain_label(label, configfile, policyref): # sanity checks: make sure this label can be instantiated later on @@ -109,9 +136,35 @@ def add_domain_label(label, configfile, config_fd.write(new_label) config_fd.close() +def add_domain_label_xapi(label, domainname, policyref, policy_type): + if xm_main.serverType != xm_main.SERVER_XEN_API: + raise OptionError('Xm must be configured to use the xen-api.') + uuids = server.xenapi.VM.get_by_name_label(domainname) + if len(uuids) == 0: + raise OptionError('A VM with that name does not exist.') + if len(uuids) != 1: + raise OptionError('There are multiple domains with the same name.') + uuid = uuids[0] + sec_lab = "%s:%s:%s" % (policy_type, policyref, label) + try: + old_lab = server.xenapi.VM.get_security_label(uuid) + rc = server.xenapi.VM.set_security_label(uuid, sec_lab, old_lab) + except: + rc = -1 + if int(rc) < 0: + raise OptionError('Could not label domain.') + else: + ssidref = int(rc) + if ssidref != 0: + print "Set the label of domain '%s' to '%s'. New ssidref = %08x" % \ + (domainname,label,ssidref) + else: + print "Set the label of dormant domain '%s' to '%s'." % \ + (domainname,label) def main(argv): policyref = None + policy_type = "" if len(argv) not in (4, 5): raise OptionError('Needs either 2 or 3 arguments') @@ -121,6 +174,7 @@ def main(argv): policyref = argv[4] elif security.on(): policyref = security.active_policy + policy_type = xsconstants.ACM_POLICY_ID else: raise OptionError("No active policy. Must specify policy on the " "command line.") @@ -136,11 +190,27 @@ def main(argv): raise OptionError('Invalid config file') else: add_domain_label(label, configfile, policyref) + elif argv[2].lower() == "mgt": + domain = argv[3] + if policy_type == "": + tmp = policyref.split(":") + if len(tmp) != 2: + raise OptionError("Policy name in wrong format.") + policy_type, policyref = tmp + add_domain_label_xapi(label, domain, policyref, policy_type) elif argv[2].lower() == "res": resource = argv[3] - add_resource_label(label, resource, policyref) - else: - raise OptionError('Need to specify either "dom" or "res" as ' + if policy_type == "": + tmp = policyref.split(":") + if len(tmp) == 1: + policy_type = xsconstants.ACM_POLICY_ID + elif len(tmp) == 2: + policy_type, policyref = tmp + else: + raise OptionError("Policy name in wrong format.") + add_resource_label(label, resource, policyref, policy_type) + else: + raise OptionError('Need to specify either "dom", "mgt" or "res" as ' 'object to add label to.') if __name__ == '__main__': @@ -149,6 +219,3 @@ if __name__ == '__main__': except Exception, e: sys.stderr.write('Error: %s\n' % str(e)) sys.exit(-1) - - - diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/cfgbootpolicy.py --- a/tools/python/xen/xm/cfgbootpolicy.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/cfgbootpolicy.py Wed Jul 11 10:49:43 2007 +0100 @@ -31,7 +31,11 @@ from xen.util.security import boot_filen from xen.util.security import boot_filename, altboot_filename from xen.util.security import any_title_re, xen_kernel_re, any_module_re from xen.util.security import empty_line_re, binary_name_re, policy_name_re +from xen.util import xsconstants from xen.xm.opts import OptionError +from xen.xm import main as xm_main +from xen.xm.main import server +from xen.util.acmpolicy import ACMPolicy def help(): return """ @@ -144,6 +148,39 @@ def insert_policy(boot_file, alt_boot_fi pass return extended_titles[0] +def cfgbootpolicy_xapi(policy, user_title=None): + xstype = int(server.xenapi.XSPolicy.get_xstype()) + if xstype & xsconstants.XS_POLICY_ACM == 0: + raise OptionError("ACM policy not supported on system.") + if user_title: + raise OptionError("Only the default title is supported with Xen-API.") + + policystate = server.xenapi.XSPolicy.get_xspolicy() + if int(policystate['type']) == 0: + print "No policy is installed." + return + + if int(policystate['type']) != xsconstants.XS_POLICY_ACM: + print "Unknown policy type '%s'." % policystate['type'] + return + else: + xml = policystate['repr'] + xs_ref = policystate['xs_ref'] + if not xml: + OptionError("No policy installed on system?") + acmpol = ACMPolicy(xml=xml) + if acmpol.get_name() != policy: + OptionError("Policy installed on system '%s' does not match the " + "request policy '%s'" % (acmpol.get_name(), policy)) + flags = int(policystate['flags']) | xsconstants.XS_INST_BOOT + rc = int(server.xenapi.XSPolicy.activate_xspolicy(xs_ref, flags)) + if rc == flags: + print "Successfully enabled the policy for having the system" \ + " booted with." + else: + print "An error occurred during the operation: %s" % \ + xsconstants.xserr2string(rc) + def main(argv): user_kver = None @@ -159,24 +196,27 @@ def main(argv): if not policy_name_re.match(policy): raise OptionError("Illegal policy name: '%s'" % policy) - policy_file = '/'.join([policy_dir_prefix] + policy.split('.')) - src_binary_policy_file = policy_file + ".bin" - #check if .bin exists or if policy file exists - if not os.path.isfile(src_binary_policy_file): - if not os.path.isfile(policy_file + "-security_policy.xml"): - raise OptionError("Unknown policy '%s'" % policy) - else: - err_msg = "Cannot find binary file for policy '%s'." % policy - err_msg += " Please use makepolicy to create binary file." - raise OptionError(err_msg) - - dst_binary_policy_file = "/boot/" + policy + ".bin" - shutil.copyfile(src_binary_policy_file, dst_binary_policy_file) - - entryname = insert_policy(boot_filename, altboot_filename, - user_title, policy) - print "Boot entry '%s' extended and \'%s\' copied to /boot" \ - % (entryname, policy + ".bin") + if xm_main.serverType == xm_main.SERVER_XEN_API: + cfgbootpolicy_xapi(policy) + else: + policy_file = '/'.join([policy_dir_prefix] + policy.split('.')) + src_binary_policy_file = policy_file + ".bin" + #check if .bin exists or if policy file exists + if not os.path.isfile(src_binary_policy_file): + if not os.path.isfile(policy_file + "-security_policy.xml"): + raise OptionError("Unknown policy '%s'" % policy) + else: + err_msg = "Cannot find binary file for policy '%s'." % policy + err_msg += " Please use makepolicy to create binary file." + raise OptionError(err_msg) + + dst_binary_policy_file = "/boot/" + policy + ".bin" + shutil.copyfile(src_binary_policy_file, dst_binary_policy_file) + + entryname = insert_policy(boot_filename, altboot_filename, + user_title, policy) + print "Boot entry '%s' extended and \'%s\' copied to /boot" \ + % (entryname, policy + ".bin") if __name__ == '__main__': try: diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/create.dtd --- a/tools/python/xen/xm/create.dtd Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/create.dtd Wed Jul 11 10:49:43 2007 +0100 @@ -38,6 +38,7 @@ memory, vbd*, vif*, + vtpm*, console*, platform*, vcpu_param*, @@ -49,7 +50,8 @@ actions_after_shutdown %NORMAL_EXIT; #REQUIRED actions_after_reboot %NORMAL_EXIT; #REQUIRED actions_after_crash %CRASH_BEHAVIOUR; #REQUIRED - PCI_bus CDATA #REQUIRED> + PCI_bus CDATA #REQUIRED + security_label CDATA #IMPLIED> <!ELEMENT memory EMPTY> <!ATTLIST memory static_min CDATA #REQUIRED @@ -73,6 +75,9 @@ device CDATA #REQUIRED qos_algorithm_type CDATA #REQUIRED network CDATA #IMPLIED> + +<!ELEMENT vtpm (name*)> +<!ATTLIST vtpm backend CDATA #REQUIRED> <!ELEMENT console (other_config*)> <!ATTLIST console protocol (vt100|rfb|rdp) #REQUIRED> diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/create.py Wed Jul 11 10:49:43 2007 +0100 @@ -643,22 +643,12 @@ def configure_security(config, vals): ['policy', policy], ['label', label] ] - #ssidref cannot be specified together with access_control - if sxp.child_value(config, 'ssidref'): - err("ERROR: SSIDREF and access_control are mutually exclusive but both specified!") - #else calculate ssidre from label + #calculate ssidref from label ssidref = security.label2ssidref(label, policy, 'dom') if not ssidref : err("ERROR calculating ssidref from access_control.") security_label = ['security', [ config_access_control, ['ssidref' , ssidref ] ] ] config.append(security_label) - elif num == 0: - if hasattr(vals, 'ssidref'): - if not security.on(): - err("ERROR: Security ssidref specified but no policy active.") - ssidref = getattr(vals, 'ssidref') - security_label = ['security', [ [ 'ssidref' , int(ssidref) ] ] ] - config.append(security_label) elif num > 1: err("VM config error: Multiple access_control definitions!") @@ -1231,13 +1221,13 @@ def config_security_check(config, verbos except security.ACMError: print " %s: DENIED" % (resource) - (res_label, res_policy) = security.get_res_label(resource) + (poltype, res_label, res_policy) = security.get_res_label(resource) if not res_label: res_label = "" - print " --> res: %s (%s)" % (str(res_label), - str(res_policy)) - print " --> dom: %s (%s)" % (str(domain_label), - str(domain_policy)) + print " --> res: %s (%s:%s)" % (str(res_label), + str(poltype), str(res_policy)) + print " --> dom: %s (%s:%s)" % (str(domain_label), + str(poltype), str(domain_policy)) answer = 0 diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/getlabel.py --- a/tools/python/xen/xm/getlabel.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/getlabel.py Wed Jul 11 10:49:43 2007 +0100 @@ -21,14 +21,19 @@ import sys, os, re import sys, os, re from xen.util import dictio from xen.util import security +from xen.util import xsconstants from xen.xm.opts import OptionError +from xen.xm import main as xm_main +from xen.xm.main import server def help(): return """ Usage: xm getlabel dom <configfile> + xm getlabel mgt <domain name> xm getlabel res <resource> - This program shows the label for a domain or resource.""" + This program shows the label for a domain, resource or virtual network + interface of a Xend-managed domain.""" def get_resource_label(resource): """Gets the resource label @@ -37,17 +42,24 @@ def get_resource_label(resource): resource = security.unify_resname(resource) # read in the resource file - file = security.res_label_filename + fil = security.res_label_filename try: - access_control = dictio.dict_read("resources", file) + access_control = dictio.dict_read("resources", fil) except: raise OptionError("Resource label file not found") # get the entry and print label if access_control.has_key(resource): - policy = access_control[resource][0] - label = access_control[resource][1] - print "policy="+policy+",label="+label + tmp = access_control[resource] + if len(tmp) == 2: + policy, label = tmp + policytype = xsconstants.ACM_POLICY_ID + elif len(tmp) == 3: + policytype, policy, label = tmp + else: + raise security.ACMError("Resource not properly labeled. " + "Please relabel the resource.") + print policytype+":"+policy+":"+label else: raise security.ACMError("Resource not labeled") @@ -89,8 +101,19 @@ def get_domain_label(configfile): data = data.strip() data = data.lstrip("[\'") data = data.rstrip("\']") - print data + print "policytype=%s," % xsconstants.ACM_POLICY_ID + data +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.') + uuids = server.xenapi.VM.get_by_name_label(domainname) + if len(uuids) == 0: + raise OptionError('A VM with that name does not exist.') + if len(uuids) != 1: + raise OptionError('There are multiple domains with the same name.') + uuid = uuids[0] + sec_lab = server.xenapi.VM.get_security_label(uuid) + print "%s" %sec_lab def main(argv): if len(argv) != 3: @@ -99,11 +122,15 @@ def main(argv): if argv[1].lower() == "dom": configfile = argv[2] get_domain_label(configfile) + elif argv[1].lower() == "mgt": + domainname = argv[2] + get_domain_label_xapi(domainname) elif argv[1].lower() == "res": resource = argv[2] get_resource_label(resource) else: - raise OptionError('First subcommand argument must be "dom" or "res"') + raise OptionError('First subcommand argument must be "dom"' + ', "mgt" or "res"') if __name__ == '__main__': try: @@ -111,6 +138,4 @@ if __name__ == '__main__': except Exception, e: sys.stderr.write('Error: %s\n' % str(e)) sys.exit(-1) - - diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/getpolicy.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xm/getpolicy.py Wed Jul 11 10:49:43 2007 +0100 @@ -0,0 +1,94 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2007 International Business Machines Corp. +# Author: Stefan Berger <stefanb@xxxxxxxxxx> +#============================================================================ + +"""Get the managed policy of the system. +""" + +import sys +from xen.util import xsconstants +from xml.dom import minidom +from xen.xm.opts import OptionError +from xen.util.acmpolicy import ACMPolicy +from xen.xm import main as xm_main +from xen.xm.main import server + +def help(): + return """ + Usage: xm getpolicy [options] + + The following options are defined + --dumpxml Display the XML of the policy + + Get the policy managed by xend.""" + +def getpolicy(dumpxml): + if xm_main.serverType != xm_main.SERVER_XEN_API: + raise OptionError('xm needs to be configured to use the xen-api.') + types = [] + xstype = int(server.xenapi.XSPolicy.get_xstype()) + if xstype & xsconstants.XS_POLICY_ACM: + types.append("ACM") + xstype ^= xsconstants.XS_POLICY_ACM + if xstype != 0: + types.append("unsupported (%08x)" % xstype) + print "Supported security subsystems : %s \n" % ", ".join(types) + + policystate = server.xenapi.XSPolicy.get_xspolicy() + if int(policystate['type']) == 0: + print "No policy is installed." + return + if int(policystate['type']) != xsconstants.XS_POLICY_ACM: + print "Unknown policy type '%s'." % policystate['type'] + else: + xml = policystate['repr'] + acmpol = None + if xml: + acmpol = ACMPolicy(xml=xml) + print "Policy installed on the system:" + if acmpol: + print "Policy name : %s" % acmpol.get_name() + print "Policy type : %s" % xsconstants.ACM_POLICY_ID + print "Reference : %s" % policystate['xs_ref'] + print "Version of XML policy : %s" % policystate['version'] + state = [] + flags = int(policystate['flags']) + if flags & xsconstants.XS_INST_LOAD: + state.append("loaded") + if flags & xsconstants.XS_INST_BOOT: + state.append("system booted with") + print "State of the policy : %s" % ", ".join(state) + if dumpxml: + xml = policystate['repr'] + if xml: + dom = minidom.parseString(xml.encode("utf-8")) + print "%s" % dom.toprettyxml(indent=" ",newl="\n") + +def main(argv): + dumpxml = False + + if '--dumpxml' in argv: + dumpxml = True + + getpolicy(dumpxml) + +if __name__ == '__main__': + try: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) + sys.exit(-1) diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/labels.py --- a/tools/python/xen/xm/labels.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/labels.py Wed Jul 11 10:49:43 2007 +0100 @@ -24,6 +24,10 @@ from xen.util.security import ACMError, from xen.util.security import ACMError, err, list_labels, active_policy from xen.util.security import vm_label_re, res_label_re, all_label_re from xen.xm.opts import OptionError +from xen.util.acmpolicy import ACMPolicy +from xen.util import xsconstants +from xen.xm.main import server +from xen.xm import main as xm_main def help(): @@ -48,6 +52,12 @@ def main(argv): else: raise OptionError('Unrecognised option: %s' % arg) + if xm_main.serverType != xm_main.SERVER_XEN_API: + labels(policy, ptype) + else: + labels_xapi(policy, ptype) + +def labels(policy, ptype): if not policy: policy = active_policy if active_policy in ['NULL', 'INACTIVE', 'DEFAULT']: @@ -73,7 +83,30 @@ def main(argv): except: traceback.print_exc(limit = 1) +def labels_xapi(policy, ptype): + policystate = server.xenapi.XSPolicy.get_xspolicy() + if int(policystate['type']) == xsconstants.XS_POLICY_ACM: + acmpol = ACMPolicy(xml=policystate['repr']) + if policy and policy != acmpol.get_name(): + print "Warning: '%s' is not the currently loaded policy." % policy + return labels(policy, ptype) + names1 = [] + names2 = [] + if not ptype or ptype == 'dom' or ptype == 'any': + names1 = acmpol.policy_get_virtualmachinelabel_names() + if ptype == 'res' or ptype == 'any': + names2 = acmpol.policy_get_resourcelabel_names() + if len(names1) > 0: + names = set(names1) + names.union(names2) + else: + names = set(names2) + for n in names: + print n + elif int(policystate['type']) == 0: + print "No policy installed on the system." + else: + print "Unsupported type of policy installed on the system." + if __name__ == '__main__': main(sys.argv) - - diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/loadpolicy.py --- a/tools/python/xen/xm/loadpolicy.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/loadpolicy.py Wed Jul 11 10:49:43 2007 +0100 @@ -22,6 +22,11 @@ import traceback import traceback from xen.util.security import ACMError, err, load_policy from xen.xm.opts import OptionError +from xen.xm import main as xm_main +from xen.util import xsconstants +from xen.xm.activatepolicy import activate_policy +from xen.xm.main import server +from xen.util.acmpolicy import ACMPolicy def help(): return """Load the compiled binary (.bin) policy into the running @@ -30,8 +35,31 @@ def main(argv): def main(argv): if len(argv) != 2: raise OptionError('No policy defined') - - load_policy(argv[1]) + if xm_main.serverType == xm_main.SERVER_XEN_API: + policy = argv[1] + print "This command is deprecated for use with Xen-API " \ + "configuration. Consider using\n'xm activatepolicy'." + policystate = server.xenapi.XSPolicy.get_xspolicy() + if int(policystate['type']) == 0: + print "No policy is installed." + return + + if int(policystate['type']) != xsconstants.XS_POLICY_ACM: + print "Unknown policy type '%s'." % policystate['type'] + return + else: + xml = policystate['repr'] + xs_ref = policystate['xs_ref'] + if not xml: + OptionError("No policy installed on system?") + acmpol = ACMPolicy(xml=xml) + if acmpol.get_name() != policy: + OptionError("Policy installed on system '%s' does not match"\ + " the request policy '%s'" % \ + (acmpol.get_name(), policy)) + activate_policy(xsconstants.XS_INST_LOAD) + else: + load_policy(argv[1]) if __name__ == '__main__': try: diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/main.py Wed Jul 11 10:49:43 2007 +0100 @@ -50,6 +50,7 @@ from xen.xm.opts import OptionError, Opt from xen.xm.opts import OptionError, Opts, wrap, set_true from xen.xm import console from xen.util.xmlrpcclient import ServerProxy +from xen.util.security import ACMError import XenAPI @@ -171,11 +172,12 @@ SUBCOMMAND_HELP = { # security - 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>} [<policy>]', + 'addlabel' : ('<label> {dom <ConfigFile>|res <resource>|mgt <managed domain>}\n' + ' [<policy>]', 'Add security label to domain.'), - 'rmlabel' : ('{dom <ConfigFile>|res <Resource>}', + 'rmlabel' : ('{dom <ConfigFile>|res <Resource>|mgt<managed domain>}', 'Remove a security label from domain.'), - 'getlabel' : ('{dom <ConfigFile>|res <Resource>}', + 'getlabel' : ('{dom <ConfigFile>|res <Resource>|mgt <managed domain>}', 'Show security label for domain or resource.'), 'dry-run' : ('<ConfigFile>', 'Test if a domain can access its resources.'), @@ -186,6 +188,10 @@ SUBCOMMAND_HELP = { 'loadpolicy' : ('<policy.bin>', 'Load binary policy into hypervisor.'), 'makepolicy' : ('<policy>', 'Build policy and create .bin/.map ' 'files.'), + 'setpolicy' : ('<policytype> <policyfile> [options]', + 'Set the policy of the system.'), + 'getpolicy' : ('[options]', 'Get the policy of the system.'), + 'activatepolicy': ('[options]', 'Activate the xend-managed policy.'), 'labels' : ('[policy] [type=dom|res|any]', 'List <type> labels for (active) policy.'), 'serve' : ('', 'Proxy Xend XMLRPC over stdio.'), @@ -343,6 +349,9 @@ acm_commands = [ "loadpolicy", "cfgbootpolicy", "dumppolicy", + "activatepolicy", + "setpolicy", + "getpolicy", ] all_commands = (domain_commands + host_commands + scheduler_commands + @@ -861,13 +870,17 @@ def parse_doms_info(info): 'up_time' : up_time } - # We're not supporting security stuff just yet via XenAPI - if serverType != SERVER_XEN_API: from xen.util import security parsed_info['seclabel'] = security.get_security_printlabel(info) else: - parsed_info['seclabel'] = "" + label = get_info('security_label', unicode, '') + tmp = label.split(":") + if len(tmp) != 3: + label = "" + else: + label = tmp[2] + parsed_info['seclabel'] = label if serverType == SERVER_XEN_API: parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024 @@ -925,28 +938,26 @@ def xm_brief_list(doms): print format % d def xm_label_list(doms): - print '%-32s %5s %5s %5s %5s %9s %-8s' % \ + print '%-32s %5s %5s %5s %10s %9s %-8s' % \ ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label') output = [] format = '%(name)-32s %(domid)5s %(mem)5d %(vcpus)5d %(state)10s ' \ '%(cpu_time)8.1f %(seclabel)9s' - if serverType != SERVER_XEN_API: - from xen.util import security + from xen.util import security - for dom in doms: - d = parse_doms_info(dom) - - if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']: - if not d['seclabel']: - d['seclabel'] = 'ERROR' - elif security.active_policy in ['DEFAULT']: - d['seclabel'] = 'DEFAULT' - else: - d['seclabel'] = 'INACTIVE' - - output.append((format % d, d['seclabel'])) + for dom in doms: + d = parse_doms_info(dom) + if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']: + if not d['seclabel']: + d['seclabel'] = 'ERROR' + elif security.active_policy in ['DEFAULT']: + d['seclabel'] = 'DEFAULT' + else: + d['seclabel'] = 'INACTIVE' + + output.append((format % d, d['seclabel'])) #sort by labels output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower())) @@ -1989,16 +2000,24 @@ def xm_block_list(args): % ni) def xm_vtpm_list(args): - xenapi_unsupported() (use_long, params) = arg_check_for_resource_list(args, "vtpm-list") dom = params[0] + + if serverType == SERVER_XEN_API: + vtpm_refs = server.xenapi.VM.get_VTPMs(get_single_vm(dom)) + vtpm_properties = \ + map(server.xenapi.VTPM.get_runtime_properties, vtpm_refs) + devs = map(lambda (handle, properties): [handle, map2sxp(properties)], + zip(range(len(vtpm_properties)), vtpm_properties)) + else: + devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm') + if use_long: - devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm') map(PrettyPrint.prettyprint, devs) else: hdr = 0 - for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'): + for x in devs: if hdr == 0: print 'Idx BE handle state evt-ch ring-ref BE-path' hdr = 1 @@ -2440,6 +2459,9 @@ IMPORTED_COMMANDS = [ 'getlabel', 'dry-run', 'resources', + 'getpolicy', + 'setpolicy', + 'activatepolicy', ] for c in IMPORTED_COMMANDS: @@ -2563,6 +2585,8 @@ def _run_cmd(cmd, cmd_name, args): print e.usage except XenAPIUnsupportedException, e: err(str(e)) + except ACMError, e: + err(str(e)) except Exception, e: if serverType != SERVER_XEN_API: from xen.util import security diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/makepolicy.py --- a/tools/python/xen/xm/makepolicy.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/makepolicy.py Wed Jul 11 10:49:43 2007 +0100 @@ -20,7 +20,10 @@ import sys import sys import traceback from xen.util.security import ACMError, err, make_policy +from xen.util import xsconstants from xen.xm.opts import OptionError +from xen.xm import main as xm_main +from xen.xm.setpolicy import setpolicy def usage(): print "\nUsage: xm makepolicy <policy>\n" @@ -32,8 +35,13 @@ def main(argv): def main(argv): if len(argv) != 2: raise OptionError('No XML policy file specified') - - make_policy(argv[1]) + if xm_main.serverType == xm_main.SERVER_XEN_API: + print "This command is deprecated for use with Xen-API " \ + "configuration. Consider using\n'xm setpolicy'." + setpolicy(xsconstants.ACM_POLICY_ID, argv[1], + xsconstants.XS_INST_LOAD, True) + else: + make_policy(argv[1]) if __name__ == '__main__': try: @@ -41,5 +49,3 @@ if __name__ == '__main__': except Exception, e: sys.stderr.write('Error: %s\n' % str(e)) sys.exit(-1) - - diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/resources.py --- a/tools/python/xen/xm/resources.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/resources.py Wed Jul 11 10:49:43 2007 +0100 @@ -21,7 +21,10 @@ import sys import sys from xen.util import dictio from xen.util import security +from xen.util import xsconstants from xen.xm.opts import OptionError +from xen.xm import main as xm_main +from xen.xm.main import server def help(): return """ @@ -32,20 +35,32 @@ def print_resource_data(access_control): """Prints out a resource dictionary to stdout """ for resource in access_control: - (policy, label) = access_control[resource] + tmp = access_control[resource] + if len(tmp) == 2: + policytype = xsconstants.ACM_POLICY_ID + (policy, label) = access_control[resource] + elif len(tmp) == 3: + policytype, policy, label = access_control[resource] print resource - print " policy: "+policy - print " label: "+label + print " type: "+ policytype + print " policy: "+ policy + print " label: "+ label def main (argv): if len(argv) > 1: raise OptionError("No arguments required") - - try: - filename = security.res_label_filename - access_control = dictio.dict_read("resources", filename) - except: - raise OptionError("Resource file not found") + + if xm_main.serverType == xm_main.SERVER_XEN_API: + access_control = server.xenapi.XSPolicy.get_labeled_resources() + for key, value in access_control.items(): + access_control[key] = tuple(value.split(':')) + else: + try: + filename = security.res_label_filename + access_control = dictio.dict_read("resources", filename) + print access_control + except: + raise OptionError("Resource file not found") print_resource_data(access_control) diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/rmlabel.py --- a/tools/python/xen/xm/rmlabel.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/rmlabel.py Wed Jul 11 10:49:43 2007 +0100 @@ -22,35 +22,52 @@ from xen.util import dictio from xen.util import dictio from xen.util import security from xen.xm.opts import OptionError +from xen.xm import main as xm_main +from xen.xm.main import server def help(): return """ Example: xm rmlabel dom <configfile> xm rmlabel res <resource> + xm rmlabel mgt <domain name> This program removes an acm_label entry from the 'configfile' - for a domain or from the global resource label file for a - resource. If the label does not exist for the given domain or - resource, then rmlabel fails.""" + for a domain, from a Xend-managed domain, from the global resource label + file for a resource or from the virtual network interface of a Xend-managed + domain. If the label does not exist for the given domain or resource, then + rmlabel fails.""" def rm_resource_label(resource): """Removes a resource label from the global resource label file. """ + # Try Xen-API first if configured to use it + if xm_main.serverType == xm_main.SERVER_XEN_API: + try: + oldlabel = server.xenapi.XSPolicy.get_resource_label(resource) + if oldlabel != "": + server.xenapi.XSPolicy.set_resource_label(resource,"", + oldlabel) + else: + raise security.ACMError("Resource not labeled") + except Exception, e: + print "Could not remove label from resource: %s" % e + return + #build canonical resource name resource = security.unify_resname(resource) # read in the resource file - file = security.res_label_filename + fil = security.res_label_filename try: - access_control = dictio.dict_read("resources", file) + access_control = dictio.dict_read("resources", fil) except: raise security.ACMError("Resource file not found, cannot remove label!") # remove the entry and update file if access_control.has_key(resource): del access_control[resource] - dictio.dict_write(access_control, "resources", file) + dictio.dict_write(access_control, "resources", fil) else: raise security.ACMError("Resource not labeled") @@ -58,15 +75,15 @@ def rm_domain_label(configfile): def rm_domain_label(configfile): # open the domain config file fd = None - file = None + fil = None if configfile[0] == '/': - file = configfile - fd = open(file, "rb") + fil = configfile + fd = open(fil, "rb") else: for prefix in [".", "/etc/xen"]: - file = prefix + "/" + configfile - if os.path.isfile(file): - fd = open(file, "rb") + fil = prefix + "/" + configfile + if os.path.isfile(fil): + fd = open(fil, "rb") break if not fd: raise OptionError("Configuration file '%s' not found." % configfile) @@ -93,9 +110,24 @@ def rm_domain_label(configfile): raise security.ACMError('Domain not labeled') # write the data back out to the file - fd = open(file, "wb") + fd = open(fil, "wb") fd.writelines(file_contents) fd.close() + +def rm_domain_label_xapi(domainname): + if xm_main.serverType != xm_main.SERVER_XEN_API: + raise OptionError('Need to be configure for using xen-api.') + uuids = server.xenapi.VM.get_by_name_label(domainname) + if len(uuids) == 0: + raise OptionError('A VM with that name does not exist.') + if len(uuids) != 1: + raise OptionError('Too many domains with the same name.') + uuid = uuids[0] + try: + old_lab = server.xenapi.VM.get_security_label(uuid) + server.xenapi.VM.set_security_label(uuid, "", old_lab) + except Exception, e: + print('Could not remove label from domain: %s' % e) def main (argv): @@ -103,12 +135,15 @@ def main (argv): if len(argv) != 3: raise OptionError('Requires 2 arguments') - if argv[1].lower() not in ('dom', 'res'): + 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() == "res": resource = argv[2] rm_resource_label(resource) @@ -119,5 +154,3 @@ if __name__ == '__main__': except Exception, e: sys.stderr.write('Error: %s\n' % str(e)) sys.exit(-1) - - diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/setpolicy.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xm/setpolicy.py Wed Jul 11 10:49:43 2007 +0100 @@ -0,0 +1,117 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2007 International Business Machines Corp. +# Author: Stefan Berger <stefanb@xxxxxxxxxx> +#============================================================================ + +"""Get the managed policy of the system. +""" + +import base64 +import struct +import sys +import string +from xen.util import xsconstants +from xen.xm.opts import OptionError +from xen.util.security import policy_dir_prefix +from xen.xm import main as xm_main +from xen.xm.main import server + +def help(): + return """ + Usage: xm setpolicy <policytype> <policy> [options] + + Set the policy managed by xend. + + The only policytype that is currently supported is 'ACM'. + + The following options are defined + --load Load the policy immediately + --boot Have the system load the policy during boot + """ + +def setpolicy(policytype, policy_name, flags, overwrite): + if xm_main.serverType != xm_main.SERVER_XEN_API: + raise OptionError('xm needs to be configured to use the xen-api.') + if policytype != xsconstants.ACM_POLICY_ID: + raise OptionError("Unsupported policytype '%s'." % policytype) + else: + xs_type = xsconstants.XS_POLICY_ACM + + policy_file = policy_dir_prefix + "/" + \ + string.join(string.split(policy_name, "."), "/") + policy_file += "-security_policy.xml" + + try: + f = open(policy_file,"r") + xml = f.read(-1) + f.close() + except: + raise OptionError("Not a valid policy file") + + try: + policystate = server.xenapi.XSPolicy.set_xspolicy(xs_type, + xml, + flags, + overwrite) + except Exception, e: + print "An error occurred setting the policy: %s" % str(e) + return + xserr = int(policystate['xserr']) + if xserr != 0: + print "An error occurred trying to set the policy: %s" % \ + xsconstants.xserr2string(abs(xserr)) + errors = policystate['errors'] + if len(errors) > 0: + print "Hypervisor reported errors:" + err = base64.b64decode(errors) + i = 0 + while i + 7 < len(err): + code, data = struct.unpack("!ii", errors[i:i+8]) + print "(0x%08x, 0x%08x)" % (code, data) + i += 8 + else: + print "Successfully set the new policy." + + +def main(argv): + if len(argv) < 3: + raise OptionError("Need at least 3 arguments.") + + if "-?" in argv: + help() + return + + policytype = argv[1] + policy_name = argv[2] + + flags = 0 + if '--load' in argv: + flags |= xsconstants.XS_INST_LOAD + if '--boot' in argv: + flags |= xsconstants.XS_INST_BOOT + + overwrite = True + if '--nooverwrite' in argv: + overwrite = False + + setpolicy(policytype, policy_name, flags, overwrite) + +if __name__ == '__main__': + try: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) + sys.exit(-1) diff -r 637ff26be6ff -r 73b6733e4bb1 tools/python/xen/xm/xenapi_create.py --- a/tools/python/xen/xm/xenapi_create.py Wed Jul 11 10:48:15 2007 +0100 +++ b/tools/python/xen/xm/xenapi_create.py Wed Jul 11 10:49:43 2007 +0100 @@ -25,6 +25,7 @@ from xen.xend.XendAPIConstants import XE from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \ XEN_API_ON_CRASH_BEHAVIOUR from xen.xm.opts import OptionError +from xen.util import xsconstants import sys import os @@ -308,6 +309,12 @@ class xenapi_create: "" } + if vm.attributes.has_key("security_label"): + vm_record.update({ + "security_label": + vm.attributes["security_label"].value + }) + if len(vm.getElementsByTagName("pv")) > 0: vm_record.update({ "PV_bootloader": @@ -348,6 +355,12 @@ class xenapi_create: self.create_vifs(vm_ref, vifs, networks) + # Now create vtpms + + vtpms = vm.getElementsByTagName("vtpm") + + self.create_vtpms(vm_ref, vtpms) + # Now create consoles consoles = vm.getElementsByTagName("console") @@ -441,6 +454,21 @@ class xenapi_create: self._network_refs = server.xenapi.network.get_all() return self._network_refs.pop(0) + def create_vtpms(self, vm_ref, vtpms): + if len(vtpms) > 1: + vtpms = [ vtpms[0] ] + log(DEBUG, "create_vtpms") + return map(lambda vtpm: self.create_vtpm(vm_ref, vtpm), vtpms) + + def create_vtpm(self, vm_ref, vtpm): + vtpm_record = { + "VM": + vm_ref, + "backend": + vtpm.attributes["backend"].value + } + return server.xenapi.VTPM.create(vtpm_record) + def create_consoles(self, vm_ref, consoles): log(DEBUG, "create_consoles") return map(lambda console: self.create_console(vm_ref, console), @@ -482,6 +510,10 @@ class sxp2xml: vifs_sxp = map(lambda x: x[1], [device for device in devices if device[1][0] == "vif"]) + + vtpms_sxp = map(lambda x: x[1], [device for device in devices + if device[1][0] == "vtpm"]) + # Create XML Document impl = getDOMImplementation() @@ -530,6 +562,14 @@ class sxp2xml: = str(get_child_by_name(config, "vcpus", 1)) vm.attributes["vcpus_at_startup"] \ = str(get_child_by_name(config, "vcpus", 1)) + + sec_data = get_child_by_name(config, "security") + if sec_data: + try : + vm.attributes['security_label'] = \ + "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, sec_data[0][1][1],sec_data[0][2][1]) + except Exception, e: + raise "Invalid security data format: %s" % str(sec_data) # Make the name tag @@ -601,6 +641,12 @@ class sxp2xml: map(vm.appendChild, vifs) + # And now the vTPMs + + vtpms = map(lambda vtpm: self.extract_vtpm(vtpm, document), vtpms_sxp) + + map(vm.appendChild, vtpms) + # Last but not least the consoles... consoles = self.extract_consoles(image, document) @@ -707,6 +753,15 @@ class sxp2xml: = get_child_by_name(vif_sxp, "bridge") return vif + + def extract_vtpm(self, vtpm_sxp, document): + + vtpm = document.createElement("vtpm") + + vtpm.attributes["backend"] \ + = get_child_by_name(vtpm_sxp, "backend", "0") + + return vtpm _eths = -1 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |