📄 acm.py
字号:
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 __update_label_policy_change(sec_lab, cur_poltype, cur_polname, new_poltype, new_polname, polnew_labels, label_map): """ Determine a new resource label given the new policy's type and name and the new policy's (resource/VM) labels and the (resource/VM) label map that indicates renaming rules for labels. """ is_deleted = False policytype, policy, label = sec_lab if cur_poltype != policytype or \ cur_polname != policy: return sec_lab, is_deleted if policytype != xsconstants.ACM_POLICY_ID: return sec_lab, is_deleted elif label_map.has_key(label) and policy == cur_polname: # renaming of an active label; policy may have been renamed label = label_map[label] polname = new_polname elif label not in polnew_labels: # label been removed policytype = xsconstants.INVALID_POLICY_PREFIX + policytype polname = policy is_deleted = True else: # no change to label policytype = xsconstants.ACM_POLICY_ID polname = new_polname return tuple( [ policytype, polname, label ] ), is_deleteddef change_acm_policy(bin_pol, del_array, chg_array, vmlabel_map, reslabel_map, cur_acmpol, new_acmpol, is_reset): """ 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("----------------------------------------------") label_changes = [] # 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, "" new_sec_lab, is_deleted = \ __update_label_policy_change( tuple([policytype, policy, label]), cur_policytype, cur_policyname, new_policytype, new_policyname, polnew_reslabels, reslabel_map) if is_deleted: label_changes.append(key) # Update entry access_control[key] = new_sec_lab # 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) and \ (not is_reset or name == "Domain-0") : # renaming of the label; this is only allowed if it's # not a reset of the policy or if it is a reset, then # only for Domain-0 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, "") for dominfo in dominfos: # relabel the VIF interfaces changed = False for vif_uuid in dominfo.get_vifs(): sec_lab = dominfo.info['devices'][vif_uuid][1]\ .get('security_label') if sec_lab: result, _ = \ __update_label_policy_change(tuple(sec_lab.split(':')), cur_policytype, cur_policyname, new_policytype, new_policyname, polnew_reslabels, reslabel_map) new_sec_lab = ':'.join(list(result)) if new_sec_lab != sec_lab: changed = True dominfo.info['devices'][vif_uuid][1]\ ['security_label'] = new_sec_lab if changed: XendDomain.instance().managed_config_save(dominfo) rc, errors = hv_chg_policy(bin_pol, del_array, chg_array) if rc == 0: for key in label_changes: run_resource_label_change_script(key, "", "remove") # 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 labeldef check_can_run(sec_label): """ Check whether a VM could run, given its vm label. A VM can run if - it is authorized - is not in conflict with any running domain """ try: mapfile_lock() if sec_label == None or sec_label == "": vm_label = ACM_LABEL_UNLABELED else: poltype, policy, vm_label = sec_label.split(':') if policy != get_active_policy_name(): return -xsconstants.XSERR_BAD_POLICY_NAME ssidref = label2ssidref(vm_label, policy, 'dom') if ssidref != xsconstants.INVALID_SSIDREF: if not has_authorization(ssidref): return -xsconstants.XSERR_VM_NOT_AUTHORIZED if is_in_conflict(ssidref): return -xsconstants.XSERR_VM_IN_CONFLICT return -xsconstants.XSERR_SUCCESS else: return -xsconstants.XSERR_BAD_LABEL finally: mapfile_unlock()__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 + -