├── demo
├── demo
│ ├── __init__.py
│ ├── templates
│ │ └── home.html
│ ├── urls.py
│ ├── wsgi.py
│ └── settings.py
└── manage.py
├── requirements.txt
├── sslserver
├── management
│ ├── __init__.py
│ └── commands
│ │ ├── __init__.py
│ │ └── runsslserver.py
├── __init__.py
└── certs
│ ├── development.crt
│ └── development.key
├── .gitignore
├── test.exp
├── MANIFEST.in
├── AUTHORS
├── LICENSE
├── setup.py
└── README.rst
/demo/demo/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | django>=1.8
2 |
--------------------------------------------------------------------------------
/sslserver/management/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sslserver/management/commands/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sslserver/__init__.py:
--------------------------------------------------------------------------------
1 | __version__ = "0.20"
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | lint
2 | *.py[co]
3 | __pycache__
4 | dist
5 | MANIFEST
6 | .idea
7 | venv/
8 | *.sw[po]
9 | django_sslserver.egg-info/
10 | build/
11 |
--------------------------------------------------------------------------------
/demo/demo/templates/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | It works !
7 |
8 |
9 |
--------------------------------------------------------------------------------
/test.exp:
--------------------------------------------------------------------------------
1 | #!/usr/bin/expect
2 |
3 | spawn python demo/manage.py runsslserver
4 |
5 | expect "Starting development server at https://127.0.0.1:8000/"
6 | expect "Quit the server with CONTROL-C."
7 |
8 | send "\x03"
9 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include *.txt
2 | include AUTHORS
3 | include LICENSE
4 | include README.rst
5 | recursive-include sslserver development.*
6 |
7 | recursive-exclude demo *
8 | global-exclude *.pyc *.pyo
9 | global-exclude .git
10 |
--------------------------------------------------------------------------------
/demo/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
7 |
8 | from django.core.management import execute_from_command_line
9 |
10 | execute_from_command_line(sys.argv)
11 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | Ted Dziuba
2 | Adam Stokes
3 | titusz
4 | Allan Daemon
5 | Ben Dean-Kawamura
6 | Collin Anderson
7 | Joseph Schilz
8 | Kevin Turner
9 | Nguyễn Hà Dương
10 | Rob Dennis
11 | Steve Gregory
12 | Yurii Zolot'ko
13 | myrs
14 | Anthony Monthe (ZuluPro)
15 |
--------------------------------------------------------------------------------
/demo/demo/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 | from django.shortcuts import render
3 |
4 |
5 | def home(request):
6 | return render(request, 'home.html')
7 |
8 | # Uncomment the next two lines to enable the admin:
9 | # from django.contrib import admin
10 | # admin.autodiscover()
11 |
12 | urlpatterns = [
13 | url('', home),
14 | # Examples:
15 | # url(r'^$', 'demo.views.home', name='home'),
16 | # url(r'^demo/', include('demo.foo.urls')),
17 |
18 | # Uncomment the admin/doc line below to enable admin documentation:
19 | # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
20 |
21 | # Uncomment the next line to enable the admin:
22 | # url(r'^admin/', include(admin.site.urls)),
23 | ]
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Ted Dziuba
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from setuptools import setup, find_packages
3 | import sslserver
4 |
5 | setup(name="django-sslserver",
6 | version=sslserver.__version__,
7 | author="Ted Dziuba",
8 | author_email="tjdziuba@gmail.com",
9 | description="An SSL-enabled development server for Django",
10 | url="https://github.com/teddziuba/django-sslserver",
11 | packages=find_packages(exclude=['demo']),
12 | include_package_data=True,
13 | install_requires=["Django >= 1.8"],
14 | license="MIT",
15 | classifiers=[
16 | "Environment :: Web Environment",
17 | "License :: OSI Approved :: MIT License",
18 | "Operating System :: OS Independent",
19 | "Programming Language :: Python",
20 | "Programming Language :: Python :: 2",
21 | "Programming Language :: Python :: 2.7",
22 | "Programming Language :: Python :: 3",
23 | "Programming Language :: Python :: 3.4",
24 | "Programming Language :: Python :: 3.5",
25 | "Programming Language :: Python :: 3.6",
26 | "Programming Language :: Python :: 3.7",
27 | "Framework :: Django",
28 | "Framework :: Django :: 1.8",
29 | "Framework :: Django :: 1.9",
30 | "Framework :: Django :: 1.10",
31 | "Framework :: Django :: 1.11",
32 | "Framework :: Django :: 2.0",
33 | "Framework :: Django :: 2.1",
34 | "Framework :: Django :: 2.2"],
35 | )
36 |
--------------------------------------------------------------------------------
/demo/demo/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for demo project.
3 |
4 | This module contains the WSGI application used by Django's development server
5 | and any production WSGI deployments. It should expose a module-level variable
6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
7 | this application via the ``WSGI_APPLICATION`` setting.
8 |
9 | Usually you will have the standard Django WSGI application here, but it also
10 | might make sense to replace the whole Django WSGI application with a custom one
11 | that later delegates to the Django one. For example, you could introduce WSGI
12 | middleware here, or combine a Django application with an application of another
13 | framework.
14 |
15 | """
16 | import os
17 |
18 | # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
19 | # if running multiple sites in the same mod_wsgi process. To fix this, use
20 | # mod_wsgi daemon mode with each site in its own daemon process, or use
21 | # os.environ["DJANGO_SETTINGS_MODULE"] = "demo.settings"
22 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
23 |
24 | # This application object is used by any WSGI server configured to use this
25 | # file. This includes Django's development server, if the WSGI_APPLICATION
26 | # setting points here.
27 | from django.core.wsgi import get_wsgi_application
28 | application = get_wsgi_application()
29 |
30 | # Apply WSGI middleware here.
31 | # from helloworld.wsgi import HelloWorldApplication
32 | # application = HelloWorldApplication(application)
33 |
--------------------------------------------------------------------------------
/sslserver/certs/development.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIGSTCCBDGgAwIBAgIJAPc4JnQC+MORMA0GCSqGSIb3DQEBCwUAMIG6MQswCQYD
3 | VQQGEwJVUzEaMBgGA1UECAwRREVWRUxPUE1FTlQgU1RBVEUxGTAXBgNVBAcMEERF
4 | VkVMT1BNRU5UIENJVFkxHDAaBgNVBAoME0RFVkVMT1BNRU5UIENPTVBBTlkxGjAY
5 | BgNVBAsMEURKQU5HTyBERVZFTE9QRVJTMRIwEAYDVQQDDAlsb2NhbGhvc3QxJjAk
6 | BgkqhkiG9w0BCQEWF2RldmVsb3BtZW50QGV4YW1wbGUuY29tMB4XDTE3MDcyMzIy
7 | NTMxOVoXDTI3MDcyMTIyNTMxOVowgboxCzAJBgNVBAYTAlVTMRowGAYDVQQIDBFE
8 | RVZFTE9QTUVOVCBTVEFURTEZMBcGA1UEBwwQREVWRUxPUE1FTlQgQ0lUWTEcMBoG
9 | A1UECgwTREVWRUxPUE1FTlQgQ09NUEFOWTEaMBgGA1UECwwRREpBTkdPIERFVkVM
10 | T1BFUlMxEjAQBgNVBAMMCWxvY2FsaG9zdDEmMCQGCSqGSIb3DQEJARYXZGV2ZWxv
11 | cG1lbnRAZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
12 | AQC44Me+Wb3x9kfW9BfHqNpDcQS3sEZuboirglbz6cLej2gIb6zaz93MFGjw4nyp
13 | 6lfm/Rss56gCfcVwmrrxZFjqnKLbIM7b2Fes3VeMFOGtYGFS4X60EPq11T5MG2VX
14 | 8ARJnDRX4oKWaMawUg3UrjTOWadoBwdp+k3EWLyOc9miMHOrPhmKiaYcZJdM78nl
15 | TLG7DqMStltVpDn4IuJWkw0Y9QYeRAESsQ+DLp+jvIRv7DJ7UjOAXa0IpiJyr1bJ
16 | 7qcCBd6/Yxz8lj/2yQrOSvHHjN69eYB8gcZaVoP++N8uYyea205UmzR/b3KUhFII
17 | wUXJKhWnsf0Yv4a/9RU8/ZVxPsw+43bvnW/VvFMXc7+Rm8gJHg5qIXJB+2AmbM0k
18 | g7DwgkM6f+DLn7m/SIZrgk6Pv2Zrv+k6AkPuCcTD8VY5yYRAddJZ9cWKIwCYUwVO
19 | 32+UKN8A41xShB7XPyd9VtpPMhAZQrwvuWJTbiWYoQGXyktGSKr3GGe6keU8NNxW
20 | QU4Hn0+nhe/LOzHYw7sSoTjgBfvP8By+ei4zhiWUetyogd18m9F1HnkOJHdXn8uf
21 | Fy0kblCWu83jIGzDwW8uke2Osdm4N5hJL2Qj0AXGOWON4OM6JeJETuXjZXsqAqWV
22 | ZqM4A7gGo12rIRfg2cZ9tx3JhOhvSMWBE5MA9x7SGT2fAQIDAQABo1AwTjAdBgNV
23 | HQ4EFgQUyjHyDG2Yos8dxhoiUT04oVR+JdwwHwYDVR0jBBgwFoAUyjHyDG2Yos8d
24 | xhoiUT04oVR+JdwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEASpqo
25 | aUHGEMGHpszdYowLRq9me8XqJkxFWuKPIZgZL/fb6nf5hjICtjpZGic79x13A2eV
26 | paXPmQa7MK1JbGGnVEJN07W7CKnwB2lgV/WZuARDPzJ/9anLtRTs8OhuOIcDYIsg
27 | f5pfTwWosNwZej1coosK04Dp8/8gt0qq6Ri1nH/HV5r7bzYmtMquv6N1sKtS4QGG
28 | lPBnGptToj4zN9x0w57JvUzGnUAVwuaRJerizmxMggS1j2Q3iK70xG9860fMJvCC
29 | pX2tsOjHsyxw/qRYZPeANGQlwVX+93cV4LV7XE4tK2QvyUOJMjwqB1EMmJEcSDXw
30 | 65zWZrCTpVsSkPmlQcL7gVYWPGyPpAWJICuvdvG4klbAcQS9EhK8w4rnrV2B3wzm
31 | KNp1c48gmIOsxRYYOQYB9TKfqmv6icYUPZ7wUhahYyf5z5EMnvfXEyflmSAsHOy6
32 | kkSLd8TfC8VQxAhL87DeCEkWkDl1xeEcPuRu3gOm90dxVZfphrqlBZ9hW9j7dysg
33 | Xp2xSqDYOcyKAMR5mMajOogE8vDXgoSRkQK+/HYCNCtKthVIXT2x5h8VP8MGFWNH
34 | YBQwmKnIT6PT2DV2TgpF3X9T9lLdPbg+TwnaoBuYxCIIEbTK+LNKnqaj2dLCxdOq
35 | VjVM6fboLD/7AqtVyld7pX/5FbcD3PaZURQw3p0=
36 | -----END CERTIFICATE-----
37 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | =================
2 | Django SSL Server
3 | =================
4 |
5 | .. image:: https://img.shields.io/pypi/v/django-sslserver.svg
6 | :target: https://pypi.python.org/pypi/django-sslserver
7 |
8 | .. image:: https://img.shields.io/pypi/pyversions/django-sslserver.svg
9 | :target: https://pypi.python.org/pypi/django-sslserver/
10 |
11 | Django SSL Server is a SSL-enabled development server for the Django Framework.
12 |
13 | Please note that this `should not be used for production setups
14 | `_. This
15 | app is intended for special use-cases. Most people should instead do a proper
16 | `production deployment
17 | `_ where a real
18 | webserver such as Apache or NGINX handles SSL.
19 |
20 | Getting Started
21 | ===============
22 |
23 | Install the module in your Python distribution or virtualenv::
24 |
25 | $ pip install django-sslserver
26 |
27 | Add the application to your `INSTALLED_APPS`::
28 |
29 | INSTALLED_APPS = (...
30 | "sslserver",
31 | ...
32 | )
33 |
34 | Start a SSL-enabled debug server::
35 |
36 | $ python manage.py runsslserver
37 |
38 | and access app on https://localhost:8000 or start server on specified port::
39 |
40 | $ python manage.py runsslserver 127.0.0.1:9000
41 |
42 | IPv6 support::
43 |
44 | $ python manage.py runsslserver -6 [::]:7443
45 |
46 | You'll now be able to access your Django app on https://localhost:9000/
47 |
48 |
49 | Browser Certificate Errors
50 | ==========================
51 |
52 | Using the default settings, your local browser will make all sorts of noise that it *doesn't trust the certificate*. **This is expected.**
53 |
54 | Django SSL Server ships "batteries included" with a self-signed server certificate. With self-signed certificates,
55 | the server is effectively telling the user, "I'm such-and-such server, because I said so". Whereas, with a commercial
56 | SSL certificate, the server tells the user, "I'm Bank of America, because VeriSign said so (or any other commercial certificate authority)."
57 |
58 | There are two options for making the certificate warning go away in development:
59 |
60 | **Option 1**: Tell your browser to explicitly trust the certificate. You can do this in your browser's "advanced settings"
61 | tab, by installing ``sslserver/certs/development.crt`` as a trusted certificate. The mechanism for this varies from browser to browser.
62 |
63 | **Option 2**: Use a certificate from a CA that your browser trusts, for example `Letsencrypt `_.
64 | If you have a certificate/key pair from a certificate authority,
65 | you can tell Django SSL Server to use it with the following arguments::
66 |
67 | $ python manage.py runsslserver --certificate /path/to/certificate.crt --key /path/to/key.key
68 |
69 |
70 | Third-Party Static File Handlers
71 | ================================
72 |
73 | If you're using a wrapper around your WSGI application such as dj_static or WhiteNoise, you probably want to let it handle serving
74 | static files. Otherwise, you may see 404s when requesting static files. You can disable the default behavior by using the ``--nostatic``
75 | option.
76 |
77 | Getting Involved
78 | ================
79 |
80 | Feel free to open pull requests or issues. GitHub is the canonical location of this project.
81 |
--------------------------------------------------------------------------------
/sslserver/certs/development.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQC44Me+Wb3x9kfW
3 | 9BfHqNpDcQS3sEZuboirglbz6cLej2gIb6zaz93MFGjw4nyp6lfm/Rss56gCfcVw
4 | mrrxZFjqnKLbIM7b2Fes3VeMFOGtYGFS4X60EPq11T5MG2VX8ARJnDRX4oKWaMaw
5 | Ug3UrjTOWadoBwdp+k3EWLyOc9miMHOrPhmKiaYcZJdM78nlTLG7DqMStltVpDn4
6 | IuJWkw0Y9QYeRAESsQ+DLp+jvIRv7DJ7UjOAXa0IpiJyr1bJ7qcCBd6/Yxz8lj/2
7 | yQrOSvHHjN69eYB8gcZaVoP++N8uYyea205UmzR/b3KUhFIIwUXJKhWnsf0Yv4a/
8 | 9RU8/ZVxPsw+43bvnW/VvFMXc7+Rm8gJHg5qIXJB+2AmbM0kg7DwgkM6f+DLn7m/
9 | SIZrgk6Pv2Zrv+k6AkPuCcTD8VY5yYRAddJZ9cWKIwCYUwVO32+UKN8A41xShB7X
10 | Pyd9VtpPMhAZQrwvuWJTbiWYoQGXyktGSKr3GGe6keU8NNxWQU4Hn0+nhe/LOzHY
11 | w7sSoTjgBfvP8By+ei4zhiWUetyogd18m9F1HnkOJHdXn8ufFy0kblCWu83jIGzD
12 | wW8uke2Osdm4N5hJL2Qj0AXGOWON4OM6JeJETuXjZXsqAqWVZqM4A7gGo12rIRfg
13 | 2cZ9tx3JhOhvSMWBE5MA9x7SGT2fAQIDAQABAoICAGE2qTF5hPyfUQVBkuOE8Ug3
14 | PJDOWyqkaq8suUZGrBZVeBG/jzf7x5gRP2Ey5vR96jzm6IxDP8AXnGNqqVRXPL4Z
15 | ITVyWfOWHfwi428gZ86/+E0Zj4Nlzj8g40InwbFs3wRJ4+g2jg5DB/8dFnK4K8I5
16 | uGJmF8rtOEk/k96gIlc7fQcVf16upK8XYcut5w7wtiAzQSKMyxgMZAMLbNKzPlba
17 | OJ5fieTnP83uDTmO3mDv5VedUMF2AI+ktEZz1oIWQLE6nvcqScqzwuykqE7zb5FL
18 | jLA7HInbv44vIfdHrCt7Lg8qtFSezAsacjiQH4bFAkoWHA7y87A4vcVgPQu2GAbv
19 | k3RCGbvVzaAq+INudeQWl3kwwvnugrxjZ67O+UJRieXPy0mqtG0xxbiRsP8ifnIi
20 | dPXFoP8BUcz8H/ntXfIve/5PCH2mWd48rpKZWZes3HQXYAupAeBRX5HXfFTjYVVT
21 | Lf39ROJlIZyXFxCTuAohP4RaQscwdh3xifSgQS0Bc+NzxtOBeziu1y4Tsg7OCr2p
22 | fvcQzJrnjXdO0/dsMndtsjYWXD1IkoQuCswA6iLNyBgH5J5TwFm3g/NzfOhRd77V
23 | XvN8fLLyGNxQu7H9kYKMuQEM7BPZbRwHLhLqQIE+yhfy7VUE/DwLey4ca+zAO3s1
24 | FGqe8zjU08UMdO5ZZZe1AoIBAQDuCXNCjp3QI5YyJh9BhtFbA75bVNrgEQL0H87D
25 | hNNiZXzlavzoLE5kUWxIxPAlLiqtz6dYHLayfSAxoeN4B8DAES+M2ZtaJkdkxEg3
26 | a52IFvlQSsqzqIlzWqNrgfdhphDLfBFUONHWDQMiyyetm5ziQHU0a24ZSmGli8Q/
27 | ogPMUsu8QoH2w4JdLPEv7zeSZQQrznfeiBqiE8r7tzHbVZAl00JBSqRUhgfgwWao
28 | h+IFIvESQIZEhEc7gzPa2g1kmHE6qbRKOrF1KXVV+MJkU3+/X1HlrAPP+ESfRPPy
29 | BSqHDwNYSsnuEzPnehY9FujzHtiIytJEYh7M8UwJI/K3DtYXAoIBAQDG1F94XJ26
30 | AIrr8IbXj0EEresfOcI8H3GScxYRiUOFrzV3cMU5wttliUZ8b0b+zNjcQfeP/WOU
31 | 0+I8kKC9l4txJxJ2Yrl9nwiSiLcCtJWbReg/LPAS8R0+2tYIHxz+HAN4+CVqCc5j
32 | UIvng6h1pBXGGmuAOSK9Jy4P8Op/0aKV5hAY6ELc993ZYJNBVj2x/qDBWmyvXk8N
33 | TBerfJ/KLTfe7b2Tv1QIayukOXGNGaZTDnVqZTIIkLpNAW5EjYJbO97EPzcqwyeM
34 | YXxnKsLw09KQ47Orzt5b7pUjGWygUQ2YuLokBZ1h+9NORh0aaKDhcQNUWz50ZEbm
35 | nIW/krdmX3qnAoIBAHiSONvBuZYwMGf+f16Fl43ue4Fvnd5ZP5HAes72fMwedAER
36 | DEHeD2cpBxxlBO8QT3Xy9OTgxnnqf2AkjD/ETZH8IoXJw7MKKKeV9K59yDGi0W4m
37 | ND6EY/sWMijGkDPaFi+8DFsI3OD7flclaFe7tt+znqqKsB4HWyargSBqRFo+pgwZ
38 | 9BK2PVZM6W5KUW/J0y8NShJiBnuKYwrVZF+hG37NX4YK9OoLafoifIlpKsdHR6zj
39 | Gh+ikSJH9wAn6xjFTrVUOIpQ6IpcEZ8WfgCres3IzobzdorlSn0SRC6XB0+Z/yu9
40 | 1kLNX0Ekyhbvf9eGDFBdy9vvh4Jvxv/qQYsP7MkCggEAcMY8cFR30exE35ZJpTJH
41 | upO67LciCF/9VweX2NJ2TfkW5mw8MYroTisSo7mqFxOxXRy9ghpCxUN46slNoru2
42 | B7QVsLhGZY4ymoqY4xvyT2PTWyHt+ZBw+hm9lFWxaCATiCWXcxGk0of5EpOGlVNA
43 | VmDd4JiHr6ntYnVPTLhm84bOUpJKenLMjmNMop57192I6KKVStK/G9exBT9mkpIb
44 | QoKuKIM48p1232sFkPafdDSbPIGxY1JTmSHanV92NLE8pSsF62dNoz4YBZwnfdln
45 | cW71ldl8HcCxLntZNYVDpQAB9DSLE+x16cuy7iuyNKyZKtumDPZjkKHu6r4Y8CPv
46 | uQKCAQEAlkgFgNAsiOtPwFBZ6FW3q/YrlFE+hdhIieIZkS41qxAjgteiRMCANv7B
47 | SvFO3i4bzwuB3WtxnGSsk+uybb4u+Sju6cwWnYk5plpvG5w2I1i9Udmd+UDCblLy
48 | zmy12NHMkmQp9VGaFujjbOB/pboIQvocvqPj6FngCwLYPpmx8w0EG9LNCosPFCo6
49 | 6T4413Iadde0g55MpxC7SvOWK08uxBXVksEacGBD1qZ8ghB6CbFoTGymI3Gvj8Wl
50 | Mm98jE/Xih/zgp8YXe4i7N8wDiV/Jn16Ic5U1uQtfiNhEwBCIyKYeuW/ybaLT8IV
51 | ywoqq7w2QdhJK/vom01mFY8wglE8lQ==
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/demo/demo/settings.py:
--------------------------------------------------------------------------------
1 | # Django settings for demo project.
2 | from os import path
3 |
4 | DEBUG = True
5 | TEMPLATE_DEBUG = DEBUG
6 |
7 | PROJECT_ROOT = path.dirname(__file__)
8 |
9 | ADMINS = (
10 | # ('Your Name', 'your_email@example.com'),
11 | )
12 |
13 | MANAGERS = ADMINS
14 |
15 | DATABASES = {
16 | 'default': {
17 | 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
18 | 'NAME': '', # Or path to database file if using sqlite3.
19 | # The following settings are not used with sqlite3:
20 | 'USER': '',
21 | 'PASSWORD': '',
22 | 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
23 | 'PORT': '', # Set to empty string for default.
24 | }
25 | }
26 |
27 | # Hosts/domain names that are valid for this site; required if DEBUG is False
28 | # See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
29 | ALLOWED_HOSTS = []
30 |
31 | # Local time zone for this installation. Choices can be found here:
32 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
33 | # although not all choices may be available on all operating systems.
34 | # In a Windows environment this must be set to your system time zone.
35 | TIME_ZONE = 'America/Chicago'
36 |
37 | # Language code for this installation. All choices can be found here:
38 | # http://www.i18nguy.com/unicode/language-identifiers.html
39 | LANGUAGE_CODE = 'en-us'
40 |
41 | SITE_ID = 1
42 |
43 | # If you set this to False, Django will make some optimizations so as not
44 | # to load the internationalization machinery.
45 | USE_I18N = True
46 |
47 | # If you set this to False, Django will not format dates, numbers and
48 | # calendars according to the current locale.
49 | USE_L10N = True
50 |
51 | # If you set this to False, Django will not use timezone-aware datetimes.
52 | USE_TZ = True
53 |
54 | # Absolute filesystem path to the directory that will hold user-uploaded files.
55 | # Example: "/var/www/example.com/media/"
56 | MEDIA_ROOT = ''
57 |
58 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a
59 | # trailing slash.
60 | # Examples: "http://example.com/media/", "http://media.example.com/"
61 | MEDIA_URL = ''
62 |
63 | # Absolute path to the directory static files should be collected to.
64 | # Don't put anything in this directory yourself; store your static files
65 | # in apps' "static/" subdirectories and in STATICFILES_DIRS.
66 | # Example: "/var/www/example.com/static/"
67 | STATIC_ROOT = ''
68 |
69 | # URL prefix for static files.
70 | # Example: "http://example.com/static/", "http://static.example.com/"
71 | STATIC_URL = '/static/'
72 |
73 | # Additional locations of static files
74 | STATICFILES_DIRS = (
75 | # Put strings here, like "/home/html/static" or "C:/www/django/static".
76 | # Always use forward slashes, even on Windows.
77 | # Don't forget to use absolute paths, not relative paths.
78 | )
79 |
80 | # List of finder classes that know how to find static files in
81 | # various locations.
82 | STATICFILES_FINDERS = (
83 | 'django.contrib.staticfiles.finders.FileSystemFinder',
84 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
85 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
86 | )
87 |
88 | # Make this unique, and don't share it with anybody.
89 | SECRET_KEY = '3a=fu+&h1njr4pjuwr^4n0rmd6)5vw!o!44e*y61qil=zr5$^g'
90 |
91 | # List of callables that know how to import templates from various sources.
92 | TEMPLATE_LOADERS = (
93 | 'django.template.loaders.filesystem.Loader',
94 | 'django.template.loaders.app_directories.Loader',
95 | # 'django.template.loaders.eggs.Loader',
96 | )
97 |
98 | MIDDLEWARE_CLASSES = (
99 | 'django.middleware.common.CommonMiddleware',
100 | 'django.contrib.sessions.middleware.SessionMiddleware',
101 | 'django.middleware.csrf.CsrfViewMiddleware',
102 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
103 | 'django.contrib.messages.middleware.MessageMiddleware',
104 | # Uncomment the next line for simple clickjacking protection:
105 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
106 | )
107 |
108 | ROOT_URLCONF = 'demo.urls'
109 |
110 | # Python dotted path to the WSGI application used by Django's runserver.
111 | WSGI_APPLICATION = 'demo.wsgi.application'
112 |
113 | TEMPLATE_DIRS = (
114 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
115 | # Always use forward slashes, even on Windows.
116 | # Don't forget to use absolute paths, not relative paths.
117 | path.join(PROJECT_ROOT, 'templates'),
118 | )
119 |
120 | TEMPLATES = [
121 | {
122 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
123 | 'DIRS': TEMPLATE_DIRS
124 | }
125 | ]
126 |
127 | INSTALLED_APPS = (
128 | 'django.contrib.auth',
129 | 'django.contrib.contenttypes',
130 | 'django.contrib.sessions',
131 | 'django.contrib.sites',
132 | 'django.contrib.messages',
133 | 'django.contrib.staticfiles',
134 | 'sslserver',
135 | # Uncomment the next line to enable the admin:
136 | # 'django.contrib.admin',
137 | # Uncomment the next line to enable admin documentation:
138 | # 'django.contrib.admindocs',
139 | )
140 |
141 | # A sample logging configuration. The only tangible logging
142 | # performed by this configuration is to send an email to
143 | # the site admins on every HTTP 500 error when DEBUG=False.
144 | # See http://docs.djangoproject.com/en/dev/topics/logging for
145 | # more details on how to customize your logging configuration.
146 | LOGGING = {
147 | 'version': 1,
148 | 'disable_existing_loggers': False,
149 | 'filters': {
150 | 'require_debug_false': {
151 | '()': 'django.utils.log.RequireDebugFalse'
152 | }
153 | },
154 | 'handlers': {
155 | 'mail_admins': {
156 | 'level': 'ERROR',
157 | 'filters': ['require_debug_false'],
158 | 'class': 'django.utils.log.AdminEmailHandler'
159 | }
160 | },
161 | 'loggers': {
162 | 'django.request': {
163 | 'handlers': ['mail_admins'],
164 | 'level': 'ERROR',
165 | 'propagate': True,
166 | },
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/sslserver/management/commands/runsslserver.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 |
3 | import os
4 | import ssl
5 | import sys
6 |
7 | try:
8 | from pathlib import Path
9 | except ImportError:
10 | # removed in django version 3
11 | from django.utils._os import upath
12 |
13 | from django.core.servers.basehttp import WSGIRequestHandler
14 | from django.core.management.base import CommandError
15 | from django.core.management.commands import runserver
16 | from django.contrib.staticfiles.handlers import StaticFilesHandler
17 |
18 |
19 | if (sys.version_info[0] > 3) or \
20 | (sys.version_info[0] == 3 and sys.version_info[1] >= 6) or \
21 | (sys.version_info[0] == 3 and sys.version_info[1] == 5 and sys.version_info[2] >= 3) or \
22 | (sys.version_info[0] == 2 and sys.version_info[1] == 7 and sys.version_info[2] >= 13):
23 | _ssl_version = ssl.PROTOCOL_TLS
24 | else:
25 | _ssl_version = ssl.PROTOCOL_SSLv23
26 |
27 | try:
28 | from django.core.servers.basehttp import WSGIServerException
29 | except ImportError:
30 | from socket import error as WSGIServerException
31 |
32 | try:
33 | # introduced in Django 2.0
34 | from django.core.servers.basehttp import ThreadedWSGIServer
35 | except ImportError:
36 | try:
37 | import socketserver
38 | except ImportError:
39 | # Python 2 compatibility
40 | import SocketServer as socketserver
41 | from django.core.servers.basehttp import WSGIServer
42 |
43 | class ThreadedWSGIServer(socketserver.ThreadingMixIn, WSGIServer):
44 | """A threaded version of the WSGIServer"""
45 | pass
46 |
47 |
48 | class SecureHTTPServer(ThreadedWSGIServer):
49 | def __init__(self, address, handler_cls, certificate, key, ipv6=False):
50 | super(SecureHTTPServer, self).__init__(address, handler_cls, ipv6=ipv6)
51 | self.socket = ssl.wrap_socket(self.socket, certfile=certificate,
52 | keyfile=key, server_side=True,
53 | ssl_version=_ssl_version,
54 | cert_reqs=ssl.CERT_NONE)
55 |
56 |
57 | class WSGIRequestHandler(WSGIRequestHandler):
58 | def get_environ(self):
59 | env = super(WSGIRequestHandler, self).get_environ()
60 | env['HTTPS'] = 'on'
61 | return env
62 |
63 |
64 | def default_ssl_files_dir():
65 | import sslserver as app_module
66 |
67 | try:
68 | ssl_dir = str(Path(app_module.__file__).parent / 'certs')
69 | except NameError:
70 | # Django < 3 backwards compatibility
71 | mod_path = os.path.dirname(upath(app_module.__file__))
72 | ssl_dir = os.path.join(mod_path, "certs")
73 |
74 | return ssl_dir
75 |
76 |
77 | class Command(runserver.Command):
78 | def add_arguments(self, parser):
79 | super(Command, self).add_arguments(parser)
80 | parser.add_argument("--certificate",
81 | default=os.path.join(default_ssl_files_dir(),
82 | "development.crt"),
83 | help="Path to the certificate"),
84 | parser.add_argument("--key",
85 | default=os.path.join(default_ssl_files_dir(),
86 | "development.key"),
87 | help="Path to the key file"),
88 | parser.add_argument("--nostatic", dest='use_static_handler',
89 | action='store_false', default=None,
90 | help="Do not use internal static file handler"),
91 | parser.add_argument("--static", dest='use_static_handler',
92 | action='store_true',
93 | help="Use internal static file handler"),
94 |
95 | help = "Run a Django development server over HTTPS"
96 |
97 | def get_handler(self, *args, **options):
98 | """
99 | Returns the static files serving handler wrapping the default handler,
100 | if static files should be served. Otherwise just returns the default
101 | handler.
102 |
103 | """
104 | handler = super(Command, self).get_handler(*args, **options)
105 | insecure_serving = options.get('insecure_serving', False)
106 | if self.should_use_static_handler(options):
107 | return StaticFilesHandler(handler)
108 | return handler
109 |
110 | def should_use_static_handler(self, options):
111 | # it's a bit weird to import settings in the middle of the method, but
112 | # this is what inner_run does
113 | from django.conf import settings
114 | use_static_handler = options.get('use_static_handler')
115 | if use_static_handler:
116 | return True
117 | if (use_static_handler is None and
118 | 'django.contrib.staticfiles' in settings.INSTALLED_APPS):
119 | return True
120 | return False
121 |
122 | def check_certs(self, key_file, cert_file):
123 | # TODO: maybe validate these? wrap_socket doesn't...
124 |
125 | if not os.path.exists(key_file):
126 | raise CommandError("Can't find key at %s" % key_file)
127 | if not os.path.exists(cert_file):
128 | raise CommandError("Can't find certificate at %s" %
129 | cert_file)
130 |
131 |
132 | def inner_run(self, *args, **options):
133 | # Django did a shitty job abstracting this.
134 |
135 | key_file = options.get("key")
136 | cert_file = options.get("certificate")
137 | self.check_certs(key_file, cert_file)
138 |
139 | from django.conf import settings
140 | from django.utils import translation
141 |
142 | threading = options.get('use_threading')
143 | shutdown_message = options.get('shutdown_message', '')
144 | quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'
145 |
146 | self.stdout.write("Validating models...\n\n")
147 | self.check(display_num_errors=True)
148 | self.stdout.write((
149 | "%(started_at)s\n"
150 | "Django version %(version)s, using settings %(settings)r\n"
151 | "Starting development server at https://%(addr)s:%(port)s/\n"
152 | "Using SSL certificate: %(cert)s\n"
153 | "Using SSL key: %(key)s\n"
154 | "Quit the server with %(quit_command)s.\n"
155 | ) % {
156 | "started_at": datetime.now().strftime('%B %d, %Y - %X'),
157 | "version": self.get_version(),
158 | "settings": settings.SETTINGS_MODULE,
159 | "addr": self._raw_ipv6 and '[%s]' % self.addr or self.addr,
160 | "port": self.port,
161 | "quit_command": quit_command,
162 | "cert": cert_file,
163 | "key": key_file
164 | })
165 | # django.core.management.base forces the locale to en-us. We should
166 | # set it up correctly for the first request (particularly important
167 | # in the "--noreload" case).
168 | translation.activate(settings.LANGUAGE_CODE)
169 |
170 | try:
171 | handler = self.get_handler(*args, **options)
172 | server = SecureHTTPServer((self.addr, int(self.port)),
173 | WSGIRequestHandler,
174 | cert_file, key_file, ipv6=self.use_ipv6)
175 | server.set_app(handler)
176 | server.serve_forever()
177 |
178 | except WSGIServerException:
179 | e = sys.exc_info()[1]
180 | # Use helpful error messages instead of ugly tracebacks.
181 | ERRORS = {
182 | 13: "You don't have permission to access that port.",
183 | 98: "That port is already in use.",
184 | 99: "That IP address can't be assigned-to.",
185 | }
186 | try:
187 | error_text = ERRORS[e.args[0].args[0]]
188 | except (AttributeError, KeyError):
189 | error_text = str(e)
190 | self.stderr.write("Error: %s" % error_text)
191 | # Need to use an OS exit because sys.exit doesn't work in a thread
192 | os._exit(1)
193 | except KeyboardInterrupt:
194 | if shutdown_message:
195 | self.stdout.write(shutdown_message)
196 | sys.exit(0)
197 |
198 |
--------------------------------------------------------------------------------