From 2281608065a10d76a33407863147be0a0f900971 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 30 Oct 2024 22:15:45 -0300 Subject: [PATCH 1/7] (feat) add security config for backend api --- CONFIG.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CONFIG.py b/CONFIG.py index bd702cb..771f804 100644 --- a/CONFIG.py +++ b/CONFIG.py @@ -17,7 +17,9 @@ DEFAULT_MINER_COINS = ["Avalanche"] CERTIFIED_EXCHANGES = ["ascendex", "binance", "bybit", "gate.io", "hitbtc", "huobi", "kucoin", "okx", "gateway"] CERTIFIED_STRATEGIES = ["xemm", "cross exchange market making", "pmm", "pure market making"] -AUTH_SYSTEM_ENABLED = os.getenv("AUTH_SYSTEM_ENABLED", "False").lower() in ("true", "1", "t") +AUTH_SYSTEM_ENABLED = os.getenv("AUTH_SYSTEM_ENABLED", "True").lower() in ("true", "1", "t") BACKEND_API_HOST = os.getenv("BACKEND_API_HOST", "127.0.0.1") BACKEND_API_PORT = os.getenv("BACKEND_API_PORT", 8000) +BACKEND_API_USERNAME = os.getenv("BACKEND_API_USERNAME", "admin") +BACKEND_API_PASSWORD = os.getenv("BACKEND_API_PASSWORD", "admin") From 8bbb5831e53ad5515b3edb9e89dcdfaf41024ff2 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 30 Oct 2024 22:16:24 -0300 Subject: [PATCH 2/7] (feat) update environment --- environment_conda.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/environment_conda.yml b/environment_conda.yml index 19faacf..1699708 100644 --- a/environment_conda.yml +++ b/environment_conda.yml @@ -19,13 +19,10 @@ dependencies: - statsmodels - pandas_ta==0.3.14b - pyyaml - - jupyter - - optuna - - optuna-dashboard - pathlib - - st-pages + - st_pages - streamlit-elements==0.1.* - - streamlit-authenticator + - streamlit-authenticator==0.3.2 - pydantic==1.10.4 - flake8 - isort From 4787685897449358e3bf41c52342a2dbb853da8a Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 30 Oct 2024 22:22:06 -0300 Subject: [PATCH 3/7] (feat) add security to backend api client --- backend/services/backend_api_client.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/backend/services/backend_api_client.py b/backend/services/backend_api_client.py index a7ae154..4fefb68 100644 --- a/backend/services/backend_api_client.py +++ b/backend/services/backend_api_client.py @@ -4,6 +4,7 @@ import pandas as pd import requests import streamlit as st from hummingbot.strategy_v2.models.executors_info import ExecutorInfo +from requests.auth import HTTPBasicAuth class BackendAPIClient: @@ -20,10 +21,11 @@ class BackendAPIClient: cls._shared_instance = BackendAPIClient(*args, **kwargs) return cls._shared_instance - def __init__(self, host: str = "localhost", port: int = 8000): + def __init__(self, host: str = "localhost", port: int = 8000, username: str = "admin", password: str = "admin"): self.host = host self.port = port self.base_url = f"http://{self.host}:{self.port}" + self.auth = HTTPBasicAuth(username, password) def post(self, endpoint: str, payload: Optional[Dict] = None, params: Optional[Dict] = None): """ @@ -34,7 +36,7 @@ class BackendAPIClient: :return: """ url = f"{self.base_url}/{endpoint}" - response = requests.post(url, json=payload, params=params) + response = requests.post(url, json=payload, params=params, auth=self.auth) return self._process_response(response) def get(self, endpoint: str): @@ -44,12 +46,15 @@ class BackendAPIClient: :return: """ url = f"{self.base_url}/{endpoint}" - response = requests.get(url) + response = requests.get(url, auth=self.auth) return self._process_response(response) @staticmethod def _process_response(response): - if response.status_code == 400: + if response.status_code == 401: + st.error("You are not authorized to access Backend API. Please check your credentials.") + return + elif response.status_code == 400: st.error(response.json()["detail"]) return return response.json() From 7d29288d593ec3d9c3d1008cbe11b9ec222ebf05 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 30 Oct 2024 22:22:44 -0300 Subject: [PATCH 4/7] (feat) improve error message when deploying bots --- frontend/components/launch_strategy_v2.py | 60 +++++++++++++---------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/frontend/components/launch_strategy_v2.py b/frontend/components/launch_strategy_v2.py index 98f59d1..354db3b 100644 --- a/frontend/components/launch_strategy_v2.py +++ b/frontend/components/launch_strategy_v2.py @@ -49,35 +49,41 @@ class LaunchStrategyV2(Dashboard.Item): self._controller_config_selected = [param + ".yml" for param in params] def launch_new_bot(self): - if self._bot_name and self._image_name and len(self._controller_config_selected) > 0: - start_time_str = time.strftime("%Y.%m.%d_%H.%M") - bot_name = f"{self._bot_name}-{start_time_str}" - script_config = { - "name": bot_name, - "content": { - "markets": {}, - "candles_config": [], - "controllers_config": self._controller_config_selected, - "config_update_interval": 10, - "script_file_name": "v2_with_controllers.py", - "time_to_cash_out": None, - } + if not self._bot_name: + st.warning("You need to define the bot name.") + return + if not self._image_name: + st.warning("You need to select the hummingbot image.") + return + if not self._controller_config_selected or len(self._controller_config_selected) == 0: + st.warning("You need to select the controllers configs. Please select at least one controller " + "config by clicking on the checkbox.") + return + start_time_str = time.strftime("%Y.%m.%d_%H.%M") + bot_name = f"{self._bot_name}-{start_time_str}" + script_config = { + "name": bot_name, + "content": { + "markets": {}, + "candles_config": [], + "controllers_config": self._controller_config_selected, + "config_update_interval": 10, + "script_file_name": "v2_with_controllers.py", + "time_to_cash_out": None, } + } - self._backend_api_client.add_script_config(script_config) - deploy_config = { - "instance_name": bot_name, - "script": "v2_with_controllers.py", - "script_config": bot_name + ".yml", - "image": self._image_name, - "credentials_profile": self._credentials, - } - self._backend_api_client.create_hummingbot_instance(deploy_config) - with st.spinner('Starting Bot... This process may take a few seconds'): - time.sleep(3) - else: - st.warning("You need to define the bot name and select the controllers configs " - "that you want to deploy.") + self._backend_api_client.add_script_config(script_config) + deploy_config = { + "instance_name": bot_name, + "script": "v2_with_controllers.py", + "script_config": bot_name + ".yml", + "image": self._image_name, + "credentials_profile": self._credentials, + } + self._backend_api_client.create_hummingbot_instance(deploy_config) + with st.spinner('Starting Bot... This process may take a few seconds'): + time.sleep(3) def delete_selected_configs(self): if self._controller_config_selected: From a19b87db62353f68265efdb37d8b45ae33294e19 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 30 Oct 2024 22:23:21 -0300 Subject: [PATCH 5/7] (feat) get the instance of backend api correctly --- frontend/pages/config/utils.py | 5 ++--- .../orchestration/launch_bot_v2_st/README.md | 19 ------------------- .../launch_bot_v2_st/__init__.py | 0 .../orchestration/launch_bot_v2_st/app.py | 8 -------- 4 files changed, 2 insertions(+), 30 deletions(-) delete mode 100644 frontend/pages/orchestration/launch_bot_v2_st/README.md delete mode 100644 frontend/pages/orchestration/launch_bot_v2_st/__init__.py delete mode 100644 frontend/pages/orchestration/launch_bot_v2_st/app.py diff --git a/frontend/pages/config/utils.py b/frontend/pages/config/utils.py index 591cc68..8d90252 100644 --- a/frontend/pages/config/utils.py +++ b/frontend/pages/config/utils.py @@ -3,8 +3,7 @@ import datetime import pandas as pd import streamlit as st -from backend.services.backend_api_client import BackendAPIClient -from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT +from frontend.st_utils import get_backend_api_client def get_max_records(days_to_download: int, interval: str) -> int: @@ -16,7 +15,7 @@ def get_max_records(days_to_download: int, interval: str) -> int: @st.cache_data def get_candles(connector_name="binance", trading_pair="BTC-USDT", interval="1m", days=7): - backend_client = BackendAPIClient(BACKEND_API_HOST, BACKEND_API_PORT) + backend_client = get_backend_api_client() end_time = datetime.datetime.now() - datetime.timedelta(minutes=15) start_time = end_time - datetime.timedelta(days=days) diff --git a/frontend/pages/orchestration/launch_bot_v2_st/README.md b/frontend/pages/orchestration/launch_bot_v2_st/README.md deleted file mode 100644 index 18f4d94..0000000 --- a/frontend/pages/orchestration/launch_bot_v2_st/README.md +++ /dev/null @@ -1,19 +0,0 @@ -### Description - -This page helps you deploy and manage Hummingbot instances: - -- Starting and stopping Hummingbot Broker -- Creating, starting and stopping bot instances -- Managing strategy and script files that instances run -- Fetching status of running instances - -### Maintainers - -This page is maintained by Hummingbot Foundation as a template other pages: - -* [cardosfede](https://github.com/cardosfede) -* [fengtality](https://github.com/fengtality) - -### Wiki - -See the [wiki](https://github.com/hummingbot/dashboard/wiki/%F0%9F%90%99-Bot-Orchestration) for more information. \ No newline at end of file diff --git a/frontend/pages/orchestration/launch_bot_v2_st/__init__.py b/frontend/pages/orchestration/launch_bot_v2_st/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/pages/orchestration/launch_bot_v2_st/app.py b/frontend/pages/orchestration/launch_bot_v2_st/app.py deleted file mode 100644 index 0766de0..0000000 --- a/frontend/pages/orchestration/launch_bot_v2_st/app.py +++ /dev/null @@ -1,8 +0,0 @@ -from frontend.components.deploy_v2_with_controllers import LaunchV2WithControllers -from frontend.st_utils import initialize_st_page - -initialize_st_page(title="Launch Bot ST", icon="🙌") - - -launcher = LaunchV2WithControllers() -launcher() From 982b15f36129cfc24469953b4854449f39bf3b52 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 30 Oct 2024 22:26:09 -0300 Subject: [PATCH 6/7] (feat) improve conditions --- frontend/st_utils.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/frontend/st_utils.py b/frontend/st_utils.py index 984399e..9b667ed 100644 --- a/frontend/st_utils.py +++ b/frontend/st_utils.py @@ -73,20 +73,16 @@ def style_metric_cards( def get_backend_api_client(): from backend.services.backend_api_client import BackendAPIClient - from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT - is_docker_running = False + from CONFIG import BACKEND_API_HOST, BACKEND_API_PASSWORD, BACKEND_API_PORT, BACKEND_API_USERNAME try: - backend_api_client = BackendAPIClient.get_instance(host=BACKEND_API_HOST, port=BACKEND_API_PORT) - is_docker_running = backend_api_client.is_docker_running() - except Exception as e: - st.error( - f"There was an error trying to connect to the Backend API. Please make sure the Backend API is running.\n\n" - f"Error: \n\n{str(e)}") + backend_api_client = BackendAPIClient.get_instance(host=BACKEND_API_HOST, port=BACKEND_API_PORT, + username=BACKEND_API_USERNAME, password=BACKEND_API_PASSWORD) + if not backend_api_client.is_docker_running(): + st.error("Docker is not running. Please make sure Docker is running.") + st.stop() + return backend_api_client + except Exception: st.stop() - if not is_docker_running: - st.error("Docker is not running. Please make sure Docker is running.") - st.stop() - return backend_api_client def auth_system(): @@ -102,7 +98,6 @@ def auth_system(): config['cookie']['name'], config['cookie']['key'], config['cookie']['expiry_days'], - config['pre-authorized'] ) show_pages(main_page() + public_pages()) st.session_state.authenticator.login() From 0c9238aa5559501b88555a2a758ef8e196e679d3 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 30 Oct 2024 22:26:46 -0300 Subject: [PATCH 7/7] (feat) disable auth by default --- CONFIG.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONFIG.py b/CONFIG.py index 771f804..3a3c88e 100644 --- a/CONFIG.py +++ b/CONFIG.py @@ -17,7 +17,7 @@ DEFAULT_MINER_COINS = ["Avalanche"] CERTIFIED_EXCHANGES = ["ascendex", "binance", "bybit", "gate.io", "hitbtc", "huobi", "kucoin", "okx", "gateway"] CERTIFIED_STRATEGIES = ["xemm", "cross exchange market making", "pmm", "pure market making"] -AUTH_SYSTEM_ENABLED = os.getenv("AUTH_SYSTEM_ENABLED", "True").lower() in ("true", "1", "t") +AUTH_SYSTEM_ENABLED = os.getenv("AUTH_SYSTEM_ENABLED", "False").lower() in ("true", "1", "t") BACKEND_API_HOST = os.getenv("BACKEND_API_HOST", "127.0.0.1") BACKEND_API_PORT = os.getenv("BACKEND_API_PORT", 8000)