def delete(self, account_id, code): AM = get_am(current_app, request.headers) key_check = AM.verify_user_key(account_id) debug_log.info("Verifying User Key resulted: {}".format(key_check)) sq.task("Load json payload as object") js = request.json sq.task("Load account_id from database") code = js["code"] try: stored_session_from_db = self.helper.restore_session(code) except TypeError as e: debug_log.info("Failed restoring session from DB with code '{}'".format(code)) debug_log.exception(e) raise DetailedHTTPException(status=403, detail={"msg": "Invalid or expired session"}, title="Invalid session") debug_log.debug("The session data contains: {}".format(stored_session_from_db)) session_data = loads(stored_session_from_db) debug_log.debug("{} {}".format(type(stored_session_from_db), stored_session_from_db)) account_id_from_session = session_data["account_id"] if account_id_from_session == account_id: self.helper.delete_session(code) return {"msg": {"status": "deleted", "id": code}}, 200
def get(self, cr_id): '''get :return: Returns Auth_token to service ''' ## # Generate Auth Token and save it. # helper.py has the function template, look into it. ## am = get_am(current_app, request.headers) try: sq.opt("Generate Auth Token") sq.message_from("SrvMgmtsink", "GET AuthToken") sq.activate() sq.send_to("acc", "Get AuthTokenInfo") result = am.get_AuthTokenInfo(cr_id) sq.reply_from("acc", "AuthTokenInfo") except AttributeError as e: raise DetailedHTTPException( status=502, title= "It would seem initiating Account Manager Handler has failed.", detail="Account Manager might be down or unresponsive.", trace=traceback.format_exc(limit=100).splitlines()) debug_log.info( "Account Manager gave following Auth Token Info:\n{}".format( dumps(result, indent=2))) sq.task("Generate AuthToken") token = self.gen_auth_token(result) debug_log.info("Generated auth token: {}".format(token)) sq.reply_to("SrvMgmtsink", "AuthToken") sq.deactivate() sq.opt(end=True) return {"auth_token": token}
def post(self): try: sq.task("Load json payload as object") js = request.json sq.task("Load account_id and service_id from database") code = js["code"] try: stored_session_from_db = self.helpers.restore_session(code) except TypeError as e: debug_log.info( "Failed restoring session from DB with code '{}'".format( code)) debug_log.exception(e) raise DetailedHTTPException( status=403, detail={"msg": "Invalid or expired session"}, title="Invalid session") debug_log.debug( "Type of session data fetched from db is: {}".format( type(stored_session_from_db))) debug_log.debug( "The session data contains: {}".format(stored_session_from_db)) session_data = loads(stored_session_from_db) debug_log.debug("{} {}".format(type(stored_session_from_db), stored_session_from_db)) account_id = session_data["account_id"] # Get Account Manager Handler AM = get_am(current_app, request.headers) key_check = AM.verify_user_key(account_id, user_key=session_data["user_key"]) debug_log.info("Verifying User Key resulted: {}".format(key_check)) self.payload["service_id"] = session_data["service_id"] service_info = self.service_registry_handler.getService( self.payload["service_id"]) # TODO: Use serviceType field added into ServiceDescription service_type = service_info["serviceDescription"][ "serviceDataDescription"][0]["dataset"][0]["serviceDataType"] # Check Surrogate_ID exists. # Fill token_key try: sq.task( "Verify surrogate_id and token_key exist in the payload json" ) self.payload["surrogate_id"] = js["surrogate_id"] #self.payload["token_key"] = {"key": token_key} if service_type == "input" or service_type == "both": sq.task( "Store surrogate_id and keys for CR steps later on.") token_key = js[ "token_key"] # Todo: source has no need to send this, make the difference. service_keys = { "token_key": token_key, "pop_key": token_key } self.helpers.store_service_key_json( kid=token_key["kid"], surrogate_id=js["surrogate_id"], key_json=service_keys, service_id=service_info["id"]) except Exception as e: debug_log.exception(e) if "code" in locals(): self.helper.delete_session(code) raise DetailedHTTPException( exception=e, detail={ "msg": "Received Invalid JSON that may not contain surrogate_id", "json": js }) # Create template # TODO: Currently you can generate endlessly new slr even if one exists already if service_type == "input" or service_type == "both": result = AM.init_slr(code, pop_key=token_key) else: result = AM.init_slr(code) self.payload["link_id"] = result self.payload["iat"] = int(time.time()) sq.task("Fill template for Account Manager") template = { "code": code, "data": { "type": "ServiceLinkRecord", "attributes": self.payload } } debug_log.info("########### Template for Account Manager #") debug_log.info(dumps(template, indent=2)) debug_log.info("########################################") sq.send_to("Account Manager", "Sign SLR at Account Manager") try: reply = AM.sign_slr(template, account_id) except AttributeError as e: self.helpers.delete_session(code) raise DetailedHTTPException( status=502, title= "It would seem initiating Account Manager Handler has failed.", detail="Account Manager might be down or unresponsive.", trace=traceback.format_exc(limit=100).splitlines()) debug_log.info(dumps(reply, indent=2)) # Parse JSON form Account Manager to format Service_Mgmnt understands. try: req = { "data": { "code": code, }, "slr": reply["data"]["attributes"] } debug_log.info( "SLR in format sent to Service Mgmnt: {}".format( dumps(req, indent=2))) except Exception as e: raise DetailedHTTPException( exception=e, detail="Parsing JSON form Account Manager " "to format Service_Mgmnt understands has failed.", trace=traceback.format_exc(limit=100).splitlines()) try: sq.send_to( "Service_Components Mgmnt", "Send created and signed SLR to Service_Components Mgmnt") endpoint = "/api/1.3/slr/slr" # TODO Where do we get this endpoint? service_url = self.service_registry_handler.getService_url( self.payload["service_id"].encode()) debug_log.info("Service_ulr = {}, type: {}".format( service_url, type(service_url))) response = post("{}{}".format(service_url, endpoint), json=req, timeout=self.request_timeout) debug_log.info( "Service Mgmnt replied with status code ({})".format( response.status_code)) if not response.ok: self.helpers.delete_session(code) raise DetailedHTTPException( status=response.status_code, detail={ "Error from Service_Components Mgmnt": loads(response.text) }, title=response.reason) except DetailedHTTPException as e: raise e except Exception as e: self.helpers.delete_session(code) raise DetailedHTTPException( exception=e, detail="Sending SLR to service has failed", trace=traceback.format_exc(limit=100).splitlines()) except DetailedHTTPException as e: if "code" in locals(): self.helpers.delete_session(code) raise e except Exception as e: if "code" in locals(): self.helpers.delete_session(code) raise DetailedHTTPException( title="Creation of SLR has failed.", exception=e, trace=traceback.format_exc(limit=100).splitlines()) # SLR is made at this point and returned to the Service Mgmnt, session can be deleted. if "code" in locals(): self.helpers.delete_session(code) return loads(response.text), 201
def post(self): sq.task("Load SLR to object") slr = request.json["slr"] debug_log.info("{} {}".format("SLR from request payload json:\n", slr)) sq.task("Load slr payload as object") slr_payload = slr["payload"] debug_log.info("{} {}".format("Payload before fix:", slr_payload)) sq.task("Fix possible incorrect padding in payload") slr_payload += '=' * (-len(slr_payload) % 4) # Fix incorrect padding of base64 string. debug_log.info("{} {}".format("Payload after fix :", slr_payload)) sq.task("Decode slr payload to a string and store it into variable") content = decode(slr_payload.encode()) sq.task("Load slr payload string as python dict") slr_payload = loads(content.decode("utf-8")) debug_log.info(slr_payload) debug_log.info(type(slr_payload)) sq.task("Fetch code from request") code = request.json["data"]["code"] debug_log.info("Found code {} from request".format(code)) try: ## # Verify SLR with key from Service_Components Management ## sq.task("Load account_id from database") query = self.Helpers.query_db("select * from session_store where code=%s;", (code,)) session_data = loads(query) account_id = session_data["account_id"] AM = get_am(current_app, request.headers) key_check = AM.verify_user_key(account_id, user_key=session_data["user_key"]) debug_log.info("Verifying User Key resulted: {}".format(key_check)) debug_log.info("################Verify########################") debug_log.info(dumps(request.json)) debug_log.info("########################################") sq.send_to("Account Manager", "Verify SLR at Account Manager.") try: reply = AM.verify_slr(slr_payload, code, slr, account_id) except AttributeError as e: raise DetailedHTTPException(status=500, title="Verification of SLR failed", detail="SLR verification has failed.", trace=traceback.format_exc(limit=100).splitlines()) if reply.ok: # TODO: Should session db be cleared here? sq.reply_to("Service_Components Mgmnt", "201, SLR VERIFIED") debug_log.info("Account Manager replied {} with content:\n{}".format(reply.status_code, reply.text)) return reply.text, reply.status_code else: raise DetailedHTTPException(status=reply.status_code, detail={ "msg": "Something went wrong while verifying SLR at Account Manager", "content": reply.json()}, title=reply.reason ) except DetailedHTTPException as e: raise e except Exception as e: raise DetailedHTTPException(exception=e, detail="Verifying SLR failed for unknown reason, access is denied.")
def get(self, account_id): """get :return: Returns Consent form to UI for user input. """ sq.opt("UI Gets Consent Form from Operator") sq.activate() sq.message_from("OpUi", "GET Consent Form") sq.task("Verify MyData Account Key") am = get_am(current_app, request.headers) key_check = am.verify_user_key(account_id) debug_log.info("Verifying User Key resulted: {}".format(key_check)) _consent_form = Consent_form_Out service_ids = request.args # Check that We don't have existing Active Consent between the two services sq.task( "Check for existing SLR's and that no Active CR exist for the service pair." ) am.check_existing_consent(service_id_sink=service_ids["sink"], service_id_source=service_ids["source"], account_id=account_id) sq.send_to("SrvReg", "Fetch service descriptions.") sq.reply_from("SrvReg", "Service Description.") sq.task("Create Consent Form template.") sink = self.getService(service_ids["sink"]) _consent_form["sink"]["service_id"] = sink["serviceId"] _consent_form["sink"]["dataset"] = [] # Clear out template. for dataset in sink["serviceDescription"]["serviceDataDescription"][0][ "dataset"]: item = { "dataset_id": dataset["datasetId"], "title": dataset["title"], "description": dataset["description"], "keyword": dataset["keyword"], "publisher": dataset["publisher"], "purposes": [{ "title": purpose, "selected": "Bool", "required": "Bool" } for purpose in dataset["purpose"]] } _consent_form["sink"]["dataset"].append(item) source = self.getService(service_ids["source"]) _consent_form["source"]["service_id"] = source["serviceId"] _consent_form["source"]["dataset"] = [] # Clear out template. for dataset in source["serviceDescription"]["serviceDataDescription"][ 0]["dataset"]: item = { "dataset_id": dataset["datasetId"], "title": dataset["title"], "description": dataset["description"], "keyword": dataset["keyword"], "publisher": dataset["publisher"], "distribution": { "distribution_id": dataset["distribution"][0]["distributionId"], "access_url": "{}{}{}".format( source["serviceInstance"][0]["domain"], source["serviceInstance"][0]["serviceAccessEndPoint"] ["serviceAccessURI"], dataset["distribution"][0]["accessURL"]), }, "component_specification_label": dataset["title"], "selected": "Bool" } _consent_form["source"]["dataset"].append(item) sq.task("Generate RS_ID for the template.") source_domain = source["serviceInstance"][0]["domain"] rs_id = self.Helpers.gen_rs_id(source_domain) sq.task("Store generated RS_ID") _consent_form["source"]["rs_id"] = rs_id sq.reply_to("OpUi", "Return Consent Form+RS_ID") sq.deactivate() sq.opt(end=True) return _consent_form
def post(self, account_id): """post :return: Returns 201 when consent has been created """ sq.opt("Operator Receives ConsentForm and creates CR/CSR") sq.message_from("OpUi", "POST ConsentForm") sq.activate() sq.task("Verify MyData Account Key") am = get_am(current_app, request.headers) key_check = am.verify_user_key(account_id) debug_log.info("Verifying User Key resulted: {}".format(key_check)) _consent_form = request.json sink_srv_id = _consent_form["sink"]["service_id"] source_srv_id = _consent_form["source"]["service_id"] # Check that We don't have existing Active Consent between the two services am.check_existing_consent(service_id_sink=sink_srv_id, service_id_source=source_srv_id, account_id=account_id) sq.task("Validate RS_ID in ConsentForm") # Validate RS_ID (RS_ID exists and not used before) if self.Helpers.validate_rs_id(_consent_form["source"]["rs_id"]): self.Helpers.store_consent_form( _consent_form) # Store Consent Form else: raise DetailedHTTPException(title="RS_ID Validation error.", detail="RS_ID could not be validated.", status=403) sq.send_to("acc", "GET surrogate_id & slr_id") # Get slr and surrogate_id slr_id_sink, surrogate_id_sink = am.get_surrogate_and_slr_id( account_id, sink_srv_id) # One for Sink, one for Source slr_id_source, surrogate_id_source = am.get_surrogate_and_slr_id( account_id, source_srv_id) sq.reply_from("acc", "surrogate_id & slr_id") sq.task("Fetch sink_keys's") sink_keys = self.Helpers.get_service_keys(surrogate_id_sink) try: # TODO: We technically support fetching multiple keys, but use only 1 sink_key = loads(sink_keys[0]) except IndexError as e: raise DetailedHTTPException( status=500, title="Fetching service keys for sink has failed.", detail="Couldn't find keys for surrogate id ({}).".format( surrogate_id_sink), trace=traceback.format_exc(limit=100).splitlines()) debug_log.info("Sink keys:\n{}".format(dumps(sink_key, indent=2))) sink_pop_key = sink_key["pop_key"] # Generate common_cr for both sink and source. sq.task("Generate common CR") issued = int( time.time()) #datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ") # TODO: Not before and not after are Optional. Verify who says when to put them? not_before = int( time.time()) #datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ") not_after = int( time.time() + current_app.config["NOT_AFTER_INTERVAL"] ) #datetime.fromtimestamp(time.time()+current_app.config["NOT_AFTER_INTERVAL"]).strftime("%Y-%m-%dT%H:%M:%SZ") operator_id = current_app.config["UID"] common_cr_source = self.Helpers.gen_cr_common( surrogate_id_source, _consent_form["source"]["rs_id"], slr_id_source, issued, not_before, not_after, source_srv_id, operator_id, "Source") common_cr_sink = self.Helpers.gen_cr_common( surrogate_id_sink, _consent_form["source"]["rs_id"], slr_id_sink, issued, not_before, not_after, sink_srv_id, operator_id, "Sink") sq.task("Generate ki_cr") ki_cr = self.Helpers.Gen_ki_cr(self) # TODO: Implement sq.task("Generate CR for sink") sink_cr = self.Helpers.gen_cr_sink(common_cr_sink, _consent_form, ki_cr, common_cr_source["cr_id"]) sq.task("Generate CR for source") source_cr = self.Helpers.gen_cr_source(common_cr_source, _consent_form, ki_cr, sink_pop_key) sink_cr["cr"]["common_part"]["rs_description"] = source_cr["cr"][ "common_part"]["rs_description"] debug_log.info("CR generated for sink:\n{}".format(sink_cr)) debug_log.info("CR generated for source:\n{}".format(source_cr)) sq.task("Generate CSR's") sink_csr = self.Helpers.gen_csr(surrogate_id_sink, sink_cr["cr"]["common_part"]["cr_id"], "Active", "null") source_csr = self.Helpers.gen_csr( surrogate_id_source, source_cr["cr"]["common_part"]["cr_id"], "Active", "null") sq.send_to("acc", "Send CR/CSR to sign and store") result = am.signAndstore(sink_cr, sink_csr, source_cr, source_csr, account_id) sq.reply_from("acc", "Signed Sink and Source CR/CSR") debug_log.info( "CR/CSR structure the Account Manager signed:\n{}".format( dumps(result, indent=2))) sink_cr = result["data"]["sink"]["consent_record"]["attributes"] sink_csr = result["data"]["sink"]["consent_status_record"][ "attributes"] source_cr = result["data"]["source"]["consent_record"]["attributes"] source_csr = result["data"]["source"]["consent_status_record"][ "attributes"] crs_csrs_payload = { "sink": { "cr": sink_cr, "csr": sink_csr }, "source": { "cr": source_cr, "csr": source_csr } } debug_log.info("CR/CSR payload sent to celery task" " for sending to services:\n{}".format( dumps(crs_csrs_payload, indent=2))) sq.send_to("SrvMgmtsink", "Post CR-Sink, CSR-Sink") sq.send_to("SrvMgmtsource", "Post CR-Source, CSR-Source") CR_installer.delay(crs_csrs_payload, self.SH.getService_url(sink_srv_id), self.SH.getService_url(source_srv_id)) sq.reply_to("OpUi", "Sink & Source cr_id") sq.deactivate() return { "data": { "attributes": { "sink_cr_id": common_cr_sink["cr_id"], "source_cr_id": common_cr_source["cr_id"] }, "type": "ConsentRecordIDs", } }, 201
def post(self, account_id, service_id, slr_id): """ :param slr_id: Id of SLR we want to change :param account_id: Account Manager user id :param service_id: Service id as in Service Registry """ service_url = self.service_registry_handler.getService_url(service_id) try: am = get_am(current_app, request.headers) # Verify Api-Key-User key_check = am.verify_user_key(account_id) debug_log.info("Verifying User Key resulted: {}".format(key_check)) try: # Get SLR slr = am.get_slr(slr_id, account_id) decoded_slr = base_token_tool.decode_payload( slr["data"]["attributes"]["payload"]) surrogate_id = decoded_slr["surrogate_id"] last_ssr = am.get_last_slr_status(slr_id) last_ssr_payload = base_token_tool.decode_payload( last_ssr["data"]["attributes"]["payload"]) if last_ssr_payload["sl_status"] != "Active": raise TypeError("This SLR isn't Active to begin with.") prev_record_id = last_ssr_payload["record_id"] debug_log.info( "Got Decoded SLR Payload:\n {}".format(decoded_slr)) consents = am.get_crs(slr_id, account_id, pairs=True)["data"] # Loop trough the consents and fetch pairs. # Step redundant since endpoint at Account gives us paired consent as well. except Exception as e: raise e self.helper.change_cr_pair_status(slr_id, account_id, am, self.service_registry_handler, "Withdrawn") try: # Create new SLR status created_ssr = am.create_ssr( surrogate_id=surrogate_id, slr_id=slr_id, sl_status="Removed", prev_record_id=prev_record_id, ) except Exception as e: raise e try: # Notify Service of SLR status chanege endpoint = "/api/1.3/slr/status" req = post(service_url + endpoint, json=created_ssr) debug_log.debug( "Posted SSR to service:\n{} {} {} {}".format( req.status_code, req.reason, req.text, req.content)) return created_ssr, 201 except Exception as e: raise e except DetailedHTTPException as e: raise e except Exception as e: raise DetailedHTTPException( status=500, title="Something went really wrong during SLR Status Change.", detail="Error: {}".format(repr(e)), exception=e, trace=traceback.format_exc(limit=100).splitlines())
def post(self, acc_id, srv_id, cr_id, new_status): '''post :return: Change status of CR ''' sq.opt("Start CR status change.") sq.message_from("OpUi", "POST: Change CR status") sq.activate() sq.task("Verify new state is supported one.") try: allowed_states = ["Active", "Disabled", "Withdrawn"] if new_status in allowed_states: debug_log.info( "We received status change request for cr_id ({}) for srv_id ({}) on account ({})" .format(cr_id, srv_id, acc_id)) # How do we authorize this request? Who is allowed to make it? # Now only those who have Account User Key can successfully make this. # Get previous_csr_id am = get_am(current_app, request.headers) key_check = am.verify_user_key(acc_id) debug_log.info( "Verifying User Key resulted: {}".format(key_check)) link_id, surrogate_id = am.get_surrogate_and_slr_id( acc_id, srv_id) previous_csr = am.get_last_csr(cr_id, link_id) previous_csr_id = previous_csr["record_id"] previous_status = previous_csr["consent_status"] if previous_status == new_status: raise DetailedHTTPException( title="Unable to change consent status from {} to {}.". format(previous_csr["consent_status"], new_status), detail={ "msg": "Status change must happen from one state to another." }, status=409) elif previous_status == "Withdrawn": raise DetailedHTTPException( title="Unable to change consent status from {} to {}.". format(previous_csr["consent_status"], new_status), detail={"msg": "Status change to Withdrawn is final."}, status=409) csr = self.helper_object.change_cr_pair_status( link_id, acc_id, am, self.service_registry_handler, new_status) else: raise DetailedHTTPException( title="Unable to change consent status to {}.".format( new_status), detail={"msg": "Unsupported Status Change"}, status=409) except Exception as e: raise DetailedHTTPException( status=500, title="Consent Status Change Failed.", detail= "Server encountered unexpected error while trying consent status change," " please try again.", trace=traceback.format_exc(limit=100).splitlines()) return csr, 201
def get(self, account_id, service_id): """ :param account_id: Account Manager user id :param service_id: Service id as in Service Registry """ debug_log.info("#### Request to start SLR flow with parameters: account_id ({}), service_id ({})" .format(account_id, service_id)) try: AM = get_am(current_app, request.headers) key_check = AM.verify_user_key(account_id) debug_log.info("Verifying User Key resulted: {}".format(key_check)) # Check Active SLR for this account/service pair doesn't exist AM.check_for_existing_slr(service_id, account_id) # We need to store some session information for later parts of flow. session_information = {} sq.task("Fetch service address from Service Registry") service_json = self.service_registry_handler.getService(service_id) service_domain = service_json["serviceInstance"][0]["loginDomain"] # Domain to Login of Service service_access_uri = service_json["serviceInstance"][0]["serviceAccessEndPoint"]["serviceAccessURI"] service_login_uri = service_json["serviceInstance"][0]["loginUri"] sq.task("Generate code for session") code = str(guid()) debug_log.info("Session information contains: code {}, account id {} and service_id {}" .format(code, account_id, service_id)) sq.task("Store session_information to database") session_information[code] = {"account_id": account_id, "service_id": service_id, "user_key": request.headers["Api-Key-User"]} self.store_session(session_information) service_endpoint = "{}{}{}".format(service_domain, service_access_uri, service_login_uri) service_query = "?code={}&operator_id={}&return_url={}&linkingFrom={}".format( # TODO: Get return url from somewhere code, self.uid, urlsafe_b64encode(self.return_url), "Operator") debug_log.info("Redirect url with parameters:\n{}{}\nCode contains: {}".format(service_endpoint, service_query, code)) sq.send_to("UI(Operator)", "Redirect user to Service Mockup login") response = make_response(redirect(service_endpoint+service_query)) return response except DetailedHTTPException as e: debug_log.exception(e) if "code" in locals(): self.helper.delete_session(code) raise DetailedHTTPException(exception=e, title="SLR registration failed.", status=500, detail="Something failed during creation of SLR.", trace=traceback.format_exc(limit=100).splitlines()) except Exception as e: debug_log.exception(e) if "code" in locals(): self.helper.delete_session(code) raise DetailedHTTPException(status=500, title="Something went really wrong during SLR registration.", detail="Error: {}".format(repr(e)), exception=e, trace=traceback.format_exc(limit=100).splitlines())