(self, domain: str)
| 125 | log.warning(">>> Install this file in your browser's Trusted Root CAs! <<<") |
| 126 | |
| 127 | def get_server_context(self, domain: str) -> ssl.SSLContext: |
| 128 | if domain not in self._ctx_cache: |
| 129 | key_pem, cert_pem = self._generate_domain_cert(domain) |
| 130 | |
| 131 | safe = _safe_domain_filename(domain) |
| 132 | cert_file = os.path.join(self._cert_dir, f"{safe}.crt") |
| 133 | key_file = os.path.join(self._cert_dir, f"{safe}.key") |
| 134 | |
| 135 | ca_pem = self._ca_cert.public_bytes(serialization.Encoding.PEM) |
| 136 | with open(cert_file, "wb") as f: |
| 137 | f.write(cert_pem + ca_pem) |
| 138 | with open(key_file, "wb") as f: |
| 139 | f.write(key_pem) |
| 140 | # Restrict private key to current user only on POSIX. |
| 141 | # os.chmod is effectively a no-op on Windows (NTFS ACLs govern |
| 142 | # access there), but the temp directory is already user-scoped. |
| 143 | if os.name == "posix": |
| 144 | try: |
| 145 | os.chmod(key_file, 0o600) |
| 146 | except OSError: |
| 147 | pass |
| 148 | |
| 149 | ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
| 150 | ctx.set_alpn_protocols(["http/1.1"]) |
| 151 | ctx.load_cert_chain(cert_file, key_file) |
| 152 | self._ctx_cache[domain] = ctx |
| 153 | |
| 154 | return self._ctx_cache[domain] |
| 155 | |
| 156 | def _generate_domain_cert(self, domain: str): |
| 157 | key = rsa.generate_private_key( |
no test coverage detected