ia64/xen-unstable

annotate tools/python/xen/xend/XendXSPolicyAdmin.py @ 16051:2e5e948bf69d

Extend 'xm dumppolicy' to support Xen-API

I am extending 'xm dumppolicy' to be used via the Xen-API. For this
there are two new functions in the ACM policy class:
- get the currently enforced policy including statistical data from
the hypervisor
- get the ACM 'ssidref' of a Domain. Since this may be a ACM-specific
variable or type (int) I put it into the ACM class.

I extended the Xen-API documentation with the two new functions.

Signed-off-by: Stefan Berger <Stefanb@us.ibm.com>
author Keir Fraser <keir@xensource.com>
date Wed Oct 03 14:04:51 2007 +0100 (2007-10-03)
parents 993655d24b55
children de68316bd2fa
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 XS_MANAGED_POLICIES_FILE = "/etc/xen/acm-security/policies/managed_policies"
kfraser@15548 32
kfraser@15548 33 class XSPolicyAdmin:
kfraser@15548 34 """ The class that handles the managed policies in the system.
kfraser@15548 35 Handles adding and removing managed policies. All managed
kfraser@15548 36 policies are handled using a reference (UUID) which is
kfraser@15548 37 assigned to the policy by this class.
kfraser@15548 38 """
kfraser@15548 39
kfraser@15548 40 def __init__(self, maxpolicies):
kfraser@15548 41 """ Create a management class for managing the system's
kfraser@15548 42 policies.
kfraser@15548 43
kfraser@15548 44 @param maxpolicies: The max. number of policies allowed
kfraser@15548 45 on the system (currently '1')
kfraser@15548 46 """
kfraser@15548 47 self.maxpolicies = maxpolicies
kfraser@15548 48 try:
kfraser@15548 49 self.policies = dictio.dict_read("managed_policies",
kfraser@15548 50 XS_MANAGED_POLICIES_FILE)
kfraser@15548 51 except Exception, e:
kfraser@15548 52 self.policies = {}
kfraser@15548 53
kfraser@15548 54 self.xsobjs = {}
kfraser@15548 55 for ref, data in self.policies.items():
kfraser@15548 56 name = data[0]
kfraser@15548 57 typ = data[1]
kfraser@15548 58 try:
kfraser@15548 59 if typ == xsconstants.ACM_POLICY_ID:
kfraser@15615 60 try:
kfraser@15615 61 self.xsobjs[ref] = ACMPolicy(name=name, ref=ref)
kfraser@15615 62 except Exception, e:
kfraser@15615 63 del self.policies[ref]
kfraser@15548 64 else:
kfraser@15548 65 del self.policies[ref]
kfraser@15548 66 except Exception, e:
kfraser@15548 67 log.error("XSPolicyAdmin: Could not find policy '%s': %s" %
kfraser@15548 68 (name, str(e)))
kfraser@15548 69 del self.policies[ref]
kfraser@15548 70 log.debug("XSPolicyAdmin: Known policies: %s" % self.policies)
kfraser@15548 71
kfraser@15548 72 def isXSEnabled(self):
kfraser@15548 73 """ Check whether 'security' is enabled on this system.
kfraser@15548 74 This currently only checks for ACM-enablement.
kfraser@15548 75 """
kfraser@15548 76 rc = 0
kfraser@15548 77 if security.on():
kfraser@15548 78 rc |= xsconstants.XS_POLICY_ACM
kfraser@15548 79 return rc
kfraser@15548 80
kfraser@15548 81 def add_acmpolicy_to_system(self, xmltext, flags, overwrite):
kfraser@15548 82 """ Add an ACM policy's xml representation to the system. The
kfraser@15548 83 policy will automatically be compiled
kfraser@15548 84 flags:
kfraser@15548 85 XS_INST_BOOT : make policy the one to boot the system with
kfraser@15548 86 by default; if there's a policy already installed,
kfraser@15548 87 refuse to install this policy unless its one with
kfraser@15548 88 the same name
kfraser@15548 89 XS_INST_LOAD : load the policy immediately; if this does not work
kfraser@15548 90 refuse to install this policy
kfraser@15548 91 overwrite:
kfraser@15548 92 If any policy is installed and this is False, refuse to install
kfraser@15548 93 this policy
kfraser@15548 94 If flags is True, then any existing policy will be removed from
kfraser@15548 95 the system and the new one will be installed
kfraser@15548 96 """
kfraser@15548 97 errors = ""
kfraser@15548 98 loadedpol = self.get_loaded_policy()
kfraser@15548 99 if loadedpol:
kfraser@15548 100 # This is meant as an update to a currently loaded policy
kfraser@15548 101 if flags & xsconstants.XS_INST_LOAD == 0:
kfraser@15548 102 raise SecurityError(-xsconstants.XSERR_POLICY_LOADED)
kfraser@15548 103 rc, errors = loadedpol.update(xmltext)
kfraser@15548 104 if rc == 0:
kfraser@15548 105 self.rm_bootpolicy()
kfraser@15548 106 irc = self.activate_xspolicy(loadedpol, flags)
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 dictio.dict_write(self.policies,
kfraser@15548 161 "managed_policies",
kfraser@15548 162 XS_MANAGED_POLICIES_FILE)
kfraser@15548 163 return (acmpol, xsconstants.XSERR_SUCCESS, errors)
kfraser@15548 164
kfraser@15548 165 def make_boot_policy(self, acmpol):
kfraser@15548 166 spolfile = acmpol.get_filename(".bin")
kfraser@15548 167 dpolfile = "/boot/" + acmpol.get_filename(".bin","",dotted=True)
kfraser@15548 168 if not os.path.isfile(spolfile):
kfraser@15548 169 log.error("binary policy file does not exist.")
kfraser@15548 170 return -xsconstants.XSERR_FILE_ERROR
kfraser@15548 171 try:
kfraser@15548 172 shutil.copyfile(spolfile, dpolfile)
kfraser@15548 173 except:
kfraser@15548 174 return -xsconstants.XSERR_FILE_ERROR
kfraser@15548 175
kfraser@15548 176 try:
kfraser@15548 177 filename = acmpol.get_filename(".bin","",dotted=True)
kfraser@15548 178 if bootloader.set_default_boot_policy(filename) != True:
kfraser@15548 179 return xsconstants.XSERR_BOOTPOLICY_INSTALL_ERROR
kfraser@15548 180 except:
kfraser@15548 181 return xsconstants.XSERR_FILE_ERROR
kfraser@15548 182 return xsconstants.XSERR_SUCCESS
kfraser@15548 183
kfraser@15548 184 def activate_xspolicy(self, xspol, flags):
kfraser@15548 185 rc = xsconstants.XSERR_SUCCESS
kfraser@15548 186 if flags & xsconstants.XS_INST_LOAD:
kfraser@15548 187 rc = xspol.loadintohv()
kfraser@15548 188 if rc == xsconstants.XSERR_SUCCESS and \
kfraser@15548 189 flags & xsconstants.XS_INST_BOOT:
kfraser@15548 190 rc = self.make_boot_policy(xspol)
kfraser@15548 191 if rc == xsconstants.XSERR_SUCCESS:
kfraser@15548 192 rc = flags
kfraser@15548 193 return rc
kfraser@15548 194
kfraser@15548 195 def rm_policy_from_system(self, ref, force=False):
kfraser@15548 196 if self.policies.has_key(ref):
kfraser@15548 197 acmpol = self.xsobjs[ref]
kfraser@15548 198 rc = acmpol.destroy()
kfraser@15548 199 if rc == xsconstants.XSERR_SUCCESS or force:
kfraser@15548 200 del self.policies[ref]
kfraser@15548 201 del self.xsobjs[ref]
kfraser@15548 202 dictio.dict_write(self.policies,
kfraser@15548 203 "managed_policies",
kfraser@15548 204 XS_MANAGED_POLICIES_FILE)
kfraser@15548 205 rc = xsconstants.XSERR_SUCCESS
kfraser@15548 206 return rc
kfraser@15548 207
kfraser@15548 208 def rm_bootpolicy(self):
kfraser@15548 209 """ Remove any (ACM) boot policy from the grub configuration file
kfraser@15548 210 """
kfraser@15548 211 rc = 0
kfraser@15548 212 title = bootloader.get_default_title()
kfraser@15548 213 if title != None:
kfraser@15548 214 polnames = []
kfraser@15548 215 for (k, v) in self.xsobjs.items():
kfraser@15548 216 polnames.append(v.get_filename(".bin","",dotted=True))
kfraser@15548 217 bootloader.rm_policy_from_boottitle(title, polnames)
kfraser@15548 218 else:
kfraser@15548 219 rc = -xsconstants.XSERR_NO_DEFAULT_BOOT_TITLE
kfraser@15548 220 return rc
kfraser@15548 221
kfraser@15548 222 def get_policy_flags(self, acmpol):
kfraser@15548 223 """ Get the currently active flags of a policy, i.e., whether the
kfraser@15548 224 system is using this policy as its boot policy for the default
kfraser@15548 225 boot title.
kfraser@15548 226 """
kfraser@15548 227 flags = 0
kfraser@15548 228
kfraser@15548 229 filename = acmpol.get_filename(".bin","", dotted=True)
kfraser@15548 230 if bootloader.loads_default_policy(filename):
kfraser@15548 231 flags |= xsconstants.XS_INST_BOOT
kfraser@15548 232
kfraser@15548 233 if acmpol.isloaded():
kfraser@15548 234 flags |= xsconstants.XS_INST_LOAD
kfraser@15548 235 return flags
kfraser@15548 236
kfraser@15548 237 def get_policies(self):
kfraser@15548 238 """ Get all managed policies. """
kfraser@15548 239 return self.xsobjs.values()
kfraser@15548 240
kfraser@15548 241 def get_policies_refs(self):
kfraser@15548 242 """ Get all managed policies' references. """
kfraser@15548 243 return self.xsobjs.keys()
kfraser@15548 244
kfraser@15548 245 def has_ref(self, ref):
kfraser@15548 246 """ Check whether there is a policy with the given reference """
kfraser@15548 247 return self.xsobjs.has_key(ref)
kfraser@15548 248
kfraser@15548 249 def policy_from_ref(self, ref):
kfraser@15548 250 """ Get the policy's object given its reference """
kfraser@15548 251 if ref in self.xsobjs.keys():
kfraser@15548 252 return self.xsobjs[ref]
kfraser@15548 253 return None
kfraser@15548 254
kfraser@15548 255 def ref_from_polname(self, polname):
kfraser@15548 256 """ Get the reference of the policy given its name """
kfraser@15548 257 ref = None
kfraser@15548 258 for (k, v) in self.xsobjs.items():
kfraser@15548 259 if v.get_name() == polname:
kfraser@15548 260 ref = k
kfraser@15548 261 break
kfraser@15548 262 return ref
kfraser@15548 263
kfraser@15548 264 def lock_policy(self, ref):
kfraser@15548 265 """ get exclusive access to a policy """
kfraser@15548 266 self.xsobjs[ref].grab_lock()
kfraser@15548 267
kfraser@15548 268 def unlock_policy(self, ref):
kfraser@15548 269 """ release exclusive access to a policy """
kfraser@15548 270 self.xsobjs[ref].unlock()
kfraser@15548 271
kfraser@15548 272 def get_loaded_policy(self):
kfraser@15548 273 for pol in self.xsobjs.values():
kfraser@15548 274 if pol.isloaded():
kfraser@15548 275 return pol
kfraser@15548 276 return None
kfraser@15548 277
kfraser@15615 278 def get_hv_loaded_policy_name(self):
kfraser@15615 279 security.refresh_security_policy()
kfraser@15615 280 return security.active_policy
kfraser@15615 281
kfraser@15548 282 def get_policy_by_name(self, name):
kfraser@15548 283 for pol in self.xsobjs.values():
kfraser@15548 284 if pol.get_name() == name:
kfraser@15548 285 return pol
kfraser@15548 286 return None
kfraser@15548 287
kfraser@15548 288 def get_domain0_bootlabel(self):
kfraser@15548 289 """ Get the domain0 bootlabel from the default boot title """
kfraser@15548 290 title = ""
kfraser@15548 291 def_title = bootloader.get_default_title()
kfraser@15548 292 line = bootloader.get_kernel_val(def_title, "ssidref")
kfraser@15548 293 if line:
kfraser@15548 294 parms = line.split(":",1)
kfraser@15548 295 if len(parms) > 1:
kfraser@15548 296 title = parms[1]
kfraser@15548 297 return title
kfraser@15548 298
kfraser@15548 299 def set_domain0_bootlabel(self, xspol, label):
kfraser@15548 300 """ Set the domain-0 bootlabel under the given policy """
kfraser@15548 301 return xspol.set_vm_bootlabel(label)
kfraser@15548 302
kfraser@15548 303 def rm_domain0_bootlabel(self):
kfraser@15548 304 """ Remove the domain-0 bootlabel from the default boot title """
kfraser@15548 305 def_title = bootloader.get_default_title()
kfraser@15548 306 return bootloader.set_kernel_attval(def_title, "ssidref", None)
kfraser@15548 307
kfraser@15548 308 def ssidref_to_vmlabel(self, ssidref):
kfraser@15548 309 """ Given an ssidref, return the vmlabel under the current policy """
kfraser@15548 310 vmlabel = ""
kfraser@15548 311 pol = self.get_loaded_policy()
kfraser@15548 312 if pol:
kfraser@15548 313 vmlabel = pol.policy_get_domain_label_by_ssidref_formatted(ssidref)
kfraser@15548 314 return vmlabel
kfraser@15548 315
kfraser@15625 316 def get_stes_of_vmlabel(self, vmlabel_xapi):
kfraser@15625 317 """ Get the list of STEs given a VM label in XenAPI format """
kfraser@15625 318 stes = []
kfraser@15625 319 loadedpol = self.get_loaded_policy()
kfraser@15625 320 if loadedpol:
kfraser@15625 321 tmp = vmlabel_xapi.split(":")
kfraser@15625 322 if len(tmp) != 3:
kfraser@15625 323 return []
kfraser@15625 324 stes = loadedpol.policy_get_stes_of_vmlabel(tmp[2])
kfraser@15625 325 return stes
kfraser@15625 326
keir@16051 327 def get_enforced_binary(self, xstype):
keir@16051 328 res = None
keir@16051 329 if xstype == xsconstants.XS_POLICY_ACM:
keir@16051 330 res = ACMPolicy.get_enforced_binary()
keir@16051 331 return res
kfraser@15625 332
kfraser@15548 333 poladmin = None
kfraser@15548 334
kfraser@15548 335 def XSPolicyAdminInstance(maxpolicies=1):
kfraser@15548 336 global poladmin
kfraser@15548 337 if poladmin == None:
kfraser@15548 338 poladmin = XSPolicyAdmin(maxpolicies)
kfraser@15551 339 return poladmin