2

I want to pull my ssl certificate and key from environment variables and not store them on the filesystem. But I am running into a road block with twisted ssl

from io import StringIO
from twisted.internet import reactor, task, threads, ssl

key = StringIO()
key.write(os.environ['SSLKEY'])
cert = StringIO()
cert.write(os.environ['SSLCERT'])

contextFactory = ssl.DefaultOpenSSLContextFactory(key, cert)    

gives me the following exception

2018-04-03 16:01:28-0500 [-] TypeError: Path must be represented as bytes or unicode string

or

contextFactory = ssl.DefaultOpenSSLContextFactory(key.getvalue(), cert.getvalue())    

gives me the following exception.

2018-04-03 16:02:44-0500 [-] OpenSSL.SSL.Error: [('system library', 'fopen', 'File name too long'), ('BIO routines', 'file_ctrl', 'system lib'), ('SSL routines', 'SSL_CTX_use_certificate_file', 'system lib')]

twisted.internet.ssl is looking for a string or bytes object of the filename and io.StringIO gives me a io.StringIO object.

Is there anyway to accomplish this?

user1601716
  • 1,893
  • 4
  • 24
  • 53

2 Answers2

1

Twisted uses OpenSSL to actually implement TLS. Twisted merely provides a wrapper around OpenSSL's APIs to make them easier to use.

The DefaultOpenSSLContextFactory initializer takes certificate and key filenames, not certificate and key themselves. So, you cannot accomplish what you want with this API.

twisted.internet.ssl.CertificateOptions, however, will accept key and certificate objects to its initializer:

from os import environb
from twisted.internet.ssl import (
    CertificateOptions,
    PrivateCertificate,
)

cert = PrivateCertificate.loadPEM(
    environb['SSLKEY'] + b'\n' + environb['SSLCERT'],
)
key = cert.privateKey

contextFactory = CertificateOptions(
    privateKey=key.original,
    certificate=cert.original,
)

There is probably also a better way to load the certificates using the cryptography library (which will hopefully supplant a lot of twisted.internet.ssl key and certificate management APIs in the near future).

Also note that putting your private key into an environment variable in your process exposes it to all other users and processes on the same host. This is a pretty bad idea (it's not very private, after all). So you should probably put your key somewhere else.

Jean-Paul Calderone
  • 47,755
  • 6
  • 94
  • 122
  • I was not able to get this to work, however I am marking this as successful as this is a bad idea and I am instead storing these secrets as a file on the system instead. – user1601716 Apr 04 '18 at 16:09
0

Use io.BytesIO instead of io.StringIO

from io import BytesIO
key = BytesIO()
key.write(os.environ['SSLKEY'].encode())
scnerd
  • 5,836
  • 2
  • 21
  • 36