Skip to main content

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

autocert-0.0.7.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

autocert-0.0.7-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

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

Hashes for autocert-0.0.7.tar.gz
Algorithm Hash digest
SHA256 91fc60facc4527be2a05b49ac63364704970edf706881b33c519f76fb4e29f8f
MD5 117ff3fb5838f8bf5e6c355da4455e91
BLAKE2b-256 4935167dea8945f745a29a6c12b6ef17623fd27eda5eccd7b15d11438f9b61b9

See more details on using hashes here.

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

Hashes for autocert-0.0.7-py3-none-any.whl
Algorithm Hash digest
SHA256 0030abf9648c604e7c345748631e68999e078287a1fcade785d690427b6fd758
MD5 6ee06ea549f22d4bc444065080a07ebb
BLAKE2b-256 865e75c9c775d6cfd04055c8c9d7761943f656aeefa1c976f6322c7708355ff0

See more details on using hashes here.

Supported by

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