def check_reference(resource, attrs): # # Reference check for VPNBind records # # If a IPsecEnforcer is using a VPNBind record, then the VPNBind should not # be allowed to be deleted. if resource in VPN_BIND: relation = RESOURCE_TO_RELATION_MAP[resource] # Find the VPNEndpoint/Peer-VPNEndpoint field names vpnendpoint_field, peer_vpnendpoint_field = get_vpnendpoints_field( relation) # Get the list of IPsecEnforcers ipsecenforcers = ( IPsecEnforcerInfo().get_vpnendpoint_to_ipsecenforcer_and_fqdn_list( attrs[vpnendpoint_field])) peer_ipsecenforcers = ( IPsecEnforcerInfo().get_vpnendpoint_to_ipsecenforcer_and_fqdn_list( attrs[peer_vpnendpoint_field])) if ipsecenforcers or peer_ipsecenforcers: raise serializers.ValidationError("Resource can not be deleted. " "The resource configuration is " "in use by IPsecEnforcer(s)") # # Reference check for Non-VPNBind records # dependencies = RESOURCE_DEPENDENCY_MAP.get(resource, None) if dependencies is None: return resources = dependencies[0] relations = [RESOURCE_TO_RELATION_MAP[relation] for relation in resources] fields = RESOURCE_DEPENDENCY_MAP[resource][1:] reference_exists = False for relation, field in itertools.product(relations, fields): value = attrs.get('id', None) if value is not None: records = storage.plugin.get_records(relation) for record in records: if record[field] == str(attrs['id']): reference_exists = True break if reference_exists: raise serializers.ValidationError("Resource can not be deleted. " "{0} with id {1} is in " "use".format( resource, str(value)))
def ipsec_enforcer_registration(request, version, namespace, pk='None'): """Create, list(one or all), update or delete resource. Args: version (str): API version namespace (str): Tenant name request (HttpRequest): Complete HTTP request with header and body pk (str): Primary Key of Record. Defaults to 'None'. Note: version and namespace is currently not used. It is for future support of multiple API versions and multi tenants. Returns: HTTPResponse with data/error and status code. """ # Retrieve record(s) to be used by later operations(except POST) # pk = 'None' means retrieve all records if request.method != 'POST': try: record = IPsecEnforcerRegistration.get(id=pk) except ResourceNotFound: raise NotFound( detail=("Resource {0} with id {1} not " "found").format(IPsecEnforcerRegistration, pk)) # Get the record with id 'pk' if request.method == 'GET': policy = IPsecEnforcerConfig().prepare_ipsec_enforcer_config(pk) return Response(policy, status=status.HTTP_200_OK) # Create and store a record if request.method == 'POST': data = JSONParser().parse(request) serializer = IPsecEnforcerRegistrationSerializer( data=data, context={'resource_name': 'IPsecEnforcerRegistration'}) if serializer.is_valid(): serializer.save() IPsecEnforcerNotification.client_ipsecenforcer_register( serializer.data['id']) return Response(serializer.data, status=status.HTTP_201_CREATED) else: serializer.log_invalid() return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # Delete the record with id 'pk' if request.method == 'DELETE': # Before de-registration(deletion), fetch all the VPNEndpoint(s) # associated with IPsecEnforcer mapping_records = ( IPsecEnforcerInfo.get_ipsecenforcer_to_vpnendpoint_map(record.id)) # Delete the record record.delete() # Notify the peer IPsecEnforcer(s) IPsecEnforcerNotification.client_ipsecenforcer_deregister( record.id, mapping_records) return HttpResponse(status=status.HTTP_204_NO_CONTENT)
def client_ipsecenforcer_register(cls, ipsecenforcer_id): """IPC Client for IPsecEnforcer Registration Args: ipsecenforcer_id: id of IPsecEnforcer """ try: client = Client((cls.process_fqdn, cls.process_port)) except socket_error: return mapping_records = ( IPsecEnforcerInfo.get_ipsecenforcer_to_vpnendpoint_map( ipsecenforcer_id) ) notification_message = { 'notification_type': 'REGISTRATION', 'ipsecenforcer_id': ipsecenforcer_id, 'mapping_records': mapping_records } # Send the notification_message to the IPsecEnforcer Notification # listener try: client.send(notification_message) except socket_error: return
def _add_config_version(self, ipsecenforcer_id): """Add config version Args: ipsecenforcer_id (str): id of IPsecEnforcer """ config_version = (IPsecEnforcerInfo( ).increment_ipsecenforcer_config_version(ipsecenforcer_id)) self.ipsecenforcer_config.update({'version': config_version})
def save(self): """Write the record in the storage backend Returns: self (Resource): Return the object itself Raises: TypeError: When error storing the resource in backend """ try: IPsecEnforcerInfo().register_ipsecenforcer(self) return self except TypeError: LOG.error( _("Error in storing data for %s with id %s" % (self.resource_name, self.id))) raise finally: IPsecEnforcerInfo().delete_ipsecenforcer_to_vpnendpoint_map( self.id, temp=True)
def notify_ipsecenforcers_of_vpnendpoint(cls, vpnendpoint_id): """Notify all the IPsecEnforcer(s) of the VPNEndpoint record Args: vpnendpoint_id (str): ID of VPNEndpoint record """ # Fetch all the IPsecEnforcers that belong to VPNEndpoint record ipsecenforcers_fqdn_id = (IPsecEnforcerInfo( ).get_vpnendpoint_to_ipsecenforcer_and_fqdn_list(vpnendpoint_id)) # Remove duplicates to make sure that each IPsecEnforcer will receive a # single notification ipsecenforcers_fqdn_id = { v['fqdn']: v for v in ipsecenforcers_fqdn_id }.values() map(cls.notify_ipsecenforcers, ipsecenforcers_fqdn_id)
def _add_fqdn_list_of_vpnendpoint(self, vpnendpoint_id): """Add FQDN of Peer VPNEndpoint to the configuration policy Args: vpnendpoint_id (str): id of VPNEndpointgroup Returns: list : List of FQDN for VPNEndpoint """ records = (IPsecEnforcerInfo( ).get_vpnendpoint_to_ipsecenforcer_and_fqdn_list(vpnendpoint_id)) fqdn_list = [record['fqdn_tunnel'] for record in records] if fqdn_list: self.ipsecenforcer_config['fqdn_list'].update( {vpnendpoint_id: fqdn_list}) return fqdn_list
def validate(self, attrs): """Check that the endpoint_name is valid""" endpoint_name = attrs['endpoint_name'] endpoint_type = attrs['endpoint_type'] if len(endpoint_name) != len(set(endpoint_name)): raise serializers.ValidationError( _("Duplicates are not allowed in " "the list of endpoint_name")) if len(endpoint_name) != len(endpoint_type): raise serializers.ValidationError( _("Number of entries in the list " "of endpoint_type and " "endpoint_name should be same")) for endpoint_name, endpoint_type in izip_longest( endpoint_name, endpoint_type): if endpoint_type == 'group': record = storage.plugin.get_records_by_secondary_index( 'vpnendpointgroups', 'name', endpoint_name) elif endpoint_type == 'localsite': record = storage.plugin.get_records_by_secondary_index( 'vpnendpointlocalsites', 'name', endpoint_name) elif endpoint_type == 'remotesite': record = storage.plugin.get_records_by_secondary_index( 'vpnendpointremotesites', 'name', endpoint_name) if (record is None) or (not record): raise serializers.ValidationError( ("endpoint_name {0} is not " "a valid endpoint_type " "{1}").format(endpoint_name, endpoint_type)) else: IPsecEnforcerInfo().put_ipsecenforcer_to_vpnendpoint_map( attrs['id'], { 'endpoint_id': record[0]['id'], 'endpoint_type': endpoint_type }, temp=True) return attrs
def _add_psk(self, vpnbind_id, psk, peer_vpnendpoint_id, fqdn, peer): """Add PSK(Pre-Shared Key) Args: vpnbind_id (str): id of VPNBind record psk (str): PSK provided with the VPNBind record peer_vpnendpoint_id (str): id of peer VPNEndpoint fqdn (str): FQDN of IPsecEnforcer Tunnel Interface peer (bool): True, If IPsecEnforcer belongs to peer VPNEndpoint or Else False. """ records = (IPsecEnforcerInfo( ).get_vpnendpoint_to_ipsecenforcer_and_fqdn_list(peer_vpnendpoint_id)) fqdn_list = [record['fqdn_tunnel'] for record in records] if peer: fqdn_pairs = itertools.product([fqdn], fqdn_list) else: fqdn_pairs = itertools.product(fqdn_list, [fqdn]) fqdn_pair_with_psk = self._generate_psk(vpnbind_id, fqdn_pairs, psk) self.ipsecenforcer_config['fqdn_pair_psk'].update(fqdn_pair_with_psk)
def delete(self): IPsecEnforcerInfo().deregister_ipsecenforcer(self)
def prepare_ipsec_enforcer_config(self, ipsecenforcer_id): """Prepare VPN configuration for IPsecEnforcer Args: ipsecenforcer_id (str) : id of IPsecEnforcer Returns: dict : IPsecEnforcer VPN Configuration """ # Reset the ipsecenforcer_config for key in self.ipsecenforcer_config.iterkeys(): self.ipsecenforcer_config[key].clear() # Fetch the IPsecEnforcer record ipsec_enforcer_record = storage.plugin.get_record( 'ipsec_enforcer_registrations', ipsecenforcer_id) # Fetch the VPNEndpoint(s) corresponding to the IPsecEnforcer mapping_records = ( IPsecEnforcerInfo.get_ipsecenforcer_to_vpnendpoint_map( ipsecenforcer_id)) for mapping_record in mapping_records: if mapping_record['endpoint_type'] == 'group': LOG.debug( _("Preparing VPN configurations for IPsecEnforcer id " "%(ipsecenforcer_id)s with vpnendpointgroup id " "%(vpnendpoint_id)s") % { 'ipsecenforcer_id': ipsecenforcer_id, 'vpnendpoint_id': mapping_record['endpoint_id'] }) endpoint_record = storage.plugin.get_record( RESOURCE_TO_RELATION_MAP['VPNEndpointGroup'], mapping_record['endpoint_id']) self.process_vpnbind_config(ipsec_enforcer_record, VPN_BIND_GROUP, endpoint_record['id']) elif mapping_record['endpoint_type'] == 'localsite': LOG.debug( _("Preparing VPN configurations for IPsecEnforcer id " "%(ipsecenforcer_id)s with vpnendpointlocalsite id " "%(vpnendpoint_id)s") % { 'ipsecenforcer_id': ipsecenforcer_id, 'vpnendpoint_id': mapping_record['endpoint_id'] }) endpoint_record = storage.plugin.get_record( RESOURCE_TO_RELATION_MAP['VPNEndpointLocalSite'], mapping_record['endpoint_id']) self.process_vpnbind_config(ipsec_enforcer_record, VPN_BIND_LOCALSITE, endpoint_record['id']) elif mapping_record['endpoint_type'] == 'remotesite': LOG.debug( _("Preparing VPN configurations for IPsecEnforcer id " "%(ipsecenforcer_id)s with vpnendpointremotesite " "id %(vpnendpoint_id)s") % { 'ipsecenforcer_id': ipsecenforcer_id, 'vpnendpoint_id': mapping_record['endpoint_id'] }) endpoint_record = storage.plugin.get_record( RESOURCE_TO_RELATION_MAP['VPNEndpointRemoteSite'], mapping_record['endpoint_id']) self.process_vpnbind_config(ipsec_enforcer_record, VPN_BIND_REMOTESITE, endpoint_record['id']) if mapping_records: self._add_config_version(ipsecenforcer_id) return self.ipsecenforcer_config