Exemple #1
0
    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
Exemple #2
0
 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)),
     ]
Exemple #3
0
 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
Exemple #4
0
    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')
Exemple #6
0
    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,
            ))
Exemple #7
0
    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)