def _get_session_static_rules( self, imsi: str, apn: str, ) -> List[StaticRuleInstall]: """ Get the list of static rules to be installed for a subscriber NOTE: Remove "IMSI" prefix from imsi argument. """ if imsi not in self._apn_rules_by_sid: return [] sub_apn_policies = self._apn_rules_by_sid[imsi] assigned_static_rules = [] # type: List[StaticRuleInstall] # Add global rules global_rules = self._get_global_static_rules(sub_apn_policies) assigned_static_rules += \ list(map(lambda id: StaticRuleInstall(rule_id=id), global_rules)) # Add APN specific rules for apn_policy_set in sub_apn_policies.rules_per_apn: if apn_policy_set.apn != apn: continue # Only add rules if the APN matches static_rule_ids = self._get_static_rules(apn_policy_set) assigned_static_rules +=\ list(map(lambda id: StaticRuleInstall(rule_id=id), static_rule_ids)) return assigned_static_rules
def EnableStaticRules( self, request: EnableStaticRuleRequest, context, ) -> Void: """ Associate the static rules with the specified subscriber. Also send a RAR to sessiond to install the specified rules for the subscriber. """ try: self._subscriberdb_stub.EnableStaticRules(request) except grpc.RpcError: logging.error('Unable to enable rules for subscriber %s. ', request.imsi) context.set_code(grpc.StatusCode.NOT_FOUND) context.set_details('Failed to update rule assignments in orc8r') return Void() rules_to_install = self._get_rules(request.rule_ids, request.base_names) rar = PolicyReAuthRequest( # Leave session id empty, re-auth for all sessions imsi=request.imsi, rules_to_install=[ StaticRuleInstall(rule_id=rule_id) for rule_id in rules_to_install ], ) success = self._reauth_handler.handle_policy_re_auth(rar) if not success: context.set_code(grpc.StatusCode.UNKNOWN) context.set_details('Failed to enable all static rules for ' 'subscriber. Partial update may have succeeded') return Void()
def _get_rules_for_imsi(self, imsi: str) -> List[StaticRuleInstall]: try: info = self._subscriberdb_stub.GetSubscriberData(NetworkID(id=imsi)) return [StaticRuleInstall(rule_id=rule_id) for rule_id in info.lte.assigned_policies] except grpc.RpcError: logging.error('Unable to find data for subscriber %s', imsi) return []
def test_SuccessfulUpdate(self): """ Test the happy path where updates come in for added rules, and sessiond accepts the RAR without issue. """ install_dict = {} handler = ReAuthHandler( install_dict, MockSessionProxyResponderStub(), ) rar = PolicyReAuthRequest( imsi='s1', rules_to_install=[ StaticRuleInstall(rule_id=rule_id) for rule_id in ['p1', 'p2'] ], ) handler.handle_policy_re_auth(rar) s1_policies = install_dict['s1'].installed_policies expected = 2 self.assertEqual( len(s1_policies), expected, 'There should be 2 installed policies for s1', ) self.assertTrue( 'p1' in s1_policies, 'Policy p1 should be marked installed for p1', ) rar = PolicyReAuthRequest( imsi='s1', rules_to_install=[StaticRuleInstall(rule_id='p3')], ) handler.handle_policy_re_auth(rar) s1_policies = install_dict['s1'].installed_policies expected = 3 self.assertEqual( len(s1_policies), expected, 'There should be 3 installed policies for s1', ) self.assertTrue( 'p3' in s1_policies, 'Policy p1 should be marked installed for p1', )
def _build_sub_rule_set( self, subscriber_id: str, sub_apn_policies: SubscriberPolicySet, ) -> RulesPerSubscriber: apn_rule_sets = [] # type: List[RuleSet] global_rules = self._get_global_static_rules(sub_apn_policies) for apn_policy_set in sub_apn_policies.rules_per_apn: # Static rule installs static_rule_ids = self._get_desired_static_rules(apn_policy_set) static_rules = [] # type: List[StaticRuleInstall] for rule_id in static_rule_ids: static_rules.append(StaticRuleInstall(rule_id=rule_id)) # Add global rules for rule_id in global_rules: static_rules.append(StaticRuleInstall(rule_id=rule_id)) # Dynamic rule installs dynamic_rules = [] # type: List[DynamicRuleInstall] # Build the rule id to be globally unique rule = DynamicRuleInstall( policy_rule=get_allow_all_policy_rule( subscriber_id, apn_policy_set.apn, ), ) dynamic_rules.append(rule) # Build the APN rule set apn_rule_sets.append( RuleSet( apply_subscriber_wide=False, apn=apn_policy_set.apn, static_rules=static_rules, dynamic_rules=dynamic_rules, ), ) return RulesPerSubscriber( imsi=subscriber_id, rule_set=apn_rule_sets, )
def _get_rules_for_imsi(self, imsi: str) -> List[StaticRuleInstall]: """ Get the list of static rules to be installed for a subscriber NOTE: Remove "IMSI" prefix from imsi argument. """ try: info = self._subscriberdb_stub.GetSubscriberData(NetworkID(id=imsi)) return [StaticRuleInstall(rule_id=rule_id) for rule_id in info.lte.assigned_policies] except grpc.RpcError: logging.error('Unable to find data for subscriber %s', imsi) return []
def _generate_rar( self, subscriber_id: str, added_rules: List[str], removed_rules: List[str], ) -> PolicyReAuthRequest: rules_to_install = [ StaticRuleInstall(rule_id=rule_id) for rule_id in added_rules ] return PolicyReAuthRequest( # Skip the session ID, so apply to all sessions of the subscriber imsi=subscriber_id, rules_to_install=rules_to_install, rules_to_remove=removed_rules, # No changes to dynamic rules # No event triggers # No additional usage monitoring credits # No QoS info )
def test_Update(self): """ Test the happy path where updates come in for rules, and sessiond accepts the SessionRules without issue. """ # Expected call arguments to SetSessionRules allow_all_flow_list = [ FlowDescription( match=FlowMatch( direction=FlowMatch.Direction.Value("UPLINK"), ), action=FlowDescription.Action.Value("PERMIT"), ), FlowDescription( match=FlowMatch( direction=FlowMatch.Direction.Value("DOWNLINK"), ), action=FlowDescription.Action.Value("PERMIT"), ), ] # type: List[FlowDescription] no_tracking_type = PolicyRule.TrackingType.Value("NO_TRACKING") expected = SessionRules(rules_per_subscriber=[ RulesPerSubscriber( imsi='imsi_1', rule_set=[ RuleSet( apply_subscriber_wide=False, apn="apn1", static_rules=[ StaticRuleInstall(rule_id="p1"), ], dynamic_rules=[ DynamicRuleInstall(policy_rule=PolicyRule( id="allowlist_sid-imsi_1-apn1", priority=2, flow_list=allow_all_flow_list, tracking_type=no_tracking_type, )) ], ), ]), RulesPerSubscriber( imsi='imsi_2', rule_set=[ RuleSet( apply_subscriber_wide=False, apn="apn1", static_rules=[ StaticRuleInstall(rule_id="p5"), ], dynamic_rules=[ DynamicRuleInstall(policy_rule=PolicyRule( id="allowlist_sid-imsi_2-apn1", priority=2, flow_list=allow_all_flow_list, tracking_type=no_tracking_type, )) ], ), ]) ]) # Setup the test apn_rules_dict = {} basenames_dict = { 'bn1': ChargingRuleNameSet(RuleNames=['p5']), 'bn2': ChargingRuleNameSet(RuleNames=['p6']), } stub = MockLocalSessionManagerStub() stub_call_args = [] # type: List[SessionRules] side_effect = get_SetSessionRules_side_effect(stub_call_args) stub.SetSessionRules = Mock(side_effect=side_effect) callback = ApnRuleMappingsStreamerCallback( stub, basenames_dict, apn_rules_dict, ) # Construct a set of updates, keyed by subscriber ID updates = [ DataUpdate( key="imsi_1", value=SubscriberPolicySet(rules_per_apn=[ ApnPolicySet( apn="apn1", assigned_base_names=[], assigned_policies=["p1"], ), ], ).SerializeToString(), ), DataUpdate( key="imsi_2", value=SubscriberPolicySet(rules_per_apn=[ ApnPolicySet( apn="apn1", assigned_base_names=["bn1"], assigned_policies=[], ), ], ).SerializeToString(), ), ] callback.process_update("stream", updates, False) # Since we used a stub which always succeeds when a RAR is made, # We should expect the assignments_dict to be updated imsi_1_policies = apn_rules_dict["imsi_1"] self.assertEqual(len(imsi_1_policies.rules_per_apn), 1, 'There should be 1 active APNs for imsi_1') self.assertEqual(len(stub_call_args), 1, 'Stub should have been called once') called_with = stub_call_args[0].SerializeToString() self.assertEqual(called_with, expected.SerializeToString(), 'SetSessionRules call has incorrect arguments') # Stream down a second update, and now IMSI_1 gets access to a new APN updates_2 = [ DataUpdate( key="imsi_1", value=SubscriberPolicySet(rules_per_apn=[ ApnPolicySet( apn="apn2", assigned_base_names=["bn1"], assigned_policies=[], ), ], ).SerializeToString(), ), DataUpdate( key="imsi_2", value=SubscriberPolicySet( global_base_names=["bn2"], global_policies=[], rules_per_apn=[ ApnPolicySet( apn="apn1", assigned_base_names=[], assigned_policies=[], ), ], ).SerializeToString(), ), ] expected_2 = SessionRules(rules_per_subscriber=[ RulesPerSubscriber( imsi='imsi_1', rule_set=[ RuleSet( apply_subscriber_wide=False, apn="apn2", static_rules=[ StaticRuleInstall(rule_id="p5"), ], dynamic_rules=[ DynamicRuleInstall(policy_rule=PolicyRule( id="allowlist_sid-imsi_1-apn2", priority=2, flow_list=allow_all_flow_list, tracking_type=no_tracking_type, )) ], ), ]), RulesPerSubscriber( imsi='imsi_2', rule_set=[ RuleSet( apply_subscriber_wide=False, apn="apn1", static_rules=[ StaticRuleInstall(rule_id="p6"), ], dynamic_rules=[ DynamicRuleInstall(policy_rule=PolicyRule( id="allowlist_sid-imsi_2-apn1", priority=2, flow_list=allow_all_flow_list, tracking_type=no_tracking_type, )) ], ), ]), ]) callback.process_update("stream", updates_2, False) imsi_1_policies = apn_rules_dict["imsi_1"] self.assertEqual(len(imsi_1_policies.rules_per_apn), 1, 'There should be 1 active APNs for imsi_1') self.assertEqual(len(stub_call_args), 2, 'Stub should have been called twice') called_with = stub_call_args[1].SerializeToString() self.assertEqual(called_with, expected_2.SerializeToString(), 'SetSessionRules call has incorrect arguments')
def _get_static_rules(self) -> List[StaticRuleInstall]: """ Return a static rule for redirection to captive portal """ if self.redirect_rule_name in self._rules: return [StaticRuleInstall(rule_id=self.redirect_rule_name)] return []
def _get_static_rule(self) -> StaticRuleInstall: """ Return a static rule for redirection to captive portal """ return StaticRuleInstall( rule_id = self.redirect_rule_name, )