This is an automated email from the ASF dual-hosted git repository.
vincbeck pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 59d592f2eb2 Add back ProxyFix Middleware for flask app builder (#49942)
59d592f2eb2 is described below
commit 59d592f2eb2e261631ef46dbd44d65acba263e25
Author: Glenn Schuurman <[email protected]>
AuthorDate: Wed Apr 30 23:26:29 2025 +0200
Add back ProxyFix Middleware for flask app builder (#49942)
* Add back ProxyFix Middleware for flask app builder
Fixes Issues #49781 #49705
Add back the Removed ProxyFix Middleware to allow Oauth2 authentication
when using a reverse proxy like nginx or traefik.
When not using proxyFix the redirect_url incorectly gets set to http://
instead of the expected https://, This breaks many authentication flows,
especially azure, which does not allow http:// redirect_urls for
anything other than localhost.
Help is needed with adjusting the configuration from webserver to
api-server.
* Add config documentation to fab provider
Add the original proxy_fix documentation back into the FAB provider
package and update the section to match fab instead of websever.
* Use correct versioning scheme for provider
* Fix typo in import
* Bypass missing extention test
---------
Co-authored-by: Glenn Schuurman <[email protected]>
---
.../tests/unit/always/test_project_structure.py | 1 +
providers/fab/provider.yaml | 52 ++++++++++++++++++++++
.../src/airflow/providers/fab/get_provider_info.py | 42 +++++++++++++++++
providers/fab/src/airflow/providers/fab/www/app.py | 2 +
.../fab/www/extensions/init_wsgi_middlewares.py | 41 +++++++++++++++++
5 files changed, 138 insertions(+)
diff --git a/airflow-core/tests/unit/always/test_project_structure.py
b/airflow-core/tests/unit/always/test_project_structure.py
index af628f4b32c..a1cfba80cf6 100644
--- a/airflow-core/tests/unit/always/test_project_structure.py
+++ b/airflow-core/tests/unit/always/test_project_structure.py
@@ -138,6 +138,7 @@ class TestProjectStructure:
"providers/fab/tests/unit/fab/www/extensions/test_init_security.py",
"providers/fab/tests/unit/fab/www/extensions/test_init_session.py",
"providers/fab/tests/unit/fab/www/extensions/test_init_views.py",
+
"providers/fab/tests/unit/fab/www/extensions/test_init_wsgi_middlewares.py",
"providers/fab/tests/unit/fab/www/security/test_permissions.py",
"providers/fab/tests/unit/fab/www/test_airflow_flask_app.py",
"providers/fab/tests/unit/fab/www/test_app.py",
diff --git a/providers/fab/provider.yaml b/providers/fab/provider.yaml
index c069b3b12bd..7805ca3a0d7 100644
--- a/providers/fab/provider.yaml
+++ b/providers/fab/provider.yaml
@@ -119,6 +119,58 @@ config:
type: integer
example: ~
default: "43200"
+ enable_proxy_fix:
+ description: |
+ Enable werkzeug ``ProxyFix`` middleware for reverse proxy
+ version_added: 2.1.0
+ type: boolean
+ example: ~
+ default: "False"
+ proxy_fix_x_for:
+ description: |
+ Number of values to trust for ``X-Forwarded-For``.
+ See `Werkzeug: X-Forwarded-For Proxy Fix
+
<https://werkzeug.palletsprojects.com/en/2.3.x/middleware/proxy_fix/>`__ for
more details.
+ version_added: 2.1.0
+ type: integer
+ example: ~
+ default: "1"
+ proxy_fix_x_proto:
+ description: |
+ Number of values to trust for ``X-Forwarded-Proto``.
+ See `Werkzeug: X-Forwarded-For Proxy Fix
+
<https://werkzeug.palletsprojects.com/en/2.3.x/middleware/proxy_fix/>`__ for
more details.
+ version_added: 2.1.0
+ type: integer
+ example: ~
+ default: "1"
+ proxy_fix_x_host:
+ description: |
+ Number of values to trust for ``X-Forwarded-Host``.
+ See `Werkzeug: X-Forwarded-For Proxy Fix
+
<https://werkzeug.palletsprojects.com/en/2.3.x/middleware/proxy_fix/>`__ for
more details.
+ version_added: 2.1.0
+ type: integer
+ example: ~
+ default: "1"
+ proxy_fix_x_port:
+ description: |
+ Number of values to trust for ``X-Forwarded-Port``.
+ See `Werkzeug: X-Forwarded-For Proxy Fix
+
<https://werkzeug.palletsprojects.com/en/2.3.x/middleware/proxy_fix/>`__ for
more details.
+ version_added: 2.1.0
+ type: integer
+ example: ~
+ default: "1"
+ proxy_fix_x_prefix:
+ description: |
+ Number of values to trust for ``X-Forwarded-Prefix``.
+ See `Werkzeug: X-Forwarded-For Proxy Fix
+
<https://werkzeug.palletsprojects.com/en/2.3.x/middleware/proxy_fix/>`__ for
more details.
+ version_added: 2.1.0
+ type: integer
+ example: ~
+ default: "1"
auth-managers:
- airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager
diff --git a/providers/fab/src/airflow/providers/fab/get_provider_info.py
b/providers/fab/src/airflow/providers/fab/get_provider_info.py
index 924dfca466a..6558807420a 100644
--- a/providers/fab/src/airflow/providers/fab/get_provider_info.py
+++ b/providers/fab/src/airflow/providers/fab/get_provider_info.py
@@ -79,6 +79,48 @@ def get_provider_info():
"example": None,
"default": "43200",
},
+ "enable_proxy_fix": {
+ "description": "Enable werkzeug ``ProxyFix``
middleware for reverse proxy\n",
+ "version_added": "2.1.0",
+ "type": "boolean",
+ "example": None,
+ "default": "False",
+ },
+ "proxy_fix_x_for": {
+ "description": "Number of values to trust for
``X-Forwarded-For``.\nSee `Werkzeug: X-Forwarded-For Proxy
Fix\n<https://werkzeug.palletsprojects.com/en/2.3.x/middleware/proxy_fix/>`__
for more details.\n",
+ "version_added": "2.1.0",
+ "type": "integer",
+ "example": None,
+ "default": "1",
+ },
+ "proxy_fix_x_proto": {
+ "description": "Number of values to trust for
``X-Forwarded-Proto``.\nSee `Werkzeug: X-Forwarded-For Proxy
Fix\n<https://werkzeug.palletsprojects.com/en/2.3.x/middleware/proxy_fix/>`__
for more details.\n",
+ "version_added": "2.1.0",
+ "type": "integer",
+ "example": None,
+ "default": "1",
+ },
+ "proxy_fix_x_host": {
+ "description": "Number of values to trust for
``X-Forwarded-Host``.\nSee `Werkzeug: X-Forwarded-For Proxy
Fix\n<https://werkzeug.palletsprojects.com/en/2.3.x/middleware/proxy_fix/>`__
for more details.\n",
+ "version_added": "2.1.0",
+ "type": "integer",
+ "example": None,
+ "default": "1",
+ },
+ "proxy_fix_x_port": {
+ "description": "Number of values to trust for
``X-Forwarded-Port``.\nSee `Werkzeug: X-Forwarded-For Proxy
Fix\n<https://werkzeug.palletsprojects.com/en/2.3.x/middleware/proxy_fix/>`__
for more details.\n",
+ "version_added": "2.1.0",
+ "type": "integer",
+ "example": None,
+ "default": "1",
+ },
+ "proxy_fix_x_prefix": {
+ "description": "Number of values to trust for
``X-Forwarded-Prefix``.\nSee `Werkzeug: X-Forwarded-For Proxy
Fix\n<https://werkzeug.palletsprojects.com/en/2.3.x/middleware/proxy_fix/>`__
for more details.\n",
+ "version_added": "2.1.0",
+ "type": "integer",
+ "example": None,
+ "default": "1",
+ },
},
}
},
diff --git a/providers/fab/src/airflow/providers/fab/www/app.py
b/providers/fab/src/airflow/providers/fab/www/app.py
index be29f28bd67..873e7adb8f0 100644
--- a/providers/fab/src/airflow/providers/fab/www/app.py
+++ b/providers/fab/src/airflow/providers/fab/www/app.py
@@ -41,6 +41,7 @@ from airflow.providers.fab.www.extensions.init_views import (
init_error_handlers,
init_plugins,
)
+from airflow.providers.fab.www.extensions.init_wsgi_middlewares import
init_wsgi_middleware
from airflow.providers.fab.www.utils import get_session_lifetime_config
app: Flask | None = None
@@ -103,6 +104,7 @@ def create_app(enable_plugins: bool):
init_jinja_globals(flask_app, enable_plugins=enable_plugins)
init_xframe_protection(flask_app)
init_airflow_session_interface(flask_app)
+ init_wsgi_middleware(flask_app)
return flask_app
diff --git
a/providers/fab/src/airflow/providers/fab/www/extensions/init_wsgi_middlewares.py
b/providers/fab/src/airflow/providers/fab/www/extensions/init_wsgi_middlewares.py
new file mode 100644
index 00000000000..bcb9d3919f6
--- /dev/null
+++
b/providers/fab/src/airflow/providers/fab/www/extensions/init_wsgi_middlewares.py
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from werkzeug.middleware.proxy_fix import ProxyFix
+
+from airflow.configuration import conf
+
+if TYPE_CHECKING:
+ from flask import Flask
+
+
+def init_wsgi_middleware(flask_app: Flask) -> None:
+ """Handle X-Forwarded-* headers and base_url support."""
+ # Apply ProxyFix middleware
+ if conf.getboolean("fab", "ENABLE_PROXY_FIX"):
+ flask_app.wsgi_app = ProxyFix( # type: ignore
+ flask_app.wsgi_app,
+ x_for=conf.getint("fab", "PROXY_FIX_X_FOR", fallback=1),
+ x_proto=conf.getint("fab", "PROXY_FIX_X_PROTO", fallback=1),
+ x_host=conf.getint("fab", "PROXY_FIX_X_HOST", fallback=1),
+ x_port=conf.getint("fab", "PROXY_FIX_X_PORT", fallback=1),
+ x_prefix=conf.getint("fab", "PROXY_FIX_X_PREFIX", fallback=1),
+ )