From baeb2dfb8332293b6f93ad235a9e2f95be92feb8 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Mon, 24 Aug 2026 13:35:19 +0200 Subject: [PATCH] fix: apply RDS IAM token auth to the pgvector engine (#27754) With `DATABASE_ENABLE_IAM_TOKEN_AUTH=true` and `VECTOR_DB=pgvector`, startup failed at vector store initialisation with `fe_sendauth: no password supplied`, so the two features could not be used together. `PgvectorClient` builds its own engine and never got the `do_connect` listener that refreshes the RDS IAM token, and the `ScopedSession` branch that would have reused the instrumented main engine is unreachable because `PGVECTOR_DB_URL` defaults to `DATABASE_URL` and is therefore never falsy. The pgvector engine now goes through `enable_iam_token_auth()` like the main and Alembic engines. Since a token authenticates exactly one host/port/user, that function now attaches the listener only to engines pointing at the same target, so a `PGVECTOR_DB_URL` aimed at a separate database keeps the password from its own URL instead of having it overwritten; the skip is logged with both identities. Fixes #27752 --- backend/open_webui/internal/db.py | 14 ++++++++++++++ .../open_webui/retrieval/vector/dbs/pgvector.py | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/backend/open_webui/internal/db.py b/backend/open_webui/internal/db.py index e0d9c9ede6..aa96d2f2a0 100644 --- a/backend/open_webui/internal/db.py +++ b/backend/open_webui/internal/db.py @@ -202,6 +202,20 @@ def enable_iam_token_auth(connectable) -> None: return engine = getattr(connectable, 'sync_engine', connectable) + url = engine.url + auth = _rds_iam_token_auth + # The token is bound to one host/port/user pair; leave other databases on their own credentials. + if (url.host, url.port or 5432, url.username) != (auth.host, auth.port, auth.username): + log.warning( + 'AWS RDS IAM token auth not applied to %s: the token is issued for %s@%s:%s, ' + 'so this connection uses the password from its own URL', + url.render_as_string(hide_password=True), + auth.username, + auth.host, + auth.port, + ) + return + if not event.contains(engine, 'do_connect', _set_iam_token_password): event.listen(engine, 'do_connect', _set_iam_token_password) diff --git a/backend/open_webui/retrieval/vector/dbs/pgvector.py b/backend/open_webui/retrieval/vector/dbs/pgvector.py index 91158bcc03..75daeccd12 100644 --- a/backend/open_webui/retrieval/vector/dbs/pgvector.py +++ b/backend/open_webui/retrieval/vector/dbs/pgvector.py @@ -17,6 +17,7 @@ from open_webui.config import ( PGVECTOR_POOL_TIMEOUT, PGVECTOR_USE_HALFVEC, ) +from open_webui.internal.db import ScopedSession, enable_iam_token_auth from open_webui.retrieval.vector.main import ( GetResult, SearchResult, @@ -87,8 +88,6 @@ class PgvectorClient(VectorDBBase): def __init__(self) -> None: # if no pgvector uri, use the existing database connection if not PGVECTOR_DB_URL: - from open_webui.internal.db import ScopedSession - self.session = ScopedSession else: if isinstance(PGVECTOR_POOL_SIZE, int): @@ -107,6 +106,7 @@ class PgvectorClient(VectorDBBase): else: engine = create_engine(PGVECTOR_DB_URL, pool_pre_ping=True) + enable_iam_token_auth(engine) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine, expire_on_commit=False) self.session = scoped_session(SessionLocal)