Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lightechllc/django-nginx-secure-links
This repository serves as a module for creating private URLs in the Django Framework using the Nginx module ngx_http_secure_link_module.
https://github.com/lightechllc/django-nginx-secure-links
django nginx-secure-links python
Last synced: 3 months ago
JSON representation
This repository serves as a module for creating private URLs in the Django Framework using the Nginx module ngx_http_secure_link_module.
- Host: GitHub
- URL: https://github.com/lightechllc/django-nginx-secure-links
- Owner: LighTechLLC
- License: mit
- Created: 2022-11-16T09:34:42.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2024-08-12T21:38:49.000Z (5 months ago)
- Last Synced: 2024-10-11T07:21:24.492Z (3 months ago)
- Topics: django, nginx-secure-links, python
- Language: Python
- Homepage: https://django-nginx-secure-links.readthedocs.io/en/latest/
- Size: 47.9 KB
- Stars: 15
- Watchers: 2
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.rst
- Changelog: CHANGELOG.rst
- License: LICENSE
Awesome Lists containing this project
README
.. image:: https://github.com/LighTechLLC/django-nginx-secure-links/actions/workflows/ci.yml/badge.svg
:target: https://github.com/LighTechLLC/django-nginx-secure-links/actions/workflows/ci.yml
:alt: Build Status.. image:: https://coveralls.io/repos/LighTechLLC/django-nginx-secure-links/badge.svg?branch=master
:target: https://coveralls.io/r/LighTechLLC/django-nginx-secure-links?branch=master
:alt: CoverageDjango Nginx Secure Links
=========================This module is a Django extension for using `ngx_http_secure_link_module `_.
It provides private urls with expiration lifetime by implementing described logic of ngx_http_secure_link_module.
The major advantage of the extension is that Django delegates file serving on Nginx layer and does only pre-signed urls generation.Requirements
============Django Nginx Secure Links requires Django 3.2 or later.
Installation
============Installing from PyPI is as easy as doing:
.. code-block:: bash
pip install django-nginx-secure-links
If you want to install it from source, grab the git repository from GitHub and run setup.py:
.. code-block:: bash
git clone git://github.com/lighTechLLC/django-nginx-secure-links.git
cd django-nginx-secure-links
python setup.py installNginx module set up
===================**Option 1**
Install using apt (Ubuntu example):
.. code-block:: bash
sudo apt install nginx-extras
**Option 2**
Build from sources:
.. code-block:: bash
./configure .... --with-http_secure_link_module
Quick example
=============1. Django settings set up **settings.py**:
.. code-block:: python
INSTALLED_APPS = (
...
'nginx_secure_links',
...
)
MEDIA_ROOT = '/var/www/media/'
MEDIA_URL = '/media/'
SECURE_LINK_SECRET_KEY = 'KfM6aA6M7H'- Django < 4.2
.. code-block:: python
DEFAULT_FILE_STORAGE = 'nginx_secure_links.storages.FileStorage'
- Django >= 4.2
.. code-block:: python
STORAGES = {
"default": {
"BACKEND": "nginx_secure_links.storages.FileStorage",
},
"staticfiles": {
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
},
}2. Create a private file inside your ``settings.MEDIA_ROOT``:
.. code-block:: bash
echo "I'm private text file" > /var/www/media/sample.txt
3. Let's start ``runserver`` and access the file outside of Django file storage. It works and the file is available. There is no access denied, because of ``runserver`` mode:
.. code-block:: bash
curl http://127.0.0.1:8000/media/sample.txt
4. Set up Nginx virtual host file **site.conf**:
.. code-block:: nginx
server 127.0.0.1;
listen 80;...
location /media/ {
secure_link $arg_token,$arg_expires;
secure_link_md5 "$secure_link_expires$uri KfM6aA6M7H";if ($secure_link = "") {
return 403;
}if ($secure_link = "0") {
return 410;
}alias /var/www/media/;
}...
5. Let's access the file through Nginx host/port.
.. code-block:: bash
curl http://127.0.0.1/media/sample.txt
Because of Nginx secure link module protection, the file won't be served
without ``?token=...&expires=...`` parameters. Only django users will be able
to access files which urls generated by django storage.Usage
=====**models.py**
.. code-block:: python
class Report(models.Model):
pdf_file = models.FileField(upload_to='reports')**views.py**
.. code-block:: python
def report_details(request, report_id)
instance = Report.objects.get(id=report_id)
return JsonResponse({'url': instance.pdf_file.url})**json response**
.. code-block:: json
{
"url": "/media/reports/29974.pdf?expires=1599214310&token=ErLcMm96-4h2qsuj2Avo-w"
}That's it, all uploaded media files through Django will be pre-signed.
If you work locally and do not want to install Nginx, let's skip it for
local development- django will generate pre-signed urls, but all files will be
available because of ``runserver`` command serves files and does not provide
3rd-party ``nginx-secure-link`` module functionality.Settings
========- ``SECURE_LINK_SECRET_KEY``
Your specific secret string which Nginx is going to use in ``secure_link_md5`` directive.
- ``SECURE_LINK_TOKEN_FIELD`` (optional, default: ``token``)
Your custom name of the hash GET-parameter (?token=xyz)
- ``SECURE_LINK_EXPIRES_FIELD`` (optional, default: ``expires``)
Your custom name of expiration timestamp GET-parameter (?expires=1599215210)
- ``SECURE_LINK_EXPIRATION_SECONDS`` (optional, default: ``86400``- 1 day)
Your custom value of expiration seconds. Any pre-signed link will be expired after ``SECURE_LINK_EXPIRATION_SECONDS``.
- ``SECURE_LINK_PRIVATE_PREFIXES`` (optional, default: ``[]``)
List of private paths without ``MEDIA_URL`` prefix. Just leave it empty for making all media urls private. Example:
.. code-block:: python
MEDIA_URL = '/media/'
SECURE_LINK_PRIVATE_PREFIXES = [
'documents/',
'reports/',
]In such case all ``/media/documents/`` and ``/media/reports/`` urls will be private and pre-signed by using token and expiration time. If any of existing prefixes on the project are not listed in ``SECURE_LINK_PRIVATE_PREFIXES``, so the url will be public.
- ``SECURE_LINK_PUBLIC_PREFIXES`` (optional, default: ``[]``)
List of private paths without ``MEDIA_URL`` prefix. Example:
.. code-block:: python
MEDIA_URL = '/media/'
SECURE_LINK_PUBLIC_PREFIXES = [
'avatars/',
'shared/',
]In such case only ``/media/avatars/`` and ``/media/shared/`` urls will be public and generated without pre-signed urls. All other urls, will be private and pre-signed by using token and expiration time.
**Important** If you want to keep all media files privately, ``SECURE_LINK_PRIVATE_PREFIXES`` and ``SECURE_LINK_PUBLIC_PREFIXES`` should be ``[]``.
Custom storage for non-media files
==================================**Example 1:** We are going to use our own server directory and url prefix instead
of ``settings.MEDIA_ROOT`` / ``settings.MEDIA_URL``.
The example is going to use all default ``settings.SECURE_LINK_*``.. code-block:: python
from nginx_secure_links.storages import FileStorage
storage = FileStorage(location='/var/www/personal_data/', base_url='/personal/')
storage.url('profile.pdf')
storage.url('profile.pdf', lifetime=60)
storage.url('profile.pdf', lifetime=0)**Example 2**: We are going to use custom storage with all overridden settings.
.. code-block:: python
from nginx_secure_links.storages import FileStorage
storage = FileStorage(
location='/var/www/personal_data/',
base_url='/personal/'
nginx_secret_key='91rdywY7d4494X',
expires_field_name='expires_timestamp',
token_field_name='hash',
private_prefixes=[],
public_prefixes=[],
expires_seconds=60 * 60, # 60min
) # all private
storage.url('profile.pdf') # /personal/profile.pdf?hash=mlkiuhbhu83d&expires_timestamp=2147483647Using It
========Generate pre-signed url by passing public url::
python manage.py secure_links_gen_signed /media/reports/sample.pdf
Generates a sample of Nginx location basing on the settings::
python manage.py secure_links_nginx_location
Found a Bug?
============
Issues are tracked via GitHub issues at the `project issue page
`_.