Skip to content

Commit

Permalink
feat: Whitelist des ips de Brevo pour inbound emails (#1620)
Browse files Browse the repository at this point in the history
  • Loading branch information
Guilouf authored Dec 31, 2024
1 parent d35c21d commit e33ed12
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
3 changes: 3 additions & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,9 @@

BREVO_TENDERS_MIN_AMOUNT_TO_SEND = env.int("BREVO_TENDERS_MIN_AMOUNT_TO_SEND", 34998)

# ip ranges here (webhook):
# https://help.brevo.com/hc/en-us/articles/15127404548498-Brevo-IP-ranges-List-of-publicly-exposed-services
BREVO_IP_WHITELIST_RANGE: str = env.str("BREVO_IP_WHITELIST_RANGE", "127.0.0.0/20")

# Caching
# https://docs.djangoproject.com/en/4.0/topics/cache/
Expand Down
19 changes: 18 additions & 1 deletion lemarche/api/emails/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os

from django.core import mail
from django.test import TestCase
from django.test import TestCase, override_settings
from django.urls import reverse
from django.utils.text import slugify

Expand Down Expand Up @@ -110,3 +110,20 @@ def test_encoded_items(self):
self.assertEqual(self.conv.siae_encoded.split("_")[:-1], slugify(self.conv.siae.contact_full_name).split("-"))
siae_conv = Conversation.objects.get_conv_from_uuid(conv_uuid=self.conv.siae_encoded, version=1)
self.assertEqual(siae_conv, self.conv)


@override_settings(BREVO_IP_WHITELIST_RANGE="1.179.112.0/20")
class PermissionInboundEmailTestCase(TestCase):
"""Check that BrevoWhitelistPermission is working by only allowing ips
defined in BREVO_IP_WHITELIST_RANGE and mocked above"""

def setUp(self):
self.url = reverse("api:inbound-email-parsing")

def test_ip_rejected(self):
response = self.client.post(path=self.url, data={}, REMOTE_ADDR="127.0.0.1")
self.assertEqual(response.status_code, 401) # unauthorized

def test_ip_allowed(self):
response = self.client.post(path=self.url, data={}, REMOTE_ADDR="1.179.112.0")
self.assertEqual(response.status_code, 400) # bad request
18 changes: 18 additions & 0 deletions lemarche/api/emails/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import ipaddress
import logging

from django.conf import settings
from drf_spectacular.utils import extend_schema
from rest_framework import status
from rest_framework.permissions import BasePermission
from rest_framework.response import Response
from rest_framework.views import APIView

Expand Down Expand Up @@ -30,7 +33,22 @@ def clean_saved_data_of_inbound(data_inbound: dict):
return clean_saved_data


class BrevoWhitelistPermission(BasePermission):
"""
Permission check for allowed IPs.
"""

def has_permission(self, request, view) -> bool:
"""Check if ip adress is in network range"""
ip_addr = ipaddress.ip_address(request.META["REMOTE_ADDR"])
network = ipaddress.ip_network(settings.BREVO_IP_WHITELIST_RANGE)

return ip_addr in network


class InboundParsingEmailView(APIView):
permission_classes = [BrevoWhitelistPermission] + APIView.permission_classes

@extend_schema(exclude=True)
def post(self, request):
serializer = EmailsSerializer(data=request.data)
Expand Down

0 comments on commit e33ed12

Please sign in to comment.