@@ -131,7 +131,7 @@ spec:
131131 export HOME=/tmp && \
132132 pip install --no-cache-dir --quiet "psycopg[binary]" && \
133133 {{- if .Values.mlflow.auth.enabled }}
134- pip install --no-cache-dir --quiet "mlflow-oidc-auth" && \
134+ pip install --no-cache-dir --quiet "mlflow-oidc-auth>=7.3.1,<8 " && \
135135 {{- end }}
136136 {{- if and .Values.openshift .Values.mlflow.auth.enabled }}
137137 # Combine system CAs with the ingress CA so Python can verify both
@@ -192,24 +192,41 @@ spec:
192192 # IMPORTANT: Patch BEFORE importing app (app is created at import time)
193193 from mlflow_oidc_auth.middleware.auth_middleware import AuthMiddleware
194194 import mlflow_oidc_auth.middleware.fastapi_permission_middleware as fpm
195+ import mlflow_oidc_auth.hooks.before_request as _before_request
195196
196197 # Assert patched APIs exist — fail fast on mlflow-oidc-auth upgrades
197198 assert hasattr(AuthMiddleware, "_is_unprotected_route"), \
198199 "mlflow-oidc-auth API changed: AuthMiddleware._is_unprotected_route not found"
199200 assert hasattr(fpm, "_find_fastapi_validator"), \
200201 "mlflow-oidc-auth API changed: _find_fastapi_validator not found"
202+ assert hasattr(_before_request, "_is_unprotected_route"), \
203+ "mlflow-oidc-auth API changed: before_request._is_unprotected_route not found"
201204
202- # Patch 1: Exclude /v1/traces from OIDC auth
205+ # Patch 1: Exclude /v1/traces, /version, /ping from OIDC auth (FastAPI gate)
203206 # The OTel collector authenticates via OAuth2 client credentials (Bearer token)
204207 # but may not have a user profile in the MLflow users table.
205- # Skip auth entirely — Istio mTLS protects this path.
208+ # /version and /ping are health-check endpoints that should never require auth.
209+ # Skip auth entirely — Istio mTLS protects /v1/traces.
206210 original_is_unprotected = AuthMiddleware._is_unprotected_route
207211 def patched_is_unprotected(self, path: str) -> bool:
208- if path.startswith("/v1/traces"):
212+ if path.startswith("/v1/traces") or path in ("/version", "/ping") :
209213 return True
210214 return original_is_unprotected(self, path)
211215 AuthMiddleware._is_unprotected_route = patched_is_unprotected
212- print("Excluded /v1/traces from OIDC auth (mTLS via Istio)")
216+ print("Excluded /v1/traces, /version, /ping from OIDC auth (FastAPI gate)")
217+
218+ # Patch 1b: Exclude /version, /ping from Flask before_request auth gate
219+ # /version and /ping are Flask routes that pass through both FastAPI middleware
220+ # AND the Flask before_request hook. Without this patch, Gate A (above) skips
221+ # auth (so no username is set), then Gate B returns 401 because username is None.
222+ # /health is already natively exempt at this layer.
223+ _original_flask_is_unprotected = _before_request._is_unprotected_route
224+ def _patched_flask_is_unprotected(path: str) -> bool:
225+ if path in ("/version", "/ping"):
226+ return True
227+ return _original_flask_is_unprotected(path)
228+ _before_request._is_unprotected_route = _patched_flask_is_unprotected
229+ print("Excluded /version, /ping from Flask before_request auth gate")
213230
214231 # Patch 2: Skip permission validation for /v1/traces
215232 # mlflow-oidc-auth v7+ adds a FastAPI permission middleware that checks
0 commit comments