def DestroyPolicy(self, request, context): """Delete a policy.""" asn_str, client = get_client_from_metadata( context.invocation_metadata()) asn = ASN(asn_str) if request.asn != asn_str: context.abort(grpc.StatusCode.PERMISSION_DENIED, "Cannot delete policies of other ASes") serializer = PolicyProtoSerializer(message=request) if not serializer.is_valid(): context.abort(grpc.StatusCode.INVALID_ARGUMENT, _fmt_validation_errors(serializer.errors)) try: policy = serializer.get() except ObjectDoesNotExist: context.abort(grpc.StatusCode.NOT_FOUND, "Policy does not exist") _assert_policy_write_permission(context, asn, client, request.vlan) policy.delete() # Update links and notify clients policy_resolver.update_accepted_peers(policy.vlan, policy.asys) policy_resolver.update_links(policy.vlan, policy.asys) return Empty()
def _set_policies( self, request, context ) -> Tuple[typing.List[peering_pb2.Policy], typing.List[str]]: # Delete old policies. Parse the new ones, and try saving them to the DB. # Returns the unsuccessful policies and matching error descriptions. # context.abort() is called on fatal errors to abort the RPC and trigger a transaction # rollback. asn_str, client = get_client_from_metadata( context.invocation_metadata()) asn = ASN(asn_str) # Delete previous policies if request.vlan: try: vlan_id = VLAN.objects.get(name=request.vlan).id except VLAN.DoesNotExist: context.abort(grpc.StatusCode.NOT_FOUND, "VLAN does not exist") _assert_policy_write_permission(context, asn, client, request.vlan) _delete_policies(asn, vlan_id) else: _assert_policy_write_permission(context, asn, client) _delete_policies(asn) # Create new policies rejected_policies = [] errors = [] for policy in request.policies: serializer = PolicyProtoSerializer(message=policy) if policy.asn != asn_str: rejected_policies.append(policy) errors.append("Policy ASN belongs to foreign AS") continue if request.vlan and policy.vlan != request.vlan: rejected_policies.append(policy) errors.append("VLAN excluded by filter") continue if not serializer.is_valid(): rejected_policies.append(policy) errors.append(_fmt_validation_errors(serializer.errors)) continue try: serializer.save() except ValidationError as e: msg, _ = _translate_validation_errors(e) rejected_policies.append(policy) errors.append(msg) continue # Update links and notify clients asys = AS.objects.get(asn=asn) for vlan in asys.get_connected_vlans(): policy_resolver.update_accepted_peers(vlan, asys) policy_resolver.update_links(vlan, asys) return rejected_policies, errors
def test_priority(self): """Test priority of AS-level over Owner-level over ISD-level policies.""" vlan = self.vlan[0] # Accept 2-ff00:0:4 -> 1-ff00:0:1 # Accept 2-ff00:0:5 -> 1-ff00:0:1 AsPeerPolicy.objects.create(vlan=vlan, asys=self.asys[4], peer_as=self.asys[1], accept=True) AsPeerPolicy.objects.create(vlan=vlan, asys=self.asys[5], peer_as=self.asys[1], accept=True) update_accepted_peers(vlan, self.asys[4]) update_accepted_peers(vlan, self.asys[5]) # Accept 1-ff00:0:1 -> ISD 2 _add_isd_policy(vlan, self.asys[1], self.isd[1], True) self.assertEqual(self.asys[1].accept.count(), 2) self.assertEqual(_count_links(self.asys[1]), 2) self.assertTrue(_links_exists(self, vlan, Link.Type.PEERING, self.asys[1], self.asys[4])) self.assertTrue(_links_exists(self, vlan, Link.Type.PEERING, self.asys[1], self.asys[5])) # Reject 1-ff00:0:1 -> Owner 3 _add_owner_policy(vlan, self.asys[1], self.owner[2], False) self.assertEqual(self.asys[1].accept.count(), 1) self.assertEqual(_count_links(self.asys[1]), 1) self.assertTrue(_links_exists(self, vlan, Link.Type.PEERING, self.asys[1], self.asys[5])) # Reject 1-ff00:0:1 -> 2-ff00:0:5 _add_as_policy(vlan, self.asys[1], self.asys[5], False) self.assertEqual(self.asys[1].accept.count(), 0) self.assertEqual(_count_links(self.asys[1]), 0)
def CreatePolicy(self, request, context): """Create a new policy.""" asn_str, client = get_client_from_metadata( context.invocation_metadata()) asn = ASN(asn_str) if request.asn != asn_str: context.abort(grpc.StatusCode.PERMISSION_DENIED, "Cannot create policies for other ASes") serializer = PolicyProtoSerializer(message=request) if not serializer.is_valid(): context.abort(grpc.StatusCode.INVALID_ARGUMENT, _fmt_validation_errors(serializer.errors)) _assert_policy_write_permission(context, asn, client, request.vlan) try: policy = serializer.save() except ValidationError as e: msg, code = _translate_validation_errors(e) context.abort(code, msg) # Update links and notify clients policy_resolver.update_accepted_peers(policy.vlan, policy.asys) policy_resolver.update_links(policy.vlan, policy.asys) return serializer.message
def _add_default_policy(vlan, asys, accept): """Add a default policy and apply it. :returns: The newly created policy instance. """ policy = DefaultPolicy.objects.create(vlan=vlan, asys=asys, accept=accept) update_accepted_peers(vlan, asys) update_links(vlan, asys) return policy
def _add_isd_policy(vlan, asys, peer_isd, accept): """Add an ISD peering policy and apply it. :returns: The newly created policy instance. """ policy = IsdPeerPolicy.objects.create(vlan=vlan, asys=asys, peer_isd=peer_isd, accept=accept) update_accepted_peers(vlan, asys) update_links(vlan, asys) return policy
def test_example(self): vlan = self.vlan[0] # AS-level policies # B accept C AsPeerPolicy.objects.create(vlan=vlan, asys=self.asys['B'], peer_as=self.asys['C'], accept=True) # C accept B, D AsPeerPolicy.objects.create(vlan=vlan, asys=self.asys['C'], peer_as=self.asys['B'], accept=True) AsPeerPolicy.objects.create(vlan=vlan, asys=self.asys['C'], peer_as=self.asys['D'], accept=True) # D accept C, E AsPeerPolicy.objects.create(vlan=vlan, asys=self.asys['D'], peer_as=self.asys['C'], accept=True) AsPeerPolicy.objects.create(vlan=vlan, asys=self.asys['D'], peer_as=self.asys['E'], accept=True) # E reject G, H AsPeerPolicy.objects.create(vlan=vlan, asys=self.asys['E'], peer_as=self.asys['G'], accept=False) AsPeerPolicy.objects.create(vlan=vlan, asys=self.asys['E'], peer_as=self.asys['H'], accept=False) # Owner-level policies # F accept [F, G] OwnerPeerPolicy.objects.create(vlan=vlan, asys=self.asys['F'], peer_owner=self.owner[1], accept=True) # G accept [F, G] OwnerPeerPolicy.objects.create(vlan=vlan, asys=self.asys['G'], peer_owner=self.owner[1], accept=True) # ISD-level policies # E accept ISD 2 IsdPeerPolicy.objects.create(vlan=vlan, asys=self.asys['E'], peer_isd=self.isd[1], accept=True) # G accept ISD 2 IsdPeerPolicy.objects.create(vlan=vlan, asys=self.asys['G'], peer_isd=self.isd[1], accept=True) # H accept ISD 2 IsdPeerPolicy.objects.create(vlan=vlan, asys=self.asys['H'], peer_isd=self.isd[1], accept=True) for asys in self.asys.values(): update_accepted_peers(vlan, asys) for asys in self.asys.values(): update_links(vlan, asys) self.assertEqual(Link.objects.count(), 4) self.assertTrue(_links_exists(self, vlan, Link.Type.CORE, self.asys['B'], self.asys['C'])) self.assertTrue(_links_exists(self, vlan, Link.Type.PEERING, self.asys['D'], self.asys['E'])) self.assertTrue(_links_exists(self, vlan, Link.Type.PEERING, self.asys['F'], self.asys['G'])) self.assertTrue(_links_exists(self, vlan, Link.Type.PEERING, self.asys['G'], self.asys['H']))
def delete_queryset(self, request, queryset): update = {(obj.vlan, obj.asys) for obj in queryset} super().delete_queryset(request, queryset) for vlan, asys in update: policy_resolver.update_accepted_peers(vlan, asys)
def delete_model(self, request, obj): super().delete_model(request, obj) policy_resolver.update_accepted_peers(obj.vlan, obj.asys)
def save_model(self, request, obj, form, change): super().save_model(request, obj, form, change) policy_resolver.update_accepted_peers(obj.vlan, obj.asys)
def _delete_policy(policy): """Delete a peering policy and apply the changes.""" policy.delete() update_accepted_peers(policy.vlan, policy.asys) update_links(policy.vlan, policy.asys)