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 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 SetPortRange(self, request, context): """Set the UDP port range used for SCION underlay connections.""" asn_str, _ = get_client_from_metadata(context.invocation_metadata()) asn = ASN(asn_str) # Validate arguments and retrieve the interface try: vlan = VLAN.objects.get(name=request.interface_vlan) except VLAN.DoesNotExist: context.abort(grpc.StatusCode.NOT_FOUND, "VLAN does not exist") try: ip = ipaddress.ip_address(request.interface_ip) except ValueError: context.abort(grpc.StatusCode.INVALID_ARGUMENT, "Invalid IP address") try: interface = Interface.objects.get(vlan=vlan, public_ip=ip) except (Interface.DoesNotExist, Interface.MultipleObjectsReturned): context.abort(grpc.StatusCode.NOT_FOUND, "Interface not found") recreate_links = not (request.first_port <= interface.first_port and request.last_port >= interface.last_port) try: interface.first_port = request.first_port interface.last_port = request.last_port interface.save() except ValidationError: context.abort(grpc.StatusCode.INVALID_ARGUMENT, "Invalid port range") if recreate_links: # Recreate the interface's links with the new ports for link in interface.query_links().all(): link.delete() policy_resolver.update_links(vlan, AS.objects.get(asn=asn)) return peering_pb2.google_dot_protobuf_dot_empty__pb2.Empty()
def update_links(modeladmin, request, queryset): for iface in queryset.all(): policy_resolver.update_links(iface.vlan, iface.peering_client.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)