ephraimbuddy commented on code in PR #74700:
URL: https://github.com/apache/airflow/pull/74700#discussion_r4361112918


##########
airflow-core/src/airflow/api_fastapi/execution_api/routes/session_tokens.py:
##########
@@ -0,0 +1,105 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""Exchange an authenticated workload identity for a Dag processor session."""
+
+from __future__ import annotations
+
+from typing import Annotated
+
+import jwt
+import svcs
+from cadwyn import VersionedAPIRouter
+from fastapi import Depends, HTTPException, Request, Response, status
+from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
+from pydantic import ValidationError
+
+from airflow.api_fastapi.auth.tokens import JWKSUnavailableError, JWTGenerator
+from airflow.api_fastapi.core_api.openapi.exceptions import 
create_openapi_http_exception_doc
+from airflow.api_fastapi.execution_api.dag_processor_tokens import (
+    ExpiredDagProcessorToken,
+    generate_dag_processor_session_token,
+    get_token_lifetime,
+)
+from airflow.api_fastapi.execution_api.datamodels.job import 
DagProcessorSessionTokenResponse
+from airflow.api_fastapi.execution_api.deps import DepContainer
+from airflow.api_fastapi.execution_api.workload_identity import (
+    DagProcessorIdentity,
+    DagProcessorIdentityVerifier,
+    WorkloadIdentityNotAllowed,
+)
+
+router = VersionedAPIRouter()
+identity_bearer = HTTPBearer(auto_error=False, 
scheme_name="DagProcessorWorkloadIdentity")
+
+
+async def require_workload_identity(
+    request: Request,
+    credentials: Annotated[HTTPAuthorizationCredentials | None, 
Depends(identity_bearer)],
+) -> DagProcessorIdentity:
+    verifier: DagProcessorIdentityVerifier | None = 
request.app.state.dag_processor_identity_verifier
+    if verifier is None:
+        raise HTTPException(status.HTTP_404_NOT_FOUND, "Workload identity 
provisioning is not enabled")
+    if credentials is None:
+        raise HTTPException(
+            status.HTTP_401_UNAUTHORIZED, "Workload identity required", 
headers={"WWW-Authenticate": "Bearer"}
+        )
+    try:
+        return await verifier.authenticate(credentials.credentials)
+    except JWKSUnavailableError:
+        raise HTTPException(
+            status.HTTP_503_SERVICE_UNAVAILABLE,
+            "Workload identity signing keys are unavailable",
+            headers={"Retry-After": 
str(verifier.jwks.refresh_retry_interval_secs)},
+        ) from None
+    except (jwt.PyJWTError, ValidationError, TypeError, OverflowError):

Review Comment:
   They are reachable on our lower bound. airflow-core allows `pyjwt>=2.11.0`, 
and on 2.11.0 `"exp": []` raises a bare `TypeError` and `"exp": Infinity` a 
bare `OverflowError` out of `jwt.decode`; 2.15.0 is the first release that 
converts them. The `{"exp": []}` and `{"exp": inf}` cases in 
`test_rejects_invalid_signed_claims` would hit that in the lowest-dependencies 
job.
   
   You're right that the route was the wrong place, though. `authenticate` now 
converts only those two, around the decode call, and logs a warning; the route 
catches just `PyJWTError` and `ValidationError`. A `TypeError` anywhere else in 
the verifier now surfaces as a 500, which 
`test_verifier_bugs_are_not_reported_as_invalid_identity` checks.
   
   ---
   Drafted-by: Claude Code (Opus 5.5); reviewed by @ephraimbuddy before posting



-- 
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]

Reply via email to