ia64/xen-unstable

annotate tools/python/xen/xend/XendXSPolicyAdmin.py @ 15625:f1aed243f3f0

[xend / libxen] Add support for labeling of virtual network interfaces.

This patch adds labeling of virtual network interfaces to xend and
makes this manageable through the Xen-API. It's a feature that is
only usable if ACM is enabled in Xen and xend is used through the
xen-api. A labeled virtual network interface will be plugged into a
bridge where other domains with the same-labeled network interface are
connected to, so that only same-colored domains can communicate with
each other. The bridge should be connected to the outside world using
VLAN for isolation, extending the isolation beyond the local machine.
If a virtual machine is labeled with a VM label that only has one
Simple Type Enforcement Type then it is not necessary to label the
virtual network interface, but the color of the network interface is
determined from the VM's label. If, however, a virtual machine is
labeled with a VM label that has multiple Simple Type Enforcement
Types, then the explicit labeling of each virtual network interface is
required. To specify the label of a network interface, the vif line in
the VM's configuration file has been extended with parameters similar
use for specifying the label of the VM:

vif = ['policy=<policy name>,label=<resource label>']

This labels the VIF of the virtual machine for usage under the policy
'policy name' and labels it with the label 'resource label'.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author kfraser@localhost.localdomain
date Thu Jul 19 16:59:48 2007 +0100 (2007-07-19)
parents 9c077fc8ccf1
children 993655d24b55
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@15548 25 from xen.util import security, xsconstants, dictio, bootloader
kfraser@15548 26 from xen.util.xspolicy import XSPolicy
kfraser@15548 27 from xen.util.acmpolicy import ACMPolicy
kfraser@15548 28 from xen.xend.XendError import SecurityError
kfraser@15548 29
kfraser@15548 30 XS_MANAGED_POLICIES_FILE = "/etc/xen/acm-security/policies/managed_policies"
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
kfraser@15548 47 try:
kfraser@15548 48 self.policies = dictio.dict_read("managed_policies",
kfraser@15548 49 XS_MANAGED_POLICIES_FILE)
kfraser@15548 50 except Exception, e:
kfraser@15548 51 self.policies = {}
kfraser@15548 52
kfraser@15548 53 self.xsobjs = {}
kfraser@15548 54 for ref, data in self.policies.items():
kfraser@15548 55 name = data[0]
kfraser@15548 56 typ = data[1]
kfraser@15548 57 try:
kfraser@15548 58 if typ == xsconstants.ACM_POLICY_ID:
kfraser@15615 59 try:
kfraser@15615 60 self.xsobjs[ref] = ACMPolicy(name=name, ref=ref)
kfraser@15615 61 except Exception, e:
kfraser@15615 62 del self.policies[ref]
kfraser@15548 63 else:
kfraser@15548 64 del self.policies[ref]
kfraser@15548 65 except Exception, e:
kfraser@15548 66 log.error("XSPolicyAdmin: Could not find policy '%s': %s" %
kfraser@15548 67 (name, str(e)))
kfraser@15548 68 del self.policies[ref]
kfraser@15548 69 log.debug("XSPolicyAdmin: Known policies: %s" % self.policies)
kfraser@15548 70
kfraser@15548 71 def isXSEnabled(self):
kfraser@15548 72 """ Check whether 'security' is enabled on this system.
kfraser@15548 73 This currently only checks for ACM-enablement.
kfraser@15548 74 """
kfraser@15548 75 rc = 0
kfraser@15548 76 if security.on():
kfraser@15548 77 rc |= xsconstants.XS_POLICY_ACM
kfraser@15548 78 return rc
kfraser@15548 79
kfraser@15548 80 def add_acmpolicy_to_system(self, xmltext, flags, overwrite):
kfraser@15548 81 """ Add an ACM policy's xml representation to the system. The
kfraser@15548 82 policy will automatically be compiled
kfraser@15548 83 flags:
kfraser@15548 84 XS_INST_BOOT : make policy the one to boot the system with
kfraser@15548 85 by default; if there's a policy already installed,
kfraser@15548 86 refuse to install this policy unless its one with
kfraser@15548 87 the same name
kfraser@15548 88 XS_INST_LOAD : load the policy immediately; if this does not work
kfraser@15548 89 refuse to install this policy
kfraser@15548 90 overwrite:
kfraser@15548 91 If any policy is installed and this is False, refuse to install
kfraser@15548 92 this policy
kfraser@15548 93 If flags is True, then any existing policy will be removed from
kfraser@15548 94 the system and the new one will be installed
kfraser@15548 95 """
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)
kfraser@15548 106 return (loadedpol, rc, errors)
kfraser@15548 107
kfraser@15548 108 try:
kfraser@15548 109 dom = minidom.parseString(xmltext.encode("utf-8"))
kfraser@15548 110 except:
kfraser@15548 111 raise SecurityError(-xsconstants.XSERR_BAD_XML)
kfraser@15548 112
kfraser@15548 113 ref = uuid.createString()
kfraser@15548 114
kfraser@15548 115 acmpol = ACMPolicy(dom=dom, ref=ref)
kfraser@15548 116
kfraser@15548 117 #First some basic tests that do not modify anything:
kfraser@15548 118
kfraser@15548 119 if flags & xsconstants.XS_INST_BOOT and not overwrite:
kfraser@15548 120 filename = acmpol.get_filename(".bin","",dotted=True)
kfraser@15548 121 if bootloader.get_default_policy != None and \
kfraser@15548 122 not bootloader.loads_default_policy(filename):
kfraser@15548 123 raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED)
kfraser@15548 124
kfraser@15548 125 if not overwrite and len(self.policies) >= self.maxpolicies:
kfraser@15548 126 raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED)
kfraser@15548 127
kfraser@15548 128 if overwrite:
kfraser@15548 129 #This should only give one key since only one policy is
kfraser@15548 130 #allowed.
kfraser@15548 131 keys = self.policies.keys()
kfraser@15548 132 for k in keys:
kfraser@15548 133 self.rm_bootpolicy()
kfraser@15548 134 rc = self.rm_policy_from_system(k, force=overwrite)
kfraser@15548 135 if rc != xsconstants.XSERR_SUCCESS:
kfraser@15548 136 raise SecurityError(rc)
kfraser@15548 137
kfraser@15548 138 rc = acmpol.compile()
kfraser@15548 139 if rc != 0:
kfraser@15548 140 raise SecurityError(rc)
kfraser@15548 141
kfraser@15548 142 if flags & xsconstants.XS_INST_LOAD:
kfraser@15548 143 rc = acmpol.loadintohv()
kfraser@15548 144 if rc != 0:
kfraser@15548 145 raise SecurityError(rc)
kfraser@15548 146
kfraser@15548 147 if flags & xsconstants.XS_INST_BOOT:
kfraser@15548 148 rc = self.make_boot_policy(acmpol)
kfraser@15548 149 if rc != 0:
kfraser@15548 150 # If it cannot be installed due to unsupported
kfraser@15548 151 # bootloader, let it be ok.
kfraser@15548 152 pass
kfraser@15548 153
kfraser@15548 154 if dom:
kfraser@15548 155 new_entry = { ref : tuple([acmpol.get_name(),
kfraser@15548 156 xsconstants.ACM_POLICY_ID]) }
kfraser@15548 157 self.policies.update(new_entry)
kfraser@15548 158 self.xsobjs[ref] = acmpol
kfraser@15548 159 dictio.dict_write(self.policies,
kfraser@15548 160 "managed_policies",
kfraser@15548 161 XS_MANAGED_POLICIES_FILE)
kfraser@15548 162 return (acmpol, xsconstants.XSERR_SUCCESS, errors)
kfraser@15548 163
kfraser@15548 164 def make_boot_policy(self, acmpol):
kfraser@15548 165 spolfile = acmpol.get_filename(".bin")
kfraser@15548 166 dpolfile = "/boot/" + acmpol.get_filename(".bin","",dotted=True)
kfraser@15548 167 if not os.path.isfile(spolfile):
kfraser@15548 168 log.error("binary policy file does not exist.")
kfraser@15548 169 return -xsconstants.XSERR_FILE_ERROR
kfraser@15548 170 try:
kfraser@15548 171 shutil.copyfile(spolfile, dpolfile)
kfraser@15548 172 except:
kfraser@15548 173 return -xsconstants.XSERR_FILE_ERROR
kfraser@15548 174
kfraser@15548 175 try:
kfraser@15548 176 filename = acmpol.get_filename(".bin","",dotted=True)
kfraser@15548 177 if bootloader.set_default_boot_policy(filename) != True:
kfraser@15548 178 return xsconstants.XSERR_BOOTPOLICY_INSTALL_ERROR
kfraser@15548 179 except:
kfraser@15548 180 return xsconstants.XSERR_FILE_ERROR
kfraser@15548 181 return xsconstants.XSERR_SUCCESS
kfraser@15548 182
kfraser@15548 183 def activate_xspolicy(self, xspol, flags):
kfraser@15548 184 rc = xsconstants.XSERR_SUCCESS
kfraser@15548 185 if flags & xsconstants.XS_INST_LOAD:
kfraser@15548 186 rc = xspol.loadintohv()
kfraser@15548 187 if rc == xsconstants.XSERR_SUCCESS and \
kfraser@15548 188 flags & xsconstants.XS_INST_BOOT:
kfraser@15548 189 rc = self.make_boot_policy(xspol)
kfraser@15548 190 if rc == xsconstants.XSERR_SUCCESS:
kfraser@15548 191 rc = flags
kfraser@15548 192 return rc
kfraser@15548 193
kfraser@15548 194 def rm_policy_from_system(self, ref, force=False):
kfraser@15548 195 if self.policies.has_key(ref):
kfraser@15548 196 acmpol = self.xsobjs[ref]
kfraser@15548 197 rc = acmpol.destroy()
kfraser@15548 198 if rc == xsconstants.XSERR_SUCCESS or force:
kfraser@15548 199 del self.policies[ref]
kfraser@15548 200 del self.xsobjs[ref]
kfraser@15548 201 dictio.dict_write(self.policies,
kfraser@15548 202 "managed_policies",
kfraser@15548 203 XS_MANAGED_POLICIES_FILE)
kfraser@15548 204 rc = xsconstants.XSERR_SUCCESS
kfraser@15548 205 return rc
kfraser@15548 206
kfraser@15548 207 def rm_bootpolicy(self):
kfraser@15548 208 """ Remove any (ACM) boot policy from the grub configuration file
kfraser@15548 209 """
kfraser@15548 210 rc = 0
kfraser@15548 211 title = bootloader.get_default_title()
kfraser@15548 212 if title != None:
kfraser@15548 213 polnames = []
kfraser@15548 214 for (k, v) in self.xsobjs.items():
kfraser@15548 215 polnames.append(v.get_filename(".bin","",dotted=True))
kfraser@15548 216 bootloader.rm_policy_from_boottitle(title, polnames)
kfraser@15548 217 else:
kfraser@15548 218 rc = -xsconstants.XSERR_NO_DEFAULT_BOOT_TITLE
kfraser@15548 219 return rc
kfraser@15548 220
kfraser@15548 221 def get_policy_flags(self, acmpol):
kfraser@15548 222 """ Get the currently active flags of a policy, i.e., whether the
kfraser@15548 223 system is using this policy as its boot policy for the default
kfraser@15548 224 boot title.
kfraser@15548 225 """
kfraser@15548 226 flags = 0
kfraser@15548 227
kfraser@15548 228 filename = acmpol.get_filename(".bin","", dotted=True)
kfraser@15548 229 if bootloader.loads_default_policy(filename):
kfraser@15548 230 flags |= xsconstants.XS_INST_BOOT
kfraser@15548 231
kfraser@15548 232 if acmpol.isloaded():
kfraser@15548 233 flags |= xsconstants.XS_INST_LOAD
kfraser@15548 234 return flags
kfraser@15548 235
kfraser@15548 236 def get_policies(self):
kfraser@15548 237 """ Get all managed policies. """
kfraser@15548 238 return self.xsobjs.values()
kfraser@15548 239
kfraser@15548 240 def get_policies_refs(self):
kfraser@15548 241 """ Get all managed policies' references. """
kfraser@15548 242 return self.xsobjs.keys()
kfraser@15548 243
kfraser@15548 244 def has_ref(self, ref):
kfraser@15548 245 """ Check whether there is a policy with the given reference """
kfraser@15548 246 return self.xsobjs.has_key(ref)
kfraser@15548 247
kfraser@15548 248 def policy_from_ref(self, ref):
kfraser@15548 249 """ Get the policy's object given its reference """
kfraser@15548 250 if ref in self.xsobjs.keys():
kfraser@15548 251 return self.xsobjs[ref]
kfraser@15548 252 return None
kfraser@15548 253
kfraser@15548 254 def ref_from_polname(self, polname):
kfraser@15548 255 """ Get the reference of the policy given its name """
kfraser@15548 256 ref = None
kfraser@15548 257 for (k, v) in self.xsobjs.items():
kfraser@15548 258 if v.get_name() == polname:
kfraser@15548 259 ref = k
kfraser@15548 260 break
kfraser@15548 261 return ref
kfraser@15548 262
kfraser@15548 263 def lock_policy(self, ref):
kfraser@15548 264 """ get exclusive access to a policy """
kfraser@15548 265 self.xsobjs[ref].grab_lock()
kfraser@15548 266
kfraser@15548 267 def unlock_policy(self, ref):
kfraser@15548 268 """ release exclusive access to a policy """
kfraser@15548 269 self.xsobjs[ref].unlock()
kfraser@15548 270
kfraser@15548 271 def get_loaded_policy(self):
kfraser@15548 272 for pol in self.xsobjs.values():
kfraser@15548 273 if pol.isloaded():
kfraser@15548 274 return pol
kfraser@15548 275 return None
kfraser@15548 276
kfraser@15615 277 def get_hv_loaded_policy_name(self):
kfraser@15615 278 security.refresh_security_policy()
kfraser@15615 279 return security.active_policy
kfraser@15615 280
kfraser@15548 281 def get_policy_by_name(self, name):
kfraser@15548 282 for pol in self.xsobjs.values():
kfraser@15548 283 if pol.get_name() == name:
kfraser@15548 284 return pol
kfraser@15548 285 return None
kfraser@15548 286
kfraser@15548 287 def get_domain0_bootlabel(self):
kfraser@15548 288 """ Get the domain0 bootlabel from the default boot title """
kfraser@15548 289 title = ""
kfraser@15548 290 def_title = bootloader.get_default_title()
kfraser@15548 291 line = bootloader.get_kernel_val(def_title, "ssidref")
kfraser@15548 292 if line:
kfraser@15548 293 parms = line.split(":",1)
kfraser@15548 294 if len(parms) > 1:
kfraser@15548 295 title = parms[1]
kfraser@15548 296 return title
kfraser@15548 297
kfraser@15548 298 def set_domain0_bootlabel(self, xspol, label):
kfraser@15548 299 """ Set the domain-0 bootlabel under the given policy """
kfraser@15548 300 return xspol.set_vm_bootlabel(label)
kfraser@15548 301
kfraser@15548 302 def rm_domain0_bootlabel(self):
kfraser@15548 303 """ Remove the domain-0 bootlabel from the default boot title """
kfraser@15548 304 def_title = bootloader.get_default_title()
kfraser@15548 305 return bootloader.set_kernel_attval(def_title, "ssidref", None)
kfraser@15548 306
kfraser@15548 307 def ssidref_to_vmlabel(self, ssidref):
kfraser@15548 308 """ Given an ssidref, return the vmlabel under the current policy """
kfraser@15548 309 vmlabel = ""
kfraser@15548 310 pol = self.get_loaded_policy()
kfraser@15548 311 if pol:
kfraser@15548 312 vmlabel = pol.policy_get_domain_label_by_ssidref_formatted(ssidref)
kfraser@15548 313 return vmlabel
kfraser@15548 314
kfraser@15625 315 def get_stes_of_vmlabel(self, vmlabel_xapi):
kfraser@15625 316 """ Get the list of STEs given a VM label in XenAPI format """
kfraser@15625 317 stes = []
kfraser@15625 318 loadedpol = self.get_loaded_policy()
kfraser@15625 319 if loadedpol:
kfraser@15625 320 tmp = vmlabel_xapi.split(":")
kfraser@15625 321 if len(tmp) != 3:
kfraser@15625 322 return []
kfraser@15625 323 stes = loadedpol.policy_get_stes_of_vmlabel(tmp[2])
kfraser@15625 324 return stes
kfraser@15625 325
kfraser@15625 326
kfraser@15548 327 poladmin = None
kfraser@15548 328
kfraser@15548 329 def XSPolicyAdminInstance(maxpolicies=1):
kfraser@15548 330 global poladmin
kfraser@15548 331 if poladmin == None:
kfraser@15548 332 poladmin = XSPolicyAdmin(maxpolicies)
kfraser@15551 333 return poladmin