예제 #1
0
    def __init__(self):
        super(RegisterSurrogate, self).__init__()
        self.app = current_app
        self.helpers = Helpers(self.app.config)
        operator_id = self.app.config["UID"]
        self.service_registry_handler = ServiceRegistryHandler(
            current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
            current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
        self.operator_key = self.helpers.get_key()
        self.request_timeout = self.app.config["TIMEOUT"]

        self.payload = \
            {
                "version": "1.3",
                "link_id": "",
                "operator_id": operator_id,
                "service_id": "",
                "surrogate_id": "",
                "operator_key": self.operator_key["pub"],
                "cr_keys": "",
                "iat": 0,  # Set below once we know link_id
            }
        debug_log.info("SLR payload in init is: \n{}".format(
            dumps(self.payload, indent=2)))
        self.service_registry_handler = ServiceRegistryHandler(
            current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
            current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
        self.am_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
        self.am_user = current_app.config["ACCOUNT_MANAGEMENT_USER"]
        self.am_password = current_app.config["ACCOUNT_MANAGEMENT_PASSWORD"]
        self.timeout = current_app.config["TIMEOUT"]
예제 #2
0
 def __init__(self):
     super(LinkingUi, self).__init__()
     self.helper = Helpers(current_app.config)
     self.account_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
     self.operator_id = current_app.config["OPERATOR_UID"]
     self.parser = reqparse.RequestParser()
     self.parser.add_argument('surrogate_id',
                              type=str,
                              help='Surrogate_id from a service.')
     self.parser.add_argument('service_id',
                              type=str,
                              help='ID of linking service.')
     self.parser.add_argument('username',
                              type=str,
                              help='Username for MyDataAccount')
     self.parser.add_argument('pword',
                              type=str,
                              help='Password for MyDataAccount')
     self.parser.add_argument('return_url',
                              type=str,
                              help='Url safe Base64 coded return url.')
     self.parser.add_argument('linkingFrom',
                              type=str,
                              help='Origin of the linking request(?)')
     self.store_session = self.helper.store_session
     self.service_registry_handler = ServiceRegistryHandler(
         current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
         current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
예제 #3
0
 def __init__(self):
     super(VerifySLR, self).__init__()
     self.app = current_app
     self.am_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
     self.am_user = current_app.config["ACCOUNT_MANAGEMENT_USER"]
     self.am_password = current_app.config["ACCOUNT_MANAGEMENT_PASSWORD"]
     self.timeout = current_app.config["TIMEOUT"]
     self.Helpers = Helpers(current_app.config)
예제 #4
0
 def __init__(self):
     super(StatusChange, self).__init__()
     self.am_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
     self.am_user = current_app.config["ACCOUNT_MANAGEMENT_USER"]
     self.am_password = current_app.config["ACCOUNT_MANAGEMENT_PASSWORD"]
     self.timeout = current_app.config["TIMEOUT"]
     self.helper_object = Helpers(current_app.config)
     self.service_registry_handler = ServiceRegistryHandler(
         current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
         current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
예제 #5
0
 def __init__(self):
     """
     
     """
     super(SlrStatus, self).__init__()
     self.service_registry_handler = ServiceRegistryHandler(
         current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
         current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
     self.request_timeout = current_app.config["TIMEOUT"]
     self.uid = current_app.config["UID"]
     self.helper = Helpers(current_app.config)
     self.store_session = self.helper.store_session
예제 #6
0
    def __init__(self):
        super(ConsentFormHandler, self).__init__()
        self.am_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
        self.am_user = current_app.config["ACCOUNT_MANAGEMENT_USER"]
        self.am_password = current_app.config["ACCOUNT_MANAGEMENT_PASSWORD"]
        self.timeout = current_app.config["TIMEOUT"]
        self.debug_mode = current_app.config["DEBUG_MODE"]

        self.SH = ServiceRegistryHandler(
            current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
            current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
        self.getService = self.SH.getService
        self.Helpers = Helpers(current_app.config)
        self.operator_url = current_app.config["OPERATOR_URL"]
예제 #7
0
 def __init__(self):
     super(AuthToken, self).__init__()
     self.am_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
     self.am_user = current_app.config["ACCOUNT_MANAGEMENT_USER"]
     self.am_password = current_app.config["ACCOUNT_MANAGEMENT_PASSWORD"]
     self.timeout = current_app.config["TIMEOUT"]
     helper_object = Helpers(current_app.config)
     self.gen_auth_token = helper_object.gen_auth_token
예제 #8
0
class CancelSlrFlow(Resource):
    def __init__(self):
        """

        """
        super(CancelSlrFlow, self).__init__()
        self.helper = Helpers(current_app.config)

    @error_handler
    @api_logging
    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
예제 #9
0
class RegisterSurrogate(Resource):
    def __init__(self):
        super(RegisterSurrogate, self).__init__()
        self.app = current_app
        self.helpers = Helpers(self.app.config)
        operator_id = self.app.config["UID"]
        self.service_registry_handler = ServiceRegistryHandler(
            current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
            current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
        self.operator_key = self.helpers.get_key()
        self.request_timeout = self.app.config["TIMEOUT"]

        self.payload = \
            {
                "version": "1.3",
                "link_id": "",
                "operator_id": operator_id,
                "service_id": "",
                "surrogate_id": "",
                "operator_key": self.operator_key["pub"],
                "cr_keys": "",
                "iat": 0,  # Set below once we know link_id
            }
        debug_log.info("SLR payload in init is: \n{}".format(
            dumps(self.payload, indent=2)))
        self.service_registry_handler = ServiceRegistryHandler(
            current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
            current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
        self.am_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
        self.am_user = current_app.config["ACCOUNT_MANAGEMENT_USER"]
        self.am_password = current_app.config["ACCOUNT_MANAGEMENT_PASSWORD"]
        self.timeout = current_app.config["TIMEOUT"]

    @error_handler
    @api_logging
    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
예제 #10
0
class VerifySLR(Resource):
    def __init__(self):
        super(VerifySLR, self).__init__()
        self.app = current_app
        self.am_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
        self.am_user = current_app.config["ACCOUNT_MANAGEMENT_USER"]
        self.am_password = current_app.config["ACCOUNT_MANAGEMENT_PASSWORD"]
        self.timeout = current_app.config["TIMEOUT"]
        self.Helpers = Helpers(current_app.config)

    @error_handler
    @api_logging
    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.")
예제 #11
0
class ConsentFormHandler(Resource):
    def __init__(self):
        super(ConsentFormHandler, self).__init__()
        self.am_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
        self.am_user = current_app.config["ACCOUNT_MANAGEMENT_USER"]
        self.am_password = current_app.config["ACCOUNT_MANAGEMENT_PASSWORD"]
        self.timeout = current_app.config["TIMEOUT"]
        self.debug_mode = current_app.config["DEBUG_MODE"]

        self.SH = ServiceRegistryHandler(
            current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
            current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
        self.getService = self.SH.getService
        self.Helpers = Helpers(current_app.config)
        self.operator_url = current_app.config["OPERATOR_URL"]

    @error_handler
    @api_logging
    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

    @error_handler
    @api_logging
    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
예제 #12
0
class SlrStatus(Resource):
    def __init__(self):
        """
        
        """
        super(SlrStatus, self).__init__()
        self.service_registry_handler = ServiceRegistryHandler(
            current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
            current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
        self.request_timeout = current_app.config["TIMEOUT"]
        self.uid = current_app.config["UID"]
        self.helper = Helpers(current_app.config)
        self.store_session = self.helper.store_session

    @error_handler
    @api_logging
    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())
예제 #13
0
class StatusChange(Resource):
    def __init__(self):
        super(StatusChange, self).__init__()
        self.am_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
        self.am_user = current_app.config["ACCOUNT_MANAGEMENT_USER"]
        self.am_password = current_app.config["ACCOUNT_MANAGEMENT_PASSWORD"]
        self.timeout = current_app.config["TIMEOUT"]
        self.helper_object = Helpers(current_app.config)
        self.service_registry_handler = ServiceRegistryHandler(
            current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
            current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])

    @error_handler
    @api_logging
    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
예제 #14
0
class StartSlrFlow(Resource):
    def __init__(self):
        """

        """
        super(StartSlrFlow, self).__init__()
        self.service_registry_handler = ServiceRegistryHandler(current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
                                                               current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])
        self.request_timeout = current_app.config["TIMEOUT"]
        self.uid = current_app.config["UID"]
        self.return_url = current_app.config["RETURN_URL"]
        self.helper = Helpers(current_app.config)
        self.store_session = self.helper.store_session

    @error_handler
    @api_logging
    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())
예제 #15
0
    def __init__(self):
        """

        """
        super(CancelSlrFlow, self).__init__()
        self.helper = Helpers(current_app.config)
예제 #16
0
class LinkingUi(Resource):
    def __init__(self):
        super(LinkingUi, self).__init__()
        self.helper = Helpers(current_app.config)
        self.account_url = current_app.config["ACCOUNT_MANAGEMENT_URL"]
        self.operator_id = current_app.config["OPERATOR_UID"]
        self.parser = reqparse.RequestParser()
        self.parser.add_argument('surrogate_id',
                                 type=str,
                                 help='Surrogate_id from a service.')
        self.parser.add_argument('service_id',
                                 type=str,
                                 help='ID of linking service.')
        self.parser.add_argument('username',
                                 type=str,
                                 help='Username for MyDataAccount')
        self.parser.add_argument('pword',
                                 type=str,
                                 help='Password for MyDataAccount')
        self.parser.add_argument('return_url',
                                 type=str,
                                 help='Url safe Base64 coded return url.')
        self.parser.add_argument('linkingFrom',
                                 type=str,
                                 help='Origin of the linking request(?)')
        self.store_session = self.helper.store_session
        self.service_registry_handler = ServiceRegistryHandler(
            current_app.config["SERVICE_REGISTRY_SEARCH_DOMAIN"],
            current_app.config["SERVICE_REGISTRY_SEARCH_ENDPOINT"])

    @error_handler
    @api_logging
    def get(self):
        args = self.parser.parse_args()
        args["operator_id"] = self.operator_id
        args["provider"] = args["service_id"]

        # Check headers for Account API key

        # If key is n

        # TODO: Use template file or get this from somewhere.
        tmpl_str = '''
        <html><header></header><body>
                    <form class="form-horizontal" action="" method="POST">
              <fieldset>
                <legend>Link {{provider}} with Operator({{ operator_id }})</legend>
                <div class="form-group">
                  <div class="col-lg-10 col-lg-offset-1">
                    Username:<input name="username" id="username"></input><br>
                    Password:<input name="pword" id="pword"></input>
                    <button type="reset" class="btn btn-default">Cancel</button>
                    <button type="submit" class="btn btn-primary">Submit</button>
                  </div>
                </div>
              </fieldset>
              <div {{ fromOperator }}>
                <p> By linking service to Operator, you agree to the <a href="#LinkToToS">Terms of Service</a></p>
              </div>
              <input type="hidden" name="surrogate_id" value="{{ surrogate_id }}">
              <input type="hidden" name="service_id" value="{{ service_id }}">
              <input type="hidden" name="return_url" value="{{ return_url }}">
              <input type="hidden" name="linkingFrom" value="{{ linkingFrom }}">
            </form>
        </body></html>
        '''
        # Render Login template
        response = make_response(render_template_string(tmpl_str, **args), 200)
        return response

    @error_handler
    @api_logging
    def post(self):
        args = self.parser.parse_args()

        def get_api_key(account_url=self.account_url + "account/api/v1.3/",
                        user=None,
                        password=None,
                        endpoint="external/auth/user/"):
            debug_log.info(
                "\nFetching Account Key for account '{}' from endpoint: {}".
                format(user + ":" + password, account_url + endpoint))
            api_json = get(account_url + endpoint, auth=(user, password))
            #debug_log.info("Received following key:\n {}".format(api_json))
            if api_json.ok:
                return loads(api_json.text)
            else:
                raise DetailedHTTPException(
                    title="Authentication to Account failed.", status=403)

        # Check Account is valid account, this is dummy UI, this is dumm test.
        account_info = get_api_key(user=args["username"],
                                   password=args["pword"])
        account_id = account_info["account_id"]
        account_api_key = account_info["Api-Key-User"]

        # Initialize all common variables
        surrogate_id = args["surrogate_id"]
        service_id = args["service_id"]
        return_url = args["return_url"]

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

        debug_log.info("Store session_information to database")

        session_information = {
            code: {
                "account_id": account_id,
                "service_id": service_id,
                "user_key": account_api_key
            }
        }
        self.store_session(session_information)

        try:
            # Make request to register surrogate_id
            data = {
                "code": code,
                "operator_id": self.operator_id,
                "return_url": return_url,
                "surrogate_id": surrogate_id,
            }

            # Fetch service information:
            service_json = self.service_registry_handler.getService(service_id)
            service_domain = service_json["serviceInstance"][0][
                "domain"]  # Domain to Login of Service
            service_access_uri = service_json["serviceInstance"][0][
                "serviceAccessEndPoint"]["serviceAccessURI"]
            service_linking_uri = "/slr/linking"

            service_url = service_domain + service_access_uri + service_linking_uri

            # Initiate Service Link Process
            debug_log.info("Sending linking request to Service at: {}".format(
                service_url))
            linking_result = post(service_url, json=data)
            debug_log.debug("Service Linking resulted in:\n {}\n {}".format(
                linking_result.status_code, linking_result.text))
            # If SLR was created success fully load it as a dictionary, on errors we delete session.
            if linking_result.ok:
                reply_json = loads(linking_result.text)
            else:
                self.helper.delete_session(code)
                raise DetailedHTTPException(
                    title=linking_result.reason,
                    status=linking_result.status_code,
                    detail={"msg": linking_result.text})
            debug_log.info(
                "Encoding json as reply to ui: \n{}".format(reply_json))
            if isinstance(reply_json, dict):
                reply_json = dumps(reply_json)
            self.helper.delete_session(code)
            return redirect("{}?results={}".format(
                decode64(args["return_url"]), encode64(reply_json)),
                            code=302)

        except DetailedHTTPException as e:
            self.helper.delete_session(code)
            raise e
        except Exception as e:
            self.helper.delete_session(code)
            raise DetailedHTTPException(
                status=500,
                exception=e,
                title="Something went wrong during service linking, try again."
            )