ColtenOuO opened a new pull request, #71645: URL: https://github.com/apache/airflow/pull/71645
### Sumarry The api server exposes the certificate, key, CA file and client-verification mode for its TLS listener, but not the cipher list. Deployments with a TLS policy that requires pinning an explicit set of cipher suites have no way to express it, and are stuck with whatever Python's `ssl` module defaults to. This adds an `[api] ssl_ciphers` configuration option and the matching `airflow api-server --ssl-ciphers` flag, wired into both server backends: `ssl_ciphers` for uvicorn and `ciphers` for gunicorn. Leaving the option empty keeps the current behaviour, so existing deployments are unaffected. Both uvicorn and gunicorn default their cipher setting to `None` (meaning "use the Python default"), so an unset value is passed through unchanged rather than substituting a value of our own. A cipher list that OpenSSL cannot resolve is rejected during argument handling with an `AirflowConfigException`, instead of surfacing later as a bare `ssl.SSLError: No cipher can be selected` while the server binds its socket. The linked issue also suggests being able to override *any* uvicorn/gunicorn option. That is a much larger design question about how much of the underlying servers' surface Airflow should expose, so this PR is deliberately scoped to the cipher list that was actually blocking the reporter. ### Changes - **`airflow-core/src/airflow/config_templates/config.yml`** Adds the `[api] ssl_ciphers` option (`version_added: 3.4.0`, default empty), documented as an OpenSSL cipher list with a link to the cipher-list format reference. - **`airflow-core/src/airflow/cli/cli_config.py`** Adds `ARG_SSL_CIPHERS` (`--ssl-ciphers`), defaulting to the config value, and registers it on the `api-server` command next to the existing `--ssl-*` flags. - **`airflow-core/src/airflow/cli/commands/api_server_command.py`** Adds a `_ssl_ciphers()` helper alongside the existing `_ssl_cert_reqs()` / `_get_ssl_filepaths()` helpers. It normalises an empty value to `None` and validates a non-empty list by applying it to a throwaway `SSLContext`, raising `AirflowConfigException` if OpenSSL cannot resolve it. Both the uvicorn and the gunicorn code paths call it. - **`airflow-core/src/airflow/api_fastapi/gunicorn_app.py`** `create_gunicorn_app()` takes a new `ssl_ciphers` argument and maps it to gunicorn's `ciphers` option. It is set inside the existing `if ssl_cert and ssl_key:` block, matching how `ca_certs` and `cert_reqs` are already handled, so ciphers never leak into a plain-HTTP configuration. closes: #71426 --- ##### Was generative AI tooling used to co-author this PR? - [X] Yes — Claude Code (Opus 5) for writting unit test. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
