"""Create Docker TLSConfig from CertificateKeyPair""" from pathlib import Path from tempfile import gettempdir from typing import Optional from docker.tls import TLSConfig from passbook.crypto.models import CertificateKeyPair class DockerInlineTLS: """Create Docker TLSConfig from CertificateKeyPair""" verification_kp: Optional[CertificateKeyPair] authentication_kp: Optional[CertificateKeyPair] def __init__( self, verification_kp: Optional[CertificateKeyPair], authentication_kp: Optional[CertificateKeyPair], ) -> None: self.verification_kp = verification_kp self.authentication_kp = authentication_kp def write_file(self, name: str, contents: str) -> str: """Wrapper for mkstemp that uses fdopen""" path = Path(gettempdir(), name) with open(path, "w") as _file: _file.write(contents) return str(path) def write(self) -> TLSConfig: """Create TLSConfig with Certificate Keypairs""" # So yes, this is quite ugly. But sadly, there is no clean way to pass # docker-py (which is using requests (which is using urllib3)) a certificate # for verification or authentication as string. # Because we run in docker, and our tmpfs is isolated to us, we can just # write out the certificates and keys to files and use their paths config_args = {} if self.verification_kp: ca_cert_path = self.write_file( f"{self.verification_kp.pk.hex}-cert.pem", self.verification_kp.certificate_data, ) config_args["ca_cert"] = ca_cert_path if self.authentication_kp: auth_cert_path = self.write_file( f"{self.authentication_kp.pk.hex}-cert.pem", self.authentication_kp.certificate_data, ) auth_key_path = self.write_file( f"{self.authentication_kp.pk.hex}-key.pem", self.authentication_kp.key_data, ) config_args["client_cert"] = (auth_cert_path, auth_key_path) return TLSConfig(**config_args)