Example #1
0
    def encode_message(self, destination_id=None, component_type=None, component_name=None,
                       payload=None, reply_to=None):
        """
        Creates a basic dictionary to represent the message and then pickles it using JSON.

        :param payload: Dictionary to send.
        :param destination_id:
        :return:
        """
        if destination_id is None:
            destination_id = "all"

        message_id = random_string(length=20)
        body = {
            "payload": payload,
            "time_sent": time(),
            "source_id": self.gateway_id,
            "destination_id": destination_id,
            "message_id": message_id,
            "component_type": component_type,
            "component_name": component_name,
            "reply_to": reply_to,
            "protocol_version": 2,
            }
        message_out = {
            "body": data_pickle(body, "msgpack_base85"),
        }
        message_out["hash"] = sha256_compact(message_out["body"])
        message = {
            "body": body,
            "hash": message_out["hash"],
        }
        return message_id, message, data_pickle(message_out, "msgpack_base85")
    def get_device_hash(self, discover_id, source=None):
        if discover_id in self.discovered:
            return discover_id

        if source is None:
            source = "unknown"
        return sha256_compact(str(source + discover_id).encode("utf-8"))
    def get_idempotence(self, request, session):
        """
        Check if idempotence is in the request and if that key has already been processed for the given user. If it
        has, return the same response.

        :param self:
        :param request:
        :param session:
        :return:
        """
        request.setHeader("Content-Type", CONTENT_TYPE_JSON)
        idempotence = request.getHeader("x-idempotence")
        if idempotence is None:
            arguments = args_to_dict(request.args)
            idempotence = arguments.get("_idempotence", None)
        if idempotence is not None:
            request.idempotence = idempotence
            idempotence = sha256_compact(f"{session.auth_id}:{idempotence}")
            if idempotence in self.idempotence:
                results = msgpack.loads(zlib.uncompress(self.idempotence[idempotence]))
                print(f"get_idempotence results {results}")
                return False
                request.setHeader("Idempotence", "true")
                request.setResponseCode(results["response_code"])
                return results["data"]
        return False
    def render_api(self, request, session, data_type, attributes=None, meta=None, included=None,
                   response_code=None):
        """
        Renders content to an API based client.
        :param request:
        :param session:
        :param data_type:
        :param attributes: A dictionary or list of dictionaries
        :param meta:
        :param included:
        :param response_code:
        :return:
        """
        if attributes is None:
            raise YomboWarning("Attributes is required for rendering to API.")

        response = {}

        if isinstance(attributes, list):
            response["data"] = []
            for item in attributes:
                response["data"].append({
                    "type": data_type,
                    "id": item["id"],
                    "attributes": item,
                })
        elif isinstance(attributes, dict):
            response["data"] = {
                "type": data_type,
                "id": attributes["id"],
                "attributes": attributes,
            }
        else:
            raise YomboWarning("Attributes must be a dictionary or list of dictionaries.")

        if included is not None:
            response["included"] = included
        if meta is not None:
            response["meta"] = meta

        if response_code is None:
            response_code = 200

        request.setResponseCode(response_code)
        request.setHeader("Content-Type", CONTENT_TYPE_JSON)
        idempotence = request.getHeader("x-idempotence")
        if idempotence is None:
            arguments = args_to_dict(request.args)
            idempotence = arguments.get("_idempotence", None)
        if idempotence is not None:
            idempotence = sha256_compact(f"{session.auth_id}:{idempotence}")
            self.idempotence[idempotence] = zlib.compress(msgpack.packb(json.dumps(
                {
                    "data": response,
                    "response_code": response_code,
                }
            )))
        return json.dumps(response)
Example #5
0
    def check_destination(self, destination, file_id, mangle_name):
        """
        Checks the destinations and returns three items within a list:
        1) urlparsed results from the destination
        2) urlparse results from destination meant for thumbnails.
        3) an extra random id that is used to further hide the URL of the resource.

        :param destination:
        :param file_id:
        :param mangle_name:
        :return:
        """
        # print(f"storage: save file dest: {destination}")
        # print(f"storage: manglename: {mangle_name}")
        mangle_id = sha224_compact(random_string(length=100))[0:20]
        if mangle_name > 0:
            folder, filename = ntpath.split(destination)
            file, extension = path.splitext(filename)
            if mangle_name == 1:
                destination = f"{folder}/{file}_{file_id}_{mangle_id}{extension}"
                destination_thumb = f"{folder}/{file}_{file_id}_{mangle_id}_thumb{extension}"
            if mangle_name == 2:
                destination = f"{folder}/{file_id}_{mangle_id}{extension}"
                destination_thumb = f"{folder}/{file_id}_{mangle_id}_thumb{extension}"
            if mangle_name == 3:
                destination = f"{folder}/{file_id}_{mangle_id}"
                destination_thumb = f"{folder}/{file_id}_{mangle_id}_thumb"
            if mangle_name == 4:
                new_filename = sha256_compact(random_string(length=200))
                destination = f"{folder}/{new_filename}{extension}"
                destination_thumb = f"{folder}/{new_filename}{extension}_thumb"
            if mangle_name >= 5:
                new_filename = sha256_compact(random_string(length=200))
                destination = f"{folder}/{new_filename}"
                destination_thumb = f"{folder}/{new_filename}_thumb"

            # print(f"storage: save file new dest: {destination}")
        dest_parts = urlparse(destination)
        scheme = dest_parts.scheme
        if scheme not in self.storage:
            raise KeyError(f"Unknown file storage location type: {scheme}")
        dest_parts_thumb = urlparse(destination_thumb)
        return dest_parts, dest_parts_thumb, mangle_id
Example #6
0
    def decode_message(self, topic, raw_message):
        """
        Decode a message from another gateway.

        :param payload: Dictionary to send.
        :param destination_id:
        :return:
        """
        # ybo_req/src_gwid/dest_gwid
        topic_parts = topic.split("/", 3)

        message = data_unpickle(raw_message, encoder="msgpack_base85")

        required_keys = ("body", "hash")
        if all(required in message for required in required_keys) is False:
            raise YomboWarning("MQTT Gateway is dropping message, missing a required message field.")

        message_hash = message["hash"]
        generated_hash = sha256_compact(message["body"])
        if message_hash != generated_hash:
            raise YomboWarning("Invalid incoming check hash.")

        message["body"] = data_unpickle(message["body"], encoder="msgpack_base85")
        message["body"]["time_received"] = time()
        required_keys = ("payload", "time_sent", "source_id", "destination_id", "message_id",
                         "component_type", "component_name", "reply_to", "protocol_version")
        if all(required in message["body"] for required in required_keys) is False:
            raise YomboWarning("MQTT Gateway is dropping message, missing a required body field.")

        body = message["body"]

        if body["source_id"] != topic_parts[1]:
            raise YomboWarning("Gateway source_id doesn't match topic source_id")
        if body["destination_id"] != topic_parts[2]:
            raise YomboWarning("Gateway destination_id doesn't match topic destination_id")

        return message
 def _do_sync_config(self):
     print("auth key: do_sync_config")
     tosave = {
         "source": self.source,
         "label": self.label,
         "description": self.description,
         # "auth_data": self.auth_data,
         "enabled": self.enabled,
         "roles": list(self.roles),
         "auth_id": self.auth_id,
         "created_by": self.created_by,
         "created_by_type": self.created_by_type,
         "last_access_at": self.last_access_at,
         "created_at": self.created_at,
         "updated_at": self.updated_at,
         "item_permissions": self.item_permissions,
         "saved_permissions": self.item_permissions
     }
     self._Parent._Configs.set("rbac_authkeys",
                               sha256_compact(self.auth_id),
                               data_pickle(tosave,
                                           encoder="msgpack_base64",
                                           local=True),
                               ignore_case=True)
    def generate_csr(self, args):
        """
        This function shouldn't be called directly. Instead, use the queue
        "self.generate_csr_queue.put(request, callback, callback_args)" or
        "self._SSLCerts.generate_csr_queue.put()".
        
        Requests certs to be made. Will return right away with a request ID. A callback can be set to return
        the cert once it's complete.

        :return:
        """
        logger.debug("Generate_CSR called with args: {args}", args=args)
        kwargs = self.check_csr_input(args)

        if kwargs["key_type"] == "rsa":
            kwargs["key_type"] = crypto.TYPE_RSA
        else:
            kwargs["key_type"] = crypto.TYPE_DSA

        req = crypto.X509Req()
        req.get_subject().CN = kwargs["cn"]
        req.get_subject().countryName = "US"
        req.get_subject().stateOrProvinceName = "California"
        req.get_subject().localityName = "Sacramento"
        req.get_subject().organizationName = "Yombo"
        req.get_subject(
        ).organizationalUnitName = "Gateway " + self.gateway_id[0:15]

        # Appends SAN to have "DNS:"
        if kwargs["sans"] is not None:
            san_string = []
            for i in kwargs["sans"]:
                san_string.append(f"DNS: {i}")
            san_string = ", ".join(san_string)
            x509_extensions = [
                crypto.X509Extension(b"subjectAltName", False,
                                     unicode_to_bytes(san_string))
            ]
            req.add_extensions(x509_extensions)

        start = time()
        key = yield threads.deferToThread(
            self._generate_key, **{
                "key_type": kwargs["key_type"],
                "key_size": kwargs["key_size"]
            })
        duration = round(float(time()) - start, 4)
        self._Events.new("sslcerts", "generate_new",
                         (args["sslname"], kwargs["cn"], san_string, duration))

        req.set_pubkey(key)

        req.sign(key, "sha256")

        csr = crypto.dump_certificate_request(crypto.FILETYPE_PEM, req)
        key_file = crypto.dump_privatekey(crypto.FILETYPE_PEM, key)

        if kwargs["csr_file"] is not None:
            yield save_file(kwargs["csr_file"], csr)
        if kwargs["key_file"] is not None:
            yield save_file(kwargs["key_file"], key_file)

        return {
            "csr": csr,
            "csr_hash": sha256_compact(unicode_to_bytes(csr)),
            "key": key_file
        }
    def update_attributes(self, attributes):
        """
        Update various attributes. Should only be used by the SQLCerts system when loading updated things from
        a library or module.

        The attributes have already been screened by the parent.

        :param attributes:
        :return:
        """
        if "update_callback" in attributes:
            self.update_callback = attributes["update_callback"]
        if "update_callback_type" in attributes:
            self.update_callback_type = attributes["update_callback_type"]
        if "update_callback_component" in attributes:
            self.update_callback_component = attributes["update_callback_component"]
        if "update_callback_function" in attributes:
            self.update_callback_function = attributes["update_callback_function"]

        if "key_size" in attributes:
            self.key_size = int(attributes["key_size"]) if attributes["key_size"] else None
        if "key_type" in attributes:
            self.key_type = attributes["key_type"]

        if "current_cert" in attributes:
            self.current_cert = attributes["current_cert"]
        if "current_chain" in attributes:
            self.current_chain = attributes["current_chain"]
        if "current_key" in attributes:
            self.current_key = attributes["current_key"]
        self.set_crypto()

        if "current_status" in attributes:
            self.current_status = attributes["current_status"]
        if "current_status_msg" in attributes:
            self.current_status_msg = attributes["current_status_msg"]
        if "current_csr_hash" in attributes:
            self.current_csr_hash = attributes["current_csr_hash"]
        if "current_created_at" in attributes:
            self.current_created_at = int(attributes["current_created_at"]) if attributes["current_created_at"] else None
        if "current_expires_at" in attributes:
            self.current_expires_at = int(attributes["current_expires_at"]) if attributes["current_expires_at"] else None
        if "current_signed_at" in attributes:
            self.current_signed_at = int(attributes["current_signed_at"]) if attributes["current_signed_at"] else None
        if "current_submitted_at" in attributes:
            self.current_submitted_at = int(attributes["current_submitted_at"]) if attributes["current_submitted_at"] else None
        if "current_fqdn" in attributes:
            self.current_fqdn = attributes["current_fqdn"]
        if "current_is_valid" in attributes:
            self.current_is_valid = attributes["current_is_valid"]

        if "next_status" in attributes:
            self.next_status = attributes["next_status"]
        if "next_status_msg" in attributes:
            self.next_status_msg = attributes["next_status_msg"]
        if "next_csr_hash" in attributes:
            self.next_csr_hash = attributes["next_csr_hash"]
        if "next_csr" in attributes:
            self.next_csr = attributes["next_csr"]
        if "next_cert" in attributes:
            self.next_cert = attributes["next_cert"]
        if "next_chain" in attributes:
            self.next_chain = attributes["next_chain"]
        if "next_key" in attributes:
            self.next_key = attributes["next_key"]
        if "next_created_at" in attributes:
            self.next_created_at = int(attributes["next_created_at"]) if attributes["next_created_at"] else None
        if "next_expires_at" in attributes:
            self.next_expires_at = int(attributes["next_expires_at"]) if attributes["next_expires_at"] else None
        if "next_signed_at" in attributes:
            self.next_signed_at = int(attributes["next_signed_at"]) if attributes["next_signed_at"] else None
        if "next_submitted_at" in attributes:
            self.next_submitted_at = int(attributes["next_submitted_at"]) if attributes["next_submitted_at"] else None
        if "next_fqdn" in attributes:
            self.next_fqdn = attributes["next_fqdn"]
        if "next_is_valid" in attributes:
            self.next_is_valid = attributes["next_is_valid"]

        # do some back checks.
        if self.next_csr is not None and self.next_csr_hash is None:
            self.next_csr_hash = sha256_compact(unicode_to_bytes(self.next_csr))
        self.dirty = True