Fix race condition in AWS CLI cache creation during parallel KubernetesPodOperator auth (#60943)#1
Draft
Vamsi-klu wants to merge 640 commits into
Draft
Fix race condition in AWS CLI cache creation during parallel KubernetesPodOperator auth (#60943)#1Vamsi-klu wants to merge 640 commits into
Vamsi-klu wants to merge 640 commits into
Conversation
…#61253) Co-authored-by: Anton Nitochkin <[email protected]>
…integration tests (apache#61311)
* Fix Keycloak double-slash URL bug (apache#61121) - Normalize server_url in _get_token_url to prevent double-slashes - Add .rstrip('/') to handle trailing slashes in server_url configuration - Add comprehensive tests for URL normalization scenarios - Resolves compatibility issue with Keycloak 26.4+ strict path validation When server_url has a trailing slash (e.g., 'https://host/auth/'), the previous implementation would create invalid URLs with double-slashes (e.g., 'https://host/auth//realms/...'), which Keycloak 26.4+ rejects with HTTP 400 'missingNormalization' error. This fix allows users to configure server_url with or without trailing slashes while ensuring properly normalized URLs are always generated. Fixes apache#61121 * Refactor URL normalization tests to use parametrize - Consolidate 4 separate test methods into a single parametrized test - Improves maintainability and reduces code duplication - Covers same scenarios: no trailing slash, single slash, multiple slashes, root path
apache#61287) * Fix OAuth session race condition causing false 401 errors during login Fixes apache#57981 When users authenticate via Azure OAuth SSO (and other OAuth providers), the UI briefly displays an authentication error message during the OAuth redirect flow. The error appears for approximately 1 second before disappearing once authentication successfully completes. Root Cause: The issue stems from a race condition during the OAuth authentication flow. After the OAuth callback completes and the user is authenticated, the Flask session containing OAuth tokens and user data may not be fully committed to the session backend (cookie or database) before the redirect response is sent to the client. When the UI loads and immediately makes API requests (like /ui/config), these requests arrive before the session is available, causing temporary 401 Unauthorized errors. Solution: This commit introduces a CustomAuthOAuthView that extends Flask-AppBuilder's AuthOAuthView to explicitly ensure the session is committed before redirecting. The fix: 1. Created providers/fab/src/airflow/providers/fab/auth_manager/views/auth_oauth.py with CustomAuthOAuthView class 2. Override oauth_authorized() method to mark session.modified = True after parent's OAuth callback handling completes 3. Updated security_manager/override.py to use CustomAuthOAuthView instead of the default AuthOAuthView This ensures Flask's session interface saves the session via the after_request handler before the HTTP redirect response is sent to the client, eliminating the race condition. The fix addresses the root cause as suggested by maintainer feedback on PR apache#58037, rather than masking the error in the UI. Testing: - Syntax validated with py_compile - Works with both session backends (database and securecookie) - Maintains backward compatibility with existing OAuth flows Related Issues: - apache#55612 - Airflow UI initial XHR returns 401 before session cookie is set - apache#57534 - Airflow 3.1.1 oauth login failure - apache#57485 - Airflow 3.1.1 oauth login broken - PR apache#58037 - Previous UI-based workaround attempt (closed) Signed-off-by: Jgprog117 <[email protected]> * Fix logging to use %-formatting instead of f-strings * Add tests for CustomAuthOAuthView * Fix linting and formatting issues in OAuth session race condition fix Remove unused imports, fix import ordering, and apply ruff formatting: - Remove unused pytest import from test_auth_oauth.py - Remove unused AuthOAuthView import from override.py - Fix import ordering to comply with ruff formatting rules - Apply ruff format to test file * Address PR review feedback from SameerMesiah97 - Remove redundant if/else branching that did the same thing in both paths - Fix misleading "completed successfully" log message to neutral wording - Replace brittle __class__.__bases__[0] mocking with explicit AuthOAuthView - Consolidate duplicate backend tests into a single parametrized test * Fix test RuntimeError by avoiding Flask session LocalProxy access Use mock.patch with new= as context manager instead of decorator to prevent mock from inspecting the Flask session LocalProxy, which requires an active request context. --------- Signed-off-by: Jgprog117 <[email protected]>
Extract TriggerDAGRunPostBody logical_date defaulting from _get_func into a new _apply_datamodel_defaults method. This addresses review feedback to reduce cyclomatic complexity in the already-complex _get_func method and provides a centralized location for managing datamodel-specific defaults.
…pache#61352) If VERSION_SUFFIX is exported in the current terminal, it can be accidentally used as `--version-suffix` by distribution preparation commands - which in case of the PMC verification might cause preparing of `PyPI` variants of the distributions, not the `SVN` ones (without RC suffix). This PR updates the relevant commands to override the suffix with empty suffix - which also is an explicit signal that this is intended.
* doc: clarify policy for exposing sensitive data * Update airflow-core/docs/security/security_model.rst --------- Co-authored-by: Jarek Potiuk <[email protected]>
* Refactor configuration parser to respect deprecated options in default parser * Add tests to ensure deprecated options are skipped in configuration parser * Add test for handling default values of deprecated options in AirflowConfigParser * Add test case without fallback param
There were a few things raising warnings during uv sync that should be fixed: * no lower limits on few dependencies * old pcycopg2 dev dependency for postgres provider. * botocore/aiobotocore depsndencies not updated for a while * lack of quotes in some sqlalchemy deps * optional deps for sqlalchemy not sorted properly
Signed-off-by: Guan-Ming (Wesley) Chiu <[email protected]>
* Add data lineage graph to AssetGraph * Update airflow-core/src/airflow/api_fastapi/core_api/routes/ui/dependencies.py Co-authored-by: Jason(Zhe-You) Liu <[email protected]> * Refactor to use deque * Apply review comments * Add task icon * Extract get_scheduling_dependencies --------- Co-authored-by: Jason(Zhe-You) Liu <[email protected]>
The operator was incorrectly ignoring the `wait_policy` argument and always defaulting to waiting for cluster completion. This change ensures the `wait_policy` is correctly persisted and used to select the appropriate waiter (e.g., for step completion), fixing the hardcoded behavior.
…ates (apache#61407) Bumps the core-ui-package-updates group with 10 updates in the /airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui directory: | Package | From | To | | --- | --- | --- | | [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) | `0.90.10` | `0.91.1` | | [axios](https://github.com/axios/axios) | `1.13.3` | `1.13.4` | | [react](https://github.com/facebook/react/tree/HEAD/packages/react) | `19.2.3` | `19.2.4` | | [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.2.9` | `19.2.10` | | [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) | `19.2.3` | `19.2.4` | | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.53.1` | `8.54.0` | | [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.53.1` | `8.54.0` | | [@typescript-eslint/utils](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/utils) | `8.53.1` | `8.54.0` | | [happy-dom](https://github.com/capricorn86/happy-dom) | `20.3.9` | `20.4.0` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.53.1` | `8.54.0` | Updates `@hey-api/openapi-ts` from 0.90.10 to 0.91.1 - [Release notes](https://github.com/hey-api/openapi-ts/releases) - [Changelog](https://github.com/hey-api/openapi-ts/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/hey-api/openapi-ts/compare/@hey-api/[email protected]...@hey-api/[email protected]) Updates `axios` from 1.13.3 to 1.13.4 - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](axios/axios@v1.13.3...v1.13.4) Updates `react` from 19.2.3 to 19.2.4 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.4/packages/react) Updates `@types/react` from 19.2.9 to 19.2.10 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) Updates `react-dom` from 19.2.3 to 19.2.4 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.4/packages/react-dom) Updates `@types/react` from 19.2.9 to 19.2.10 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) Updates `@typescript-eslint/eslint-plugin` from 8.53.1 to 8.54.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.54.0/packages/eslint-plugin) Updates `@typescript-eslint/parser` from 8.53.1 to 8.54.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.54.0/packages/parser) Updates `@typescript-eslint/utils` from 8.53.1 to 8.54.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/utils/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.54.0/packages/utils) Updates `happy-dom` from 20.3.9 to 20.4.0 - [Release notes](https://github.com/capricorn86/happy-dom/releases) - [Commits](capricorn86/happy-dom@v20.3.9...v20.4.0) Updates `typescript-eslint` from 8.53.1 to 8.54.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.54.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: "@hey-api/openapi-ts" dependency-version: 0.91.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: core-ui-package-updates - dependency-name: axios dependency-version: 1.13.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: core-ui-package-updates - dependency-name: react dependency-version: 19.2.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: core-ui-package-updates - dependency-name: "@types/react" dependency-version: 19.2.10 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: core-ui-package-updates - dependency-name: react-dom dependency-version: 19.2.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: core-ui-package-updates - dependency-name: "@types/react" dependency-version: 19.2.10 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: core-ui-package-updates - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.54.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: core-ui-package-updates - dependency-name: "@typescript-eslint/parser" dependency-version: 8.54.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: core-ui-package-updates - dependency-name: "@typescript-eslint/utils" dependency-version: 8.54.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: core-ui-package-updates - dependency-name: happy-dom dependency-version: 20.4.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: core-ui-package-updates - dependency-name: typescript-eslint dependency-version: 8.54.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: core-ui-package-updates ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…es (apache#61404) * Bump the fab-ui-package-updates group across 1 directory with 3 updates Bumps the fab-ui-package-updates group with 3 updates in the /providers/fab/src/airflow/providers/fab/www directory: [jquery-ui](https://github.com/jquery/jquery-ui), [css-loader](https://github.com/webpack/css-loader) and [stylelint](https://github.com/stylelint/stylelint). Updates `jquery-ui` from 1.14.1 to 1.14.2 - [Release notes](https://github.com/jquery/jquery-ui/releases) - [Commits](jquery/jquery-ui@1.14.1...1.14.2) Updates `css-loader` from 7.1.2 to 7.1.3 - [Release notes](https://github.com/webpack/css-loader/releases) - [Changelog](https://github.com/webpack/css-loader/blob/main/CHANGELOG.md) - [Commits](webpack/css-loader@v7.1.2...v7.1.3) Updates `stylelint` from 17.0.0 to 17.1.0 - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md) - [Commits](stylelint/stylelint@17.0.0...17.1.0) --- updated-dependencies: - dependency-name: jquery-ui dependency-version: 1.14.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: fab-ui-package-updates - dependency-name: css-loader dependency-version: 7.1.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: fab-ui-package-updates - dependency-name: stylelint dependency-version: 17.1.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: fab-ui-package-updates ... Signed-off-by: dependabot[bot] <[email protected]> * Update hash --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: vincbeck <[email protected]>
Bumps @isaacs/brace-expansion from 5.0.0 to 5.0.1. --- updated-dependencies: - dependency-name: "@isaacs/brace-expansion" dependency-version: 5.0.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Update timer.duration labels and examples to milliseconds, and fix the OTel timing docstring to match runtime behavior. Historical context: apache#39908 introduced milliseconds alignment with a compatibility flag, and apache#43975 removed that flag and standardized milliseconds everywhere. Co-authored-by: Cursor <[email protected]>
* refactor: Added deferrable support to WinRMOperator * Update providers/microsoft/winrm/src/airflow/providers/microsoft/winrm/triggers/winrm.py Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
…e#61813) * Fix scheduler crash when enqueuing TI with null dag_version_id After upgrade from AF2, TIs might be without dag_version_id since we don't enforce this at the DB level. The solution here is to skip enqueing such TIs until the verify_integrity runs which would update the dag_version_id of the TI. Initially, the TI would be stuck but would later be cleared when the handle tasks stuck in queued deems it fit. * update warning log * update warning log * Update the caplog level in test
* flush in-memory otel metrics at process shutdown * fix module for test
Signed-off-by: Guan-Ming (Wesley) Chiu <[email protected]>
…o a shared constant (apache#61891)
Release version check for Python started to fail with rate limit, this PR changes Python version retrieval to use static information hosted on ftp site of Python (which is behind CDN and can handle much bigger traffic and is read-only so there are no rate limits involved.
* Added Informatica Plugin Provider * Added Informatica Plugin Provider * changed the informatica version which uploaded on pypi * fix: restore accidentally deleted symlink files * added tests requirements and missing tests * Fix provider compat errors in prek/breeze checks * fix prex listener issue * Apply suggestions from code review Co-authored-by: Jens Scheffler <[email protected]> * Apply suggestions from code review Co-authored-by: Copilot <[email protected]> * refactor(providers/informatica): address review comments from @jscheffl * refactor(providers/informatica): address review comments from copilot * refactor(providers/informatica): address review comments from copilot * refactor(providers/informatica&openlineage): Breeze documentation has been updated due to a provider version change and fixing tests * refactor(providers/informatica&openlineage): Breeze documentation has been updated due to a provider version change and fixing tests * Update providers/informatica/docs/index.rst Co-authored-by: Jarek Potiuk <[email protected]> * refactor(providers/informatica): address review comments from @jscheffl * Regenerate Breeze output after main merge * Fix:(providers/informatica) build-docs error for removed tests & changed CODEOWNERS * fix: removed informatica integration tests in GroupOfTests.INTEGRATION_PROVIDERS * refactor(providers/informatica) regenerated breeze docs after the common.ai provider was added * fix: deleted not necessarly init file --------- Co-authored-by: Jens Scheffler <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: Jarek Potiuk <[email protected]>
Corrected the spelling of 'VERSION_SUFFIX' in the command and clarified the note regarding its temporary unsetting.
…atus (apache#61426) - Adds a new 'airflowctl auth list-envs' command that scans AIRFLOW_HOME for environment config files and reports each environment's name, API URL, and authentication status (authenticated / not authenticated). - Filters out internal files (debug_creds_*.json, *_generated.json) so only real environments are listed.
apache#61281) * fix(api): disable uvloop if PYTHONASYNCIODEBUG=1 to prevent segfault (issue apache#61214) * docs(newsfragment): add newsfragment for uvloop/asyncio debug segfault fix (apache#61214) * fix(api): add stacklevel for debug warning and fix rst literals * fix: remove else block and correct newsfragment per review feedback * docs: document PYTHONASYNCIODEBUG/PYTHONDEVMODE incompatibility (Python 3.12+) * docs: fix RST formatting and spellcheck errors - Add blank line after warning directive to fix RST error - Quote asyncio with backticks to fix spellcheck * refactor: simplify to warning-only approach per reviewer feedback * refactor: apply reviewer suggestions --------- Co-authored-by: Jason(Zhe-You) Liu <[email protected]>
…esPodOperator auth (apache#60943) Pre-create ~/.aws/cli/cache directory in KubernetesHook.get_conn() to prevent a FileExistsError race condition when multiple KPO tasks authenticate via `aws eks get-token` concurrently on the same Celery worker. Older botocore versions (<1.40.2) call os.makedirs() without exist_ok=True, causing intermittent task failures before pod creation. closes: apache#60943
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
~/.aws/cli/cachedirectory inKubernetesHook.get_conn()to prevent aFileExistsErrorrace condition when multiple KPO tasks authenticate viaaws eks get-tokenconcurrently on the same Celery workeros.makedirs()withoutexist_ok=True, causing intermittent task failures before pod creationRoot Cause
When parallel KubernetesPodOperator tasks invoke exec-based EKS authentication on the same worker, the AWS CLI races to create
~/.aws/cli/cache. The losing process getsFileExistsError(errno 17), which surfaces as a 403 Forbidden from the Kubernetes API — the task fails before the pod is even created.Fixed upstream in botocore 1.40.2, but this defensive fix protects users on older versions.
Why this approach (and not something else)
We considered several alternatives before landing on defensive directory pre-creation:
generic_api_retryTRANSIENT_STATUS_CODESwould mask real auth failures and add retry latency to every legitimate 403. Distinguishing transient exec-auth 403s from real permission denials is not reliably possible — the Kubernetes client's ExecProvider silently swallows the subprocess error and proceeds with a bad token, so the 403 looks identical to a genuine RBAC denial.threading.Lockaround config loadingaws eks get-token) runs lazily during the first API call, not duringconfig.load_kube_config(). A lock around config loading wouldn't prevent the race. Locking around every API call would serialize all K8s operations — unacceptable for performance.botocore >= 1.40.2as a dependencyWhy pre-creation wins:
os.makedirs(..., exist_ok=True)call — the exact same fix botocore 1.40.2 applied, just done earlier in the call chainexist_ok=Trueis inherently safe for concurrent invocations — no race between our pre-creation and the AWS CLIChanges
hooks/kubernetes.py: Added_ensure_exec_plugin_cache_dirs()function called fromget_conn()before any kube config loading. Usesos.makedirs(..., exist_ok=True)to pre-create the cache directory.test_kubernetes.py: 3 new test cases verifying directory creation, idempotency, and integration withget_conn().closes: apache#60943
Test plan