Skip to content

Commit 5cb782e

Browse files
chrisburrchaen
andauthored
fix: avoid httpx2 verify=<str> deprecation in the client auth patches (#952)
* fix: avoid httpx2 verify=<str> deprecation in client patches httpx2 deprecated passing verify as a path string. The client credential flow converts verify to a CA-bundle path when ca_path is configured and passed it straight to httpx2.get/post, triggering a DeprecationWarning in normal usage. Add a prepare_verify helper in diracx.core.utils that builds an ssl.SSLContext from a CA file/directory path (booleans pass through) and use it at the httpx2 call sites in the sync and async client patches. * refactor: drop unused DiracClientMixin from client patches DiracClientMixin (and its DiracTokenCredential / DiracBearerTokenCredentialPolicy helpers) in patches/utils.py were never imported; the live clients are SyncDiracClient/AsyncDiracClient, which use the per-mode mixins in patches/client/{sync,aio}.py. Remove the dead classes and the imports that only they used. * refactor: consolidate client auth patches into one module patches/utils.py duplicated the token helpers already present in patches/client/common.py; the async client used one copy and the sync client the other. Merge them into patches/client/common.py (imported by both sync.py and aio.py) and delete patches/utils.py. With a single home for the helpers, flip their verify parameter to the native httpx2 type (bool | ssl.SSLContext) and convert the CA path once in each client __init__, keeping the bool/str form only for azure-core's connection_verify. --------- Co-authored-by: chaen <christophe.haen@cern.ch>
1 parent ced845d commit 5cb782e

6 files changed

Lines changed: 54 additions & 340 deletions

File tree

diracx-client/src/diracx/client/patches/client/aio.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from __future__ import annotations
44

5+
import ssl
56
from importlib.metadata import PackageNotFoundError, distribution
67
from pathlib import Path
78
from types import TracebackType
@@ -12,8 +13,9 @@
1213
from azure.core.pipeline import PipelineRequest
1314
from azure.core.pipeline.policies import AsyncBearerTokenCredentialPolicy
1415
from diracx.core.preferences import get_diracx_preferences, DiracxPreferences
16+
from diracx.core.utils import prepare_verify
1517

16-
from ..utils import get_openid_configuration, get_token
18+
from .common import get_openid_configuration, get_token
1719
from ..._generated.aio._client import Dirac as _Dirac
1820

1921
__all__ = [
@@ -30,7 +32,7 @@ def __init__(
3032
token_endpoint: str,
3133
client_id: str,
3234
*,
33-
verify: bool | str = True,
35+
verify: bool | ssl.SSLContext = True,
3436
) -> None:
3537
self.location = location
3638
self.verify = verify
@@ -122,11 +124,16 @@ def __init__(
122124
if verify is True and diracx_preferences.ca_path:
123125
verify = str(diracx_preferences.ca_path)
124126
kwargs["connection_verify"] = verify
127+
# azure-core wants a bool/path for connection_verify, but httpx2 wants
128+
# an SSLContext, so convert the CA path once here for the httpx2 calls.
129+
ssl_verify = prepare_verify(verify)
125130
self._endpoint = str(endpoint or diracx_preferences.url)
126131
self._client_id = client_id or "myDIRACClientID"
127132

128133
# Get .well-known configuration
129-
openid_configuration = get_openid_configuration(self._endpoint, verify=verify)
134+
openid_configuration = get_openid_configuration(
135+
self._endpoint, verify=ssl_verify
136+
)
130137

131138
try:
132139
self.client_version = distribution("diracx").version
@@ -149,7 +156,7 @@ def __init__(
149156
location=diracx_preferences.credentials_path,
150157
token_endpoint=openid_configuration["token_endpoint"],
151158
client_id=self._client_id,
152-
verify=verify,
159+
verify=ssl_verify,
153160
),
154161
),
155162
**kwargs,

diracx-client/src/diracx/client/patches/client/common.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
from __future__ import annotations
44

55
__all__ = [
6-
"DiracAuthMixin",
6+
"get_openid_configuration",
7+
"get_token",
8+
"refresh_token",
79
]
810

911
import fcntl
1012
import json
1113
import os
14+
import ssl
1215
from datetime import datetime, timedelta, timezone
1316
from dataclasses import dataclass
1417
from enum import Enum
@@ -19,7 +22,10 @@
1922
import httpx2
2023
import jwt
2124
from azure.core.credentials import AccessToken
22-
from diracx.core.utils import EXPIRES_GRACE_SECONDS, serialize_credentials
25+
from diracx.core.utils import (
26+
EXPIRES_GRACE_SECONDS,
27+
serialize_credentials,
28+
)
2329
from diracx.core.models import TokenResponse
2430

2531

@@ -37,7 +43,7 @@ class TokenResult:
3743

3844

3945
def get_openid_configuration(
40-
endpoint: str, *, verify: bool | str = True
46+
endpoint: str, *, verify: bool | ssl.SSLContext = True
4147
) -> dict[str, str]:
4248
"""Get the openid configuration from the .well-known endpoint"""
4349
response = httpx2.get(
@@ -54,7 +60,7 @@ def get_token(
5460
token: AccessToken | None,
5561
token_endpoint: str,
5662
client_id: str,
57-
verify: bool | str,
63+
verify: bool | ssl.SSLContext,
5864
) -> AccessToken:
5965
"""Get the access token if available and still valid."""
6066
# Immediately return the token if it is available and still valid
@@ -117,7 +123,7 @@ def refresh_token(
117123
client_id: str,
118124
refresh_token: str,
119125
*,
120-
verify: bool | str = True,
126+
verify: bool | ssl.SSLContext = True,
121127
) -> TokenResponse:
122128
"""Refresh the access token using the refresh_token flow."""
123129
response = httpx2.post(

diracx-client/src/diracx/client/patches/client/sync.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"Dirac",
77
]
88

9+
import ssl
910
from importlib.metadata import PackageNotFoundError, distribution
1011
from pathlib import Path
1112
from typing import Any, Optional
@@ -14,6 +15,7 @@
1415
from azure.core.pipeline import PipelineRequest
1516
from azure.core.pipeline.policies import BearerTokenCredentialPolicy
1617
from diracx.core.preferences import DiracxPreferences, get_diracx_preferences
18+
from diracx.core.utils import prepare_verify
1719

1820
from .common import get_openid_configuration, get_token
1921
from ..._generated._client import Dirac as _Dirac
@@ -28,7 +30,7 @@ def __init__(
2830
token_endpoint: str,
2931
client_id: str,
3032
*,
31-
verify: bool | str = True,
33+
verify: bool | ssl.SSLContext = True,
3234
) -> None:
3335
self.location = location
3436
self.verify = verify
@@ -104,10 +106,15 @@ def __init__(
104106
if verify is True and diracx_preferences.ca_path:
105107
verify = str(diracx_preferences.ca_path)
106108
kwargs["connection_verify"] = verify
109+
# azure-core wants a bool/path for connection_verify, but httpx2 wants
110+
# an SSLContext, so convert the CA path once here for the httpx2 calls.
111+
ssl_verify = prepare_verify(verify)
107112
self._client_id = client_id or "myDIRACClientID"
108113

109114
# Get .well-known configuration
110-
openid_configuration = get_openid_configuration(self._endpoint, verify=verify)
115+
openid_configuration = get_openid_configuration(
116+
self._endpoint, verify=ssl_verify
117+
)
111118

112119
try:
113120
self.client_version = distribution("diracx").version
@@ -130,7 +137,7 @@ def __init__(
130137
location=diracx_preferences.credentials_path,
131138
token_endpoint=openid_configuration["token_endpoint"],
132139
client_id=self._client_id,
133-
verify=verify,
140+
verify=ssl_verify,
134141
),
135142
),
136143
**kwargs,

0 commit comments

Comments
 (0)