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