Automatic TLS cert issuance and renewal for Python web apps
Project description
autocert
Automatic TLS cert issuance and renewal for Python web apps
Overview
Autocert is a package for automatically obtaining and renewing TLS certificates from Let's Encrypt using the ACME protocol. It is based on the API and design of the Go package with the same name: autocert. To work its magic, autocert only requires a single TCP socket listening on your desired HTTPS port (usually 443). This can come directly from an application or from a management system such as systemd.
Motivation
I often find myself with the need to host simple Python web apps as demos for friends / clients. In these situations, I want the demo to be properly secured via HTTPS but I don't want to worry about the extra infrastructure that comes with setting up a reverse proxy (NGINX, Caddy, etc). This library allows you to add an auto-renewing TLS certificate from Let's Encrypt to your website with a single line of code.
There is quite a bit of dogma surrounding the hosting of Python-based web applications. Most folks believe that utilizing a reverse proxy is a hard requirement for achieving a secure, fast, and reliable deployment. However, I really like the simplicity of hosting a Flask or Django app by combining a pure-Python WSGI server (such as Waitress) with this project. It might not be the best deployment option for a high-traffic, business-critical applications but it can easily support a few hundred requests per second on a small Digital Ocean droplet.
Install
If you are unfamiliar with virtual environments, I suggest taking a brief moment to learn about them and set one up. The Python docs provide a great tutorial for getting started with virtual environments and packages.
Autocert can be installed via pip:
pip install autocert
Examples
These examples utilize the Waitress WSGI server but you can follow your own preference. However, whichever server you choose must be able to accept pre-listening sockets (you'll see what I mean). More examples can be found in the examples directory.
Waitress can be installed via pip:
pip install waitress
basic
Here is a basic example of autocert usage (requires root):
from autocert import autocert, wsgi
import socket
import waitress
# open a socket on port 443
s443 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s443.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s443.bind(('0.0.0.0', 443))
s443.listen()
# setup automatic cert issuance and renewal
s443_tls = autocert.manage(s443, 'example.org', 'www.example.org', accept_tos=True)
# serve your app with TLS!
waitress.serve(wsgi.hello_world_app, sockets=[s443_tls], url_scheme='https')
systemd w/ redirect
Here is an example of using autocert with systemd sockets and an HTTP->HTTPS redirect:
from autocert import autocert, wsgi
import os
import socket
import threading
import waitress
# make sure systemd PID matches
if os.environ['LISTEN_PID'] != str(os.getpid()):
raise SystemExit('Mismatched LISTEN_PID')
# expecting 2 ports here: 80, 443
if os.environ['LISTEN_FDS'] != '2':
raise SystemExit('Expected 2 socket fds for ports 80 and 443')
# create sockets from the fds opened by systemd
s80 = socket.fromfd(3, socket.AF_INET, socket.SOCK_STREAM)
s443 = socket.fromfd(4, socket.AF_INET, socket.SOCK_STREAM)
# start autocert's wsgi.redirect_app in a background thread
t = threading.Thread(
target=waitress.serve,
args=(wsgi.redirect_app,),
kwargs={'sockets': [s80]},
daemon=True,
)
t.start()
# setup automatic cert issuance and renewal
s443_tls = autocert.manage(s443, 'example.org', 'www.example.org', accept_tos=True)
# serve your app with TLS!
waitress.serve(wsgi.hello_world_app, sockets=[s443_tls], url_scheme='https')
Testing
Autocert is tested using pytest. Unit tests can be executed without anything special but the integration tests expect a locally-running ACME server. Running pebble in a container is a great way to accomplish this!
To run the tests, first install pytest:
pip install pytest
Then, unit tests can be ran via:
pytest tests/unit/
The integration tests need that local ACME server so let's start it up and set some necessary vars:
docker run -p 14000:14000 --detach letsencrypt/pebble
Now the integration tests can be ran:
pytest tests/integration/
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file autocert-0.0.7.tar.gz
.
File metadata
- Download URL: autocert-0.0.7.tar.gz
- Upload date:
- Size: 13.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.4.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.8.0 tqdm/4.30.0 CPython/3.8.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 91fc60facc4527be2a05b49ac63364704970edf706881b33c519f76fb4e29f8f |
|
MD5 | 117ff3fb5838f8bf5e6c355da4455e91 |
|
BLAKE2b-256 | 4935167dea8945f745a29a6c12b6ef17623fd27eda5eccd7b15d11438f9b61b9 |
File details
Details for the file autocert-0.0.7-py3-none-any.whl
.
File metadata
- Download URL: autocert-0.0.7-py3-none-any.whl
- Upload date:
- Size: 13.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.4.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.8.0 tqdm/4.30.0 CPython/3.8.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0030abf9648c604e7c345748631e68999e078287a1fcade785d690427b6fd758 |
|
MD5 | 6ee06ea549f22d4bc444065080a07ebb |
|
BLAKE2b-256 | 865e75c9c775d6cfd04055c8c9d7761943f656aeefa1c976f6322c7708355ff0 |