Как да засилите сигурността на вашия производствен Django проект


Авторът е избрал програмата Write for DOnations.

Въведение

Разработването на Django приложение може да бъде удобно изживяване, защото е структурирано да бъде гъвкаво и мащабируемо. Тази предпоставка се простира до настройките на Django, ориентирани към сигурността, които могат да ви помогнат да подготвите проекта си за производство. Но има няколко начина за допълнителна защита на вашия проект.

Разбиването на вашите настройки ще ви позволи да настроите различни конфигурации въз основа на средата. Използването на .env за задаване на променливи на средата или скриване на поверителни настройки ще гарантира, че няма да издадете подробности, които могат да компрометират вашия проект. А промяната на URL адресите по подразбиране и други настройки ще ви помогне да избегнете често срещани уязвимости в сигурността.

Докато внедряването на тези стратегии може да изглежда отнема много време в началото, разработването на практичен работен процес ще ви позволи да внедрите версии на вашия проект, без да правите компромис със сигурността или вашата производителност.

В този урок ще използвате ориентиран към сигурността работен процес за вашия проект Django, като внедрите и конфигурирате настройки, базирани на средата, .env и вградените настройки за сигурност на Django. Всички тези функции се допълват взаимно и ще доведат до версия на вашия Django проект, която е готова за различни подходи, които можете да предприемете за внедряване.

Предпоставки

Преди да започнете това ръководство, ще ви трябва следното:

  • Съществуващ проект на Django. Ако все още нямате такъв, можете да използвате нашия урок за инсталиране на Django и настройка на среда за разработка за настройка. В този урок ще използвате проекта testsite от този урок като пример.
    • За вашия проект Django ще ви е необходим и инсталиран Python 3. Можете да го инсталирате, като следвате стъпка 1 от нашия урок, Как да инсталирате Python 3 и да настроите среда за програмиране на Ubuntu 20.04 сървър.

    • За да използвате сертификата Let’s Encrypt, трябва да имате инсталиран Nginx. Можете да го инсталирате, като следвате нашия урок Как да инсталирате Nginx на Ubuntu 20.04.

    Забележка: Ако използвате съществуващ проект на Django, може да имате различни изисквания. Този урок предлага конкретна структура на проекта; въпреки това можете да използвате всеки от разделите на този урок поотделно, ако е необходимо.

    Стъпка 1 — Преструктуриране на настройките на Django

    Преди да навлезете в тънкостите на защитата на вашия Django проект, ще трябва да влезете в директорията на вашия проект и да активирате вашата виртуална среда:

    1. cd django-apps
    2. . env/bin/activate

    В тази първа стъпка ще започнете, като пренаредите вашия файл settings.py в специфични за средата конфигурации. Това е добра практика, когато трябва да преместите проект между различни среди, например разработка и производство. Тази подредба ще означава по-малко преконфигуриране за различни среди; вместо това ще използвате променлива на средата, за да превключвате между конфигурации, които ще бъдат обсъдени по-късно в урока.

    Създайте нова директория, наречена settings в поддиректорията на вашия проект:

    1. mkdir testsite/testsite/settings

    (Съгласно предварителните условия, този урок използва testsite, но можете да замените името на вашия проект тук.)

    Тази директория ще замени текущия ви конфигурационен файл settings.py; всички ваши настройки, базирани на средата, ще бъдат в отделни файлове, съдържащи се в тази папка.

    Във вашата нова папка settings създайте три Python файла:

    1. cd testsite/testsite/settings
    2. touch base.py development.py production.py

    Файлът development.py ще съдържа настройки, които обикновено използвате по време на разработката. И production.py ще съдържа настройки за използване на производствен сървър. Трябва да ги държите отделно, защото производствената конфигурация ще използва настройки, които няма да работят в среда за разработка; например принудително използване на HTTPS, добавяне на заглавки и използване на производствена база данни.

    Файлът с настройки base.py ще съдържа настройки, от които development.py и production.py ще наследят. Това е за намаляване на излишъка и за поддържане на вашия код по-чист. Тези файлове на Python ще заменят settings.py, така че сега ще премахнете settings.py, за да избегнете объркване на Django.

    Докато все още сте във вашата директория settings, преименувайте settings.py на base.py със следната команда:

    1. mv ../settings.py base.py

    Току-що завършихте контура на вашата нова директория с настройки, базирана на средата. Вашият проект все още няма да разбере новата ви конфигурация, така че следващото ще поправите това.

    Стъпка 2 — Използване на django-environ

    В момента Django няма да разпознае новата ви директория с настройки или нейните вътрешни файлове. Така че, преди да продължите да работите с вашите базирани на среда настройки, трябва да накарате Django да работи с django-environ. Това е зависимост, която зарежда променливи на средата от файл .env. Това означава, че Django ще търси във файл .env в главната директория на вашия проект, за да определи коя конфигурация на настройките ще използва.

    Отидете в главната директория на вашия проект и след това използвайте командата ls, за да изброите съдържанието на директорията:

    1. cd ../../
    2. ls

    Файловете в основната директория на вашия проект трябва да изглеждат така:

    Output
    db.sqlite3 manage.py testsite

    Инсталирайте django-environ:

    1. pip install django-environ

    Сега трябва да конфигурирате Django да използва .env. Ще редактирате два файла, за да направите това: manage.py, за разработка, и wsgi.py, за производство.

    Започнете, като отворите manage.py за редактиране с помощта на nano или предпочитания от вас текстов редактор:

    1. nano manage.py

    Добавете следния маркиран код:

    import os
    import sys
    <^>import environ
    
    environ.Env.read_env()<^>
    
    def main():
        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testsite.settings')
    
        try:
            from django.core.management import execute_from_command_line
        except ImportError as exc:
            raise ImportError(
                "Couldn't import Django. Are you sure it's installed and "
                "available on your PYTHONPATH environment variable? Did you "
                "forget to activate a virtual environment?"
            ) from exc
        execute_from_command_line(sys.argv)
    
    
    if __name__ == '__main__':
        main()
    

    Запазете и затворете manage.py, като натиснете CTRL+X, натиснете Y за запазване и след това натиснете ENTER.

    След това отворете wsgi.py за редактиране:

    1. nano testsite/wsgi.py

    Добавете следните подчертани редове:

    
    import os
    <^>import environ
    
    environ.Env.read_env()<^>
    
    from django.core.wsgi import get_wsgi_application
    
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testsite.settings')
    
    application = get_wsgi_application()
    

    Запишете и затворете файла, като натиснете CTRL+X, натиснете Y за запазване и след това натиснете ENTER.

    Кодът, който сте добавили към двата файла, прави две неща. Първо, всеки път, когато Django се изпълнява — manage.py за текуща разработка, wsgi.py за производство — вие му казвате да търси вашия .env файл. Ако файлът съществува, инструктирате Django да използва файла с настройки, който .env препоръчва; в противен случай използвате конфигурацията за разработка по подразбиране.

    Накрая ще създадете .env в текущата директория:

    1. nano .env

    Сега добавете следния ред, за да настроите средата за разработка:

    DJANGO_SETTINGS_MODULE="testsite.settings.development"
    

    Запишете и затворете файла, като натиснете CTRL+X, натиснете Y за запазване и след това натиснете ENTER.

    Забележка: Добавете .env към вашия файл .gitignore, така че никога да не бъде включен във вашите ангажименти; ще използвате този файл, за да съдържа данни като пароли и API ключове, които не искате да се виждат публично. Всяка среда, в която работи вашият проект, ще има свой собствен .env с настройки за тази конкретна среда.

    Препоръчително е да създадете .env.example, който да включите във вашия проект, за да можете лесно да създадете нов .env, където имате нужда.

    Така че по подразбиране Django ще използва testsite.settings.development, но ако промените DJANGO_SETTINGS_MODULE на testsite.settings.production например, той ще започне да използва вашата производствена конфигурация. След това ще попълните вашите конфигурации на настройките development.py и production.py.

    Стъпка 3 — Създаване на настройки за разработка и производство

    След това ще отворите своя base.py и ще добавите конфигурацията, която искате да промените за всяка среда в отделните development.py и production.py файлове. production.py ще трябва да използва идентификационните данни за вашата производствена база данни, така че се уверете, че имате такива.

    Забележка: От вас зависи да определите кои настройки трябва да конфигурирате въз основа на средата. Този урок ще обхване само общ пример за настройки за производство и разработка (т.е. настройки за сигурност и отделни конфигурации на база данни).

    В този урок вие използвате проекта Django от предварителния урок като примерен проект. Ще преместите настройките от base.py в development.py. Започнете, като отворите development.py:

    1. nano testsite/settings/development.py

    След това добавете следния код:

    import os
    from .base import *
    
    DEBUG = True
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }
    

    Запишете и затворете файла, като натиснете CTRL+X, натиснете Y за запазване и след това натиснете ENTER.

    Първо ще импортирате от base.py—този файл наследява настройките от base.py. След това ще прехвърлите настройките, които искате да промените за средата за разработка. В този случай настройките, специфични за разработката, са следните: DEBUG, което трябва да бъде True в разработката, но не и в производството; и DATABASES, локална база данни вместо производствена база данни. Тук използвате SQLite база данни за разработка.

    Забележка: За целите на сигурността изходът DEBUG на Django никога няма да показва никакви настройки, които може да съдържат низовете API, KEY, PASS, SECRET , ПОДПИС или TOKEN.

    Това е, за да се гарантира, че тайните няма да бъдат разкрити, ако случайно внедрите проект в производство с все още активиран DEBUG.

    Като се има предвид това, никога не внедрявайте публично проект с активиран DEBUG. Това само ще изложи на риск сигурността на вашия проект.

    След това ще добавите към production.py. Отворете файла със следната команда:

    1. nano testsite/settings/production.py

    След това добавете следния код. Производството ще бъде подобно на development.py, но с различна конфигурация на база данни и DEBUG, зададен на False:

    import os
    from .base import *
    import environ
    
    env = environ.Env()
    environ.Env.read_env()
    
    DEBUG = False
    
    ALLOWED_HOSTS = []
    
    DATABASES = {
        'default': {
            'ENGINE': env('SQL_ENGINE', default='django.db.backends.sqlite3'),
            'NAME': env('SQL_DATABASE', default=os.path.join(BASE_DIR, 'db.sqlite3')),
            'USER': env('SQL_USER', default='user'),
            'PASSWORD': env('SQL_PASSWORD', default='password'),
            'HOST': env('SQL_HOST', default='localhost'),
            'PORT': env('SQL_PORT', default=''),
        }
    }
    

    Запишете и затворете файла, като натиснете CTRL+X, натиснете Y за запазване и след това натиснете ENTER.

    За дадената примерна конфигурация на база данни можете да използвате .env, за да конфигурирате всяко от дадените идентификационни данни, с включени стойности по подразбиране. Ако приемем, че вече сте настроили база данни за производствената версия на вашия проект, моля, използвайте вашата конфигурация вместо предоставения пример.

    Вече сте конфигурирали проекта си да използва различни настройки въз основа на DJANGO_SETTINGS_MODULE в .env. Предвид примерните настройки, които сте използвали, когато настроите проекта си да използва производствени настройки, DEBUG става False, ALLOWED_HOSTS се дефинира и вие започнете да използвате различна база данни, която (вече) сте конфигурирали на вашия сървър.

    Стъпка 4 — Работа с настройките за сигурност на Django

    Django включва настройки за сигурност, готови за добавяне към вашия проект. В тази стъпка ще добавите настройки за сигурност към вашия проект, които се считат за основни за всеки производствен проект. Тези настройки са предназначени за използване, когато вашият проект е достъпен за обществеността. Не се препоръчва да използвате някоя от тези настройки във вашата среда за разработка; следователно в тази стъпка вие ограничавате тези настройки до конфигурацията production.py.

    В по-голямата си част тези настройки ще наложат използването на HTTPS за различни уеб функции, като сесийни бисквитки, CSRF бисквитки, надграждане на HTTP до HTTPS и т.н. Следователно, ако все още не сте настроили сървъра си с домейн, сочещ към него, засега отложете този раздел. Ако трябва да настроите сървъра си готов за внедряване, вижте Заключението за предложени статии по този въпрос.

    Първо отворете production.py:

    1. nano testsite/settings/production.py

    Във вашия файл добавете маркираните настройки, които работят за вашия проект, в съответствие с обясненията след кода:

    import os
    from .base import *
    import environ
    
    env = environ.Env()
    environ.Env.read_env()
    
    DEBUG = False
    
    ALLOWED_HOSTS = ['your_domain', 'www.your_domain']
    
    DATABASES = {
        'default': {
            'ENGINE': env('SQL_ENGINE', default='django.db.backends.sqlite3'),
            'NAME': env('SQL_DATABASE', default=os.path.join(BASE_DIR, 'db.sqlite3')),
            'USER': env('SQL_USER', default='user'),
            'PASSWORD': env('SQL_PASSWORD', default='password'),
            'HOST': env('SQL_HOST', default='localhost'),
            'PORT': env('SQL_PORT', default=''),
        }
    }
    
    SECURE_SSL_REDIRECT = True
    
    SESSION_COOKIE_SECURE = True
    
    CSRF_COOKIE_SECURE = True
    
    SECURE_BROWSER_XSS_FILTER = True
    

    • ALLOWED_HOSTS е списък от низове, които представляват имената на хост/домейни, които вашият проект може да обслужва. Това е мярка за сигурност за предотвратяване на нападател да отрови кеш паметта и DNS. Намерете повече подробности за ALLOWED_HOSTS в документацията на Django.
    • SECURE_SSL_REDIRECT пренасочва всички HTTP заявки към HTTPS (освен ако не е изключено). Това означава, че вашият проект винаги ще се опитва да използва криптирана връзка. Ще трябва да имате конфигуриран SSL на вашия сървър, за да работи това. Обърнете внимание, че ако вече сте конфигурирали Nginx или Apache да правят това, тази настройка ще бъде излишна.
    • SESSION_COOKIE_SECURE казва на браузъра, че бисквитките могат да се обработват само през HTTPS. Това означава, че бисквитките, които вашият проект произвежда за дейности, като влизания, ще работят само през криптирана връзка.
    • CSRF_COOKIE_SECURE е същото като SESSION_COOKIE_SECURE, но се отнася за вашия CSRF токен. CSRF токените предпазват от фалшифициране на заявки между сайтове. CSRF защитата на Django прави това, като гарантира, че всички изпратени формуляри (за влизане, регистрации и т.н.) във вашия проект са създадени от вашия проект, а не от трета страна.
    • SECURE_BROWSER_XSS_FILTER задава X-XSS-Protection: 1; mode=block заглавка на всички отговори, които все още го нямат. Това гарантира, че трети страни не могат да инжектират скриптове във вашия проект. Например, ако потребител съхрани скрипт във вашата база данни с помощта на публично поле, когато този скрипт бъде извлечен и показан на други потребители, той няма да се изпълни.

    Запишете и затворете файла, като натиснете CTRL+X, натиснете Y за запазване и след това натиснете ENTER.

    Ако искате да прочетете повече за различните настройки за сигурност, налични в Django, вижте тяхната документация.

    Предупреждение: Документацията на Django посочва, че не трябва да разчитате изцяло на SECURE_BROWSER_XSS_FILTER. Никога не забравяйте да валидирате и дезинфекцирате въведеното.

    Допълнителни настройки

    Следните настройки са за поддръжка на HTTP Strict Transport Security (HSTS)—това означава, че целият ви сайт трябва да използва SSL по всяко време.

    • SECURE_HSTS_SECONDS е времето в секунди, за което е зададен HSTS. Ако зададете това за един час (в секунди), всеки път, когато посетите уеб страница на уебсайта си, това казва на браузъра ви, че през следващия час HTTPS е единственият начин, по който можете да посетите сайта. Ако през този час посетите несигурна част от уебсайта си, браузърът ще покаже грешка и несигурната страница ще бъде недостъпна.
    • SECURE_HSTS_PRELOAD работи само ако е зададен SECURE_HSTS_SECONDS. Тази заглавка инструктира браузъра да зареди предварително HSTS списък.
    • SECURE_HSTS_INCLUDE_SUBDOMAINS прилага HSTS заглавката към всички поддомейни. Активирането на тази заглавка означава, че както your_domain, така и unsecure.your_domain ще изискват криптиране, дори ако unsecure.your_domain не е свързан с този проект на Django.< /li>

    Предупреждение: Неправилното конфигуриране на тези допълнителни настройки може да повреди вашия сайт за значително време.

    Моля, прочетете документацията на Django за HSTS, преди да приложите тези настройки.

    Необходимо е да обмислите как тези настройки ще работят с вашия собствен Django проект; като цяло обсъжданата тук конфигурация е добра основа за повечето Django проекти. След това ще прегледате по-нататъшното използване на .env.

    Стъпка 5 — Използване на django-environ за Secrets

    Последната част на този урок ще ви помогне да използвате django-environ. Това ще ви позволи да скриете определена информация, като например SECRET_KEY на вашия проект или URL адреса за вход на администратора. Това е страхотна идея, ако възнамерявате да публикувате кода си на платформи като GitHub или GitLab, тъй като тези тайни няма да бъдат публикувани. Вместо това, когато първоначално настройвате проекта си в локална среда или сървър, можете да създадете нов .env файл и да дефинирате тези секретни променливи.

    Трябва да скриете вашия SECRET_KEY, така че ще започнете да работите върху това в този раздел.

    Отворете вашия .env файл в основната директория на вашия проект:

    1. nano .env

    И добавете следния ред, като се уверите, че сте заменили your_secret_key с вашите собствени секретни низове:

    DJANGO_SETTINGS_MODULE="testsite.settings.development"
    SECRET_KEY="your_secret_key"
    

    След това запазете и затворете файла, като натиснете CTRL+X, натиснете Y за запазване и след това натиснете ENTER.

    След това отворете base.py:

    1. nano testsite/settings/base.py

    Актуализирайте променливата SECRET_KEY по следния начин:

    . . .
    <^>import environ
    
    env = environ.Env()
    environ.Env.read_env()<^>
    
    SECRET_KEY = env('SECRET_KEY')
    . . .
    

    Забележка: SECRET_KEY не трябва да се заменя с действителния таен ключ. Променливата SECRET_KEY трябва да се остави такава, каквато е, а действителният таен ключ трябва да се добави към файла .env.

    След това запазете и затворете файла, като натиснете CTRL+X, натиснете Y за запазване и след това натиснете ENTER. Вашият проект вече ще използва SECRET_KEY, намиращ се в .env.

    И накрая, ще скриете своя администраторски URL, като добавите дълъг низ от произволни знаци към него. Така че вместо да отидете на your_domain/admin, ще отидете на your_domain/very_secret_url/admin. Това ще гарантира, че както ботовете, така и непознатите ще имат трудности да намерят администраторския ви URL адрес и следователно ще им е по-трудно да се опитват да принудят вашето администраторско влизане.

    Отворете отново .env:

    1. nano .env

    И добавете променлива SECRET_ADMIN_URL:

    DJANGO_SETTINGS_MODULE="testsite.settings.development"
    SECRET_KEY="your_secret_key"
    SECRET_ADMIN_URL="very_secret_url"
    

    Запишете и затворете файла, като натиснете CTRL+X, натиснете Y за запазване и след това натиснете ENTER.

    Сега ще кажете на Django да скрие вашия администраторски URL с SECRET_ADMIN_URL:

    1. nano testsite/urls.py

    Забележка: Не забравяйте да замените very_secret_url с вашия собствен таен URL адрес.

    Ако искате да използвате произволни низове за тази променлива, Python предоставя фантастични примери, които дават, са страхотни начини за създаване на малки програми на Python за генериране на сигурни произволни низове.

    Редактирайте URL адреса на администратора така:

    from django.contrib import admin
    from django.urls import path
    <^>import environ
    
    env = environ.Env()
    environ.Env.read_env()<^>
    
    urlpatterns = [
        path(env('SECRET_ADMIN_URL') + '/admin/', admin.site.urls),
    ]
    

    Запишете и затворете файла, като натиснете CTRL+X, натиснете Y за запазване и след това натиснете ENTER.

    Вече можете да намерите страницата за вход на администратора на /very_secret_url/admin/ вместо само на /admin/:

    Заключение

    В този урок вие сте конфигурирали текущия си Django проект за лесна употреба с различни среди. Вашият проект вече използва django-environ за обработка на тайни и настройки. И вашите производствени настройки вече имат активирани вградени функции за сигурност на Django.

    Ако сте активирали всички препоръчани компоненти за сигурност и сте внедрили повторно настройките според указанията, вашият проект има следните ключови характеристики:

    • SSL/HTTPS за всички комуникации (например поддомейни, бисквитки, CSRF).
    • Предотвратяване на XSS (междусайтови скриптове) атаки.
    • CSRF (Cross-site request forgery) предотвратяване на атаки.
    • Скрит секретен ключ на проекта.
    • Скрит URL адрес за влизане на администратор, предотвратяващ груби атаки.
    • Отделни настройки за разработка и производство.

    Ако се интересувате да научите повече за Django, вижте нашата серия от уроци за разработката на Django.

    Освен това, ако все още не сте пуснали проекта си в производство, ето урок на страницата с теми на Django за допълнителни уроци.

    И, разбира се, прочетете документацията за настройките на Django за допълнителна информация.