[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>
This commit is contained in:
kfraser@localhost.localdomain committed 2007-08-06 10:11:25 +01:00
1 parent b163ba1607
commit 883ff61657
6 files changed
+142 -33

No files matched your search

+46 -18
View File
@@ -142,6 +142,21 @@ class ACMPolicy(XSPolicy):
return xsconstants.XSERR_SUCCESS
def is_default_policy(self):
"""
Determine whether this is the default policy
"""
default = ['SystemManagement']
if self.policy_get_virtualmachinelabel_names() == default and \
self.policy_get_bootstrap_vmlabel() == default[0] and \
self.policy_get_stetypes_types() == default and \
self.policy_get_stes_of_vmlabel(default[0]) == default and \
self.policy_get_resourcelabel_names() == [] and \
self.policy_get_chwall_types() == default and \
self.get_name() == "DEFAULT":
return True
return False
def update(self, xml_new):
"""
Update the policy with the new XML. The hypervisor decides
@@ -156,27 +171,18 @@ class ACMPolicy(XSPolicy):
return -xsconstants.XSERR_XML_PROCESSING, errors
vmlabel_map = acmpol_new.policy_get_vmlabel_translation_map()
# An update requires version information in the current
# and new policy. The version number of the current policy
# must be the same as what is in the FromPolicy/Version node
# in the new one and the current policy's name must be the
# same as in FromPolicy/PolicyName
now_vers = acmpol_old.policy_dom_get_hdr_item("Version")
now_name = acmpol_old.policy_dom_get_hdr_item("PolicyName")
req_oldvers = acmpol_new.policy_dom_get_frompol_item("Version")
req_oldname = acmpol_new.policy_dom_get_frompol_item("PolicyName")
if now_vers == "" or \
now_vers != req_oldvers or \
now_name != req_oldname:
log.info("Policy rejected: %s != %s or %s != %s" % \
(now_vers,req_oldvers,now_name,req_oldname))
return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE, errors
if not self.isVersionUpdate(acmpol_new):
log.info("Policy rejected since new version is not an update.")
return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE, errors
# The default policy when it is set skips this step.
if not acmpol_new.is_default_policy() and \
not acmpol_old.is_default_policy():
irc = self.__do_update_version_check(acmpol_new)
if irc != xsconstants.XSERR_SUCCESS:
return irc, errors
if self.isloaded():
newvmnames = \
@@ -258,6 +264,29 @@ class ACMPolicy(XSPolicy):
self.compile()
return rc, errors
def __do_update_version_check(self, acmpol_new):
acmpol_old = self
now_vers = acmpol_old.policy_dom_get_hdr_item("Version")
now_name = acmpol_old.policy_dom_get_hdr_item("PolicyName")
req_oldvers = acmpol_new.policy_dom_get_frompol_item("Version")
req_oldname = acmpol_new.policy_dom_get_frompol_item("PolicyName")
if now_vers == "" or \
now_vers != req_oldvers or \
now_name != req_oldname:
log.info("Policy rejected: %s != %s or %s != %s" % \
(now_vers,req_oldvers,now_name,req_oldname))
return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE
if not self.isVersionUpdate(acmpol_new):
log.info("Policy rejected since new version is not an update.")
return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE
return xsconstants.XSERR_SUCCESS
def compareVersions(self, v1, v2):
"""
Compare two policy versions given their tuples of major and
@@ -848,8 +877,7 @@ class ACMPolicy(XSPolicy):
if self.isloaded():
return -xsconstants.XSERR_POLICY_LOADED
files = [ self.get_filename(".map",""),
self.get_filename(".bin",""),
self.path_from_policy_name(self.get_name())]
self.get_filename(".bin","") ]
for f in files:
try:
os.unlink(f)
+28 -4
View File
@@ -146,7 +146,7 @@ def calc_dom_ssidref_from_info(info):
raise VmError("VM label '%s' in wrong format." % seclab)
typ, policyname, vmlabel = seclab.split(":")
if typ != xsconstants.ACM_POLICY_ID:
raise VmError("Policy type '%s' not supported." % typ)
raise VmError("Policy type '%s' must be changed." % typ)
refresh_security_policy()
if active_policy != policyname:
raise VmError("Active policy '%s' different than "
@@ -502,7 +502,7 @@ def hv_chg_policy(bin_pol, del_array, chg_array):
rc, errors = acm.chgpolicy(bin_pol, del_array, chg_array)
except Exception, e:
pass
if (len(errors) > 0):
if len(errors) > 0:
rc = -xsconstants.XSERR_HV_OP_FAILED
return rc, errors
@@ -785,6 +785,24 @@ def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label):
return rtnval
def validate_label(label, policyref):
"""
Make sure that this label is part of the currently enforced policy
and that it reference the current policy.
"""
rc = xsconstants.XSERR_SUCCESS
from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
curpol = XSPolicyAdminInstance().get_loaded_policy()
if not curpol or curpol.get_name() != policyref:
rc = -xsconstants.XSERR_BAD_LABEL
else:
try:
label2ssidref(label, curpol.get_name() , 'res')
except:
rc = -xsconstants.XSERR_BAD_LABEL
return rc
def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
"""Assign a resource label to a resource
@param resource: The name of a resource, i.e., "phy:/dev/hda", or
@@ -809,10 +827,16 @@ def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
return -xsconstants.XSERR_BAD_LABEL_FORMAT
otyp, opolicyref, olabel = tmp
# Only ACM is supported
if otyp != xsconstants.ACM_POLICY_ID:
if otyp != xsconstants.ACM_POLICY_ID and \
otyp != xsconstants.INVALID_POLICY_PREFIX + \
xsconstants.ACM_POLICY_ID:
return -xsconstants.XSERR_WRONG_POLICY_TYPE
rc = validate_label(label, policyref)
if rc != xsconstants.XSERR_SUCCESS:
return rc
return set_resource_label(resource, typ, policyref, label, olabel)
def is_resource_in_use(resource):
""" Investigate all running domains whether they use this device """
from xen.xend import XendDomain
@@ -1228,7 +1252,7 @@ def change_acm_policy(bin_pol, del_array, chg_array,
sec_lab, new_seclab = labels
if sec_lab != new_seclab:
log.info("Updating domain %s to new label '%s'." % \
(new_seclab, sec_lab))
(sec_lab, new_seclab))
# This better be working!
dominfo.set_security_label(new_seclab,
sec_lab,
+26 -1
View File
@@ -23,7 +23,7 @@ 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 getpolicy, setpolicy
from xen.xm import main as xm_main
from xen.xm.main import server
@@ -38,6 +38,9 @@ def help():
--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.
--remove Attempt to remove the current policy by installing the
default policy; this works only if no domains are
running.
"""
def activate_policy(flags):
@@ -56,6 +59,25 @@ def activate_policy(flags):
def remove_bootpolicy():
server.xenapi.XSPolicy.rm_xsbootpolicy()
def install_default_policy():
if xm_main.serverType != xm_main.SERVER_XEN_API:
raise OptionError('xm needs to be configured to use the xen-api.')
xs_type = int(server.xenapi.XSPolicy.get_xstype())
if xs_type & xsconstants.XS_POLICY_ACM == 0:
raise OptionError('ACM policy type not supported on system.')
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']
flags = int(policystate['flags'])
if flags & xsconstants.XS_INST_LOAD == 0:
print "Default policy is already loaded."
return
setpolicy.setpolicy(xsconstants.ACM_POLICY_ID, 'default', flags, True,
False)
def main(argv):
if xm_main.serverType != xm_main.SERVER_XEN_API:
raise OptionError('xm needs to be configured to use the xen-api.')
@@ -69,6 +91,9 @@ def main(argv):
flags |= xsconstants.XS_INST_LOAD
elif '--noboot' == argv[c]:
remove_bootpolicy()
elif '--remove' == argv[c]:
install_default_policy()
return
else:
raise OptionError("Unknown command line option '%s'" % argv[c])
c += 1
-1
View File
@@ -58,7 +58,6 @@ def main (argv):
try:
filename = security.res_label_filename
access_control = dictio.dict_read("resources", filename)
print access_control
except:
raise OptionError("Resource file not found")
+38 -2
View File
@@ -24,6 +24,7 @@ import struct
import sys
import string
from xen.util import xsconstants
from xen.util.acmpolicy import ACMPolicy
from xen.xm.opts import OptionError
from xen.util.security import policy_dir_prefix
from xen.xm import main as xm_main
@@ -40,9 +41,38 @@ def help():
The following options are defined
--load Load the policy immediately
--boot Have the system load the policy during boot
--update Automatically adapt the policy so that it will be
treated as an update to the current policy
"""
def setpolicy(policytype, policy_name, flags, overwrite):
def create_update_xml(xml):
"""
Adapt the new policy's xml header to be a simple type of an
update to the currently enforce policy on the remote system.
Increases the minor number by '1'.
"""
policystate = server.xenapi.XSPolicy.get_xspolicy()
if int(policystate['type']) == 0:
return xml
curpol = ACMPolicy(xml = policystate['repr'])
curpol_version = curpol.get_version()
tmp = curpol_version.split('.')
if len(tmp) == 2:
maj = int(tmp[0])
min = int(tmp[1])
else:
maj = int(tmp)
min = 0
min += 1
newpol_version = ""+str(maj)+"."+str(min)
newpol = ACMPolicy(xml = xml)
newpol.set_frompolicy_name(curpol.get_name())
newpol.set_frompolicy_version(curpol.get_version())
newpol.set_policy_version(newpol_version)
return newpol.toxml()
def setpolicy(policytype, policy_name, flags, overwrite, is_update=False):
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:
@@ -61,6 +91,9 @@ def setpolicy(policytype, policy_name, flags, overwrite):
except:
raise OptionError("Not a valid policy file")
if is_update:
xml = create_update_xml(xml)
try:
policystate = server.xenapi.XSPolicy.set_xspolicy(xs_type,
xml,
@@ -96,18 +129,21 @@ def main(argv):
policytype = argv[1]
policy_name = argv[2]
is_update = False
flags = 0
if '--load' in argv:
flags |= xsconstants.XS_INST_LOAD
if '--boot' in argv:
flags |= xsconstants.XS_INST_BOOT
if '--update' in argv:
is_update = True
overwrite = True
if '--nooverwrite' in argv:
overwrite = False
setpolicy(policytype, policy_name, flags, overwrite)
setpolicy(policytype, policy_name, flags, overwrite, is_update)
if __name__ == '__main__':
try:
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.