graphql-engine/server/tests-py/fixtures/tls.py
Samir Talwar 23f78a05b1 server/tests-py: Enable TLS tests in parallel mode on CI.
Part of [NDAT-257](https://hasurahq.atlassian.net/browse/NDAT-257).

* Run the TLS tests on CI.
* Run non-TLS tests even when a TLS certificate is provided; just ignore it.

[NDAT-257]: https://hasurahq.atlassian.net/browse/NDAT-257?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7806
GitOrigin-RevId: d705e2e5131a674070a98a893323a7b98a92f688
2023-02-08 14:42:27 +00:00

48 lines
2.0 KiB
Python

import enum
import http.server
import pathlib
from typing import NamedTuple
import ssl
import subprocess
class TLSTrust(enum.Enum):
INSECURE = enum.auto()
SECURE = enum.auto()
class TLSCAConfiguration(NamedTuple):
cert_file: str
key_file: str
tmp_path: pathlib.Path
def configure(
self,
server: http.server.HTTPServer,
trust: TLSTrust,
) -> http.server.HTTPServer:
config_file = pathlib.Path(__file__).parent / 'webhook.cnf'
key_file = self.tmp_path / 'webhook-key.pem'
csr_file = self.tmp_path / 'webhook.csr'
cert_file = self.tmp_path / 'webhook.pem'
# generate a private key
subprocess.run(['openssl', 'genrsa', '-out', key_file, '2048'], check=True, capture_output=True)
# generate a certificate signing request for the private key
subprocess.run(['openssl', 'req', '-new', '-key', key_file, '-out', csr_file, '-subj', '/CN=hge-webhook', '-config', config_file], check=True, capture_output=True)
if trust == TLSTrust.INSECURE:
# self-sign the certificate with its own key, making it untrusted
subprocess.run(['openssl', 'x509', '-req', '-in', csr_file, '-signkey', key_file, '-out', cert_file, '-days', '10', '-extensions', 'v3_req', '-extfile', config_file], check=True, capture_output=True)
else:
# sign the certificate with the provided CA key, which should be trusted
subprocess.run(['openssl', 'x509', '-req', '-in', csr_file, '-CA', self.cert_file, '-CAkey', self.key_file, '-CAcreateserial', '-out', cert_file, '-days', '10', '-extensions', 'v3_req', '-extfile', config_file], check=True, capture_output=True)
ssl_context = ssl.create_default_context(
purpose=ssl.Purpose.CLIENT_AUTH,
cafile=self.cert_file,
)
ssl_context.load_cert_chain(certfile=cert_file, keyfile=key_file)
server.socket = ssl_context.wrap_socket(server.socket, server_side=True)
return server