Esempio n. 1
0
class StoreSSR(Resource):
    def __init__(self):
        super(StoreSSR, self).__init__()
        config = current_app.config
        self.helpers = Helpers(config)
        self.service_url = config["SERVICE_URL"]


    @timeme
    @error_handler
    @api_logging
    def post(self):
        # TODO: This is as naive as it gets, needs some verifications regarding ssr,
        # or are we leaving this to firewalls, eg. Only this host(operator) can use this endpoint.
        try:
            self.helpers.store_ssr_JSON(json=request.json["data"])
            endpoint = "/api/1.3/slr/store_ssr"
            debug_log.info("Posting SLR for storage in Service Mockup")
            result = post("{}{}".format(self.service_url, endpoint), json=request.json)  # Send copy to Service_Components
            return {"id":request.json["data"]["id"]}, 201
        except Exception as e:
            debug_log.exception(e)
            raise e
Esempio n. 2
0
class StoreSLR(Resource):
    def __init__(self):
        super(StoreSLR, self).__init__()
        config = current_app.config
        keysize = config["KEYSIZE"]
        cert_key_path = config["CERT_KEY_PATH"]
        self.helpers = Helpers(config)
        self.service_key = self.helpers.get_key()

        self.protti = self.service_key["prot"]
        self.headeri = self.service_key["header"]

        self.service_url = config["SERVICE_URL"]
        self.operator_url = config["OPERATOR_URL"]


    @timeme
    @error_handler
    @api_logging
    def post(self):

        def decode_payload(payload):
            sq.task("Fix possible incorrect padding in payload")
            payload += '=' * (-len(payload) % 4)  # Fix incorrect padding of base64 string.
            debug_log.info("After padding fix :{}".format(payload))

            sq.task("Decode SLR payload and store it into object")
            debug_log.info(payload.encode())
            content = decode(payload.encode())

            sq.task("Load decoded payload as python dict")
            payload = loads(content.decode("utf-8"))
            debug_log.info("Decoded SLR payload:")
            debug_log.info(type(payload))
            debug_log.info(dumps(payload, indent=2))
            return payload

        try:
            sq.task("Load SLR to object")
            slr = request.json["slr"]
            debug_log.info("SLR STORE:\n", slr)

            sq.task("Load slr payload as object")
            payload = slr["payload"]
            debug_log.info("Before padding fix:{}".format(payload))

            payload = decode_payload(payload)

            sq.task("Fetch surrogate_id from decoded SLR payload")
            surrogate_id = payload["surrogate_id"].encode()

            sq.task("Load code from json payload")
            code = request.json["data"]["code"].encode()
            debug_log.info("SLR payload contained code: {}".format(code))

            sq.task("Verify surrogate_id and code")
            debug_log.info("Surrogate {} has been verified for code {}.".format(self.helpers.verifySurrogate(code, surrogate_id), code))

        except Exception as e:
            raise DetailedHTTPException(title="Verifying Surrogate ID failed",
                                        exception=e,
                                        trace=traceback.format_exc(limit=100).splitlines())

        try:
            sq.task("Create empty JSW object")
            jwssa = jws.JWS()
            debug_log.info("SLR Received:\n"+(dumps(slr, indent=2)))

            sq.task("Deserialize slr to JWS object created before")
            jwssa.deserialize(dumps(slr))

            sq.task("Load JWK used to sign JWS from the slr payload's cr_keys field into an object")
            sign_key = jwk.JWK(**payload["cr_keys"][0])

            sq.task("Verify SLR was signed using the key shipped with it")
            debug_log.info(self.helpers.verifyJWS(slr))
            verify = jwssa.verify(sign_key)  # Verifying changes the state of this object
        except Exception as e:
            raise DetailedHTTPException(title="Verifying JWS signature failed",
                                        exception=e,
                                        trace=traceback.format_exc(limit=100).splitlines())

        try:
            sq.task("Fix possible serialization errors in JWS")
            faulty_JSON = loads(jwssa.serialize(compact=False))  # For some reason serialization messes up "header" from "header": {} to "header": "{}"
            faulty_JSON["header"] = faulty_JSON["header"]

            sq.task("Add our signature in the JWS")
            key = jwk.JWK(**self.service_key["key"])
            jwssa.add_signature(key, header=dumps(self.headeri), protected=dumps(self.protti))

            sq.task("Fix possible header errors")
            fixed = header_fix(loads(jwssa.serialize(compact=False)))
            debug_log.info("{}\n{}\n{}".format("Verified and Signed Signature:\n", dumps(fixed, indent=3),
                                               "\n###### END OF SIGNATURE #######"))

            sq.task("Create template for verifying JWS at Operator_Components")
            req = {"data": {"code": code}, "slr": fixed}
            debug_log.info(dumps(req, indent=2))
        except Exception as e:
            raise DetailedHTTPException(exception=e,
                                        title="JWS fix and subsequent signing of JWS with out key failed.",
                                        trace=traceback.format_exc(limit=100).splitlines())

        sq.send_to("Operator_Components Mgmnt", "Verify SLR(JWS)")
        endpoint = "/api/1.3/slr/verify"
        result = post("{}{}".format(self.operator_url, endpoint), json=req)
        debug_log.info("Sent SLR to Operator for verification, results:")
        debug_log.info("status code:{}\nreason: {}\ncontent: {}".format(result.status_code, result.reason, result.content))

        if result.ok:
            sq.task("Store following SLR into db")
            store = loads(result.text)
            slr_store = loads(result.text)["data"]["slr"]
            ssr_store = loads(result.text)["data"]["ssr"]
            debug_log.debug("Storing following SLR and SSR:")
            debug_log.debug(dumps(slr_store, indent=2))
            debug_log.debug(dumps(ssr_store, indent=2))
            payload = decode_payload(slr_store["attributes"]["payload"])
            if surrogate_id == payload["surrogate_id"]:
                self.helpers.store_slr_JSON(json=slr_store, slr_id=payload["link_id"], surrogate_id=payload["surrogate_id"])
                self.helpers.store_ssr_JSON(json=ssr_store)
                endpoint = "/api/1.3/slr/store_slr"
                debug_log.info("Posting SLR for storage in Service Mockup")
                result = post("{}{}".format(self.service_url, endpoint), json=store)  # Send copy to Service_Components
                # TODO: incase this fails we should try again.
            else:
                raise DetailedHTTPException(status=500,
                                            detail={
                                                "msg": "Surrogate id mismatch",
                                                "surrogate id's didn't match between requests.": loads(result.text)},
                                            title=result.reason)
        else:
            raise DetailedHTTPException(status=result.status_code,
                                        detail={"msg": "Something went wrong while verifying SLR with Operator_SLR.",
                                                "Error from Operator_SLR": loads(result.text)},
                                        title=result.reason)
        return store, 201

    @timeme
    @error_handler
    @api_logging
    def get(self):  # Fancy but only used for testing. Should be disabled/removed in production.
        sq.task("Debugging endpoint, fetch SLR's from db and return")
        jsons = {"jsons": {}}
        for storage_row in self.helpers.query_db("select * from storage;"):
            debug_log.info(storage_row["json"])
            jsons["jsons"][storage_row["surrogate_id"]] = loads(storage_row["json"])

        sq.reply_to("Operator_Components Mgmnt", "Return SLR's from db")
        return jsons