📄 acm.py
字号:
try: resfile_lock() access_control = {} try: access_control = dictio.dict_read("resources", res_label_filename) except: pass if oreslabel: if not access_control.has_key(resource): return -xsconstants.XSERR_BAD_LABEL tmp = access_control[resource] if len(tmp) != 3: return -xsconstants.XSERR_BAD_LABEL if tmp[2] != oreslabel: return -xsconstants.XSERR_BAD_LABEL if reslabel != "": new_entry = { resource : tuple([policytype, policyref, reslabel])} access_control.update(new_entry) command = "add" reslbl = ":".join([policytype, policyref, reslabel]) else: if access_control.has_key(resource): del access_control[resource] command = "remove" reslbl = "" run_resource_label_change_script(resource, reslbl, command) dictio.dict_write(access_control, "resources", res_label_filename) finally: resfile_unlock() return xsconstants.XSERR_SUCCESSdef rm_resource_label(resource, oldlabel_xapi): """Remove a resource label from a physical resource @param resource: The name of a resource, i.e., "phy:/dev/hda" @rtype: int @return Success (0) or failure value (< 0) """ tmp = oldlabel_xapi.split(":") if len(tmp) != 3: return -xsconstants.XSERR_BAD_LABEL_FORMAT otyp, opolicyref, olabel = tmp # Only ACM is supported if otyp != xsconstants.ACM_POLICY_ID and \ otyp != xsconstants.INVALID_POLICY_PREFIX + xsconstants.ACM_POLICY_ID: return -xsconstants.XSERR_WRONG_POLICY_TYPE return set_resource_label(resource, "", "", "", olabel)def get_resource_label_xapi(resource): """Get the assigned resource label of a physical resource in the format used by then Xen-API, i.e., "ACM:xm-test:blue" @rtype: string @return the string representing policy type, policy name and label of the resource """ res = get_resource_label(resource) return format_resource_label(res)def format_resource_label(res): if res: if len(res) == 2: return xsconstants.ACM_POLICY_ID + ":" + res[0] + ":" + res[1] if len(res) == 3: return ":".join(res) return ""def get_resource_label(resource): """ Xend exports this function via XML-RPC. Get the assigned resource label of a given resource @param resource: The name of a resource, i.e., "phy:/dev/hda" @rtype: list @return tuple of (policy name, resource label), i.e., (xm-test, blue) """ try: resource = unify_resname(resource, mustexist=False) except Exception: return [] reslabel_map = get_labeled_resources() if reslabel_map.has_key(resource): return list(reslabel_map[resource]) else: #Try to resolve each label entry for key, value in reslabel_map.items(): try: if resource == unify_resname(key): return list(value) except: pass return []def get_labeled_resources_xapi(): """ Get a map of all labeled resource with the labels formatted in the xen-api resource label format. """ reslabel_map = get_labeled_resources() for key, labeldata in reslabel_map.items(): reslabel_map[key] = format_resource_label(labeldata) return reslabel_mapdef get_labeled_resources(): """ Xend exports this function via XML-RPC Get a map of all labeled resources. @rtype: list @return list of labeled resources """ try: resfile_lock() try: access_control = dictio.dict_read("resources", res_label_filename) except: return {} finally: resfile_unlock() return access_controldef relabel_domains(relabel_list): """ Relabel the given domains to have a new ssidref. @param relabel_list: a list containing tuples of domid, ssidref example: [ [0, 0x00020002] ] """ rel_rules = "" for r in relabel_list: log.info("Relabeling domain with domid %d to new ssidref 0x%08x", r[0], r[1]) rel_rules += struct.pack("ii", r[0], r[1]) try: rc, errors = acm.relabel_domains(rel_rules) except Exception, e: log.info("Error after relabel_domains: %s" % str(e)) rc = -xsconstants.XSERR_GENERAL_FAILURE errors = "" if (len(errors) > 0): rc = -xsconstants.XSERR_HV_OP_FAILED return rc, errorsdef change_acm_policy(bin_pol, del_array, chg_array, vmlabel_map, reslabel_map, cur_acmpol, new_acmpol): """ Change the ACM policy of the system by relabeling domains and resources first and doing some access checks. Then update the policy in the hypervisor. If this is all successful, relabel the domains permanently and commit the relabed resources. Need to do / check the following: - relabel all resources where there is a 'from' field in the policy. [ NOT DOING THIS: and mark those as unlabeled where the label does not appear in the new policy anymore (deletion) ] - relabel all VMs where there is a 'from' field in the policy and mark those as unlabeled where the label does not appear in the new policy anymore; no running or paused VM may be unlabeled through this - check that under the new labeling conditions the VMs still have access to their resources as before. Unlabeled resources are inaccessible. If this check fails, the update failed. - Attempt changes in the hypervisor; if this step fails, roll back the relabeling of resources and VMs - Make the relabeling of resources and VMs permanent This function should be called with the lock to the domains held (XendDomain.instance().domains_lock) """ from xen.util.acmpolicy import ACM_LABEL_UNLABELED rc = xsconstants.XSERR_SUCCESS domain_label_map = {} new_policyname = new_acmpol.get_name() new_policytype = new_acmpol.get_type_name() cur_policyname = cur_acmpol.get_name() cur_policytype = cur_acmpol.get_type_name() polnew_reslabels = new_acmpol.policy_get_resourcelabel_names() errors="" try: resfile_lock() mapfile_lock() # Get all domains' dominfo. from xen.xend import XendDomain dominfos = XendDomain.instance().list('all') log.info("----------------------------------------------") # relabel resources access_control = {} try: access_control = dictio.dict_read("resources", res_label_filename) except: pass for key, labeldata in access_control.items(): if len(labeldata) == 2: policy, label = labeldata policytype = xsconstants.ACM_POLICY_ID elif len(labeldata) == 3: policytype, policy, label = labeldata else: return -xsconstants.XSERR_BAD_LABEL_FORMAT, "" if policytype != cur_policytype or \ policy != cur_policyname: continue # label been renamed or deleted? if policytype != xsconstants.ACM_POLICY_ID: continue elif reslabel_map.has_key(label) and cur_policyname == policy: # renaming of an active label; policy may have been renamed label = reslabel_map[label] polname = new_policyname elif label not in polnew_reslabels: # label been removed policytype = xsconstants.INVALID_POLICY_PREFIX + policytype run_resource_label_change_script(key, "", "remove") polname = policy else: # no change to label policytype = xsconstants.ACM_POLICY_ID polname = new_policyname # Update entry access_control[key] = \ tuple([ policytype, polname, label ]) # All resources have new labels in the access_control map # There may still be labels in there that are invalid now. # Do this in memory without writing to disk: # - Relabel all domains independent of whether they are running # or not # - later write back to config files polnew_vmlabels = new_acmpol.policy_get_virtualmachinelabel_names() for dominfo in dominfos: sec_lab = dominfo.get_security_label() if not sec_lab: continue policytype, policy, vmlabel = sec_lab.split(":") name = dominfo.getName() if policytype != cur_policytype or \ policy != cur_policyname: continue new_vmlabel = vmlabel if vmlabel_map.has_key(vmlabel): # renaming of the label new_vmlabel = vmlabel_map[vmlabel] polname = new_policyname elif new_vmlabel not in polnew_vmlabels and \ vmlabel != ACM_LABEL_UNLABELED: # removal of VM label and not the 'unlabeled' label policytype = xsconstants.INVALID_POLICY_PREFIX + policytype polname = policy else: polname = new_policyname new_seclab = "%s:%s:%s" % \ (policytype, polname, new_vmlabel) domain_label_map[dominfo] = [ sec_lab, new_seclab ] if dominfo._stateGet() in (DOM_STATE_PAUSED, DOM_STATE_RUNNING): compatible = __resources_compatible_with_vmlabel(new_acmpol, dominfo, new_vmlabel, access_control, is_policy_update=True) log.info("Domain %s with new label '%s' can access its " "resources? : %s" % (name, new_vmlabel, str(compatible))) log.info("VM labels in new policy: %s" % new_acmpol.policy_get_virtualmachinelabel_names()) if not compatible: return (-xsconstants.XSERR_RESOURCE_ACCESS, "") rc, errors = hv_chg_policy(bin_pol, del_array, chg_array) if rc == 0: # Write the relabeled resources back into the file dictio.dict_write(access_control, "resources", res_label_filename) # Properly update all VMs to their new labels for dominfo, labels in domain_label_map.items(): sec_lab, new_seclab = labels if sec_lab != new_seclab: log.info("Updating domain %s to new label '%s'." % \ (dominfo.getName(), new_seclab)) # This better be working! res = dominfo.set_security_label(new_seclab, sec_lab, new_acmpol, cur_acmpol) if res[0] != xsconstants.XSERR_SUCCESS: log.info("ERROR: Could not chg label on domain %s: %s" % (dominfo.getName(), xsconstants.xserr2string(-int(res[0])))) finally: log.info("----------------------------------------------") mapfile_unlock() resfile_unlock() return rc, errorsdef parse_security_label(security_label): tmp = security_label.split(":") if len(tmp) != 3: return "" else: return security_labeldef set_security_label(policy, label): if label and policy and label != "" and policy != "": return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, policy, label) else: return ""def ssidref2security_label(ssidref): from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance return XSPolicyAdminInstance().ssidref_to_vmlabel(ssidref)def get_security_label(self, xspol=None): """ Get the security label of a domain @param xspol The policy to use when converting the ssid into a label; only to be passed during the updating of the policy """ domid = self.getDomid() if not xspol: from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance xspol = XSPolicyAdminInstance().get_loaded_policy() label = "" if xspol: label = xspol.policy_get_domain_label_formatted(domid) if domid != 0: label = self.info.get('security_label', label) return label__cond = threading.Condition()__script_runner = None__orders = []def run_resource_label_change_script(resource, label, command): global __cond, __orders, __script_runner def __run_resource_label_change_script(): global __cond, __orders script = XendOptions.instance().get_resource_label_change_script() if script: parms = {} while True: __cond.acquire() if len(__orders) == 0: __cond.wait() parms['label'], \ parms['command'], \ parms['resource'] = __orders[0] __orders = __orders[1:] __cond.release() log.info("Running resource label change script %s: %s" % (script, parms)) parms.update(os.environ) os.spawnve(os.P_WAIT, script[0], script, parms) else: log.info("No script given for relabeling of resources.") if not __script_runner: __script_runner = \ threading.Thread(target=__run_resource_label_change_script, args=()) __script_runner.start() __cond.acquire() __orders.append((label,command,resource)) __cond.notify() __cond.release()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -