Skip to content

Instantly share code, notes, and snippets.

@webknjaz
Created June 27, 2023 22:00
Show Gist options
  • Save webknjaz/56cfb9f28a05017ea465982328b71d10 to your computer and use it in GitHub Desktop.
Save webknjaz/56cfb9f28a05017ea465982328b71d10 to your computer and use it in GitHub Desktop.
Testing CherryPy's TLS setup

The provided below cp_tls_builtin.py and cp_tls_pyopenssl.py modules are almost bare minimum CherryPy apps set up to serve a static string over HTTPS. I say "almost" because having an HTTP handler mounted isn't really necesary to verify that TLS works but having it provides a nice visual cue when using curl, for example.

This instruction assumes that you have a freshly made virtualenv where you executed something like pip install 'CherryPy[ssl]' trustme. The ssl extra is only needed to pull in pyOpenSSL and isn't needed for the built-in stdlib TLS adapter. The trustme project is needed for demonstration purposes — it'll generate a test certificate with the key and a trusted CA that signed it, along with a certificate chain file to be used by our test HTTP client (curl).

  1. Download said Python modules to a dedicated directory.
  2. Make sure that the virtualenv with the above deps is activated.
  3. In that directory, run python -m trustme — this will generate test TLS certificates and related files as described earlier.
  4. Run python -m cp_tls_builtin or python -m cp_tls_pyopenssl depending on which adapter you'd like to test. It'll run a CherryPy app with TLS in foreground.
  5. In a separate terminal tab, while being in the same directory, run curl --cacert client.pem https://localhost:4443.

As a successful outcome, you'll see "TLS works!". If you want to inspect the TLS exchange, you can run openssl s_client -CAfile client.pem -connect localhost -port 4443 -debug.

N.B. The example does not need sudo anywhere as it uses port 4443 which typically is not privileged.

from pathlib import Path
import cherrypy
PROJECT_DIR = Path(__file__).parent.resolve().absolute() # this file's directory
class RootHTTPApp:
@cherrypy.expose
def index(self):
return 'TLS works!'
def main():
cherrypy.config.update({
'server.socket_host': '0.0.0.0',
'server.socket_port': 4443,
'server.ssl_module': 'builtin',
'server.ssl_certificate': str(PROJECT_DIR / 'server.pem'),
'server.ssl_certificate_chain': str(PROJECT_DIR / 'client.pem'),
'server.ssl_private_key': str(PROJECT_DIR / 'server.key'),
})
cherrypy.tree.mount(RootHTTPApp(), '/')
cherrypy.engine.start()
cherrypy.engine.block()
if __name__ == '__main__':
main()
from pathlib import Path
import cherrypy
PROJECT_DIR = Path(__file__).parent.resolve().absolute() # this file's directory
class RootHTTPApp:
@cherrypy.expose
def index(self):
return 'TLS works!'
def main():
cherrypy.config.update({
'server.socket_host': '0.0.0.0',
'server.socket_port': 4443,
'server.ssl_module': 'pyopenssl',
'server.ssl_certificate': str(PROJECT_DIR / 'server.pem'),
'server.ssl_certificate_chain': str(PROJECT_DIR / 'client.pem'),
'server.ssl_private_key': str(PROJECT_DIR / 'server.key'),
})
cherrypy.tree.mount(RootHTTPApp(), '/')
cherrypy.engine.start()
cherrypy.engine.block()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment