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
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