Beispiel #1
0
 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}
         ])
     )
Beispiel #2
0
 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()
Beispiel #3
0
 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
             }])
     }
Beispiel #4
0
 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
Beispiel #5
0
 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,
     )
Beispiel #6
0
    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