Skip to content

Commit 143485d

Browse files
committed
feat: Add /auth/proxy route
1 parent fb1bc8a commit 143485d

3 files changed

Lines changed: 147 additions & 0 deletions

File tree

diracx-client/src/diracx/client/aio/operations/_operations.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
build_auth_do_device_flow_request,
3030
build_auth_finish_device_flow_request,
3131
build_auth_finished_request,
32+
build_auth_get_proxy_request,
3233
build_auth_get_refresh_tokens_request,
3334
build_auth_initiate_device_flow_request,
3435
build_auth_revoke_refresh_token_request,
@@ -763,6 +764,57 @@ async def userinfo(self, **kwargs: Any) -> _models.UserInfoResponse:
763764

764765
return deserialized
765766

767+
@distributed_trace_async
768+
async def get_proxy(self, **kwargs: Any) -> Any:
769+
"""Get Proxy.
770+
771+
Get Proxy.
772+
773+
:return: any
774+
:rtype: any
775+
:raises ~azure.core.exceptions.HttpResponseError:
776+
"""
777+
error_map = {
778+
401: ClientAuthenticationError,
779+
404: ResourceNotFoundError,
780+
409: ResourceExistsError,
781+
304: ResourceNotModifiedError,
782+
}
783+
error_map.update(kwargs.pop("error_map", {}) or {})
784+
785+
_headers = kwargs.pop("headers", {}) or {}
786+
_params = kwargs.pop("params", {}) or {}
787+
788+
cls: ClsType[Any] = kwargs.pop("cls", None)
789+
790+
request = build_auth_get_proxy_request(
791+
headers=_headers,
792+
params=_params,
793+
)
794+
request.url = self._client.format_url(request.url)
795+
796+
_stream = False
797+
pipeline_response: PipelineResponse = (
798+
await self._client._pipeline.run( # pylint: disable=protected-access
799+
request, stream=_stream, **kwargs
800+
)
801+
)
802+
803+
response = pipeline_response.http_response
804+
805+
if response.status_code not in [200]:
806+
map_error(
807+
status_code=response.status_code, response=response, error_map=error_map
808+
)
809+
raise HttpResponseError(response=response)
810+
811+
deserialized = self._deserialize("object", pipeline_response)
812+
813+
if cls:
814+
return cls(pipeline_response, deserialized, {})
815+
816+
return deserialized
817+
766818

767819
class ConfigOperations:
768820
"""

diracx-client/src/diracx/client/operations/_operations.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,20 @@ def build_auth_userinfo_request(**kwargs: Any) -> HttpRequest:
263263
return HttpRequest(method="GET", url=_url, headers=_headers, **kwargs)
264264

265265

266+
def build_auth_get_proxy_request(**kwargs: Any) -> HttpRequest:
267+
_headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
268+
269+
accept = _headers.pop("Accept", "application/json")
270+
271+
# Construct URL
272+
_url = "/api/auth/proxy"
273+
274+
# Construct headers
275+
_headers["Accept"] = _SERIALIZER.header("accept", accept, "str")
276+
277+
return HttpRequest(method="GET", url=_url, headers=_headers, **kwargs)
278+
279+
266280
def build_config_serve_config_request(
267281
vo: str,
268282
*,
@@ -1480,6 +1494,57 @@ def userinfo(self, **kwargs: Any) -> _models.UserInfoResponse:
14801494

14811495
return deserialized
14821496

1497+
@distributed_trace
1498+
def get_proxy(self, **kwargs: Any) -> Any:
1499+
"""Get Proxy.
1500+
1501+
Get Proxy.
1502+
1503+
:return: any
1504+
:rtype: any
1505+
:raises ~azure.core.exceptions.HttpResponseError:
1506+
"""
1507+
error_map = {
1508+
401: ClientAuthenticationError,
1509+
404: ResourceNotFoundError,
1510+
409: ResourceExistsError,
1511+
304: ResourceNotModifiedError,
1512+
}
1513+
error_map.update(kwargs.pop("error_map", {}) or {})
1514+
1515+
_headers = kwargs.pop("headers", {}) or {}
1516+
_params = kwargs.pop("params", {}) or {}
1517+
1518+
cls: ClsType[Any] = kwargs.pop("cls", None)
1519+
1520+
request = build_auth_get_proxy_request(
1521+
headers=_headers,
1522+
params=_params,
1523+
)
1524+
request.url = self._client.format_url(request.url)
1525+
1526+
_stream = False
1527+
pipeline_response: PipelineResponse = (
1528+
self._client._pipeline.run( # pylint: disable=protected-access
1529+
request, stream=_stream, **kwargs
1530+
)
1531+
)
1532+
1533+
response = pipeline_response.http_response
1534+
1535+
if response.status_code not in [200]:
1536+
map_error(
1537+
status_code=response.status_code, response=response, error_map=error_map
1538+
)
1539+
raise HttpResponseError(response=response)
1540+
1541+
deserialized = self._deserialize("object", pipeline_response)
1542+
1543+
if cls:
1544+
return cls(pipeline_response, deserialized, {})
1545+
1546+
return deserialized
1547+
14831548

14841549
class ConfigOperations:
14851550
"""

diracx-routers/src/diracx/routers/auth.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
DiracHttpResponse,
3535
ExpiredFlowError,
3636
PendingAuthorizationError,
37+
ProxyNotFoundError,
3738
)
3839
from diracx.core.models import TokenResponse, UserInfo
3940
from diracx.core.properties import (
@@ -48,6 +49,7 @@
4849
AuthDB,
4950
AvailableSecurityProperties,
5051
Config,
52+
ProxyDB,
5153
add_settings_annotation,
5254
)
5355
from .fastapi_classes import DiracxRouter
@@ -1119,3 +1121,31 @@ async def legacy_exchange(
11191121
refresh_token_expire_minutes=expires_minutes,
11201122
legacy_exchange=True,
11211123
)
1124+
1125+
1126+
@router.get("/proxy")
1127+
async def get_proxy(
1128+
proxy_db: ProxyDB,
1129+
user_info: Annotated[AuthorizedUserInfo, Depends(verify_dirac_access_token)],
1130+
config: Config,
1131+
):
1132+
voms_role = config.Registry[user_info.vo].Groups[user_info.dirac_group].VOMSRole
1133+
user_dns = config.Registry[user_info.vo].Users[user_info.sub].DNs
1134+
1135+
lifetime_seconds = 3600
1136+
for user_dn in user_dns:
1137+
try:
1138+
return await proxy_db.get_proxy(
1139+
user_dn,
1140+
user_info.vo,
1141+
user_info.dirac_group,
1142+
voms_role,
1143+
lifetime_seconds,
1144+
)
1145+
except ProxyNotFoundError:
1146+
pass
1147+
else:
1148+
raise HTTPException(
1149+
status_code=status.HTTP_400_BAD_REQUEST,
1150+
detail=f"No available proxy for {user_info.sub}",
1151+
)

0 commit comments

Comments
 (0)