ia64/xen-unstable

annotate tools/python/xen/xend/XendXSPolicyAdmin.py @ 16219:a2222599b97b

xend: Reworked initialization of XSPolicy administration class

Rather than picking up the current policy from the managed policies
file the hypervisor is asked for the name of the current policy.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author Keir Fraser <keir@xensource.com>
date Thu Oct 25 09:23:27 2007 +0100 (2007-10-25)
parents de68316bd2fa
children 5255eac35270
rev   line source
kfraser@15548 1 #============================================================================
kfraser@15548 2 # This library is free software; you can redistribute it and/or
kfraser@15548 3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
kfraser@15548 4 # License as published by the Free Software Foundation.
kfraser@15548 5 #
kfraser@15548 6 # This library is distributed in the hope that it will be useful,
kfraser@15548 7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
kfraser@15548 8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
kfraser@15548 9 # Lesser General Public License for more details.
kfraser@15548 10 #
kfraser@15548 11 # You should have received a copy of the GNU Lesser General Public
kfraser@15548 12 # License along with this library; if not, write to the Free Software
kfraser@15548 13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
kfraser@15548 14 #============================================================================
kfraser@15548 15 # Copyright (C) 2006,2007 International Business Machines Corp.
kfraser@15548 16 # Author: Stefan Berger <stefanb@us.ibm.com>
kfraser@15548 17 #============================================================================
kfraser@15548 18 import os
kfraser@15548 19 import shutil
kfraser@15548 20
kfraser@15548 21 from xml.dom import minidom, Node
kfraser@15548 22
kfraser@15548 23 from xen.xend.XendLogging import log
kfraser@15548 24 from xen.xend import uuid
kfraser@15817 25 from xen.util import xsconstants, dictio, bootloader
kfraser@15817 26 import xen.util.xsm.acm.acm as security
kfraser@15548 27 from xen.util.xspolicy import XSPolicy
kfraser@15548 28 from xen.util.acmpolicy import ACMPolicy
kfraser@15548 29 from xen.xend.XendError import SecurityError
kfraser@15548 30
kfraser@15548 31
kfraser@15548 32 class XSPolicyAdmin:
kfraser@15548 33 """ The class that handles the managed policies in the system.
kfraser@15548 34 Handles adding and removing managed policies. All managed
kfraser@15548 35 policies are handled using a reference (UUID) which is
kfraser@15548 36 assigned to the policy by this class.
kfraser@15548 37 """
kfraser@15548 38
kfraser@15548 39 def __init__(self, maxpolicies):
kfraser@15548 40 """ Create a management class for managing the system's
kfraser@15548 41 policies.
kfraser@15548 42
kfraser@15548 43 @param maxpolicies: The max. number of policies allowed
kfraser@15548 44 on the system (currently '1')
kfraser@15548 45 """
kfraser@15548 46 self.maxpolicies = maxpolicies
keir@16219 47 self.policies = {}
kfraser@15548 48 self.xsobjs = {}
keir@16219 49
keir@16219 50 act_pol_name = self.get_hv_loaded_policy_name()
keir@16219 51
keir@16219 52 ref = uuid.createString()
keir@16219 53 try:
keir@16219 54 self.xsobjs[ref] = ACMPolicy(name=act_pol_name, ref=ref)
keir@16219 55 self.policies[ref] = (act_pol_name, xsconstants.ACM_POLICY_ID)
keir@16219 56 except Exception, e:
keir@16219 57 log.error("Could not find XML representation of policy '%s': "
keir@16219 58 "%s" % (act_pol_name,e))
keir@16219 59
kfraser@15548 60 log.debug("XSPolicyAdmin: Known policies: %s" % self.policies)
kfraser@15548 61
kfraser@15548 62 def isXSEnabled(self):
kfraser@15548 63 """ Check whether 'security' is enabled on this system.
kfraser@15548 64 This currently only checks for ACM-enablement.
kfraser@15548 65 """
kfraser@15548 66 rc = 0
kfraser@15548 67 if security.on():
kfraser@15548 68 rc |= xsconstants.XS_POLICY_ACM
kfraser@15548 69 return rc
kfraser@15548 70
kfraser@15548 71 def add_acmpolicy_to_system(self, xmltext, flags, overwrite):
kfraser@15548 72 """ Add an ACM policy's xml representation to the system. The
kfraser@15548 73 policy will automatically be compiled
kfraser@15548 74 flags:
kfraser@15548 75 XS_INST_BOOT : make policy the one to boot the system with
kfraser@15548 76 by default; if there's a policy already installed,
kfraser@15548 77 refuse to install this policy unless its one with
kfraser@15548 78 the same name
kfraser@15548 79 XS_INST_LOAD : load the policy immediately; if this does not work
kfraser@15548 80 refuse to install this policy
kfraser@15548 81 overwrite:
kfraser@15548 82 If any policy is installed and this is False, refuse to install
kfraser@15548 83 this policy
kfraser@15548 84 If flags is True, then any existing policy will be removed from
kfraser@15548 85 the system and the new one will be installed
kfraser@15548 86 """
keir@16081 87 from xen.xend import XendDomain
keir@16081 88 domains = XendDomain.instance()
keir@16081 89 try:
keir@16081 90 domains.domains_lock.acquire()
keir@16081 91 return self.__add_acmpolicy_to_system(xmltext, flags, overwrite)
keir@16081 92 finally:
keir@16081 93 domains.domains_lock.release()
keir@16081 94
keir@16081 95 def __add_acmpolicy_to_system(self, xmltext, flags, overwrite):
kfraser@15548 96 errors = ""
kfraser@15548 97 loadedpol = self.get_loaded_policy()
kfraser@15548 98 if loadedpol:
kfraser@15548 99 # This is meant as an update to a currently loaded policy
kfraser@15548 100 if flags & xsconstants.XS_INST_LOAD == 0:
kfraser@15548 101 raise SecurityError(-xsconstants.XSERR_POLICY_LOADED)
kfraser@15548 102 rc, errors = loadedpol.update(xmltext)
kfraser@15548 103 if rc == 0:
kfraser@15548 104 self.rm_bootpolicy()
kfraser@15548 105 irc = self.activate_xspolicy(loadedpol, flags)
keir@16219 106 # policy is loaded; if setting the boot flag fails it's ok.
kfraser@15548 107 return (loadedpol, rc, errors)
kfraser@15548 108
kfraser@15548 109 try:
kfraser@15548 110 dom = minidom.parseString(xmltext.encode("utf-8"))
kfraser@15548 111 except:
kfraser@15548 112 raise SecurityError(-xsconstants.XSERR_BAD_XML)
kfraser@15548 113
kfraser@15548 114 ref = uuid.createString()
kfraser@15548 115
kfraser@15548 116 acmpol = ACMPolicy(dom=dom, ref=ref)
kfraser@15548 117
kfraser@15548 118 #First some basic tests that do not modify anything:
kfraser@15548 119
kfraser@15548 120 if flags & xsconstants.XS_INST_BOOT and not overwrite:
kfraser@15548 121 filename = acmpol.get_filename(".bin","",dotted=True)
kfraser@15548 122 if bootloader.get_default_policy != None and \
kfraser@15548 123 not bootloader.loads_default_policy(filename):
kfraser@15548 124 raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED)
kfraser@15548 125
kfraser@15548 126 if not overwrite and len(self.policies) >= self.maxpolicies:
kfraser@15548 127 raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED)
kfraser@15548 128
kfraser@15548 129 if overwrite:
kfraser@15548 130 #This should only give one key since only one policy is
kfraser@15548 131 #allowed.
kfraser@15548 132 keys = self.policies.keys()
kfraser@15548 133 for k in keys:
kfraser@15548 134 self.rm_bootpolicy()
kfraser@15548 135 rc = self.rm_policy_from_system(k, force=overwrite)
kfraser@15548 136 if rc != xsconstants.XSERR_SUCCESS:
kfraser@15548 137 raise SecurityError(rc)
kfraser@15548 138
kfraser@15548 139 rc = acmpol.compile()
kfraser@15548 140 if rc != 0:
kfraser@15548 141 raise SecurityError(rc)
kfraser@15548 142
kfraser@15548 143 if flags & xsconstants.XS_INST_LOAD:
kfraser@15548 144 rc = acmpol.loadintohv()
kfraser@15548 145 if rc != 0:
kfraser@15548 146 raise SecurityError(rc)
kfraser@15548 147
kfraser@15548 148 if flags & xsconstants.XS_INST_BOOT:
kfraser@15548 149 rc = self.make_boot_policy(acmpol)
kfraser@15548 150 if rc != 0:
kfraser@15548 151 # If it cannot be installed due to unsupported
kfraser@15548 152 # bootloader, let it be ok.
kfraser@15548 153 pass
kfraser@15548 154
kfraser@15548 155 if dom:
kfraser@15548 156 new_entry = { ref : tuple([acmpol.get_name(),
kfraser@15548 157 xsconstants.ACM_POLICY_ID]) }
kfraser@15548 158 self.policies.update(new_entry)
kfraser@15548 159 self.xsobjs[ref] = acmpol
kfraser@15548 160 return (acmpol, xsconstants.XSERR_SUCCESS, errors)
kfraser@15548 161
kfraser@15548 162 def make_boot_policy(self, acmpol):
kfraser@15548 163 spolfile = acmpol.get_filename(".bin")
kfraser@15548 164 dpolfile = "/boot/" + acmpol.get_filename(".bin","",dotted=True)
kfraser@15548 165 if not os.path.isfile(spolfile):
kfraser@15548 166 log.error("binary policy file does not exist.")
kfraser@15548 167 return -xsconstants.XSERR_FILE_ERROR
kfraser@15548 168 try:
kfraser@15548 169 shutil.copyfile(spolfile, dpolfile)
kfraser@15548 170 except:
kfraser@15548 171 return -xsconstants.XSERR_FILE_ERROR
kfraser@15548 172
kfraser@15548 173 try:
kfraser@15548 174 filename = acmpol.get_filename(".bin","",dotted=True)
kfraser@15548 175 if bootloader.set_default_boot_policy(filename) != True:
kfraser@15548 176 return xsconstants.XSERR_BOOTPOLICY_INSTALL_ERROR
kfraser@15548 177 except:
kfraser@15548 178 return xsconstants.XSERR_FILE_ERROR
kfraser@15548 179 return xsconstants.XSERR_SUCCESS
kfraser@15548 180
kfraser@15548 181 def activate_xspolicy(self, xspol, flags):
keir@16081 182 from xen.xend import XendDomain
keir@16081 183 domains = XendDomain.instance()
keir@16081 184 try:
keir@16081 185 domains.domains_lock.acquire()
keir@16081 186 return self.__activate_xspolicy(xspol, flags)
keir@16081 187 finally:
keir@16081 188 domains.domains_lock.release()
keir@16081 189
keir@16081 190 def __activate_xspolicy(self, xspol, flags):
kfraser@15548 191 rc = xsconstants.XSERR_SUCCESS
kfraser@15548 192 if flags & xsconstants.XS_INST_LOAD:
kfraser@15548 193 rc = xspol.loadintohv()
kfraser@15548 194 if rc == xsconstants.XSERR_SUCCESS and \
kfraser@15548 195 flags & xsconstants.XS_INST_BOOT:
kfraser@15548 196 rc = self.make_boot_policy(xspol)
kfraser@15548 197 if rc == xsconstants.XSERR_SUCCESS:
kfraser@15548 198 rc = flags
kfraser@15548 199 return rc
kfraser@15548 200
kfraser@15548 201 def rm_policy_from_system(self, ref, force=False):
kfraser@15548 202 if self.policies.has_key(ref):
kfraser@15548 203 acmpol = self.xsobjs[ref]
kfraser@15548 204 rc = acmpol.destroy()
kfraser@15548 205 if rc == xsconstants.XSERR_SUCCESS or force:
kfraser@15548 206 del self.policies[ref]
kfraser@15548 207 del self.xsobjs[ref]
kfraser@15548 208 rc = xsconstants.XSERR_SUCCESS
kfraser@15548 209 return rc
kfraser@15548 210
kfraser@15548 211 def rm_bootpolicy(self):
kfraser@15548 212 """ Remove any (ACM) boot policy from the grub configuration file
kfraser@15548 213 """
kfraser@15548 214 rc = 0
kfraser@15548 215 title = bootloader.get_default_title()
kfraser@15548 216 if title != None:
kfraser@15548 217 polnames = []
kfraser@15548 218 for (k, v) in self.xsobjs.items():
kfraser@15548 219 polnames.append(v.get_filename(".bin","",dotted=True))
kfraser@15548 220 bootloader.rm_policy_from_boottitle(title, polnames)
kfraser@15548 221 else:
kfraser@15548 222 rc = -xsconstants.XSERR_NO_DEFAULT_BOOT_TITLE
kfraser@15548 223 return rc
kfraser@15548 224
kfraser@15548 225 def get_policy_flags(self, acmpol):
kfraser@15548 226 """ Get the currently active flags of a policy, i.e., whether the
kfraser@15548 227 system is using this policy as its boot policy for the default
kfraser@15548 228 boot title.
kfraser@15548 229 """
kfraser@15548 230 flags = 0
kfraser@15548 231
kfraser@15548 232 filename = acmpol.get_filename(".bin","", dotted=True)
kfraser@15548 233 if bootloader.loads_default_policy(filename):
kfraser@15548 234 flags |= xsconstants.XS_INST_BOOT
kfraser@15548 235
kfraser@15548 236 if acmpol.isloaded():
kfraser@15548 237 flags |= xsconstants.XS_INST_LOAD
kfraser@15548 238 return flags
kfraser@15548 239
kfraser@15548 240 def get_policies(self):
kfraser@15548 241 """ Get all managed policies. """
kfraser@15548 242 return self.xsobjs.values()
kfraser@15548 243
kfraser@15548 244 def get_policies_refs(self):
kfraser@15548 245 """ Get all managed policies' references. """
kfraser@15548 246 return self.xsobjs.keys()
kfraser@15548 247
kfraser@15548 248 def has_ref(self, ref):
kfraser@15548 249 """ Check whether there is a policy with the given reference """
kfraser@15548 250 return self.xsobjs.has_key(ref)
kfraser@15548 251
kfraser@15548 252 def policy_from_ref(self, ref):
kfraser@15548 253 """ Get the policy's object given its reference """
kfraser@15548 254 if ref in self.xsobjs.keys():
kfraser@15548 255 return self.xsobjs[ref]
kfraser@15548 256 return None
kfraser@15548 257
kfraser@15548 258 def ref_from_polname(self, polname):
kfraser@15548 259 """ Get the reference of the policy given its name """
kfraser@15548 260 ref = None
kfraser@15548 261 for (k, v) in self.xsobjs.items():
kfraser@15548 262 if v.get_name() == polname:
kfraser@15548 263 ref = k
kfraser@15548 264 break
kfraser@15548 265 return ref
kfraser@15548 266
kfraser@15548 267 def lock_policy(self, ref):
kfraser@15548 268 """ get exclusive access to a policy """
kfraser@15548 269 self.xsobjs[ref].grab_lock()
kfraser@15548 270
kfraser@15548 271 def unlock_policy(self, ref):
kfraser@15548 272 """ release exclusive access to a policy """
kfraser@15548 273 self.xsobjs[ref].unlock()
kfraser@15548 274
kfraser@15548 275 def get_loaded_policy(self):
kfraser@15548 276 for pol in self.xsobjs.values():
kfraser@15548 277 if pol.isloaded():
kfraser@15548 278 return pol
kfraser@15548 279 return None
kfraser@15548 280
kfraser@15615 281 def get_hv_loaded_policy_name(self):
kfraser@15615 282 security.refresh_security_policy()
kfraser@15615 283 return security.active_policy
kfraser@15615 284
kfraser@15548 285 def get_policy_by_name(self, name):
kfraser@15548 286 for pol in self.xsobjs.values():
kfraser@15548 287 if pol.get_name() == name:
kfraser@15548 288 return pol
kfraser@15548 289 return None
kfraser@15548 290
kfraser@15548 291 def get_domain0_bootlabel(self):
kfraser@15548 292 """ Get the domain0 bootlabel from the default boot title """
kfraser@15548 293 title = ""
kfraser@15548 294 def_title = bootloader.get_default_title()
kfraser@15548 295 line = bootloader.get_kernel_val(def_title, "ssidref")
kfraser@15548 296 if line:
kfraser@15548 297 parms = line.split(":",1)
kfraser@15548 298 if len(parms) > 1:
kfraser@15548 299 title = parms[1]
kfraser@15548 300 return title
kfraser@15548 301
kfraser@15548 302 def set_domain0_bootlabel(self, xspol, label):
kfraser@15548 303 """ Set the domain-0 bootlabel under the given policy """
kfraser@15548 304 return xspol.set_vm_bootlabel(label)
kfraser@15548 305
kfraser@15548 306 def rm_domain0_bootlabel(self):
kfraser@15548 307 """ Remove the domain-0 bootlabel from the default boot title """
kfraser@15548 308 def_title = bootloader.get_default_title()
kfraser@15548 309 return bootloader.set_kernel_attval(def_title, "ssidref", None)
kfraser@15548 310
kfraser@15548 311 def ssidref_to_vmlabel(self, ssidref):
kfraser@15548 312 """ Given an ssidref, return the vmlabel under the current policy """
kfraser@15548 313 vmlabel = ""
kfraser@15548 314 pol = self.get_loaded_policy()
kfraser@15548 315 if pol:
kfraser@15548 316 vmlabel = pol.policy_get_domain_label_by_ssidref_formatted(ssidref)
kfraser@15548 317 return vmlabel
kfraser@15548 318
kfraser@15625 319 def get_stes_of_vmlabel(self, vmlabel_xapi):
kfraser@15625 320 """ Get the list of STEs given a VM label in XenAPI format """
kfraser@15625 321 stes = []
kfraser@15625 322 loadedpol = self.get_loaded_policy()
kfraser@15625 323 if loadedpol:
kfraser@15625 324 tmp = vmlabel_xapi.split(":")
kfraser@15625 325 if len(tmp) != 3:
kfraser@15625 326 return []
kfraser@15625 327 stes = loadedpol.policy_get_stes_of_vmlabel(tmp[2])
kfraser@15625 328 return stes
kfraser@15625 329
keir@16051 330 def get_enforced_binary(self, xstype):
keir@16051 331 res = None
keir@16051 332 if xstype == xsconstants.XS_POLICY_ACM:
keir@16051 333 res = ACMPolicy.get_enforced_binary()
keir@16051 334 return res
kfraser@15625 335
kfraser@15548 336 poladmin = None
kfraser@15548 337
kfraser@15548 338 def XSPolicyAdminInstance(maxpolicies=1):
kfraser@15548 339 global poladmin
kfraser@15548 340 if poladmin == None:
kfraser@15548 341 poladmin = XSPolicyAdmin(maxpolicies)
kfraser@15551 342 return poladmin