def get_caps(self): # name -> id map caps = dict( (self.CAPS_MAP[d["name"]], d["_id"]) for d in Capability._get_collection().find({ "name": { "$in": list(self.CAPS_MAP) } }, { "_id": 1, "name": 1 }) ) # object -> caps add_expr = dict( (c, {"$in": [caps[c], "$caps.capability"]}) for c in caps ) project_expr = dict((c, 1) for c in caps) project_expr["_id"] = 1 return dict( (d["_id"], dict((x, d[x]) for x in d if x != "_id")) for d in ObjectCapabilities._get_collection().aggregate([ {"$addFields": add_expr}, {"$project": project_expr} ]) )
def __call__(self, **kwargs): script_name = "%s.%s" % (self.object.profile.name, self.name) scls = loader.get_script(script_name) # Build credentials credentials = { "address": self.object.address, "cli_protocol": "beef", "beef_storage_url": self.object._beef_storage, "beef_path": self.object._beef_path, "access-preference": "CS", "snmp_ro": "public", } # Build version if self.object.vendor and self.object.platform and self.object.version: version = { "vendor": self.object.vendor.code, "platform": self.object.platform.name, "version": self.object.version.version, } if self.object.software_image: version["image"] = self.object.software_image else: version = None # scr = scls( service=get_service(self.object.pool.name), credentials=credentials, capabilities=ObjectCapabilities.get_capabilities(self.object.id), version=version, timeout=3600, name=script_name, args=kwargs, ) return scr.run()
def get_caps(self): # name -> id map caps = { self.CAPS_MAP[d["name"]]: d["_id"] for d in Capability._get_collection().find( {"name": { "$in": list(self.CAPS_MAP) }}, { "_id": 1, "name": 1 }) } # object -> caps add_expr = {c: {"$in": [caps[c], "$caps.capability"]} for c in caps} project_expr = {c: 1 for c in caps} project_expr["_id"] = 1 return { d["_id"]: {x: d[x] for x in d if x != "_id"} for d in ObjectCapabilities._get_collection().aggregate( [{ "$addFields": add_expr }, { "$project": project_expr }]) }
def _apply_caps(mo, r): # Get caps cdata = ObjectCapabilities.get_capabilities(mo) if not cdata: return caps = [] for cname in sorted(cdata): caps += [{"name": cname, "value": str(cdata[cname])}] r["capabilities"] = caps
def get_object_data(self, object_id): """ Worker to resolve credentials """ object_id = int(object_id) # Get Object's attributes with self.service.get_pg_connect() as connection: cursor = connection.cursor() cursor.execute(self.RUN_SQL, [object_id, object_id]) data = cursor.fetchall() if not data: metrics["error", ("type", "object_not_found")] += 1 raise APIError("Object is not found") # Build capabilities capabilities = ObjectCapabilities.get_capabilities(object_id) # Get object credentials ( name, is_managed, profile, vendor, platform, version, scheme, address, port, user, password, super_password, remote_path, snmp_ro, pool_id, sw_image, auth_profile_id, ap_user, ap_password, ap_super_password, ap_snmp_ro, ap_snmp_rw, privilege_policy, snmp_rate_limit, p_privilege_policy, p_snmp_rate_limit, access_preference, p_access_preference, beef_storage_id, beef_path_template_id, attrs, ) = data[0] # Check object is managed if not is_managed: metrics["error", ("type", "object_not_managed")] += 1 raise APIError("Object is not managed") if auth_profile_id: user = ap_user password = ap_password super_password = ap_super_password snmp_ro = ap_snmp_ro snmp_rw = ap_snmp_rw # noqa just to be # if privilege_policy == "E": raise_privileges = True elif privilege_policy == "P": raise_privileges = p_privilege_policy == "E" else: raise_privileges = False if access_preference == "P": access_preference = p_access_preference if not snmp_rate_limit: snmp_rate_limit = p_snmp_rate_limit # Build credentials credentials = { "name": name, "address": address, "user": user, "password": password, "super_password": super_password, "path": remote_path, "raise_privileges": raise_privileges, "access_preference": access_preference, "snmp_rate_limit": snmp_rate_limit, } if snmp_ro: credentials["snmp_ro"] = snmp_ro if capabilities.get("SNMP | v2c"): credentials["snmp_version"] = "v2c" elif capabilities.get("SNMP | v1"): credentials["snmp_version"] = "v1" if scheme in CLI_PROTOCOLS: credentials["cli_protocol"] = PROTOCOLS[scheme] if port: credentials["cli_port"] = port elif scheme in HTTP_PROTOCOLS: credentials["http_protocol"] = PROTOCOLS[scheme] if port: credentials["http_port"] = port # Build version if vendor and platform and version: vendor = Vendor.get_by_id(vendor) version = { "vendor": vendor.code[0] if vendor.code else vendor.name, "platform": Platform.get_by_id(platform).name, "version": Firmware.get_by_id(version).version, } if sw_image: version["image"] = sw_image if attrs: version["attributes"] = attrs else: version = None # Beef processing if scheme == BEEF and beef_storage_id and beef_path_template_id: mo = ManagedObject.get_by_id(object_id) tpl = Template.get_by_id(beef_path_template_id) beef_path = tpl.render_subject(object=mo) if beef_path: storage = ExtStorage.get_by_id(beef_storage_id) credentials["beef_storage_url"] = storage.url credentials["beef_path"] = beef_path return dict( profile=Profile.get_by_id(profile).name, pool_id=pool_id, credentials=credentials, capabilities=capabilities, version=version, )
def cleaned_query(self, q): nq = {} for k in q: if not k.startswith("_") and "__" not in k: nq[k] = q[k] ids = set() self.logger.debug("Cleaned query: %s" % nq) if "ids" in nq: ids = {int(nid) for nid in nq["ids"]} del nq["ids"] if "administrative_domain" in nq: ad = AdministrativeDomain.get_nested_ids( int(nq["administrative_domain"])) if ad: del nq["administrative_domain"] nq["administrative_domain__in"] = ad if "selector" in nq: s = self.get_object_or_404(ManagedObjectSelector, id=int(q["selector"])) if s: if ids: # nq["id__in"] = set(ManagedObject.objects.filter(s.Q).values_list("id", flat=True)) ids = ids.intersection( set( ManagedObject.objects.filter(s.Q).values_list( "id", flat=True))) else: ids = set( ManagedObject.objects.filter(s.Q).values_list( "id", flat=True)) del nq["selector"] mq = None c_in = [] c_nin = [] for cc in [part for part in nq if part.startswith("caps")]: """ Caps: caps0=CapsID,caps1=CapsID:true.... cq - caps query mq - main_query caps0=CapsID - caps is exists caps0=!CapsID - caps is not exists caps0=CapsID:true - caps value equal True caps0=CapsID:2~50 - caps value many then 2 and less then 50 c_ids = set(ObjectCapabilities.objects(cq).distinct('object')) """ # @todo Убирать дубликаты (повторно не добавлять) c = nq.pop(cc) if not c: continue if not mq: mq = m_Q() self.logger.info("Caps: %s" % c) if "!" in c: # @todo Добавить исключение (только этот) !ID c_id = c[1:] c_query = "nexists" elif ":" not in c: c_id = c c_query = "exists" else: c_id, c_query = c.split(":", 1) try: c_id = bson.ObjectId(c_id) except bson.errors.InvalidId as e: self.logger.warning(e) continue if "~" in c_query: l, r = c_query.split("~") if not l: cond = {"$lte": int(r)} elif not r: cond = {"$gte": int(l)} else: cond = {"$lte": int(r), "$gte": int(l)} cq = m_Q(__raw__={ "caps": { "$elemMatch": { "capability": c_id, "value": cond } } }) elif c_query in ("false", "true"): cq = m_Q(caps__match={ "capability": c_id, "value": c_query == "true" }) elif c_query == "exists": c_in += [c_id] continue elif c_query == "nexists": c_nin += [c_id] continue else: try: c_query = int(c_query) cq = m_Q( __raw__={ "caps": { "$elemMatch": { "capability": c_id, "value": int(c_query) } } }) except ValueError: cq = m_Q( __raw__={ "caps": { "$elemMatch": { "capability": c_id, "value": { "$regex": c_query } } } }) mq &= cq if c_in: mq &= m_Q(caps__capability__in=c_in) if c_nin: mq &= m_Q(caps__capability__nin=c_nin) if mq: c_ids = set(el["_id"] for el in ObjectCapabilities.objects( mq).values_list("object").as_pymongo()) self.logger.info("Caps objects count: %d" % len(c_ids)) ids = ids.intersection(c_ids) if ids else c_ids if "addresses" in nq: if isinstance(nq["addresses"], list): nq["address__in"] = nq["addresses"] else: nq["address__in"] = [nq["addresses"]] del nq["addresses"] if ids: nq["id__in"] = list(ids) xf = list((set(nq.keys())) - set(f.name for f in self.model._meta.get_fields())) # @todo move validation fields for x in xf: if x in ["address__in", "id__in", "administrative_domain__in"]: continue self.logger.warning("Remove element not in model: %s" % x) del nq[x] return nq