def _get_whitelist_rules(self) -> List[DynamicRuleInstall]: """ Get a list of dynamic rules to install for whitelisting. These rules will whitelist traffic to/from the captive portal server. """ dynamic_rules = [] for ip, ports in self.ip_whitelist.items(): if ip == 'local': ip = '192.168.128.1' for port in ports: # Build the rule id to be globally unique rule_id_info = { 'ip': ip, 'port': port, } rule_id = "whitelist_policy_id-{ip}:{port}"\ .format(**rule_id_info) rule = DynamicRuleInstall( policy_rule=self._get_whitelist_policy_rule( rule_id, ip, port ), ) # Activate now, and deactivate long in the future t2 = datetime.now() t2 = t2.replace(year=t2.year + 1) rule.activation_time.FromDatetime(datetime.now()) rule.deactivation_time.FromDatetime(t2) dynamic_rules.append(rule) return dynamic_rules
def _get_default_dynamic_rules( self, subscriber_id: str, apn: str, ) -> List[DynamicRuleInstall]: """ Get a list of dynamic rules to install Currently only includes a single rule for allow-all of traffic """ return [ DynamicRuleInstall( policy_rule=get_allow_all_policy_rule(subscriber_id, apn)), ]
def _get_default_dynamic_rules( self, sid: str, ) -> List[DynamicRuleInstall]: """ Get a list of dynamic rules to install for whitelisting. """ dynamic_rules = [] # Build the rule id to be globally unique rule_id_info = {'sid': sid} rule_id = "whitelist_sid-{sid}".format(**rule_id_info) rule = DynamicRuleInstall( policy_rule=self._get_allow_all_policy_rule(rule_id), ) dynamic_rules.append(rule) return dynamic_rules
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 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 create_ReAuthRequest(self, imsi, policy_id, flow_list, qos): """ Sends Policy RAR message to session manager """ print("Sending Policy RAR message to session manager") flow_match_list = [] res = None self.get_flow_match(flow_list, flow_match_list) policy_qos = FlowQos( qci=qos["qci"], max_req_bw_ul=qos["max_req_bw_ul"], max_req_bw_dl=qos["max_req_bw_dl"], gbr_ul=qos["gbr_ul"], gbr_dl=qos["gbr_dl"], arp=QosArp( priority_level=qos["arp_prio"], pre_capability=qos["pre_cap"], pre_vulnerability=qos["pre_vul"], ), ) policy_rule = PolicyRule( id=policy_id, priority=qos["priority"], flow_list=flow_match_list, tracking_type=PolicyRule.NO_TRACKING, rating_group=1, monitoring_key=None, qos=policy_qos, ) qos = QoSInformation(qci=qos["qci"]) # Get sessionid req = GetDirectoryFieldRequest(id=imsi, field_key="session_id") try: res = self._directorydstub.GetDirectoryField( req, DEFAULT_GRPC_TIMEOUT) except grpc.RpcError as err: logging.error( "GetDirectoryFieldRequest error for id: %s! [%s] %s", imsi, err.code(), err.details(), ) self._session_stub.PolicyReAuth( PolicyReAuthRequest( session_id=res.value, imsi=imsi, rules_to_remove=[], rules_to_install=[], dynamic_rules_to_install=[ DynamicRuleInstall(policy_rule=policy_rule) ], event_triggers=[], revalidation_time=None, usage_monitoring_credits=[], qos_info=qos, ))
def create_ReAuthRequest(self, imsi, policy_id, flow_list, qos): """ Sends Policy RAR message to session manager """ print("Sending Policy RAR message to session manager") flow_match_list = [] res = None self.get_flow_match(flow_list, flow_match_list) policy_qos = FlowQos( qci=qos["qci"], max_req_bw_ul=qos["max_req_bw_ul"], max_req_bw_dl=qos["max_req_bw_dl"], gbr_ul=qos["gbr_ul"], gbr_dl=qos["gbr_dl"], arp=QosArp( priority_level=qos["arp_prio"], pre_capability=qos["pre_cap"], pre_vulnerability=qos["pre_vul"], ), ) policy_rule = PolicyRule( id=policy_id, priority=qos["priority"], flow_list=flow_match_list, tracking_type=PolicyRule.NO_TRACKING, rating_group=1, monitoring_key=None, qos=policy_qos, ) qos = QoSInformation(qci=qos["qci"]) # Get sessionid #TODO: remove retries i = 0 MAX = 3 res = None while i < MAX: req = GetDirectoryFieldRequest(id=imsi, field_key="session_id") try: res = self._directorydstub.GetDirectoryField( req, DEFAULT_GRPC_TIMEOUT) except grpc.RpcError as err: print( "error: GetDirectoryFieldRequest error for id: %s! [%s] %s", imsi, err.code(), err.details(), ) if req != None: i = MAX else: i += 1 print( "warning: directoryd failed to return sessionId for %s. Retrying", imsi) time.sleep(3) if res == None: print("error: Couldnt find sessionid. Directoryd content:") allRecordsResponse = self._directorydstub.GetAllDirectoryRecords( Void(), DEFAULT_GRPC_TIMEOUT) for record in allRecordsResponse.recordsResponse: print("%s", str(record)) self._session_stub.PolicyReAuth( PolicyReAuthRequest( session_id=res.value, imsi=imsi, rules_to_remove=[], rules_to_install=[], dynamic_rules_to_install=[ DynamicRuleInstall(policy_rule=policy_rule) ], event_triggers=[], revalidation_time=None, usage_monitoring_credits=[], qos_info=qos, ))
def send_policy_rar(client, args): sessiond_chan = ServiceRegistry.get_rpc_channel("sessiond", ServiceRegistry.LOCAL) sessiond_client = SessionProxyResponderStub(sessiond_chan) flow_list_str = args.flow_rules.split(";") flow_match_list = [] for i, flow_str in enumerate(flow_list_str): print("%d: %s" % (i, flow_str)) flow_fields = flow_str.split(",") if flow_fields[0] == "UL": flow_direction = FlowMatch.UPLINK elif flow_fields[0] == "DL": flow_direction = FlowMatch.DOWNLINK else: print("%s is not valid" % flow_fields[0]) raise ValueError( "UL or DL are the only valid" " values for first parameter of flow match" ) ip_protocol = int(flow_fields[1]) if flow_fields[1] == FlowMatch.IPPROTO_TCP: udp_src_port = 0 udp_dst_port = 0 if flow_fields[3]: tcp_src_port = int(flow_fields[3]) else: tcp_src_port = 0 if flow_fields[5]: tcp_dst_port = int(flow_fields[5]) else: tcp_dst_port = 0 elif flow_fields[1] == FlowMatch.IPPROTO_UDP: tcp_src_port = 0 tcp_dst_port = 0 if flow_fields[3]: udp_src_port = int(flow_fields[3]) else: udp_src_port = 0 if flow_fields[5]: udp_dst_port = int(flow_fields[5]) else: udp_dst_port = 0 else: udp_src_port = 0 udp_dst_port = 0 tcp_src_port = 0 tcp_dst_port = 0 flow_match_list.append( FlowDescription( match=FlowMatch( direction=flow_direction, ip_proto=ip_protocol, ipv4_src=flow_fields[2], ipv4_dst=flow_fields[4], tcp_src=tcp_src_port, tcp_dst=tcp_dst_port, udp_src=udp_src_port, udp_dst=udp_dst_port, ), action=FlowDescription.PERMIT, ) ) qos_parameter_list = args.qos.split(",") if len(qos_parameter_list) == 7: # utilize user passed arguments policy_qos = FlowQos( qci=int(args.qci), max_req_bw_ul=int(qos_parameter_list[0]), max_req_bw_dl=int(qos_parameter_list[1]), gbr_ul=int(qos_parameter_list[2]), gbr_dl=int(qos_parameter_list[3]), arp=QosArp( priority_level=int(qos_parameter_list[4]), pre_capability=int(qos_parameter_list[5]), pre_vulnerability=int(qos_parameter_list[6]), ), ) else: # parameter missing, use default values policy_qos = FlowQos( qci=int(args.qci), max_req_bw_ul=100000, max_req_bw_dl=100000, arp=QosArp(priority_level=1, pre_capability=1, pre_vulnerability=0), ) policy_rule = PolicyRule( id=args.policy_id, priority=int(args.priority), flow_list=flow_match_list, tracking_type=PolicyRule.NO_TRACKING, rating_group=1, monitoring_key=None, qos=policy_qos, ) qos = QoSInformation(qci=int(args.qci)) reauth_result = sessiond_client.PolicyReAuth( PolicyReAuthRequest( session_id=args.session_id, imsi=args.imsi, rules_to_remove=[], rules_to_install=[], dynamic_rules_to_install=[DynamicRuleInstall(policy_rule=policy_rule)], event_triggers=[], revalidation_time=None, usage_monitoring_credits=[], qos_info=qos, ) ) print(reauth_result)