This is an automated email from the ASF dual-hosted git repository.

vincbeck pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new ddf1ebc0fe7 fix: EksPodOperator 401 with cross-account AssumeRole via 
aws_conn_id (#65335)
ddf1ebc0fe7 is described below

commit ddf1ebc0fe7e509e323b46d938600b31c82e679c
Author: Anmol Mishra <[email protected]>
AuthorDate: Fri May 22 00:29:01 2026 +0530

    fix: EksPodOperator 401 with cross-account AssumeRole via aws_conn_id 
(#65335)
---
 .../src/airflow/providers/amazon/aws/hooks/eks.py  | 24 +++++++++++++--
 .../amazon/tests/unit/amazon/aws/hooks/test_eks.py | 35 ++++++++++++++++++++++
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py 
b/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py
index fd0dd09876c..032d7e16833 100644
--- a/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py
+++ b/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py
@@ -82,8 +82,14 @@ COMMAND = """
             # Load credentials from secure file using (POSIX-compliant dot 
operator)
             . {credentials_file}
 
+            # Redirect stderr to a temporary file to prevent Python warnings,
+            # deprecation notices, or other log output from contaminating 
stdout.
+            # The token output must be the ONLY thing on stdout for bash token
+            # parsing to work, but stderr should still be reported on failure.
+            stderr_file=$(mktemp)
+            trap 'rm -f "$stderr_file"' EXIT
             output=$({python_executable} -m 
airflow.providers.amazon.aws.utils.eks_get_token \
-                --cluster-name {eks_cluster_name} --sts-url '{sts_url}' {args} 
2>&1)
+                --cluster-name {eks_cluster_name} --sts-url '{sts_url}' {args} 
2>"$stderr_file")
 
             status=$?
 
@@ -91,11 +97,16 @@ COMMAND = """
             unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
 
             if [ "$status" -ne 0 ]; then
-                printf '%s' "$output" >&2
+                printf 'eks_get_token failed with exit code %s.' "$status" >&2
+                if [ -s "$stderr_file" ]; then
+                    printf ' Stderr was: ' >&2
+                    cat "$stderr_file" >&2
+                fi
                 exit "$status"
             fi
 
             # Use pure bash below to parse so that it's posix compliant
+            # Only the token line should be on stdout (stderr captured above)
 
             last_line=${{output##*$'\\n'}}  # strip everything up to the last 
newline
 
@@ -104,6 +115,15 @@ COMMAND = """
 
             token=${{last_line##*, token: }}  # text after ", token: "
 
+            # Validate that token was extracted — empty token means parsing 
failed
+            # or eks_get_token produced unexpected output. Without this check, 
a
+            # malformed ExecCredential is sent to the API server, resulting in 
a
+            # 401 with an empty user identity in the audit logs.
+            if [ -z "$token" ]; then
+                printf 'Failed to extract token from eks_get_token output.' >&2
+                exit 1
+            fi
+
             json_string=$(printf '{{"kind": "ExecCredential","apiVersion": \
                 "{authentication_api_version}","spec": {{}},"status": \
                 {{"expirationTimestamp": "%s","token": "%s"}}}}' "$timestamp" 
"$token")
diff --git a/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py 
b/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py
index c0da40e7c03..521005a19ed 100644
--- a/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py
+++ b/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py
@@ -1273,6 +1273,41 @@ class TestEksHook:
             if expected_region_args:
                 assert expected_region_args in command_arg
 
+    def test_command_template_captures_stderr_separately(self):
+        """Verify COMMAND keeps stderr out of stdout while preserving 
errors."""
+        from airflow.providers.amazon.aws.hooks.eks import COMMAND
+
+        # Verify stderr is not merged with stdout (the core correctness 
requirement)
+        assert "2>&1" not in COMMAND, (
+            "COMMAND must not use 2>&1 — merging stderr with stdout breaks 
bash token parsing"
+        )
+        assert "stderr_file=$(mktemp)" in COMMAND
+        assert '2>"$stderr_file"' in COMMAND
+        assert 'cat "$stderr_file" >&2' in COMMAND
+        assert "2>/dev/null" not in COMMAND
+
+    def test_command_template_does_not_print_token_output_on_error(self):
+        """Verify the error path does not echo stdout, which can contain a 
token."""
+        from airflow.providers.amazon.aws.hooks.eks import COMMAND
+
+        failure_block = COMMAND.split('if [ "$status" -ne 0 ]; then', 
1)[1].split("fi", 1)[0]
+        assert '"$output"' not in failure_block
+
+    def test_command_template_validates_token(self):
+        """Verify COMMAND template validates that the token was successfully
+        extracted before producing the ExecCredential JSON. Without this check,
+        a malformed ExecCredential with an empty token is sent to the API 
server,
+        resulting in 401 Unauthorized with an empty user identity in audit 
logs.
+        """
+        from airflow.providers.amazon.aws.hooks.eks import COMMAND
+
+        # Verify token validation check exists
+        assert 'if [ -z "$token" ]' in COMMAND, (
+            "COMMAND must validate that token is non-empty before producing 
ExecCredential JSON"
+        )
+        # Verify the empty-token validation block exits with an error
+        assert "exit 1" in COMMAND, "COMMAND must exit with error when token 
extraction fails"
+
 
 # Helper methods for repeated assert combinations.
 def assert_all_arn_values_are_valid(expected_arn_values, pattern, 
arn_under_test) -> None:

Reply via email to