Resolves: #RHEL-153811 Backport upstream fixes for database connection pool exhaustion that occurred during multi-host push attestation with multiple agents, causing QueuePool timeout and HTTP 500 errors. Upstream commits: - 5b622eae Close DB sessions to prevent connection exhaustion - bc28d5d2 Include thread-safe session management - 4f5f09a6 Address some improvements from code review - 309a0ef0 Fix race condition in SessionManager - e75921f0 Fix linter errors in PersistableModel.get() and .all() - 2d809d8b refactor: Remove dead code AuthSession.authenticate_agent() - e935df8f db: Clean up scoped session after each request - 08c0c67c fix: Check active flag in _extract_identity and guard receive_pop - d74e7499 fix: Add fork-safety to DBManager via dispose() Signed-off-by: Sergio Arroutbi <sarroutb@redhat.com>
80 lines
3.0 KiB
Diff
80 lines
3.0 KiB
Diff
From 4f5f09a69e01c0116f1977aa3a741f3678bb8e67 Mon Sep 17 00:00:00 2001
|
|
From: Sergio Arroutbi <sarroutb@redhat.com>
|
|
Date: Thu, 12 Mar 2026 15:18:56 +0100
|
|
Subject: [PATCH 5/6] Address some improvements from code review
|
|
|
|
Include agent variable None initialization
|
|
and address thread safety for ContextManager
|
|
|
|
Signed-off-by: Sergio Arroutbi <sarroutb@redhat.com>
|
|
---
|
|
keylime/db/keylime_db.py | 7 ++++++-
|
|
keylime/web/verifier/session_controller.py | 3 +++
|
|
2 files changed, 9 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/keylime/db/keylime_db.py b/keylime/db/keylime_db.py
|
|
index 6fd3f08..cf608fa 100644
|
|
--- a/keylime/db/keylime_db.py
|
|
+++ b/keylime/db/keylime_db.py
|
|
@@ -1,4 +1,5 @@
|
|
import os
|
|
+import threading
|
|
from configparser import NoOptionError
|
|
from contextlib import contextmanager
|
|
from sqlite3 import Connection as SQLite3Connection
|
|
@@ -89,10 +90,12 @@ def make_engine(service: str, **engine_args: Any) -> Engine:
|
|
class SessionManager:
|
|
engine: Optional[Engine]
|
|
_scoped_session: Optional[scoped_session]
|
|
+ _lock: threading.Lock
|
|
|
|
def __init__(self) -> None:
|
|
self.engine = None
|
|
self._scoped_session = None
|
|
+ self._lock = threading.Lock()
|
|
|
|
def make_session(self, engine: Engine) -> Session:
|
|
"""
|
|
@@ -100,7 +103,9 @@ class SessionManager:
|
|
"""
|
|
self.engine = engine
|
|
if self._scoped_session is None:
|
|
- self._scoped_session = scoped_session(sessionmaker())
|
|
+ with self._lock:
|
|
+ if self._scoped_session is None:
|
|
+ self._scoped_session = scoped_session(sessionmaker())
|
|
try:
|
|
self._scoped_session.configure(bind=self.engine) # type: ignore
|
|
self._scoped_session.configure(expire_on_commit=False) # type: ignore
|
|
diff --git a/keylime/web/verifier/session_controller.py b/keylime/web/verifier/session_controller.py
|
|
index 3faa310..c8664e2 100644
|
|
--- a/keylime/web/verifier/session_controller.py
|
|
+++ b/keylime/web/verifier/session_controller.py
|
|
@@ -185,6 +185,7 @@ class SessionController(Controller):
|
|
return
|
|
|
|
# Check if agent exists - this is where we validate enrollment
|
|
+ agent = None
|
|
with get_session_context() as session:
|
|
agent = session.query(VerfierMain).filter(VerfierMain.agent_id == agent_id).one_or_none()
|
|
if agent:
|
|
@@ -382,6 +383,7 @@ class SessionController(Controller):
|
|
|
|
# POST /v3[.:minor]/agents/:agent_id/session
|
|
def create(self, agent_id, **params):
|
|
+ agent = None
|
|
with get_session_context() as session:
|
|
agent = session.query(VerfierMain).filter(VerfierMain.agent_id == agent_id).one_or_none()
|
|
if agent:
|
|
@@ -407,6 +409,7 @@ class SessionController(Controller):
|
|
self.respond(200, "Success", auth_session.render())
|
|
|
|
def update(self, agent_id, token, **params):
|
|
+ agent = None
|
|
with get_session_context() as session:
|
|
agent = session.query(VerfierMain).filter(VerfierMain.agent_id == agent_id).one_or_none()
|
|
if agent:
|
|
--
|
|
2.53.0
|
|
|