Skip to content

AirflowSDKConfigParser ignores AIRFLOW_CONFIG env var, silently breaking FAB webserver_config.py customizations (OAuth, custom security manager) #64918

@Towerhint

Description

@Towerhint

Under which category would you file this issue?

Airflow Core

Apache Airflow version

3.2.0

What happened and how to reproduce it?

After upgrading to Airflow 3.2.0, FAB auth customizations in webserver_config.py — including AUTH_TYPE, SECURITY_MANAGER_CLASS, and OAUTH_PROVIDERS — stop being applied. The login page falls back to the default username/password form even when OAuth is configured. No error or warning is logged.

# Set a non-default config path (common in Docker setups)
export AIRFLOW_CONFIG=/opt/airflow/config/airflow.cfg
export AIRFLOW_HOME=/opt/airflow

# In /opt/airflow/config/airflow.cfg:
# [fab]
# config_file = /opt/airflow/config/webserver_config.py

# In /opt/airflow/config/webserver_config.py:
# AUTH_TYPE = AUTH_OAUTH
# SECURITY_MANAGER_CLASS = MyCustomSecurityManager
# (any customization)

# Result: login page shows default DB form, not OAuth
# No error in logs
Verify the divergence:


from airflow.configuration import conf as airflow_conf
from airflow.providers.common.compat.sdk import conf as sdk_conf

print(airflow_conf.get("fab", "config_file"))  # /opt/airflow/config/webserver_config.py ✅
print(sdk_conf.get("fab", "config_file"))      # /opt/airflow/webserver_config.py ❌ (default, file missing)

What you think should happen instead?

No response

Operating System

No response

Deployment

Docker-Compose

Apache Airflow Provider(s)

fab

Versions of Apache Airflow Providers

FAB version: 3.6.0

Official Helm Chart version

Not Applicable

Kubernetes Version

No response

Helm Chart configuration

No response

Docker Image customizations

No response

Anything else?

Root cause

airflow/providers/fab/www/app.py loads the webserver config path using:

from airflow.providers.common.compat.sdk import conf # AirflowSDKConfigParser
webserver_config = conf.get_mandatory_value("fab", "config_file")
flask_app.config.from_pyfile(webserver_config, silent=True)
AirflowSDKConfigParser locates airflow.cfg using only AIRFLOW_HOME:

# airflow/sdk/configuration.py
def get_airflow_config() -> str:
    airflow_home = os.environ.get("AIRFLOW_HOME", os.path.expanduser("~/airflow"))
    return os.path.join(airflow_home, "airflow.cfg")  # always {AIRFLOW_HOME}/airflow.cfg
The standard Airflow config (airflow.configuration.conf) correctly respects the AIRFLOW_CONFIG env var. When users set AIRFLOW_CONFIG=/opt/airflow/config/airflow.cfg (a common Docker/production pattern), the SDK parser never reads it — it still looks for {AIRFLOW_HOME}/airflow.cfg. So any [fab] config_file setting in the user's actual airflow.cfg is ignored, and the SDK parser falls back to its default: {AIRFLOW_HOME}/webserver_config.py.

Since from_pyfile(..., silent=True) swallows missing-file errors, the entire webserver_config.py is silently skipped with no log output.

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions