Skip to content

Commit 6dba101

Browse files
authored
Add cert used for apiserver to client (fix for self-signed) (#53574)
* Add cert used for apiserver to client (fix for self-signed) * Correct indentation, run pre-commit checks * Add test for cert load * Update config description for api ssl_cert * Use mock instead and check error when non-existant CA is not found
1 parent b395021 commit 6dba101

File tree

3 files changed

+19
-0
lines changed

3 files changed

+19
-0
lines changed

airflow-core/src/airflow/config_templates/config.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,8 @@ api:
14081408
description: |
14091409
Paths to the SSL certificate and key for the api server. When both are
14101410
provided SSL will be enabled. This does not change the api server port.
1411+
The same SSL certificate will also be loaded into the worker to enable
1412+
it to be trusted when a self-signed certificate is used.
14111413
version_added: ~
14121414
type: string
14131415
example: ~

task-sdk/src/airflow/sdk/api/client.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
from __future__ import annotations
1919

2020
import logging
21+
import ssl
2122
import sys
2223
import uuid
2324
from http import HTTPStatus
2425
from typing import TYPE_CHECKING, Any, TypeVar
2526

27+
import certifi
2628
import httpx
2729
import msgspec
2830
import structlog
@@ -747,6 +749,7 @@ def noop_handler(request: httpx.Request) -> httpx.Response:
747749
API_RETRIES = conf.getint("workers", "execution_api_retries")
748750
API_RETRY_WAIT_MIN = conf.getfloat("workers", "execution_api_retry_wait_min")
749751
API_RETRY_WAIT_MAX = conf.getfloat("workers", "execution_api_retry_wait_max")
752+
API_SSL_CERT_PATH = conf.get("api", "ssl_cert")
750753

751754

752755
class Client(httpx.Client):
@@ -762,6 +765,10 @@ def __init__(self, *, base_url: str | None, dry_run: bool = False, token: str, *
762765
kwargs.setdefault("base_url", "dry-run://server")
763766
else:
764767
kwargs["base_url"] = base_url
768+
ctx = ssl.create_default_context(cafile=certifi.where())
769+
if API_SSL_CERT_PATH:
770+
ctx.load_verify_locations(API_SSL_CERT_PATH)
771+
kwargs["verify"] = ctx
765772
pyver = f"{'.'.join(map(str, sys.version_info[:3]))}"
766773
super().__init__(
767774
auth=auth,

task-sdk/tests/task_sdk/api/test_client.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ def test_dry_run(self, path, json_response):
8888
assert resp.status_code == 200
8989
assert resp.json() == json_response
9090

91+
@mock.patch("airflow.sdk.api.client.API_SSL_CERT_PATH", "/capath/does/not/exist/")
92+
def test_add_capath(self):
93+
def handle_request(request: httpx.Request) -> httpx.Response:
94+
return httpx.Response(status_code=200)
95+
96+
with pytest.raises(FileNotFoundError) as err:
97+
make_client(httpx.MockTransport(handle_request))
98+
99+
assert isinstance(err.value, FileNotFoundError)
100+
91101
def test_error_parsing(self):
92102
responses = [
93103
httpx.Response(422, json={"detail": [{"loc": ["#0"], "msg": "err", "type": "required"}]})

0 commit comments

Comments
 (0)