Skip to content

Commit affa8c6

Browse files
Merge pull request #91 from blacklanternsecurity/config-rework-2
Config Rework
2 parents ab8b2e6 + baa4686 commit affa8c6

29 files changed

+732
-1077
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ if __name__ == "__main__":
379379
When running tests, first start MongoDB and Redis via Docker:
380380

381381
```bash
382-
docker run --rm -p 27017:27017 mongo
382+
docker run --ulimit nofile=64000:64000 --rm -p 27017:27017 mongo
383383
docker run --rm -p 6379:6379 redis
384384
```
385385

bbot_server/api/_fastapi.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from fastapi import FastAPI, HTTPException, Depends, Request, WebSocket
66

77
from bbot_server import modules # noqa: F401
8-
import bbot_server.config as bbcfg
8+
from bbot_server.config import BBOT_SERVER_CONFIG as bbcfg
99
from bbot_server.errors import BBOTServerError, handle_bbot_server_error
1010

1111
log = logging.getLogger("bbot_server.api.fastapi")
@@ -19,12 +19,14 @@
1919
}
2020

2121
# API key header
22-
# api_key_header = APIKeyHeader(name=bbcfg.API_KEY_NAME, auto_error=False)
22+
# api_key_header = APIKeyHeader(name=bbcfg.auth_header, auto_error=False)
2323

2424

2525
def api_key_dependency_http(request: Request = None):
26+
if not bbcfg.auth_enabled:
27+
return
2628
if request is not None:
27-
api_key = request.headers.get(bbcfg.API_KEY_NAME, "")
29+
api_key = request.headers.get(bbcfg.auth_header, "")
2830
if not api_key:
2931
raise HTTPException(status_code=401, detail="API key is required")
3032
valid, reason = bbcfg.check_api_key(api_key)
@@ -34,15 +36,15 @@ def api_key_dependency_http(request: Request = None):
3436

3537

3638
async def api_key_dependency_websocket(websocket: WebSocket = None):
39+
if not bbcfg.auth_enabled:
40+
return
3741
if websocket is not None:
38-
api_key = websocket.headers.get(bbcfg.API_KEY_NAME, "")
42+
api_key = websocket.headers.get(bbcfg.auth_header, "")
3943
if not api_key:
4044
await websocket.close(code=3000, reason="API key is required")
41-
raise HTTPException(status_code=401, detail="API key is required")
4245
valid, reason = bbcfg.check_api_key(api_key)
4346
if not valid:
4447
await websocket.close(code=3000, reason=reason)
45-
raise HTTPException(status_code=401, detail=reason)
4648
return api_key
4749

4850

@@ -102,7 +104,7 @@ def custom_openapi():
102104
"APIKeyHeader": {
103105
"type": "apiKey",
104106
"in": "header",
105-
"name": bbcfg.API_KEY_NAME,
107+
"name": bbcfg.auth_header,
106108
"description": "API key authentication",
107109
}
108110
}

bbot_server/applets/_root.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import bbot_server.config as bbcfg
2-
1+
from bbot_server.config import BBOT_SERVER_CONFIG as bbcfg
32
from bbot_server.applets.base import BaseApplet
43

54

@@ -12,10 +11,10 @@ class RootApplet(BaseApplet):
1211

1312
def __init__(self, config=None, **kwargs):
1413
"""
15-
"config" can be either a dictionary or an omegaconf object
14+
"config" can be a dictionary of config overrides
1615
"""
1716
if config is not None:
18-
bbcfg.refresh_config(config)
17+
bbcfg.refresh(**config)
1918
super().__init__(**kwargs)
2019
self._interface_type = "python"
2120
self._mcp = None
@@ -52,7 +51,7 @@ def config(self):
5251

5352
@property
5453
def _config(self):
55-
return bbcfg.BBOT_SERVER_CONFIG
54+
return bbcfg
5655

5756
async def cleanup(self):
5857
if self.is_native:

bbot_server/applets/_routing.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from contextlib import suppress
88
from fastapi.responses import StreamingResponse
99
from starlette.websockets import WebSocketDisconnect
10-
import bbot_server.config as bbcfg
10+
from bbot_server.config import BBOT_SERVER_CONFIG as bbcfg
1111
from bbot_server.api.mcp import MCP_ENDPOINTS
1212
from bbot_server.utils.misc import smart_encode
1313
from bbot_server.errors import BBOTServerValueError
@@ -230,7 +230,7 @@ def wrapped_function(self):
230230
@functools.wraps(self.orig_function)
231231
async def websocket_auth_wrapper(websocket: WebSocket, *args, **kwargs):
232232
await websocket.accept()
233-
api_key = websocket.headers.get(bbcfg.API_KEY_NAME, "")
233+
api_key = websocket.headers.get(bbcfg.auth_header, "")
234234
valid, reason = bbcfg.check_api_key(api_key)
235235
if valid:
236236
await self.orig_function(websocket, *args, **kwargs)
@@ -260,7 +260,7 @@ async def websocket_wrapper(websocket: WebSocket, *args, **kwargs):
260260
"""
261261
try:
262262
await websocket.accept()
263-
api_key = websocket.headers.get(bbcfg.API_KEY_NAME, "")
263+
api_key = websocket.headers.get(bbcfg.auth_header, "")
264264
valid, reason = bbcfg.check_api_key(api_key)
265265
if not valid:
266266
await websocket.close(code=3000, reason=reason)
@@ -305,7 +305,7 @@ def wrapped_function(self):
305305
async def websocket_wrapper(self, websocket: WebSocket):
306306
try:
307307
await websocket.accept()
308-
api_key = websocket.headers.get(bbcfg.API_KEY_NAME, "")
308+
api_key = websocket.headers.get(bbcfg.auth_header, "")
309309
valid, reason = bbcfg.check_api_key(api_key)
310310
if not valid:
311311
await websocket.close(code=3000, reason=reason)

bbot_server/applets/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ def global_config(self):
658658

659659
@property
660660
def config(self):
661-
return self.global_config.get("modules", {}).get(self.name, {})
661+
return self.global_config.modules.get(self.name, {})
662662

663663
@property
664664
def tag(self):

bbot_server/cli/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from typing import Annotated # noqa
88
from functools import cached_property, wraps
99

10-
import bbot_server.config as bbcfg
10+
from bbot_server.config import BBOT_SERVER_CONFIG as bbcfg
1111
from bbot_server.utils.misc import timestamp_to_human, seconds_to_human
1212

1313

@@ -168,7 +168,7 @@ def highlight_yaml(self, data, **kwargs):
168168
Highlight a YAML string with rich
169169
"""
170170
if not isinstance(data, str):
171-
data = yaml.dump(data, indent=2)
171+
data = yaml.safe_dump(data, indent=2, sort_keys=False)
172172
if not "background_color" in kwargs:
173173
kwargs["background_color"] = "default"
174174
if not "theme" in kwargs:

bbot_server/cli/bbctl.py

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@
33
import asyncio
44
import logging
55
import traceback
6-
from pathlib import Path
7-
from omegaconf import OmegaConf
86
from rich.console import Console
97
from functools import cached_property
108

11-
import bbot_server.config as bbcfg
129
from bbot_server.cli.base import BaseBBCTL, Annotated, Option
1310
from bbot_server.errors import BBOTServerError, BBOTServerUnauthorizedError
1411

@@ -40,45 +37,33 @@ def main(
4037
self.silent = silent
4138
self.color = color
4239
self.debug = debug
43-
self.config_path = None
44-
# command line arg takes precedence over environment variable
45-
custom_config = config or os.environ.get("BBOT_SERVER_CONFIG", "")
46-
if custom_config:
47-
try:
48-
self.config_path = Path(custom_config)
49-
self.bbcfg.update_config_path(self.config_path)
50-
except Exception as e:
51-
raise BBOTServerError(f"Error loading config file at {self.config_path}: {e}")
52-
else:
53-
self.config_path = bbcfg.BBOT_SERVER_CONFIG_PATH
40+
if config:
41+
os.environ["BBOT_SERVER_CONFIG"] = str(config)
42+
self.bbcfg.refresh()
5443
if self.debug:
5544
logging.getLogger().setLevel(logging.DEBUG)
56-
if server_url is not None and server_url != bbcfg.BBOT_SERVER_URL:
45+
if server_url is not None and server_url != self.bbcfg.url:
5746
self._config.url = server_url
5847
self.server_url = self.config.url
5948

6049
self._stdout = Console(file=sys.stdout, highlight=False, color_system=("auto" if self.color else None))
6150
self._stderr = Console(file=sys.stderr, highlight=False, color_system=("auto" if self.color else None))
6251

6352
if current_config:
64-
self.print_yaml(OmegaConf.to_yaml(self.config))
53+
self.print_yaml(self.config.model_dump())
6554
return
6655

6756
@cached_property
6857
def bbot_server(self):
69-
bbot_server_kwargs = {}
70-
if self.config:
71-
bbot_server_kwargs["config"] = self.config
72-
7358
from bbot_server import BBOTServer
7459

75-
bbot_server = BBOTServer(interface="http", url=self.server_url, synchronous=True, **bbot_server_kwargs)
60+
bbot_server = BBOTServer(interface="http", url=self.server_url, synchronous=True)
7661
bbot_server.setup()
7762
return bbot_server
7863

7964
@property
8065
def _config(self):
81-
return self.bbcfg.BBOT_SERVER_CONFIG
66+
return self.bbcfg
8267

8368

8469
log = logging.getLogger("bbot_server.bbctl")

bbot_server/cli/themes.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import typer
2-
from textual.theme import Theme
2+
# from textual.theme import Theme
33

44
COLOR = "bold dark_orange"
55
DARK_COLOR = "grey50"
66

7-
# textual theme
8-
TEXTUAL_THEME = Theme(
9-
name="bbot",
10-
primary="#000000",
11-
secondary="#1a1a1a",
12-
accent="#FF8400",
13-
warning="#FF8400",
14-
error="#ff4500",
15-
success="#FF8400",
16-
foreground="#ffffff",
17-
)
7+
# # textual theme
8+
# TEXTUAL_THEME = Theme(
9+
# name="bbot",
10+
# primary="#000000",
11+
# secondary="#1a1a1a",
12+
# accent="#FF8400",
13+
# warning="#FF8400",
14+
# error="#ff4500",
15+
# success="#FF8400",
16+
# foreground="#ffffff",
17+
# )
1818

1919
# typer theme
2020
typer.rich_utils.STYLE_OPTION = "bold dark_orange"

0 commit comments

Comments
 (0)