Example #1
0
    def incoming(self, invocation):

        # log.trace("PolicyInterceptor.incoming: %s", invocation.get_arg_value('process', invocation))

        # print "========"
        # print invocation.headers

        # If missing the performative header, consider it as a failure message.
        msg_performative = invocation.get_header_value("performative", "failure")
        message_format = invocation.get_header_value("format", "")
        op = invocation.get_header_value("op", "unknown")
        process_type = invocation.get_invocation_process_type()
        sender, sender_type = invocation.get_message_sender()

        # TODO - This should be removed once better process security is implemented
        # THis fix infers that all messages that do not specify an actor id are TRUSTED wihtin the system
        policy_loaded = CFG.get_safe("system.load_policy", False)
        if policy_loaded:
            actor_id = invocation.get_header_value("ion-actor-id", None)
        else:
            actor_id = invocation.get_header_value("ion-actor-id", "anonymous")

        # Only check messages marked as the initial rpc request - TODO - remove the actor_id is not None when headless process have actor_ids
        if msg_performative == "request" and actor_id is not None:

            receiver = invocation.get_message_receiver()

            # Can's check policy if the controller is not initialized
            if self.governance_controller is None:
                log.debug("Skipping policy check for %s(%s) since governance_controller is None", receiver, op)
                invocation.message_annotations[
                    GovernanceDispatcher.POLICY__STATUS_ANNOTATION
                ] = GovernanceDispatcher.STATUS_SKIPPED
                return invocation

            # No need to check for requests from the system actor - should increase performance during startup
            if actor_id == self.governance_controller.system_actor_id:
                log.debug("Skipping policy check for %s(%s) for the system actor", receiver, op)
                invocation.message_annotations[
                    GovernanceDispatcher.POLICY__STATUS_ANNOTATION
                ] = GovernanceDispatcher.STATUS_SKIPPED
                return invocation

            # Check to see if there is a AlwaysVerifyPolicy decorator
            always_verify_policy = False
            if is_ion_object(message_format):
                try:
                    msg_class = message_classes[message_format]
                    always_verify_policy = has_class_decorator(msg_class, "AlwaysVerifyPolicy")
                except Exception:
                    pass

            # For services only - if this is a sub RPC request from a higher level service that has already been validated and set a token
            # then skip checking policy yet again - should help with performance and to simplify policy
            # All calls from the RMS must be checked
            if (
                not always_verify_policy
                and process_type == "service"
                and sender != "resource_management"
                and self.has_valid_token(invocation, PERMIT_SUB_CALLS)
            ):
                # log.debug("Skipping policy check for service call %s %s since token is valid", receiver, op)
                # print "skipping call to " + receiver + " " + op + " from " + actor_id + " process_type: " + process_type
                invocation.message_annotations[
                    GovernanceDispatcher.POLICY__STATUS_ANNOTATION
                ] = GovernanceDispatcher.STATUS_SKIPPED
                return invocation

            # log.debug("Checking request for %s: %s(%s) from %s  ", process_type, receiver, op, actor_id)

            # Annotate the message has started policy checking
            invocation.message_annotations[
                GovernanceDispatcher.POLICY__STATUS_ANNOTATION
            ] = GovernanceDispatcher.STATUS_STARTED

            ret = None

            # First check for Org boundary policies if the container is configured as such
            org_id = self.governance_controller.get_container_org_boundary_id()
            if org_id is not None:
                ret = self.governance_controller.policy_decision_point_manager.check_resource_request_policies(
                    invocation, org_id
                )

            if str(ret) != Decision.DENY_STR:
                # Next check endpoint process specific policies
                if process_type == "agent":
                    ret = self.governance_controller.policy_decision_point_manager.check_agent_request_policies(
                        invocation
                    )

                elif process_type == "service":
                    ret = self.governance_controller.policy_decision_point_manager.check_service_request_policies(
                        invocation
                    )

            # log.debug("Policy Decision: %s", ret)

            # Annonate the message has completed policy checking
            invocation.message_annotations[
                GovernanceDispatcher.POLICY__STATUS_ANNOTATION
            ] = GovernanceDispatcher.STATUS_COMPLETE

            if ret is not None:
                if str(ret) == Decision.DENY_STR:
                    self.annotate_denied_message(invocation)
                else:
                    self.permit_sub_rpc_calls_token(invocation)

        else:
            invocation.message_annotations[
                GovernanceDispatcher.POLICY__STATUS_ANNOTATION
            ] = GovernanceDispatcher.STATUS_SKIPPED

        return invocation
    def incoming(self, invocation):
        """Policy governance process interceptor for messages received.
        Checks policy based on message headers.
        """
        #log.trace("PolicyInterceptor.incoming: %s", invocation.get_arg_value('process', invocation))
        #print "========"
        #print invocation.headers

        # If missing the performative header, consider it as a failure message.
        msg_performative = invocation.get_header_value(MSG_HEADER_PERFORMATIVE, 'failure')
        message_format = invocation.get_header_value(MSG_HEADER_FORMAT, '')
        op = invocation.get_header_value(MSG_HEADER_OP, 'unknown')
        process_type = invocation.get_invocation_process_type()
        sender, sender_type = invocation.get_message_sender()

        # TODO - This should be removed once better process security is implemented
        # We assume all external requests have security headers set (even anonymous calls),
        # so that calls from within the system (e.g. headless processes) can be considered trusted.
        policy_loaded = CFG.get_safe('system.load_policy', False)
        if policy_loaded:
            # With policy: maintain the actor id
            actor_id = invocation.get_header_value(MSG_HEADER_ACTOR, None)
        else:
            # Without policy: default to anonymous
            actor_id = invocation.get_header_value(MSG_HEADER_ACTOR, ANONYMOUS_ACTOR)

        # Only check messages marked as the initial rpc request
        # TODO - remove the actor_id is not None when headless process have actor_ids
        if msg_performative == 'request' and actor_id is not None:
            receiver = invocation.get_message_receiver()

            # Can't check policy if the controller is not initialized
            if self.governance_controller is None:
                log.debug("Skipping policy check for %s(%s) since governance_controller is None", receiver, op)
                invocation.message_annotations[GovernanceDispatcher.POLICY__STATUS_ANNOTATION] = GovernanceDispatcher.STATUS_SKIPPED
                return invocation

            # No need to check for requests from the system actor - should increase performance during startup
            if actor_id == self.governance_controller.system_actor_id:
                log.debug("Skipping policy check for %s(%s) for the system actor", receiver, op)
                invocation.message_annotations[GovernanceDispatcher.POLICY__STATUS_ANNOTATION] = GovernanceDispatcher.STATUS_SKIPPED
                return invocation

            # Check to see if there is a AlwaysVerifyPolicy decorator
            always_verify_policy = False
            if is_ion_object(message_format):
                try:
                    msg_class = message_classes[message_format]
                    always_verify_policy = has_class_decorator(msg_class, DECORATOR_ALWAYS_VERIFY_POLICY)
                except Exception:
                    pass

            # For services only - if this is a sub RPC request from a higher level service that has
            # already been validated and set a token then skip checking policy yet again - should help
            # with performance and to simplify policy.
            # All calls from the RMS must be checked; it acts as generic facade forwarding many kinds of requests
            if not always_verify_policy and process_type == PROCTYPE_SERVICE and sender != 'resource_management' and \
                    self.has_valid_token(invocation, PERMIT_SUB_CALLS):
                #log.debug("Skipping policy check for service call %s %s since token is valid", receiver, op)
                invocation.message_annotations[GovernanceDispatcher.POLICY__STATUS_ANNOTATION] = GovernanceDispatcher.STATUS_SKIPPED
                return invocation

            #log.debug("Checking request for %s: %s(%s) from %s  ", process_type, receiver, op, actor_id)

            # Annotate the message has started policy checking
            invocation.message_annotations[GovernanceDispatcher.POLICY__STATUS_ANNOTATION] = GovernanceDispatcher.STATUS_STARTED

            ret = None

            # ---- POLICY RULE CHECKS HERE ----
            # First check for Org boundary policies if the container is configured as such
            org_id = self.governance_controller.get_container_org_boundary_id()
            if org_id is not None:
                ret = self.governance_controller.policy_decision_point_manager.check_resource_request_policies(invocation, org_id)

            if str(ret) != Decision.DENY_STR:
                # Next check endpoint process specific policies
                if process_type == PROCTYPE_AGENT:
                    ret = self.governance_controller.policy_decision_point_manager.check_agent_request_policies(invocation)

                elif process_type == PROCTYPE_SERVICE:
                    ret = self.governance_controller.policy_decision_point_manager.check_service_request_policies(invocation)

            #log.debug("Policy Decision: %s", ret)
            # ---- POLICY RULE CHECKS END ----

            # Annotate the message has completed policy checking
            invocation.message_annotations[GovernanceDispatcher.POLICY__STATUS_ANNOTATION] = GovernanceDispatcher.STATUS_COMPLETE

            if ret is not None:
                if str(ret) == Decision.DENY_STR:
                    self.annotate_denied_message(invocation)
                else:
                    self.permit_sub_rpc_calls_token(invocation)

        else:
            invocation.message_annotations[GovernanceDispatcher.POLICY__STATUS_ANNOTATION] = GovernanceDispatcher.STATUS_SKIPPED

        return invocation