Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions airflow-core/src/airflow/config_templates/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,8 @@ api:
description: |
Paths to the SSL certificate and key for the api server. When both are
provided SSL will be enabled. This does not change the api server port.
The same SSL certificate will also be loaded into the worker to enable
it to be trusted when a self-signed certificate is used.
version_added: ~
type: string
example: ~
Expand Down
7 changes: 7 additions & 0 deletions task-sdk/src/airflow/sdk/api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
from __future__ import annotations

import logging
import ssl
import sys
import uuid
from http import HTTPStatus
from typing import TYPE_CHECKING, Any, TypeVar

import certifi
import httpx
import msgspec
import structlog
Expand Down Expand Up @@ -660,6 +662,7 @@ def noop_handler(request: httpx.Request) -> httpx.Response:
API_RETRIES = conf.getint("workers", "execution_api_retries")
API_RETRY_WAIT_MIN = conf.getfloat("workers", "execution_api_retry_wait_min")
API_RETRY_WAIT_MAX = conf.getfloat("workers", "execution_api_retry_wait_max")
API_SSL_CERT_PATH = conf.get("api", "ssl_cert")


class Client(httpx.Client):
Expand All @@ -675,6 +678,10 @@ def __init__(self, *, base_url: str | None, dry_run: bool = False, token: str, *
kwargs.setdefault("base_url", "dry-run://server")
else:
kwargs["base_url"] = base_url
ctx = ssl.create_default_context(cafile=certifi.where())
if API_SSL_CERT_PATH:
ctx.load_verify_locations(API_SSL_CERT_PATH)
kwargs["verify"] = ctx
pyver = f"{'.'.join(map(str, sys.version_info[:3]))}"
super().__init__(
auth=auth,
Expand Down
10 changes: 10 additions & 0 deletions task-sdk/tests/task_sdk/api/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ def test_dry_run(self, path, json_response):
assert resp.status_code == 200
assert resp.json() == json_response

@mock.patch("airflow.sdk.api.client.API_SSL_CERT_PATH", "/capath/does/not/exist/")
def test_add_capath(self):
def handle_request(request: httpx.Request) -> httpx.Response:
return httpx.Response(status_code=200)

with pytest.raises(FileNotFoundError) as err:
make_client(httpx.MockTransport(handle_request))

assert isinstance(err.value, FileNotFoundError)

def test_error_parsing(self):
responses = [
httpx.Response(422, json={"detail": [{"loc": ["#0"], "msg": "err", "type": "required"}]})
Expand Down
Loading