Add rate-limiting for Signal messages

This commit is contained in:
Pēteris Caune 2021-01-11 15:07:34 +02:00
parent d4aac691ce
commit a80b831eea
No known key found for this signature in database
GPG Key ID: E28D7679E9A9EDE2
3 changed files with 25 additions and 1 deletions

View File

@ -902,6 +902,14 @@ class TokenBucket(models.Model):
# 6 messages for a single chat per minute:
return TokenBucket.authorize(value, 6, 60)
@staticmethod
def authorize_signal(phone):
salted_encoded = (phone + settings.SECRET_KEY).encode()
value = "signal-%s" % hashlib.sha1(salted_encoded).hexdigest()
# 6 messages for a single recipient per minute:
return TokenBucket.authorize(value, 6, 60)
@staticmethod
def authorize_sudo_code(user):
value = "sudo-%d" % user.id

View File

@ -6,7 +6,7 @@ from unittest.mock import patch
from django.utils.timezone import now
from django.test.utils import override_settings
from hc.api.models import Channel, Check, Notification
from hc.api.models import Channel, Check, Notification, TokenBucket
from hc.test import BaseTestCase
@ -80,3 +80,14 @@ class NotifySignalTestCase(BaseTestCase):
cmd = " ".join(args[0])
self.assertIn("Foo & Bar", cmd)
@override_settings(SECRET_KEY="test-secret")
def test_it_obeys_rate_limit(self):
# "2862..." is sha1("+123456789test-secret")
obj = TokenBucket(value="signal-2862991ccaa15c8856e7ee0abaf3448fb3c292e0")
obj.tokens = 0
obj.save()
self.channel.notify(self.check)
n = Notification.objects.first()
self.assertEqual(n.error, "Rate limit exceeded")

View File

@ -673,6 +673,11 @@ class Signal(Transport):
if not settings.SIGNAL_CLI_USERNAME:
return "Signal notifications are not enabled"
from hc.api.models import TokenBucket
if not TokenBucket.authorize_signal(self.channel.phone_number):
return "Rate limit exceeded"
text = tmpl("signal_message.html", check=check, site_name=settings.SITE_NAME)
args = settings.SIGNAL_CLI_CMD.split()