    def init_internal_ssl(self):
        """Create the certs needed to turn on internal SSL."""

        if self.internal_ssl:
            from certipy import Certipy, CertNotFoundError

            certipy = Certipy(
                store_dir=self.internal_certs_location,
                remove_existing=self.recreate_internal_certs,
            )

            # Here we define how trust should be laid out per each component
            self.internal_ssl_components_trust = {
                'hub-ca': list(self.internal_ssl_authorities.keys()),
                'proxy-api-ca': ['hub-ca', 'services-ca', 'notebooks-ca'],
                'proxy-client-ca': ['hub-ca', 'notebooks-ca'],
                'notebooks-ca': ['hub-ca', 'proxy-client-ca'],
                'services-ca': ['hub-ca', 'proxy-api-ca'],
            }

            hub_name = 'hub-ca'

            # If any external CAs were specified in external_ssl_authorities
            # add records of them to Certipy's store.
            self.internal_ssl_authorities.update(self.external_ssl_authorities)
            for authority, files in self.internal_ssl_authorities.items():
                if files:
                    self.log.info("Adding CA for %s", authority)
                    certipy.store.add_record(
                        authority, is_ca=True, files=files, overwrite=True
                    )

            self.internal_trust_bundles = certipy.trust_from_graph(
                self.internal_ssl_components_trust
            )

            default_alt_names = ["IP:127.0.0.1", "DNS:localhost"]
            if self.subdomain_host:
                default_alt_names.append(
                    f"DNS:{urlparse(self.subdomain_host).hostname}"
                )
            # The signed certs used by hub-internal components
            try:
                internal_key_pair = certipy.store.get_record("hub-internal")
            except CertNotFoundError:
                alt_names = list(default_alt_names)
                # In the event the hub needs to be accessed externally, add
                # the fqdn and (optionally) rev_proxy to the set of alt_names.
                alt_names += ["DNS:" + socket.getfqdn()] + self.trusted_alt_names
                self.log.info(
                    "Adding CA for %s: %s", "hub-internal", ";".join(alt_names)
                )
                internal_key_pair = certipy.create_signed_pair(
                    "hub-internal", hub_name, alt_names=alt_names
                )
            else:
                self.log.info("Using existing hub-internal CA")

            # Create the proxy certs
            proxy_api = 'proxy-api'
            proxy_client = 'proxy-client'
            for component in [proxy_api, proxy_client]:
                ca_name = component + '-ca'
                alt_names = default_alt_names + self.trusted_alt_names
                try:
                    record = certipy.store.get_record(component)
                except CertNotFoundError:
                    self.log.info(
                        "Generating signed pair for %s: %s",
                        component,
                        ';'.join(alt_names),
                    )
                    record = certipy.create_signed_pair(
                        component, ca_name, alt_names=alt_names
                    )
                else:
                    self.log.info("Using existing %s CA", component)

                self.internal_proxy_certs[component] = {
                    "keyfile": record['files']['key'],
                    "certfile": record['files']['cert'],
                    "cafile": record['files']['cert'],
                }

            self.internal_ssl_key = internal_key_pair['files']['key']
            self.internal_ssl_cert = internal_key_pair['files']['cert']
            self.internal_ssl_ca = self.internal_trust_bundles[hub_name]

            # Configure the AsyncHTTPClient. This will affect anything using
            # AsyncHTTPClient.
            ssl_context = make_ssl_context(
                self.internal_ssl_key,
                self.internal_ssl_cert,
                cafile=self.internal_ssl_ca,
            )
            AsyncHTTPClient.configure(None, defaults={"ssl_options": ssl_context})
Create the certs needed to turn on internal SSL.
jupyterhub/app.py