ia64/xen-unstable

changeset 15712:92e43b36d211

[ACM] Support for removing / replacing a policy

Add support for removing/replacing a policy from the running
system. This operation is only successful if currently running VMs
would also be allowed to run under the new policy. Removing the
current policy means that the default policy is installed, which then
only has support for a single VM label and STE type (SystemManagement)
and is the same policy that the system starts up with when no policy
is chosen.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author kfraser@localhost.localdomain
date Mon Aug 06 10:11:25 2007 +0100 (2007-08-06)
parents 6384e168f122
children f8d5c509f156
files tools/python/xen/util/acmpolicy.py tools/python/xen/util/security.py tools/python/xen/xm/activatepolicy.py tools/python/xen/xm/resources.py tools/python/xen/xm/setpolicy.py tools/security/Makefile
line diff
     1.1 --- a/tools/python/xen/util/acmpolicy.py	Mon Aug 06 10:10:34 2007 +0100
     1.2 +++ b/tools/python/xen/util/acmpolicy.py	Mon Aug 06 10:11:25 2007 +0100
     1.3 @@ -142,6 +142,21 @@ class ACMPolicy(XSPolicy):
     1.4          return xsconstants.XSERR_SUCCESS
     1.5  
     1.6  
     1.7 +    def is_default_policy(self):
     1.8 +        """
     1.9 +           Determine whether this is the default policy
    1.10 +        """
    1.11 +        default = ['SystemManagement']
    1.12 +        if self.policy_get_virtualmachinelabel_names() == default and \
    1.13 +           self.policy_get_bootstrap_vmlabel() == default[0] and \
    1.14 +           self.policy_get_stetypes_types() == default and \
    1.15 +           self.policy_get_stes_of_vmlabel(default[0]) == default and \
    1.16 +           self.policy_get_resourcelabel_names() == [] and \
    1.17 +           self.policy_get_chwall_types() == default and \
    1.18 +           self.get_name() == "DEFAULT":
    1.19 +            return True
    1.20 +        return False
    1.21 +
    1.22      def update(self, xml_new):
    1.23          """
    1.24              Update the policy with the new XML. The hypervisor decides
    1.25 @@ -156,27 +171,18 @@ class ACMPolicy(XSPolicy):
    1.26              return -xsconstants.XSERR_XML_PROCESSING, errors
    1.27  
    1.28          vmlabel_map = acmpol_new.policy_get_vmlabel_translation_map()
    1.29 +
    1.30          # An update requires version information in the current
    1.31          # and new policy. The version number of the current policy
    1.32          # must be the same as what is in the FromPolicy/Version node
    1.33          # in the new one and the current policy's name must be the
    1.34          # same as in FromPolicy/PolicyName
    1.35 -
    1.36 -        now_vers    = acmpol_old.policy_dom_get_hdr_item("Version")
    1.37 -        now_name    = acmpol_old.policy_dom_get_hdr_item("PolicyName")
    1.38 -        req_oldvers = acmpol_new.policy_dom_get_frompol_item("Version")
    1.39 -        req_oldname = acmpol_new.policy_dom_get_frompol_item("PolicyName")
    1.40 -
    1.41 -        if now_vers == "" or \
    1.42 -           now_vers != req_oldvers or \
    1.43 -           now_name != req_oldname:
    1.44 -            log.info("Policy rejected: %s != %s or %s != %s" % \
    1.45 -                     (now_vers,req_oldvers,now_name,req_oldname))
    1.46 -            return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE, errors
    1.47 -
    1.48 -        if not self.isVersionUpdate(acmpol_new):
    1.49 -            log.info("Policy rejected since new version is not an update.")
    1.50 -            return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE, errors
    1.51 +        # The default policy when it is set skips this step.
    1.52 +        if not acmpol_new.is_default_policy() and \
    1.53 +           not acmpol_old.is_default_policy():
    1.54 +            irc = self.__do_update_version_check(acmpol_new)
    1.55 +            if irc != xsconstants.XSERR_SUCCESS:
    1.56 +                return irc, errors
    1.57  
    1.58          if self.isloaded():
    1.59              newvmnames = \
    1.60 @@ -258,6 +264,29 @@ class ACMPolicy(XSPolicy):
    1.61              self.compile()
    1.62          return rc, errors
    1.63  
    1.64 +
    1.65 +    def __do_update_version_check(self, acmpol_new):
    1.66 +        acmpol_old = self
    1.67 +
    1.68 +        now_vers    = acmpol_old.policy_dom_get_hdr_item("Version")
    1.69 +        now_name    = acmpol_old.policy_dom_get_hdr_item("PolicyName")
    1.70 +        req_oldvers = acmpol_new.policy_dom_get_frompol_item("Version")
    1.71 +        req_oldname = acmpol_new.policy_dom_get_frompol_item("PolicyName")
    1.72 +
    1.73 +        if now_vers == "" or \
    1.74 +           now_vers != req_oldvers or \
    1.75 +           now_name != req_oldname:
    1.76 +            log.info("Policy rejected: %s != %s or %s != %s" % \
    1.77 +                     (now_vers,req_oldvers,now_name,req_oldname))
    1.78 +            return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE
    1.79 +
    1.80 +        if not self.isVersionUpdate(acmpol_new):
    1.81 +            log.info("Policy rejected since new version is not an update.")
    1.82 +            return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE
    1.83 +
    1.84 +        return xsconstants.XSERR_SUCCESS
    1.85 +
    1.86 +
    1.87      def compareVersions(self, v1, v2):
    1.88          """
    1.89              Compare two policy versions given their tuples of major and
    1.90 @@ -848,8 +877,7 @@ class ACMPolicy(XSPolicy):
    1.91          if self.isloaded():
    1.92              return -xsconstants.XSERR_POLICY_LOADED
    1.93          files = [ self.get_filename(".map",""),
    1.94 -                  self.get_filename(".bin",""),
    1.95 -                  self.path_from_policy_name(self.get_name())]
    1.96 +                  self.get_filename(".bin","") ]
    1.97          for f in files:
    1.98              try:
    1.99                  os.unlink(f)
     2.1 --- a/tools/python/xen/util/security.py	Mon Aug 06 10:10:34 2007 +0100
     2.2 +++ b/tools/python/xen/util/security.py	Mon Aug 06 10:11:25 2007 +0100
     2.3 @@ -146,7 +146,7 @@ def calc_dom_ssidref_from_info(info):
     2.4                  raise VmError("VM label '%s' in wrong format." % seclab)
     2.5              typ, policyname, vmlabel = seclab.split(":")
     2.6              if typ != xsconstants.ACM_POLICY_ID:
     2.7 -                raise VmError("Policy type '%s' not supported." % typ)
     2.8 +                raise VmError("Policy type '%s' must be changed." % typ)
     2.9              refresh_security_policy()
    2.10              if active_policy != policyname:
    2.11                  raise VmError("Active policy '%s' different than "
    2.12 @@ -502,7 +502,7 @@ def hv_chg_policy(bin_pol, del_array, ch
    2.13          rc, errors = acm.chgpolicy(bin_pol, del_array, chg_array)
    2.14      except Exception, e:
    2.15          pass
    2.16 -    if (len(errors) > 0):
    2.17 +    if len(errors) > 0:
    2.18          rc = -xsconstants.XSERR_HV_OP_FAILED
    2.19      return rc, errors
    2.20  
    2.21 @@ -785,6 +785,24 @@ def res_security_check_xapi(rlabel, rssi
    2.22      return rtnval
    2.23  
    2.24  
    2.25 +def validate_label(label, policyref):
    2.26 +    """
    2.27 +       Make sure that this label is part of the currently enforced policy
    2.28 +       and that it reference the current policy.
    2.29 +    """
    2.30 +    rc = xsconstants.XSERR_SUCCESS
    2.31 +    from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
    2.32 +    curpol = XSPolicyAdminInstance().get_loaded_policy()
    2.33 +    if not curpol or curpol.get_name() != policyref:
    2.34 +        rc = -xsconstants.XSERR_BAD_LABEL
    2.35 +    else:
    2.36 +        try:
    2.37 +            label2ssidref(label, curpol.get_name() , 'res')
    2.38 +        except:
    2.39 +            rc = -xsconstants.XSERR_BAD_LABEL
    2.40 +    return rc
    2.41 +
    2.42 +
    2.43  def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
    2.44      """Assign a resource label to a resource
    2.45      @param resource: The name of a resource, i.e., "phy:/dev/hda", or
    2.46 @@ -809,10 +827,16 @@ def set_resource_label_xapi(resource, re
    2.47              return -xsconstants.XSERR_BAD_LABEL_FORMAT
    2.48          otyp, opolicyref, olabel = tmp
    2.49          # Only ACM is supported
    2.50 -        if otyp != xsconstants.ACM_POLICY_ID:
    2.51 +        if otyp != xsconstants.ACM_POLICY_ID  and \
    2.52 +           otyp != xsconstants.INVALID_POLICY_PREFIX + \
    2.53 +                   xsconstants.ACM_POLICY_ID:
    2.54              return -xsconstants.XSERR_WRONG_POLICY_TYPE
    2.55 +    rc = validate_label(label, policyref)
    2.56 +    if rc != xsconstants.XSERR_SUCCESS:
    2.57 +        return rc
    2.58      return set_resource_label(resource, typ, policyref, label, olabel)
    2.59  
    2.60 +
    2.61  def is_resource_in_use(resource):
    2.62      """ Investigate all running domains whether they use this device """
    2.63      from xen.xend import XendDomain
    2.64 @@ -1228,7 +1252,7 @@ def change_acm_policy(bin_pol, del_array
    2.65                  sec_lab, new_seclab = labels
    2.66                  if sec_lab != new_seclab:
    2.67                      log.info("Updating domain %s to new label '%s'." % \
    2.68 -                             (new_seclab, sec_lab))
    2.69 +                             (sec_lab, new_seclab))
    2.70                      # This better be working!
    2.71                      dominfo.set_security_label(new_seclab,
    2.72                                                 sec_lab,
     3.1 --- a/tools/python/xen/xm/activatepolicy.py	Mon Aug 06 10:10:34 2007 +0100
     3.2 +++ b/tools/python/xen/xm/activatepolicy.py	Mon Aug 06 10:11:25 2007 +0100
     3.3 @@ -23,7 +23,7 @@ import sys
     3.4  from xen.util import xsconstants
     3.5  from xml.dom import minidom
     3.6  from xen.xm.opts import OptionError
     3.7 -from xen.xm import getpolicy
     3.8 +from xen.xm import getpolicy, setpolicy
     3.9  from xen.xm import main as xm_main
    3.10  from xen.xm.main import server
    3.11  
    3.12 @@ -38,6 +38,9 @@ def help():
    3.13        --boot     Have the system boot with the policy. Changes the default
    3.14                   title in grub.conf.
    3.15        --noboot   Remove the policy from the default entry in grub.conf.
    3.16 +      --remove   Attempt to remove the current policy by installing the
    3.17 +                 default policy; this works only if no domains are
    3.18 +                 running.
    3.19      """
    3.20  
    3.21  def activate_policy(flags):
    3.22 @@ -56,6 +59,25 @@ def activate_policy(flags):
    3.23  def remove_bootpolicy():
    3.24      server.xenapi.XSPolicy.rm_xsbootpolicy()
    3.25  
    3.26 +def install_default_policy():
    3.27 +    if xm_main.serverType != xm_main.SERVER_XEN_API:
    3.28 +        raise OptionError('xm needs to be configured to use the xen-api.')
    3.29 +    xs_type = int(server.xenapi.XSPolicy.get_xstype())
    3.30 +    if xs_type & xsconstants.XS_POLICY_ACM == 0:
    3.31 +        raise OptionError('ACM policy type not supported on system.')
    3.32 +    policystate = server.xenapi.XSPolicy.get_xspolicy()
    3.33 +    if int(policystate['type']) == 0:
    3.34 +        print 'No policy is installed.'
    3.35 +        return
    3.36 +    if int(policystate['type']) != xsconstants.XS_POLICY_ACM:
    3.37 +        print "Unknown policy type '%s'." % policystate['type']
    3.38 +    flags = int(policystate['flags'])
    3.39 +    if flags & xsconstants.XS_INST_LOAD == 0:
    3.40 +        print "Default policy is already loaded."
    3.41 +        return
    3.42 +    setpolicy.setpolicy(xsconstants.ACM_POLICY_ID, 'default', flags, True,
    3.43 +                        False)
    3.44 +
    3.45  def main(argv):
    3.46      if xm_main.serverType != xm_main.SERVER_XEN_API:
    3.47          raise OptionError('xm needs to be configured to use the xen-api.')
    3.48 @@ -69,6 +91,9 @@ def main(argv):
    3.49              flags |= xsconstants.XS_INST_LOAD
    3.50          elif '--noboot' == argv[c]:
    3.51              remove_bootpolicy()
    3.52 +        elif '--remove' == argv[c]:
    3.53 +            install_default_policy()
    3.54 +            return
    3.55          else:
    3.56              raise OptionError("Unknown command line option '%s'" % argv[c])
    3.57          c += 1
     4.1 --- a/tools/python/xen/xm/resources.py	Mon Aug 06 10:10:34 2007 +0100
     4.2 +++ b/tools/python/xen/xm/resources.py	Mon Aug 06 10:11:25 2007 +0100
     4.3 @@ -58,7 +58,6 @@ def main (argv):
     4.4          try:
     4.5              filename = security.res_label_filename
     4.6              access_control = dictio.dict_read("resources", filename)
     4.7 -            print access_control
     4.8          except:
     4.9              raise OptionError("Resource file not found")
    4.10  
     5.1 --- a/tools/python/xen/xm/setpolicy.py	Mon Aug 06 10:10:34 2007 +0100
     5.2 +++ b/tools/python/xen/xm/setpolicy.py	Mon Aug 06 10:11:25 2007 +0100
     5.3 @@ -24,6 +24,7 @@ import struct
     5.4  import sys
     5.5  import string
     5.6  from xen.util import xsconstants
     5.7 +from xen.util.acmpolicy import ACMPolicy
     5.8  from xen.xm.opts import OptionError
     5.9  from xen.util.security import policy_dir_prefix
    5.10  from xen.xm import main as xm_main
    5.11 @@ -40,9 +41,38 @@ def help():
    5.12      The following options are defined
    5.13        --load     Load the policy immediately
    5.14        --boot     Have the system load the policy during boot
    5.15 +      --update   Automatically adapt the policy so that it will be
    5.16 +                 treated as an update to the current policy
    5.17      """
    5.18  
    5.19 -def setpolicy(policytype, policy_name, flags, overwrite):
    5.20 +def create_update_xml(xml):
    5.21 +    """
    5.22 +        Adapt the new policy's xml header to be a simple type of an
    5.23 +        update to the currently enforce policy on the remote system.
    5.24 +        Increases the minor number by '1'.
    5.25 +    """
    5.26 +    policystate = server.xenapi.XSPolicy.get_xspolicy()
    5.27 +    if int(policystate['type']) == 0:
    5.28 +        return xml
    5.29 +    curpol = ACMPolicy(xml = policystate['repr'])
    5.30 +    curpol_version = curpol.get_version()
    5.31 +    tmp = curpol_version.split('.')
    5.32 +    if len(tmp) == 2:
    5.33 +        maj = int(tmp[0])
    5.34 +        min = int(tmp[1])
    5.35 +    else:
    5.36 +        maj = int(tmp)
    5.37 +        min = 0
    5.38 +    min += 1
    5.39 +    newpol_version = ""+str(maj)+"."+str(min)
    5.40 +
    5.41 +    newpol = ACMPolicy(xml = xml)
    5.42 +    newpol.set_frompolicy_name(curpol.get_name())
    5.43 +    newpol.set_frompolicy_version(curpol.get_version())
    5.44 +    newpol.set_policy_version(newpol_version)
    5.45 +    return newpol.toxml()
    5.46 +
    5.47 +def setpolicy(policytype, policy_name, flags, overwrite, is_update=False):
    5.48      if xm_main.serverType != xm_main.SERVER_XEN_API:
    5.49          raise OptionError('xm needs to be configured to use the xen-api.')
    5.50      if policytype != xsconstants.ACM_POLICY_ID:
    5.51 @@ -61,6 +91,9 @@ def setpolicy(policytype, policy_name, f
    5.52          except:
    5.53              raise OptionError("Not a valid policy file")
    5.54  
    5.55 +        if is_update:
    5.56 +            xml = create_update_xml(xml)
    5.57 +
    5.58          try:
    5.59              policystate = server.xenapi.XSPolicy.set_xspolicy(xs_type,
    5.60                                                                xml,
    5.61 @@ -96,18 +129,21 @@ def main(argv):
    5.62  
    5.63      policytype  = argv[1]
    5.64      policy_name = argv[2]
    5.65 +    is_update = False
    5.66  
    5.67      flags = 0
    5.68      if '--load' in argv:
    5.69          flags |= xsconstants.XS_INST_LOAD
    5.70      if '--boot' in argv:
    5.71          flags |= xsconstants.XS_INST_BOOT
    5.72 +    if '--update' in argv:
    5.73 +        is_update = True
    5.74  
    5.75      overwrite = True
    5.76      if '--nooverwrite' in argv:
    5.77          overwrite = False
    5.78  
    5.79 -    setpolicy(policytype, policy_name, flags, overwrite)
    5.80 +    setpolicy(policytype, policy_name, flags, overwrite, is_update)
    5.81  
    5.82  if __name__ == '__main__':
    5.83      try:
     6.1 --- a/tools/security/Makefile	Mon Aug 06 10:10:34 2007 +0100
     6.2 +++ b/tools/security/Makefile	Mon Aug 06 10:11:25 2007 +0100
     6.3 @@ -13,13 +13,6 @@ CFLAGS     += $(shell xml2-config --cfla
     6.4  CFLAGS     += $(shell if [[ $(XML2VERSION) < 2.6.20 ]]; then echo ""; else echo "-DVALIDATE_SCHEMA"; fi )
     6.5  LDFLAGS    += $(shell xml2-config --libs ) # if this does not work, try -L/usr/lib -lxml2 -lz -lpthread -lm
     6.6  
     6.7 -ifeq ($(ACM_DEFAULT_SECURITY_POLICY),ACM_NULL_POLICY)
     6.8 -POLICY=null
     6.9 -endif
    6.10 -ifeq ($(ACM_DEFAULT_SECURITY_POLICY),ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)
    6.11 -POLICY=chwall_ste
    6.12 -endif
    6.13 -
    6.14  SRCS_TOOL     = secpol_tool.c
    6.15  OBJS_TOOL    := $(patsubst %.c,%.o,$(filter %.c,$(SRCS_TOOL)))
    6.16  SRCS_XML2BIN  = secpol_xml2bin.c secpol_xml2bin.h
    6.17 @@ -41,6 +34,7 @@ ACM_SECGEN_CGIDIR = $(ACM_SECGEN_HTMLDIR
    6.18  
    6.19  ACM_SCHEMA        = security_policy.xsd
    6.20  ACM_EXAMPLES      = client_v1 test
    6.21 +ACM_DEF_POLICIES  = default default-ul
    6.22  ACM_POLICY_SUFFIX = security_policy.xml
    6.23  
    6.24  ifeq ($(ACM_SECURITY),y)
    6.25 @@ -62,6 +56,9 @@ install: all $(ACM_CONFIG_FILE)
    6.26  	for i in $(ACM_EXAMPLES); do \
    6.27  		$(INSTALL_DATA) policies/example/$$i-$(ACM_POLICY_SUFFIX) $(DESTDIR)$(ACM_POLICY_DIR)/example/; \
    6.28  	done
    6.29 +	for i in $(ACM_DEF_POLICIES); do \
    6.30 +		$(INSTALL_DATA) policies/$$i-$(ACM_POLICY_SUFFIX) $(DESTDIR)$(ACM_POLICY_DIR); \
    6.31 +	done
    6.32  	$(INSTALL_DIR) $(DESTDIR)$(ACM_SCRIPT_DIR)
    6.33  	$(INSTALL_PROG) $(ACM_SCRIPTS) $(DESTDIR)$(ACM_SCRIPT_DIR)
    6.34  	$(INSTALL_DIR) $(DESTDIR)$(ACM_SECGEN_HTMLDIR)