Skip to main content

Django SNS handling and signals.

Project description

A Django library for handling and validating AWS SNS (Simple Notification Service) webhook messages with cryptographic signature verification and Django signals.

Features

  • Cryptographic Signature Verification - Validates SNS message authenticity using AWS certificates

  • Django Signals - Fire signals for subscription, unsubscription, and notification events

  • Auto-confirmation - Automatically confirms SNS subscriptions and unsubscriptions

  • Certificate Caching - Configurable caching of AWS signing certificates (default: 24 hours)

  • Minimal Dependencies - Only requires Django and cryptography; uses Python’s standard library for HTTP

  • Type Safety - Full type hints with Python 3.10+

Installation

pip install django-sns-signals

Requirements

  • Python 3.10+

  • Django 4.2+

  • cryptography ~=46.0.0

Quick Start

1. Add to your Django URLs

# urls.py
from django.urls import path
from django_sns_signals.views import sns_webhook

urlpatterns = [
    path('sns/webhook/', sns_webhook, name='sns_webhook'),
]

2. Connect to Django Signals

# apps.py or signals.py
from django.apps import AppConfig
from django_sns_signals import sns_notification

def handle_notification(sender, notification_message, topic_arn, subject=None, **kwargs):
    """Handle SNS notifications"""
    print(f"Received from {topic_arn}: {notification_message}")
    # Your business logic here

class MyAppConfig(AppConfig):
    def ready(self):
        sns_notification.connect(handle_notification)

3. Configure SNS Topic (AWS Console)

  1. Create an SNS topic in AWS

  2. Add an HTTPS subscription with your webhook URL: https://yourdomain.com/sns/webhook/

  3. The library will automatically confirm the subscription

Configuration

Optional Settings

Add to your Django settings.py:

# Optional: Configure signing certificate cache timeout (in seconds)
# Default: 86400 (24 hours)
SNS_SIGNING_CERT_CACHE_TIMEOUT = 86400

The certificate cache timeout controls how long AWS SNS signing certificates are cached. AWS rarely rotates these certificates, so a longer cache period (24 hours or more) is safe and reduces HTTP requests.

Architecture

Core Components

SNSSignatureValidator

Validates AWS SNS message signatures using cryptographic verification:

  • Verifies certificate URLs come from amazonaws.com domain

  • Implements certificate caching using Django’s cache framework

  • Builds canonical signing strings based on message type

  • Uses RSA PKCS1v15 padding with SHA1 hash (AWS SNS standard)

sns_webhook View

Django view function that handles SNS webhook POST requests:

  • CSRF exempt (AWS cannot provide CSRF tokens)

  • Validates message signatures before processing

  • Handles three message types:

    • SubscriptionConfirmation: Auto-confirms by fetching SubscribeURL

    • UnsubscribeConfirmation: Auto-confirms unsubscription by fetching SubscribeURL

    • Notification: Processes actual SNS notifications and fires signals

  • Returns appropriate HTTP status codes (200-499 range required by SNS)

Django Signals

The library fires Django signals for each SNS message type:

sns_subscription_confirmation

Fired after successful subscription confirmation.

Signal Parameters:

  • message (dict) - Full parsed SNS message

  • raw_message (bytes) - Raw request body

  • message_id (str) - Unique message identifier

  • topic_arn (str) - Topic ARN

  • subject (str | None) - Optional subject

  • timestamp (str) - Message timestamp

  • subscribe_url (str) - Subscription confirmation URL

  • token (str) - Subscription token

sns_unsubscribe_confirmation

Fired after successful unsubscribe confirmation.

Signal Parameters:

  • message (dict) - Full parsed SNS message

  • raw_message (bytes) - Raw request body

  • message_id (str) - Unique message identifier

  • topic_arn (str) - Topic ARN

  • subject (str | None) - Optional subject

  • timestamp (str) - Message timestamp

  • subscribe_url (str) - Unsubscribe confirmation URL

  • token (str) - Unsubscription token

sns_notification

Fired when a notification is received.

Signal Parameters:

  • message (dict) - Full parsed SNS message

  • raw_message (bytes) - Raw request body

  • message_id (str) - Unique message identifier

  • topic_arn (str) - Topic ARN

  • subject (str | None) - Optional subject

  • timestamp (str) - Message timestamp

  • notification_message (str) - The actual notification payload

  • unsubscribe_url (str) - URL to unsubscribe from topic

Usage Examples

Basic Notification Handler

from django_sns_signals import sns_notification

def handle_sns_notification(sender, notification_message, topic_arn, subject=None, **kwargs):
    print(f"Topic: {topic_arn}")
    print(f"Subject: {subject}")
    print(f"Message: {notification_message}")

sns_notification.connect(handle_sns_notification)

Topic-Specific Handler

from django_sns_signals import sns_notification
import json

def handle_order_notifications(sender, notification_message, topic_arn, **kwargs):
    if 'orders' not in topic_arn:
        return  # Ignore non-order topics

    order_data = json.loads(notification_message)
    process_order(order_data)

sns_notification.connect(handle_order_notifications)

Subscription Tracking

from django_sns_signals import sns_subscription_confirmation, sns_unsubscribe_confirmation

def log_subscription(sender, topic_arn, **kwargs):
    print(f"Subscribed to: {topic_arn}")

def log_unsubscription(sender, topic_arn, **kwargs):
    print(f"Unsubscribed from: {topic_arn}")

sns_subscription_confirmation.connect(log_subscription)
sns_unsubscribe_confirmation.connect(log_unsubscription)

Security

Message Signature Validation

All SNS messages are cryptographically validated before processing:

  1. Extract SigningCertURL from SNS message

  2. Validate URL hostname ends with .amazonaws.com

  3. Fetch certificate (cached for performance)

  4. Build canonical string-to-sign based on message type

  5. Verify signature using certificate’s public key with PKCS1v15 padding and SHA1

  6. Reject message if signature invalid

The library follows AWS best practices for SNS message verification as documented in the AWS SNS Developer Guide.

Development

Setup

# Clone the repository
git clone https://github.com/newadventures/django-sns-signals.git
cd django-sns-signals

# Install in development mode
pip install -e .
pip install -r requirements_dev.txt

Running Tests

# Run tests with pytest
pytest tests/

# Or with Django's test runner
python -m django test --settings=tests.settings

# Run with coverage
pytest --cov=django_sns_signals tests/

Code Quality

# Format and lint code
ruff check src/ tests/
ruff format src/ tests/

Building the Package

# Build distribution packages
python -m build

# Check package for PyPI compliance
twine check dist/*

License

BSD-3-Clause License - see LICENSE file for details.

Support

For issues and questions, please use the GitHub issue tracker.

Project details


Release history Release notifications | RSS feed

This version

0.1

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_sns_signals-0.1.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_sns_signals-0.1-py3-none-any.whl (7.9 kB view details)

Uploaded Python 3

File details

Details for the file django_sns_signals-0.1.tar.gz.

File metadata

  • Download URL: django_sns_signals-0.1.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for django_sns_signals-0.1.tar.gz
Algorithm Hash digest
SHA256 63eaa8bf7e1054cd2b6173f1e263d15490723001233b99c0d08167567eb27dcf
MD5 5c2b70818dc60d09aeea5783298ed6e6
BLAKE2b-256 6582b833b011fcb8935ba0a34eab50176e19ecf3fbdf444be0908580d96592b5

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_sns_signals-0.1.tar.gz:

Publisher: publish-to-pypi.yml on newadventures/django-sns-signals

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file django_sns_signals-0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_sns_signals-0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 69364d75a6fde9c915f722d4324afc6a95992d613d232bf1c21e29b0f1db6d5f
MD5 bcb04f45fe49495143935335c9e30158
BLAKE2b-256 7d01fdf634627364c3cdc2239ab608ad3b96f3dcbb7fc0d76680ef8220f89ba6

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_sns_signals-0.1-py3-none-any.whl:

Publisher: publish-to-pypi.yml on newadventures/django-sns-signals

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page