Пример #1
0
    async def _generate_certs(
            self,       # type: HummingbotApplication
            from_client_password: bool = False
    ):
        cert_path: str = get_gateway_paths().local_certs_path.as_posix()
        if not from_client_password:
            if certs_files_exist():
                self.notify(f"Gateway SSL certification files exist in {cert_path}.")
                self.notify("To create new certification files, please first manually delete those files.")
                return

            with begin_placeholder_mode(self):
                while True:
                    pass_phase = await self.app.prompt(
                        prompt='Enter pass phase to generate Gateway SSL certifications  >>> ',
                        is_password=True
                    )
                    if pass_phase is not None and len(pass_phase) > 0:
                        break
                    self.notify("Error: Invalid pass phase")
        else:
            pass_phase = Security.password
        create_self_sign_certs(pass_phase)
        self.notify(f"Gateway SSL certification files are created in {cert_path}.")
        GatewayHttpClient.get_instance().reload_certs()
Пример #2
0
def create_self_sign_certs(pass_phase: str,
                           client_config_map: "ClientConfigAdapter"):
    """
    Create self-sign CA Cert
    """
    cert_directory: str = get_gateway_paths(
        client_config_map).local_certs_path.as_posix()

    filepath_list = {
        'ca_key': join(cert_directory, ca_key_filename),
        'ca_cert': join(cert_directory, ca_cert_filename),
        'server_key': join(cert_directory, server_key_filename),
        'server_cert': join(cert_directory, server_cert_filename),
        'server_csr': join(cert_directory, server_csr_filename),
        'client_key': join(cert_directory, client_key_filename),
        'client_cert': join(cert_directory, client_cert_filename),
        'client_csr': join(cert_directory, client_csr_filename)
    }

    # Create CA Private & Public Keys for signing
    ca_private_key = generate_private_key(pass_phase, filepath_list['ca_key'])
    generate_public_key(ca_private_key, filepath_list['ca_cert'])

    # Create Server Private & Public Keys for signing
    server_private_key = generate_private_key(pass_phase,
                                              filepath_list['server_key'])
    # Create CSR
    generate_csr(server_private_key, filepath_list['server_csr'])
    # Load CSR
    with open(filepath_list['server_csr'], 'rb') as server_csr_file:
        server_csr = x509.load_pem_x509_csr(server_csr_file.read(),
                                            default_backend())

    # Create Client CSR
    # local certificate must be unencrypted. Currently, Requests does not support using encrypted keys.
    client_private_key = generate_private_key(None,
                                              filepath_list['client_key'])
    # Create CSR
    generate_csr(client_private_key, filepath_list['client_csr'])
    # Load CSR
    with open(filepath_list['client_csr'], 'rb') as client_csr_file:
        client_csr = x509.load_pem_x509_csr(client_csr_file.read(),
                                            default_backend())

    # Load CA public key
    with open(filepath_list['ca_cert'], 'rb') as ca_cert_file:
        ca_cert = x509.load_pem_x509_certificate(ca_cert_file.read(),
                                                 default_backend())
    # Load CA private key
    with open(filepath_list['ca_key'], 'rb') as ca_key_file:
        ca_key = serialization.load_pem_private_key(
            ca_key_file.read(),
            pass_phase.encode('utf-8'),
            default_backend(),
        )

    # Sign Server Cert with CSR
    sign_csr(server_csr, ca_cert, ca_key, filepath_list['server_cert'])
    # Sign Client Cert with CSR
    sign_csr(client_csr, ca_cert, ca_key, filepath_list['client_cert'])
Пример #3
0
def certs_files_exist() -> bool:
    """
    Check if the necessary key and certificate files exist
    """
    required_certs = [
        ca_key_filename, ca_cert_filename, server_key_filename,
        server_cert_filename, client_key_filename, client_cert_filename
    ]

    file_list = listdir(get_gateway_paths().local_certs_path.as_posix())
    return all(elem in file_list for elem in required_certs)
 def _http_client(cls, client_config_map: "ClientConfigAdapter", re_init: bool = False) -> aiohttp.ClientSession:
     """
     :returns Shared client session instance
     """
     if cls._shared_client is None or re_init:
         cert_path = get_gateway_paths(client_config_map).local_certs_path.as_posix()
         ssl_ctx = ssl.create_default_context(cafile=f"{cert_path}/ca_cert.pem")
         ssl_ctx.load_cert_chain(certfile=f"{cert_path}/client_cert.pem",
                                 keyfile=f"{cert_path}/client_key.pem",
                                 password=Security.secrets_manager.password.get_secret_value())
         conn = aiohttp.TCPConnector(ssl_context=ssl_ctx)
         cls._shared_client = aiohttp.ClientSession(connector=conn)
     return cls._shared_client
Пример #5
0
    async def _create_gateway(self):
        gateway_paths: GatewayPaths = get_gateway_paths()
        gateway_container_name: str = get_gateway_container_name()
        gateway_conf_mount_path: str = gateway_paths.mount_conf_path.as_posix()
        certificate_mount_path: str = gateway_paths.mount_certs_path.as_posix()
        logs_mount_path: str = gateway_paths.mount_logs_path.as_posix()
        gateway_port: int = get_default_gateway_port()

        # remove existing container(s)
        try:
            old_container = await docker_ipc(
                "containers",
                all=True,
                filters={"name": gateway_container_name}
            )
            for container in old_container:
                self.notify(f"Removing existing gateway container with id {container['Id']}...")
                await docker_ipc(
                    "remove_container",
                    container["Id"],
                    force=True
                )
        except Exception:
            pass  # silently ignore exception

        await self._generate_certs(from_client_password=True)  # create cert

        if await self.check_gateway_image(GATEWAY_DOCKER_REPO, GATEWAY_DOCKER_TAG):
            self.notify("Found Gateway docker image. No image pull needed.")
        else:
            self.notify("Pulling Gateway docker image...")
            try:
                await self.pull_gateway_docker(GATEWAY_DOCKER_REPO, GATEWAY_DOCKER_TAG)
                self.logger().info("Done pulling Gateway docker image.")
            except Exception as e:
                self.notify("Error pulling Gateway docker image. Try again.")
                self.logger().network("Error pulling Gateway docker image. Try again.",
                                      exc_info=True,
                                      app_warning_msg=str(e))
                return
        self.notify("Creating new Gateway docker container...")
        host_config: Dict[str, Any] = await docker_ipc(
            "create_host_config",
            port_bindings={5000: gateway_port},
            binds={
                gateway_conf_mount_path: {
                    "bind": "/usr/src/app/conf/",
                    "mode": "rw"
                },
                certificate_mount_path: {
                    "bind": "/usr/src/app/certs/",
                    "mode": "rw"
                },
                logs_mount_path: {
                    "bind": "/usr/src/app/logs/",
                    "mode": "rw"
                },
            }
        )
        container_info: Dict[str, str] = await docker_ipc(
            "create_container",
            image=f"{GATEWAY_DOCKER_REPO}:{GATEWAY_DOCKER_TAG}",
            name=gateway_container_name,
            ports=[5000],
            volumes=[
                gateway_conf_mount_path,
                certificate_mount_path,
                logs_mount_path
            ],
            host_config=host_config,
            environment=[f"GATEWAY_PASSPHRASE={Security.password}"]
        )

        self.notify(f"New Gateway docker container id is {container_info['Id']}.")

        # Save the gateway port number, if it's not already there.
        if global_config_map.get("gateway_api_port").value != gateway_port:
            global_config_map["gateway_api_port"].value = gateway_port
            global_config_map["gateway_api_host"].value = "localhost"
            save_to_yml(GLOBAL_CONFIG_PATH, global_config_map)

        GatewayHttpClient.get_instance().base_url = f"https://{global_config_map['gateway_api_host'].value}:" \
                                                    f"{global_config_map['gateway_api_port'].value}"
        await start_gateway()

        # create Gateway configs
        await self._generate_gateway_confs(container_id=container_info["Id"])

        # Restarts the Gateway container to ensure that Gateway server reloads new configs
        try:
            await docker_ipc(method_name="restart",
                             container=container_info["Id"])
        except docker.errors.APIError as e:
            self.notify(f"Error restarting Gateway container. Error: {e}")

        self.notify(f"Loaded new configs into Gateway container {container_info['Id']}")
Пример #6
0
    async def _create_gateway(
        self  # type: HummingbotApplication
    ):
        gateway_paths: GatewayPaths = get_gateway_paths(self.client_config_map)
        gateway_container_name: str = get_gateway_container_name(self.client_config_map)
        gateway_conf_mount_path: str = gateway_paths.mount_conf_path.as_posix()
        certificate_mount_path: str = gateway_paths.mount_certs_path.as_posix()
        logs_mount_path: str = gateway_paths.mount_logs_path.as_posix()
        gateway_port: int = get_default_gateway_port(self.client_config_map)

        # remove existing container(s)
        try:
            old_container = await docker_ipc(
                "containers",
                all=True,
                filters={"name": gateway_container_name}
            )
            for container in old_container:
                self.notify(f"Removing existing gateway container with id {container['Id']}...")
                await docker_ipc(
                    "remove_container",
                    container["Id"],
                    force=True
                )
        except Exception:
            pass  # silently ignore exception

        await self._generate_certs(from_client_password=True)  # create cert

        if await self.check_gateway_image(GATEWAY_DOCKER_REPO, GATEWAY_DOCKER_TAG):
            self.notify("Found Gateway docker image. No image pull needed.")
        else:
            self.notify("Pulling Gateway docker image...")
            try:
                await self.pull_gateway_docker(GATEWAY_DOCKER_REPO, GATEWAY_DOCKER_TAG)
                self.logger().info("Done pulling Gateway docker image.")
            except Exception as e:
                self.notify("Error pulling Gateway docker image. Try again.")
                self.logger().network("Error pulling Gateway docker image. Try again.",
                                      exc_info=True,
                                      app_warning_msg=str(e))
                return
        self.notify("Creating new Gateway docker container...")
        host_config: Dict[str, Any] = await docker_ipc(
            "create_host_config",
            port_bindings={5000: gateway_port},
            binds={
                gateway_conf_mount_path: {
                    "bind": "/usr/src/app/conf/",
                    "mode": "rw"
                },
                certificate_mount_path: {
                    "bind": "/usr/src/app/certs/",
                    "mode": "rw"
                },
                logs_mount_path: {
                    "bind": "/usr/src/app/logs/",
                    "mode": "rw"
                },
            }
        )
        container_info: Dict[str, str] = await docker_ipc(
            "create_container",
            image=f"{GATEWAY_DOCKER_REPO}:{GATEWAY_DOCKER_TAG}",
            name=gateway_container_name,
            ports=[5000],
            volumes=[
                gateway_conf_mount_path,
                certificate_mount_path,
                logs_mount_path
            ],
            host_config=host_config,
            environment=[f"GATEWAY_PASSPHRASE={Security.secrets_manager.password.get_secret_value()}"]
        )

        self.notify(f"New Gateway docker container id is {container_info['Id']}.")

        # Save the gateway port number, if it's not already there.
        gateway_config_map = self.client_config_map.gateway
        if gateway_config_map.gateway_api_port != gateway_port:
            gateway_config_map.gateway_api_port = gateway_port
            gateway_config_map.gateway_api_host = "localhost"
            save_to_yml(CLIENT_CONFIG_PATH, self.client_config_map)

        self._get_gateway_instance().base_url = (
            f"https://{gateway_config_map.gateway_api_host}:{gateway_config_map.gateway_api_port}"
        )
        await start_gateway(self.client_config_map)

        # create Gateway configs
        await self._generate_gateway_confs(container_id=container_info["Id"])

        self.notify("Gateway is starting, please wait a moment.")
        # wait about 30 seconds for the gateway to start
        docker_and_gateway_live = await self.ping_gateway_docker_and_api(30)
        if docker_and_gateway_live:
            self.notify("Gateway has started succesfully.")
        else:
            self.notify("Error starting Gateway container.")